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.forms.modules.breadcrumbaccordion.web;
35  
36  import java.util.ArrayList;
37  import java.util.Collections;
38  import java.util.HashMap;
39  import java.util.List;
40  import java.util.Locale;
41  import java.util.Map;
42  
43  import javax.inject.Inject;
44  import javax.servlet.http.HttpServletRequest;
45  
46  import fr.paris.lutece.plugins.forms.business.FormDisplay;
47  import fr.paris.lutece.plugins.forms.business.FormDisplayHome;
48  import fr.paris.lutece.plugins.forms.business.FormQuestionResponse;
49  import fr.paris.lutece.plugins.forms.business.FormResponse;
50  import fr.paris.lutece.plugins.forms.business.Question;
51  import fr.paris.lutece.plugins.forms.business.Step;
52  import fr.paris.lutece.plugins.forms.modules.breadcrumbaccordion.service.BreadcrumbAccordionService;
53  import fr.paris.lutece.plugins.forms.web.CompositeQuestionDisplay;
54  import fr.paris.lutece.plugins.forms.web.FormResponseManager;
55  import fr.paris.lutece.plugins.forms.web.breadcrumb.IBreadcrumb;
56  import fr.paris.lutece.plugins.forms.web.entrytype.DisplayType;
57  import fr.paris.lutece.portal.service.i18n.I18nService;
58  import fr.paris.lutece.portal.service.template.AppTemplateService;
59  import fr.paris.lutece.util.html.HtmlTemplate;
60  
61  /**
62   * This class is a Breadcrumb Accordion
63   *
64   */
65  public class BreadcrumbAccordion implements IBreadcrumb
66  {
67  
68      public static final String BEAN_NAME = "forms-breadcrumbaccordion.breadcrumbAccordion";
69  
70      private static final String MARK_LIST_STEP_COMPLETED = "list_step_completed";
71      private static final String MARK_LIST_STEP_TO_COMPLETE = "list_step_to_complete";
72      private static final String MARK_CURRENT_STEP_INDEX = "current_step_index";
73      private static final String MARK_CURRENT_STEP = "current_step";
74      private static final String MARK_IS_BREADCRUMB_ACCORDION = "is_breadcrumb_accordion";
75  
76      private static final String TEMPLATE_BREADCRUMB_TOP_HTML = "/skin/plugins/forms/modules/breadcrumbaccordion/breadcrumbaccordion_top.html";
77      private static final String TEMPLATE_BREADCRUMB_BOTTOM_HTML = "/skin/plugins/forms/modules/breadcrumbaccordion/breadcrumbaccordion_bottom.html";
78      private final String _strBreadcrumbAccordionBeanName;
79      private final String _strBreadcrumbAccordionDisplayBeanName;
80  
81      // Service
82      @Inject
83      private BreadcrumbAccordionService _breadcrumbAccordionService;
84  
85      /**
86       * Constructor
87       * 
88       * @param strBreadcrumbAccordionName
89       *            The breadcrumbmd bean name
90       * @param strBreadcrumbAccordionDisplayName
91       *            The Breadcrumbmd display name
92       */
93      public BreadcrumbAccordion( String strBreadcrumbAccordionName, String strBreadcrumbAccordionDisplayName )
94      {
95          _strBreadcrumbAccordionBeanName = strBreadcrumbAccordionName;
96          _strBreadcrumbAccordionDisplayBeanName = I18nService.getLocalizedString( strBreadcrumbAccordionDisplayName, I18nService.getDefaultLocale( ) );
97      }
98  
99      /**
100      * {@inheritDoc}
101      */
102     @Override
103     public String getBreadcrumbBeanName( )
104     {
105         return _strBreadcrumbAccordionBeanName;
106     }
107 
108     /**
109      * {@inheritDoc}
110      */
111     @Override
112     public String getBreadcrumbDisplayName( )
113     {
114         return _strBreadcrumbAccordionDisplayBeanName;
115     }
116 
117     /**
118      * {@inheritDoc}
119      */
120     @Override
121     public String getTopHtml( HttpServletRequest request, FormResponseManager formResponseManager )
122     {
123         List<Step> listValidatedStep = formResponseManager.getValidatedSteps( );
124         Step stepCurrent = formResponseManager.getCurrentStep( );
125         if ( !listValidatedStep.isEmpty( ) ) {
126             listValidatedStep.remove(listValidatedStep.size( ) - 1);
127         }
128         Map<String, Object> model = new HashMap<>( );
129         model.put( MARK_LIST_STEP_COMPLETED, createStepDisplays( request, listValidatedStep, formResponseManager ) );
130         model.put( MARK_CURRENT_STEP, stepCurrent );
131 
132         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_BREADCRUMB_TOP_HTML, request.getLocale( ), model );
133 
134         return template.getHtml( );
135     }
136 
137     /**
138      * {@inheritDoc}
139      */
140     @Override
141     public Map<String, Object> getModelForCurrentStep( HttpServletRequest request, FormResponseManager formResponseManager )
142     {
143         Map<String, Object> model = new HashMap<>( );
144         Step stepCurrent = formResponseManager.getCurrentStep();
145         if ( stepCurrent == null ) {
146             model.put( MARK_CURRENT_STEP_INDEX, 0 );
147         } else {
148             List<Step> listStepToComplete = _breadcrumbAccordionService.findStepsToComplete(stepCurrent.getIdForm());
149             List<Step> listNotCompletedStep = findNotCompletedSteps(formResponseManager.getValidatedSteps(), listStepToComplete);
150             int nCurrentStepIndex = listStepToComplete.size() - listNotCompletedStep.size();
151 
152             model.put(MARK_CURRENT_STEP_INDEX, nCurrentStepIndex);
153         }
154         return model;
155     }
156 
157     /**
158      * {@inheritDoc}
159      */
160     @Override
161     public String getBottomHtml( HttpServletRequest request, FormResponseManager formResponseManager )
162     {
163         Step stepCurrent = formResponseManager.getCurrentStep();
164         List<Step> listStepToComplete;
165         List<Step> listNotCompletedStep;
166         int nCurrentStepIndex;
167         if ( stepCurrent == null ) {
168             listNotCompletedStep = new ArrayList<>();
169             nCurrentStepIndex = 0;
170         } else {
171             listStepToComplete = _breadcrumbAccordionService.findStepsToComplete(stepCurrent.getIdForm());
172             listNotCompletedStep = findNotCompletedSteps(formResponseManager.getValidatedSteps(), listStepToComplete);
173             nCurrentStepIndex = listStepToComplete.size() - listNotCompletedStep.size();
174         }
175         Map<String, Object> model = new HashMap<>( );
176         model.put( MARK_LIST_STEP_TO_COMPLETE, listNotCompletedStep );
177         model.put( MARK_CURRENT_STEP_INDEX, nCurrentStepIndex );
178 
179         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_BREADCRUMB_BOTTOM_HTML, request.getLocale( ), model );
180 
181         return template.getHtml( );
182     }
183 
184     /**
185      * Finds the not completed steps
186      * 
187      * @param listStepValidated
188      *            the list of validated steps
189      * @param listStepToComplete
190      *            the list of steps to complete
191      * @return the not completed steps
192      */
193     private List<Step> findNotCompletedSteps( List<Step> listStepValidated, List<Step> listStepToComplete )
194     {
195         List<Step> listNotCompletedStep = new ArrayList<>( );
196 
197         for ( int i = listStepToComplete.size( ) - 1; i >= 0; i-- )
198         {
199             boolean bFound = false;
200             Step stepToComplete = listStepToComplete.get( i );
201 
202             for ( Step stepValidated : listStepValidated )
203             {
204                 if ( stepToComplete.getId( ) == stepValidated.getId( ) )
205                 {
206                     bFound = true;
207                 }
208             }
209 
210             if ( bFound )
211             {
212                 break;
213             }
214             else
215             {
216                 listNotCompletedStep.add( stepToComplete );
217             }
218         }
219 
220         Collections.reverse( listNotCompletedStep );
221 
222         return listNotCompletedStep;
223     }
224 
225     /**
226      * Creates the {@code StepDisplay} objects for the specified list of steps
227      * 
228      * @param request
229      *            the request
230      * @param listStep
231      *            the steps
232      * @param formResponseManager
233      *            the form response manager
234      * @return the {@code StepDisplay} objects
235      */
236     private List<StepDisplay> createStepDisplays( HttpServletRequest request, List<Step> listStep, FormResponseManager formResponseManager )
237     {
238         List<StepDisplay> listStepDisplay = new ArrayList<>( );
239 
240         for ( Step step : listStep )
241         {
242             StepDisplay stepDisplay = new StepDisplay( step );
243 
244             for ( FormQuestionResponse formQuestionResponse : formResponseManager.findResponsesFor( step ) )
245             {
246                 stepDisplay.addHtml( buildHtmlForQuestion( request, formResponseManager.getFormResponse( ), formQuestionResponse, request.getLocale( ) ) );
247             }
248 
249             listStepDisplay.add( stepDisplay );
250         }
251 
252         return listStepDisplay;
253     }
254 
255     /**
256      * Builds the HTML for the specified question
257      * 
258      * @param request
259      *            the request
260      * @param formResponse
261      *            the form response
262      * @param formQuestionResponse
263      *            the form response associated to the questions
264      * @param locale
265      *            the locale
266      * @return the HTML
267      */
268     private String buildHtmlForQuestion( HttpServletRequest request, FormResponse formResponse, FormQuestionResponse formQuestionResponse, Locale locale )
269     {
270         Question question = formQuestionResponse.getQuestion( );
271         FormDisplay formDisplayQuestion = FormDisplayHome.getFormDisplayByFormStepAndComposite( formResponse.getFormId( ), question.getIdStep( ),
272                 question.getId( ) );
273         CompositeQuestionDisplay compositeQuestionDisplay = new CompositeQuestionDisplay( formDisplayQuestion, formResponse, question.getIterationNumber( ) );
274         List<FormQuestionResponse> listFormQuestionResponse = new ArrayList<>( );
275 
276         Map<String, Object> model = new HashMap<>( );
277         model.put( MARK_IS_BREADCRUMB_ACCORDION, true );
278         compositeQuestionDisplay.addModel( model );
279 
280         listFormQuestionResponse.add( formQuestionResponse );
281 
282         return compositeQuestionDisplay.getCompositeHtml( request, listFormQuestionResponse, locale, DisplayType.READONLY_FRONTOFFICE );
283     }
284 
285     /**
286      * This class is used to display a step
287      *
288      */
289     public static final class StepDisplay
290     {
291         private final Step _step;
292         private final List<String> _listQuestionHtml;
293 
294         /**
295          * Constructor
296          * 
297          * @param step
298          *            the step to display
299          */
300         StepDisplay( Step step )
301         {
302             _step = step;
303             _listQuestionHtml = new ArrayList<>( );
304         }
305 
306         /**
307          * Gives the step
308          * 
309          * @return the step
310          */
311         public Step getStep( )
312         {
313             return _step;
314         }
315 
316         /**
317          * Adds HTML for a question
318          * 
319          * @param strHtml
320          *            the HTML to add
321          */
322         private void addHtml( String strHtml )
323         {
324             _listQuestionHtml.add( strHtml );
325         }
326 
327         /**
328          * Gives the HTML of the questions
329          * 
330          * @return the HTML of the questions
331          */
332         public List<String> getQuestionHtml( )
333         {
334             return _listQuestionHtml;
335         }
336     }
337 
338 }