View Javadoc
1   /*
2    * Copyright (c) 2002-2018, Mairie de 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.workflow.modules.tipiforms.web.task;
35  
36  import java.util.HashMap;
37  import java.util.Map;
38  
39  import javax.servlet.http.HttpServletRequest;
40  
41  import org.apache.commons.lang3.StringUtils;
42  import org.apache.commons.lang3.math.NumberUtils;
43  
44  import fr.paris.lutece.plugins.forms.business.FormHome;
45  import fr.paris.lutece.plugins.forms.business.Question;
46  import fr.paris.lutece.plugins.forms.business.QuestionHome;
47  import fr.paris.lutece.plugins.forms.business.Step;
48  import fr.paris.lutece.plugins.forms.business.StepHome;
49  import fr.paris.lutece.plugins.workflow.modules.tipiforms.business.task.TaskTipiFormsProviderConfig;
50  import fr.paris.lutece.plugins.workflowcore.service.config.ITaskConfigService;
51  import fr.paris.lutece.plugins.workflowcore.service.task.ITask;
52  import fr.paris.lutece.portal.service.message.AdminMessage;
53  import fr.paris.lutece.portal.service.message.AdminMessageService;
54  import fr.paris.lutece.portal.service.spring.SpringContextService;
55  import fr.paris.lutece.portal.service.template.AppTemplateService;
56  import fr.paris.lutece.util.ReferenceItem;
57  import fr.paris.lutece.util.ReferenceList;
58  import fr.paris.lutece.util.html.HtmlTemplate;
59  
60  /**
61   * This class represents a controller for the configuration of the task
62   * {@link fr.paris.lutece.plugins.workflow.modules.tipiforms.service.task.TipiFormsProviderTask TipiFormsProviderTask}
63   *
64   */
65  public class TipiFormsProviderTaskConfigController
66  {
67      // Parameters
68      private static final String PARAMETER_APPLY = "apply";
69  
70      // Actions
71      private static final String ACTION_CHANGE_FORM = "changeForm";
72      private static final String ACTION_DEFAULT = "defaultAction";
73  
74      // Beans
75      private static final String SERVICE_CONFIG = "workflow-tipiforms.taskTipiFormsProviderConfigService";
76  
77      // Services
78      private static final ITaskConfigService _taskConfigService = SpringContextService.getBean( SERVICE_CONFIG );
79  
80      // Other constants
81      private static final int ID_UNSET = -1;
82  
83      private final ITask _task;
84      private TaskTipiFormsProviderConfig _config;
85  
86      /**
87       * Constructor
88       * 
89       * @param task
90       *            the task associated to the configuration
91       */
92      public TipiFormsProviderTaskConfigController( ITask task )
93      {
94          _task = task;
95  
96          findConfig( );
97      }
98  
99      /**
100      * Finds the configuration
101      */
102     private void findConfig( )
103     {
104         _config = _taskConfigService.findByPrimaryKey( _task.getId( ) );
105 
106         if ( _config == null )
107         {
108             // no configuration stored yet for this task, setting a empty one
109             _config = new TaskTipiFormsProviderConfig( );
110         }
111     }
112 
113     /**
114      * Builds the view depending on the specified request and locale
115      * 
116      * @param request
117      *            the request the locale
118      * @return the {@link HtmlTemplate} representing the view
119      */
120     public HtmlTemplate buildView( HttpServletRequest request )
121     {
122         return new View( request ).build( );
123     }
124 
125     /**
126      * Performs an action triggered by the user
127      * 
128      * @param request
129      *            the request containing the action
130      * @return the URL of the error page if there is an error during the action, {@code null} otherwise
131      */
132     public String performAction( HttpServletRequest request )
133     {
134         String strErrorUrl = null;
135         Action action = new Action( request );
136         String strAction = findAction( action, request );
137 
138         if ( ACTION_CHANGE_FORM.equals( strAction ) )
139         {
140             strErrorUrl = action.changeForm( );
141         }
142 
143         if ( ACTION_DEFAULT.equals( strAction ) )
144         {
145             strErrorUrl = action.save( );
146         }
147 
148         return strErrorUrl;
149     }
150 
151     /**
152      * Finds the action depending on the specified action and request
153      * 
154      * @param action
155      *            the action
156      * @param request
157      *            the request
158      * @return the action
159      */
160     private String findAction( Action action, HttpServletRequest request )
161     {
162         String strAction = request.getParameter( PARAMETER_APPLY );
163 
164         if ( ACTION_CHANGE_FORM.equals( strAction ) || action.isFormChanged( ) )
165         {
166             strAction = ACTION_CHANGE_FORM;
167         }
168 
169         if ( StringUtils.isBlank( strAction ) )
170         {
171             strAction = ACTION_DEFAULT;
172         }
173 
174         return strAction;
175     }
176 
177     /**
178      * This class represents a view of the task configuration
179      *
180      */
181     private final class View
182     {
183         // MARKS
184         private static final String MARK_CONFIG = "config";
185         private static final String MARK_LIST_FORM = "list_form";
186         private static final String MARK_LIST_QUESTION = "list_question";
187 
188         // TEMPLATE
189         private static final String TEMPLATE_TASK_CONFIG = "admin/plugins/workflow/modules/tipiforms/tipiformsprovider_task_config.html";
190 
191         // Other constants
192         private static final String NAME_SEPARATOR = " - ";
193 
194         private final HttpServletRequest _request;
195         private final Map<String, Object> _model;
196         private final ReferenceItem _referenceItemEmpty;
197 
198         /**
199          * Constructor
200          * 
201          * @param request
202          *            the request used by the view
203          */
204         View( HttpServletRequest request )
205         {
206             _request = request;
207             _model = new HashMap<String, Object>( );
208             _referenceItemEmpty = new ReferenceItem( );
209             _referenceItemEmpty.setCode( Integer.toString( ID_UNSET ) );
210             _referenceItemEmpty.setName( StringUtils.EMPTY );
211         }
212 
213         /**
214          * Builds the first step of the configuration
215          * 
216          * @return the {@link HtmlTemplate} representing the view
217          */
218         private HtmlTemplate build( )
219         {
220             _model.put( MARK_CONFIG, _config );
221             _model.put( MARK_LIST_FORM, findForms( ) );
222             _model.put( MARK_LIST_QUESTION, findQuestions( ) );
223 
224             return AppTemplateService.getTemplate( TEMPLATE_TASK_CONFIG, _request.getLocale( ), _model );
225         }
226 
227         /**
228          * Finds the forms
229          * 
230          * @return the forms as a {@code ReferenceList}
231          */
232         private ReferenceList findForms( )
233         {
234             ReferenceList referenceList = createReferenceListWithEmptyElement( );
235             referenceList.addAll( FormHome.getFormsReferenceList( ) );
236 
237             return referenceList;
238         }
239 
240         /**
241          * Creates a {@code ReferenceList} with an empty element
242          * 
243          * @return the {@code ReferenceList}
244          */
245         private ReferenceList createReferenceListWithEmptyElement( )
246         {
247             ReferenceList referenceList = new ReferenceList( );
248             referenceList.add( _referenceItemEmpty );
249 
250             return referenceList;
251         }
252 
253         /**
254          * finds the questions for the selected form
255          * 
256          * @return the questions as a {@code ReferenceList}
257          */
258         private ReferenceList findQuestions( )
259         {
260             ReferenceList referenceList = createReferenceListWithEmptyElement( );
261 
262             for ( Step step : StepHome.getStepsListByForm( _config.getIdForm( ) ) )
263             {
264                 for ( Question question : QuestionHome.getQuestionsListByStep( step.getId( ) ) )
265                 {
266                     referenceList.addItem( question.getId( ), buildNameForQuestion( step, question ) );
267                 }
268             }
269 
270             return referenceList;
271         }
272 
273         /**
274          * Builds the displayed name for the questions
275          * 
276          * @param step
277          *            the step of the question
278          * @param question
279          *            the question
280          * @return the displayed name
281          */
282         private String buildNameForQuestion( Step step, Question question )
283         {
284             StringBuilder sbName = new StringBuilder( step.getTitle( ) );
285             sbName.append( NAME_SEPARATOR ).append( question.getTitle( ) );
286 
287             return sbName.toString( );
288         }
289     }
290 
291     /**
292      * This class represents an action in the task configuration
293      *
294      */
295     private final class Action
296     {
297         // Messages
298         private static final String MESSAGE_MANDATORY_FORM = "module.workflow.tipiforms.task_tipiformsprovider_config.message.mandatory.form";
299         private static final String MESSAGE_MANDATORY_QUESTION_REFDET = "module.workflow.tipiforms.task_tipiformsprovider_config.message.mandatory.question.refdet";
300         private static final String MESSAGE_MANDATORY_QUESTION_AMOUNT = "module.workflow.tipiforms.task_tipiformsprovider_config.message.mandatory.question.amount";
301         private static final String MESSAGE_MANDATORY_QUESTION_EMAIL = "module.workflow.tipiforms.task_tipiformsprovider_config.message.mandatory.question.email";
302 
303         // Parameters
304         private static final String PARAMETER_FORM_ID = "idForm";
305         private static final String PARAMETER_QUESTION_REFDET_ID = "idRefDetQuestion";
306         private static final String PARAMETER_QUESTION_AMOUNT_ID = "idAmountQuestion";
307         private static final String PARAMETER_QUESTION_EMAIL_ID = "idEmailQuestion";
308 
309         private final HttpServletRequest _request;
310         private final TaskTipiFormsProviderConfig _configFromRequest;
311 
312         /**
313          * Constructor
314          * 
315          * @param request
316          *            the request used to perform the action
317          */
318         Action( HttpServletRequest request )
319         {
320             _request = request;
321             _configFromRequest = createConfigFrom( _request );
322 
323         }
324 
325         /**
326          * Creates a configuration from the specified request
327          * 
328          * @param request
329          *            the request
330          * @return the created configuration
331          */
332         private TaskTipiFormsProviderConfig createConfigFrom( HttpServletRequest request )
333         {
334             TaskTipiFormsProviderConfig config = new TaskTipiFormsProviderConfig( );
335             config.setIdTask( _task.getId( ) );
336             config.setIdForm( NumberUtils.toInt( _request.getParameter( PARAMETER_FORM_ID ), ID_UNSET ) );
337             config.setIdRefDetQuestion( NumberUtils.toInt( request.getParameter( PARAMETER_QUESTION_REFDET_ID ), ID_UNSET ) );
338             config.setIdAmountQuestion( NumberUtils.toInt( request.getParameter( PARAMETER_QUESTION_AMOUNT_ID ), ID_UNSET ) );
339             config.setIdEmailQuestion( NumberUtils.toInt( request.getParameter( PARAMETER_QUESTION_EMAIL_ID ), ID_UNSET ) );
340 
341             return config;
342         }
343 
344         /**
345          * Tests whether the user has changed the form
346          * 
347          * @return {@code true} if the form has changed, {@code false} otherwise
348          */
349         private boolean isFormChanged( )
350         {
351             return _configFromRequest.getIdForm( ) != _config.getIdForm( );
352         }
353 
354         /**
355          * Performs the actions when the form has changed
356          * 
357          * @return the URL of the error page if there is an error during the action, {@code null} otherwise
358          */
359         private String changeForm( )
360         {
361             String strErrorUrl = validateFormIsSet( );
362 
363             if ( !StringUtils.isEmpty( strErrorUrl ) )
364             {
365                 return strErrorUrl;
366             }
367 
368             fillConfigForNewForm( );
369             saveConfig( );
370 
371             return null;
372         }
373 
374         /**
375          * Saves the configuration
376          * 
377          * @return the URL of the error page if there is an error during the action, {@code null} otherwise
378          */
379         private String save( )
380         {
381             String strResult = validateAllConfig( );
382 
383             if ( !StringUtils.isEmpty( strResult ) )
384             {
385                 return strResult;
386             }
387 
388             fillAllConfig( );
389             saveConfig( );
390 
391             return null;
392 
393         }
394 
395         /**
396          * Validates that the form is set
397          * 
398          * @return the URL of the error page if there is a validation error, {@code null} otherwise
399          */
400         private String validateFormIsSet( )
401         {
402             String strErrorUrl = null;
403 
404             if ( _configFromRequest.getIdForm( ) == ID_UNSET )
405             {
406                 strErrorUrl = buildUrlForMissingForm( );
407             }
408 
409             return strErrorUrl;
410         }
411 
412         /**
413          * Validates all the attribute of the configuration
414          * 
415          * @return the URL of the error page if there is a validation error, {@code null} otherwise
416          */
417         private String validateAllConfig( )
418         {
419             String strErrorUrl = validateFormIsSet( );
420 
421             if ( !StringUtils.isEmpty( strErrorUrl ) )
422             {
423                 return strErrorUrl;
424             }
425 
426             strErrorUrl = validateRefDetQuestionIsSet( );
427 
428             if ( !StringUtils.isEmpty( strErrorUrl ) )
429             {
430                 return strErrorUrl;
431             }
432 
433             strErrorUrl = validateAmountQuestionIsSet( );
434 
435             if ( !StringUtils.isEmpty( strErrorUrl ) )
436             {
437                 return strErrorUrl;
438             }
439 
440             strErrorUrl = validateEmailQuestionIsSet( );
441 
442             if ( !StringUtils.isEmpty( strErrorUrl ) )
443             {
444                 return strErrorUrl;
445             }
446 
447             return null;
448         }
449 
450         /**
451          * Validates that the RefDet question is set
452          * 
453          * @return the URL of the error page if there is a validation error, {@code null} otherwise
454          */
455         private String validateRefDetQuestionIsSet( )
456         {
457             String strErrorUrl = null;
458 
459             if ( _configFromRequest.getIdRefDetQuestion( ) == ID_UNSET )
460             {
461                 strErrorUrl = buildUrlForMissingRefDetQuestion( );
462             }
463 
464             return strErrorUrl;
465         }
466 
467         /**
468          * Validates that the amount question is set
469          * 
470          * @return the URL of the error page if there is a validation error, {@code null} otherwise
471          */
472         private String validateAmountQuestionIsSet( )
473         {
474             String strErrorUrl = null;
475 
476             if ( _configFromRequest.getIdAmountQuestion( ) == ID_UNSET )
477             {
478                 strErrorUrl = buildUrlForMissingAmountQuestion( );
479             }
480 
481             return strErrorUrl;
482         }
483 
484         /**
485          * Validates that the email question is set
486          * 
487          * @return the URL of the error page if there is a validation error, {@code null} otherwise
488          */
489         private String validateEmailQuestionIsSet( )
490         {
491             String strErrorUrl = null;
492 
493             if ( _configFromRequest.getIdEmailQuestion( ) == ID_UNSET )
494             {
495                 strErrorUrl = buildUrlForMissingEmailQuestion( );
496             }
497 
498             return strErrorUrl;
499         }
500 
501         /**
502          * Builds the URL for missing form
503          * 
504          * @return the URL
505          */
506         private String buildUrlForMissingForm( )
507         {
508             return AdminMessageService.getMessageUrl( _request, MESSAGE_MANDATORY_FORM, AdminMessage.TYPE_STOP );
509         }
510 
511         /**
512          * Builds the URL for missing RefDet question
513          * 
514          * @return the URL
515          */
516         private String buildUrlForMissingRefDetQuestion( )
517         {
518             return AdminMessageService.getMessageUrl( _request, MESSAGE_MANDATORY_QUESTION_REFDET, AdminMessage.TYPE_STOP );
519         }
520 
521         /**
522          * Builds the URL for missing amount question
523          * 
524          * @return the URL
525          */
526         private String buildUrlForMissingAmountQuestion( )
527         {
528             return AdminMessageService.getMessageUrl( _request, MESSAGE_MANDATORY_QUESTION_AMOUNT, AdminMessage.TYPE_STOP );
529         }
530 
531         /**
532          * Builds the URL for missing email question
533          * 
534          * @return the URL
535          */
536         private String buildUrlForMissingEmailQuestion( )
537         {
538             return AdminMessageService.getMessageUrl( _request, MESSAGE_MANDATORY_QUESTION_EMAIL, AdminMessage.TYPE_STOP );
539         }
540 
541         /**
542          * Fills the configuration when a new form is selected
543          */
544         private void fillConfigForNewForm( )
545         {
546             if ( isFormChanged( ) )
547             {
548                 fillConfigWithForm( );
549                 fillConfigWithUnsetQuestions( );
550             }
551         }
552 
553         /**
554          * Fills the configuration with the form
555          */
556         private void fillConfigWithForm( )
557         {
558             _config.setIdForm( _configFromRequest.getIdForm( ) );
559         }
560 
561         /**
562          * Fills the configuration with the unset id for questions
563          */
564         private void fillConfigWithUnsetQuestions( )
565         {
566             _config.setIdRefDetQuestion( ID_UNSET );
567             _config.setIdAmountQuestion( ID_UNSET );
568             _config.setIdEmailQuestion( ID_UNSET );
569         }
570 
571         /**
572          * Fills the configuration with all the attributes
573          */
574         private void fillAllConfig( )
575         {
576             _config = _configFromRequest;
577         }
578 
579         /**
580          * Saves the configuration of the task
581          */
582         private void saveConfig( )
583         {
584             boolean bCreate = false;
585 
586             if ( _config.getIdTask( ) == 0 )
587             {
588                 _config.setIdTask( _task.getId( ) );
589                 bCreate = true;
590             }
591 
592             if ( bCreate )
593             {
594                 _taskConfigService.create( _config );
595             }
596             else
597             {
598                 _taskConfigService.update( _config );
599             }
600         }
601     }
602 }