View Javadoc
1   /*
2    * Copyright (c) 2002-2022, City of Paris
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright notice
10   *     and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright notice
13   *     and the following disclaimer in the documentation and/or other materials
14   *     provided with the distribution.
15   *
16   *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17   *     contributors may be used to endorse or promote products derived from
18   *     this software without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   *
32   * License 1.0
33   */
34  package fr.paris.lutece.plugins.appointment.web;
35  
36  import java.io.File;
37  import java.io.IOException;
38  import java.util.Map;
39  import java.util.Set;
40  
41  import javax.servlet.http.HttpServletRequest;
42  import javax.validation.ConstraintViolation;
43  
44  import org.apache.commons.collections.CollectionUtils;
45  import org.apache.commons.io.FileUtils;
46  import org.apache.commons.lang3.ArrayUtils;
47  import org.apache.commons.lang3.StringUtils;
48  
49  import fr.paris.lutece.plugins.appointment.business.calendar.CalendarTemplate;
50  import fr.paris.lutece.plugins.appointment.business.calendar.CalendarTemplateHome;
51  import fr.paris.lutece.portal.service.message.AdminMessage;
52  import fr.paris.lutece.portal.service.message.AdminMessageService;
53  import fr.paris.lutece.portal.service.util.AppLogService;
54  import fr.paris.lutece.portal.service.util.AppPathService;
55  import fr.paris.lutece.portal.service.util.AppPropertiesService;
56  import fr.paris.lutece.portal.util.mvc.admin.MVCAdminJspBean;
57  import fr.paris.lutece.portal.util.mvc.admin.annotations.Controller;
58  import fr.paris.lutece.portal.util.mvc.commons.annotations.Action;
59  import fr.paris.lutece.portal.util.mvc.commons.annotations.View;
60  import fr.paris.lutece.util.ReferenceList;
61  import fr.paris.lutece.util.datatable.DataTableManager;
62  import fr.paris.lutece.util.url.UrlItem;
63  
64  /**
65   * This class provides the user interface to manage calendar templates
66   * 
67   * @author Laurent Payen
68   *
69   */
70  @Controller( controllerJsp = CalendarTemplateJspBean.CONTROLLER_JSP, controllerPath = CalendarTemplateJspBean.CONTROLLER_PATH, right = CalendarTemplateJspBean.RIGHT_MANAGE_CALENDAR_TEMPLATES )
71  public class CalendarTemplateJspBean extends MVCAdminJspBean
72  {
73      /**
74       * Right to manage appointment calendar templates
75       */
76      public static final String RIGHT_MANAGE_CALENDAR_TEMPLATES = "APPOINTMENT_CALENDAR_TEMPLATE";
77  
78      /**
79       * Folder of the JSP of this controller
80       */
81      public static final String CONTROLLER_PATH = "jsp/admin/plugins/appointment/";
82  
83      /**
84       * Name of the JSP of this controller
85       */
86      public static final String CONTROLLER_JSP = "ManageCalendarTemplates.jsp";
87  
88      /**
89       * URL of the JSP of this controller
90       */
91      public static final String JSP_URL_MANAGE_CALENDAR_TEMPLATE = CONTROLLER_PATH + CONTROLLER_JSP;
92  
93      /**
94       * Serial version UID
95       */
96      private static final long serialVersionUID = 3406345413046194795L;
97  
98      // templates
99      private static final String TEMPLATE_MANAGE_CALENDAR_TEMPLATES = "/admin/plugins/appointment/templates/manage_calendar_templates.html";
100     private static final String TEMPLATE_CREATE_MODIFY_CALENDAR_TEMPLATE = "/admin/plugins/appointment/templates/create_modify_calendar_template.html";
101 
102     // Marks
103     private static final String MARK_DATA_TABLE_MANAGER = "dataTableManager";
104     private static final String MARK_TEMPLATE = "template";
105     private static final String MARK_REF_LIST_TEMPLATES = "refListTemplates";
106 
107     // Parameters
108     private static final String PARAMETER_ID_TEMPLATE = "idTemplate";
109     private static final String PARAMETER_TEMPLACE_PATH = "templatePath";
110 
111     // Messages
112     private static final String MESSAGE_COLUMN_TITLE_TITLE = "appointment.labelTitle";
113     private static final String MESSAGE_COLUMN_TITLE_DESCRIPTION = "appointment.labelDescription";
114     private static final String MESSAGE_COLUMN_TITLE_TEMPLATE_PATH = "appointment.manageCalendarTemplates.labelTemplatePath";
115     private static final String MESSAGE_COLUMN_TITLE_ACTIONS = "portal.util.labelActions";
116     private static final String MESSAGE_DEFAULT_PAGE_TITLE = "appointment.adminFeature.manageCalendarTemplates.name";
117     private static final String MESSAGE_CREATE_TEMPLATE_PAGE_TITLE = "appointment.labelAddTemplate";
118     private static final String MESSAGE_MODIFY_TEMPLATE_PAGE_TITLE = "appointment.createModifyCalendarTemplate.pageTitleModify";
119     private static final String MESSAGE_INFO_TEMPLATE_CREATED = "appointment.createModifyCalendarTemplate.infoTemplateCreated";
120     private static final String MESSAGE_INFO_TEMPLATE_UPDATED = "appointment.createModifyCalendarTemplate.infoTemplateUpdated";
121     private static final String MESSAGE_INFO_TEMPLATE_REMOVED = "appointment.removeCalendarTemplate.infoTemplateRemoved";
122     private static final String MESSAGE_CONFIRM_REMOVE_TEMPLATE = "appointment.removeCalendarTemplate.confirmRemoveTemplate";
123 
124     // Properties
125     private static final String PROPERTY_DEFAULT_LIST_APPOINTMENT_PER_PAGE = "appointment.listAppointments.itemsPerPage";
126     private static final String PROPERTY_FOLDER_CALENDAR_TEMPLATES = "appointment.calendarTemplates.calendarTemplatesFolder";
127     private static final String PROPERTY_TITLE = "title";
128     private static final String PROPERTY_DESCRIPTION = "description";
129     private static final String PROPERTY_TEMPLATE_PATH = "templatePath";
130 
131     // Views
132     private static final String VIEW_MANAGE_CALENDAR_TEMPLATES = "viewManageCalendarTemplates";
133     private static final String VIEW_CREATE_MODIFY_TEMPLATE = "getCreateModifyTemplate";
134     private static final String VIEW_CONFIRM_REMOVE_TEMPLATE = "getConfirmRemoveTemplate";
135 
136     // Actions
137     private static final String ACTION_CREATE_MODIFY_TEMPLATE = "doCreateModifyTemplate";
138     private static final String ACTION_REMOVE_TEMPLATE = "doRemoveTemplate";
139     private static final String ACTION_DOWNLOAD_TEMPLATE = "doDownloadTemplate";
140 
141     // Constants
142     private static final String CONSTANT_TEMPLATE_FOLDER = "/WEB-INF/templates/";
143     private static final String CONSTANT_FOLDER_UP = "..";
144 
145     // Session variables
146     private DataTableManager<CalendarTemplate> _dataTableManager;
147     private CalendarTemplate _template;
148 
149     /**
150      * Get the page to manage calendar templates.
151      * 
152      * @param request
153      *            The request
154      * @return The HTML code to display
155      */
156     @View( value = VIEW_MANAGE_CALENDAR_TEMPLATES, defaultView = true )
157     public String getManageAppointmentCalendarTemplates( HttpServletRequest request )
158     {
159         _template = null;
160 
161         if ( _dataTableManager == null )
162         {
163             _dataTableManager = new DataTableManager<>( getViewFullUrl( VIEW_MANAGE_CALENDAR_TEMPLATES ), null,
164                     AppPropertiesService.getPropertyInt( PROPERTY_DEFAULT_LIST_APPOINTMENT_PER_PAGE, 50 ), true );
165             _dataTableManager.addColumn( MESSAGE_COLUMN_TITLE_TITLE, PROPERTY_TITLE, true );
166             _dataTableManager.addColumn( MESSAGE_COLUMN_TITLE_DESCRIPTION, PROPERTY_DESCRIPTION, true );
167             _dataTableManager.addColumn( MESSAGE_COLUMN_TITLE_TEMPLATE_PATH, PROPERTY_TEMPLATE_PATH, true );
168             _dataTableManager.addActionColumn( MESSAGE_COLUMN_TITLE_ACTIONS );
169         }
170 
171         _dataTableManager.filterSortAndPaginate( request, CalendarTemplateHome.findAll( ) );
172 
173         Map<String, Object> model = getModel( );
174         model.put( MARK_DATA_TABLE_MANAGER, _dataTableManager );
175 
176         String strContent = getPage( MESSAGE_DEFAULT_PAGE_TITLE, TEMPLATE_MANAGE_CALENDAR_TEMPLATES, model );
177 
178         _dataTableManager.clearItems( );
179 
180         return strContent;
181     }
182 
183     /**
184      * Get the page to create or modify an existing template
185      * 
186      * @param request
187      *            The request
188      * @return The page to create or modify an existing template
189      */
190     @View( VIEW_CREATE_MODIFY_TEMPLATE )
191     public String getCreateModifyTemplate( HttpServletRequest request )
192     {
193         String strIdTemplate = request.getParameter( PARAMETER_ID_TEMPLATE );
194 
195         if ( StringUtils.isNotEmpty( strIdTemplate ) && StringUtils.isNumeric( strIdTemplate ) )
196         {
197             // If the id template is valid, then we load the template from the
198             // database
199             int nIdTemplate = Integer.parseInt( strIdTemplate );
200             _template = CalendarTemplateHome.findByPrimaryKey( nIdTemplate );
201         }
202         else
203         {
204             if ( _template == null )
205             {
206                 // Otherwise, we create a new template
207                 _template = new CalendarTemplate( );
208             }
209         }
210 
211         Map<String, Object> model = getModel( );
212         model.put( MARK_TEMPLATE, _template );
213 
214         String strCalendarTemplatesFolder = AppPropertiesService.getProperty( PROPERTY_FOLDER_CALENDAR_TEMPLATES, StringUtils.EMPTY );
215 
216         File calendarTemplatesFolder = new File( AppPathService.getWebAppPath( ) + CONSTANT_TEMPLATE_FOLDER + strCalendarTemplatesFolder );
217 
218         ReferenceList refListTemplates = new ReferenceList( );
219         refListTemplates.addItem( StringUtils.EMPTY, StringUtils.EMPTY );
220 
221         if ( calendarTemplatesFolder.exists( ) )
222         {
223             if ( calendarTemplatesFolder.isDirectory( ) )
224             {
225                 File [ ] listFiles = calendarTemplatesFolder.listFiles( );
226                 if ( !ArrayUtils.isEmpty( listFiles ) )
227                 {
228                     for ( File file : listFiles )
229                     {
230                         if ( file != null )
231                         {
232                             refListTemplates.addItem( strCalendarTemplatesFolder + file.getName( ), file.getName( ) );
233                         }
234                     }
235                 }
236             }
237             else
238             {
239                 // If the specified folder is a file, we add that file to the
240                 // reference list
241                 refListTemplates.addItem( strCalendarTemplatesFolder + calendarTemplatesFolder.getName( ), calendarTemplatesFolder.getName( ) );
242             }
243         }
244 
245         model.put( MARK_REF_LIST_TEMPLATES, refListTemplates );
246 
247         return getPage( ( _template.getIdCalendarTemplate( ) > 0 ) ? MESSAGE_MODIFY_TEMPLATE_PAGE_TITLE : MESSAGE_CREATE_TEMPLATE_PAGE_TITLE,
248                 TEMPLATE_CREATE_MODIFY_CALENDAR_TEMPLATE, model );
249     }
250 
251     /**
252      * Do the creation or the modification of a calendar template
253      * 
254      * @param request
255      *            The request
256      * @return The next URL to redirect to
257      */
258     @Action( ACTION_CREATE_MODIFY_TEMPLATE )
259     public String doCreateModifyTemplate( HttpServletRequest request )
260     {
261         // We reset the session template to prevent collisions with any other
262         // tab or page
263         _template = new CalendarTemplate( );
264         populate( _template, request );
265 
266         Set<ConstraintViolation<CalendarTemplate>> listErrors = validate( _template );
267 
268         if ( CollectionUtils.isNotEmpty( listErrors ) )
269         {
270             for ( ConstraintViolation<CalendarTemplate> error : listErrors )
271             {
272                 addError( error.getMessage( ) );
273             }
274 
275             return redirectView( request, VIEW_CREATE_MODIFY_TEMPLATE );
276         }
277 
278         if ( _template.getIdCalendarTemplate( ) > 0 )
279         {
280             CalendarTemplateHome.update( _template );
281             addInfo( MESSAGE_INFO_TEMPLATE_UPDATED, getLocale( ) );
282         }
283         else
284         {
285             CalendarTemplateHome.create( _template );
286             addInfo( MESSAGE_INFO_TEMPLATE_CREATED, getLocale( ) );
287         }
288 
289         return redirectView( request, VIEW_MANAGE_CALENDAR_TEMPLATES );
290     }
291 
292     /**
293      * Get the confirmation page before removing a template
294      * 
295      * @param request
296      *            The request
297      * @return The next URL to redirect to
298      */
299     @View( VIEW_CONFIRM_REMOVE_TEMPLATE )
300     public String getConfirmRemoveTemplate( HttpServletRequest request )
301     {
302         String strIdTemplate = request.getParameter( PARAMETER_ID_TEMPLATE );
303 
304         if ( StringUtils.isEmpty( strIdTemplate ) || !StringUtils.isNumeric( strIdTemplate ) )
305         {
306             return redirectView( request, VIEW_MANAGE_CALENDAR_TEMPLATES );
307         }
308 
309         UrlItem urlItem = new UrlItem( AppPathService.getBaseUrl( request ) + getActionUrl( ACTION_REMOVE_TEMPLATE ) );
310         urlItem.addParameter( PARAMETER_ID_TEMPLATE, strIdTemplate );
311 
312         return redirect( request,
313                 AdminMessageService.getMessageUrl( request, MESSAGE_CONFIRM_REMOVE_TEMPLATE, urlItem.getUrl( ), AdminMessage.TYPE_CONFIRMATION ) );
314     }
315 
316     /**
317      * Do remove a template
318      * 
319      * @param request
320      *            The request
321      * @return The next URL to redirect to
322      */
323     @Action( ACTION_REMOVE_TEMPLATE )
324     public String doRemoveTemplate( HttpServletRequest request )
325     {
326         String strIdTemplate = request.getParameter( PARAMETER_ID_TEMPLATE );
327 
328         if ( StringUtils.isEmpty( strIdTemplate ) || !StringUtils.isNumeric( strIdTemplate ) )
329         {
330             return redirectView( request, VIEW_MANAGE_CALENDAR_TEMPLATES );
331         }
332 
333         CalendarTemplateHome.delete( Integer.parseInt( strIdTemplate ) );
334 
335         addInfo( MESSAGE_INFO_TEMPLATE_REMOVED, getLocale( ) );
336 
337         return redirectView( request, VIEW_MANAGE_CALENDAR_TEMPLATES );
338     }
339 
340     /**
341      * Do download a template
342      * 
343      * @param request
344      *            The request
345      * @return The next URL to redirect to
346      */
347     @Action( ACTION_DOWNLOAD_TEMPLATE )
348     public String doDownloadTemplate( HttpServletRequest request )
349     {
350         String strTemplate = request.getParameter( PARAMETER_TEMPLACE_PATH );
351 
352         String strCalendarTemplatesFolder = AppPropertiesService.getProperty( PROPERTY_FOLDER_CALENDAR_TEMPLATES, StringUtils.EMPTY );
353 
354         if ( StringUtils.isNotEmpty( strTemplate ) && strTemplate.startsWith( strCalendarTemplatesFolder ) && !strTemplate.contains( CONSTANT_FOLDER_UP ) )
355         {
356             File file = new File( AppPathService.getWebAppPath( ) + CONSTANT_TEMPLATE_FOLDER + strTemplate );
357             byte [ ] fileContent;
358 
359             try
360             {
361                 fileContent = FileUtils.readFileToByteArray( file );
362             }
363             catch( IOException e )
364             {
365                 AppLogService.error( e.getMessage( ), e );
366 
367                 return redirectView( request, VIEW_MANAGE_CALENDAR_TEMPLATES );
368             }
369 
370             download( fileContent, file.getName( ), "text/plain" );
371 
372             return null;
373         }
374 
375         return redirectView( request, VIEW_MANAGE_CALENDAR_TEMPLATES );
376     }
377 }