View Javadoc
1   /*
2    * Copyright (c) 2002-2014, 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.quiz.web;
35  
36  import fr.paris.lutece.plugins.quiz.business.QuestionGroup;
37  import fr.paris.lutece.plugins.quiz.business.QuestionGroupHome;
38  import fr.paris.lutece.plugins.quiz.business.Quiz;
39  import fr.paris.lutece.plugins.quiz.business.images.QuizImage;
40  import fr.paris.lutece.plugins.quiz.business.images.QuizImageHome;
41  import fr.paris.lutece.plugins.quiz.service.QuizService;
42  import fr.paris.lutece.portal.service.i18n.I18nService;
43  import fr.paris.lutece.portal.service.message.SiteMessageException;
44  import fr.paris.lutece.portal.service.plugin.Plugin;
45  import fr.paris.lutece.portal.service.plugin.PluginService;
46  import fr.paris.lutece.portal.service.spring.SpringContextService;
47  import fr.paris.lutece.portal.service.template.AppTemplateService;
48  import fr.paris.lutece.portal.service.util.AppLogService;
49  import fr.paris.lutece.portal.web.xpages.XPage;
50  import fr.paris.lutece.portal.web.xpages.XPageApplication;
51  import fr.paris.lutece.util.html.HtmlTemplate;
52  
53  import java.io.IOException;
54  import java.io.OutputStream;
55  import java.text.MessageFormat;
56  import java.util.HashMap;
57  import java.util.Locale;
58  import java.util.Map;
59  
60  import javax.servlet.http.HttpServletRequest;
61  import javax.servlet.http.HttpServletResponse;
62  import javax.servlet.http.HttpSession;
63  
64  import org.apache.commons.lang.StringUtils;
65  
66  
67  /**
68   * This class manages Quiz page.
69   */
70  public class QuizApp implements XPageApplication
71  {
72      private static final String TEMPLATE_QUIZ_LIST = "skin/plugins/quiz/quiz_list.html";
73      private static final String TEMPLATE_QUIZ_RESULTS = "skin/plugins/quiz/quiz_results.html";
74      private static final String TEMPLATE_QUIZ_RESULTS_STEP = "skin/plugins/quiz/quiz_results_step.html";
75      private static final String TEMPLATE_QUIZ_ERROR = "skin/plugins/quiz/quiz_error.html";
76      private static final String TEMPLATE_QUESTIONS_LIST = "skin/plugins/quiz/quiz.html";
77      private static final String TEMPLATE_QUESTIONS_LIST_STEP = "skin/plugins/quiz/quiz_step.html";
78  
79      private static final String PROPERTY_QUIZ_LIST_PAGE_PATH = "quiz.xpage.pageQuizListPath";
80      private static final String PROPERTY_QUIZ_LIST_PAGE_TITLE = "quiz.xpage.pageQuizListTitle";
81      private static final String PROPERTY_QUIZ_PAGE_PATH = "quiz.xpage.pageQuizPath";
82      private static final String PROPERTY_QUIZ_PAGE_TITLE = "quiz.xpage.pageQuizTitle";
83      private static final String PROPERTY_QUIZ_RESULTS_PAGE_PATH = "quiz.xpage.pageQuizResultsPath";
84      private static final String PROPERTY_QUIZ_RESULTS_PAGE_TITLE = "quiz.xpage.pageQuizResultsTitle";
85      private static final String PROPERTY_QUIZ_ERROR_PAGE_PATH = "quiz.xpage.pageQuizErrorPath";
86      private static final String PROPERTY_QUIZ_ERROR_PAGE_TITLE = "quiz.xpage.pageQuizErrorTitle";
87      private static final String PROPERTY_MSG_MANY_GOOD_ANSWERS = "quiz.message.results.manyGoodAnswers";
88      private static final String PROPERTY_MSG_ONE_GOOD_ANSWER = "quiz.message.results.oneGoodAnswer";
89      private static final String PROPERTY_MSG_NO_GOOD_ANSWER = "quiz.message.results.noGoodAnswer";
90  
91      private static final String PARAMETER_RESULTS = "results";
92      private static final String PARAMETER_ID_QUIZ = "quiz_id";
93      private static final String PARAMETER_OLD_STEP = "old_step";
94      private static final String PARAMETER_ID_IMAGE = "id_image";
95      private static final String ACTION_NEXT_STEP = "nextStep";
96      private static final String ACTION_BACK_FROM_ERROR = "backFromError";
97  
98      private static final String SESSION_KEY_QUIZ_STEP = "quiz.savedQuizResult";
99  
100     private static final String MARK_ERROR = "error";
101     private static final String MARK_ID_QUIZ = "quiz_id";
102     private static final String MARK_HAS_NEXT_STEP = "hasNextStep";
103     private static final String MARK_SCORE = "score";
104     private static final String MARK_QUESTIONS_COUNT = "questions_count";
105     private static final String MARK_SCORE_MESSAGE = "score_message";
106     private static final String MARK_GROUP = "group";
107     private static final String MARK_IS_LAST_GROUP = "is_last_group";
108 
109     private QuizService _quizService = SpringContextService.getBean( QuizService.BEAN_QUIZ_SERVICE );
110 
111     /**
112      * Do download a quiz image
113      * @param request The request
114      * @param response The response
115      */
116     public static void doDownloadQuizImage( HttpServletRequest request, HttpServletResponse response )
117     {
118         String strIdImage = request.getParameter( PARAMETER_ID_IMAGE );
119         if ( StringUtils.isNotEmpty( strIdImage ) && StringUtils.isNumeric( strIdImage ) )
120         {
121             OutputStream out = null;
122             try
123             {
124                 Plugin plugin = PluginService.getPlugin( QuizService.PLUGIN_NAME );
125                 int nIdImage = Integer.parseInt( strIdImage );
126                 byte[] bArrayResult = {};
127                 String strContentType = StringUtils.EMPTY;
128                 QuizImage quizImage = QuizImageHome.getImage( nIdImage, plugin );
129 
130                 if ( quizImage != null && quizImage.getContent( ) != null )
131                 {
132                     bArrayResult = quizImage.getContent( );
133                     strContentType = quizImage.getContentType( );
134                 }
135                 // Add Cache Control HTTP header
136                 response.setHeader( "Cache-Control", "no-cache" ); // HTTP 1.1
137                 response.setDateHeader( "Expires", 0 ); // HTTP 1.0
138                 response.setContentLength( bArrayResult.length );
139                 response.setContentType( strContentType );
140 
141                 // Write the resource content
142                 out = response.getOutputStream( );
143                 out.write( bArrayResult );
144             }
145             catch ( IOException e )
146             {
147                 AppLogService.error( e.getMessage( ), e );
148             }
149             finally
150             {
151                 if ( out != null )
152                 {
153                     try
154                     {
155                         out.flush( );
156                         out.close( );
157                     }
158                     catch ( IOException e )
159                     {
160                         AppLogService.error( e.getMessage( ), e );
161                     }
162                 }
163             }
164         }
165     }
166 
167     /**
168      * Returns the Quiz XPage content depending on the request parameters and
169      * the current mode.
170      * 
171      * @param request The HTTP request.
172      * @param nMode The current mode.
173      * @param plugin The Plugin
174      * @throws fr.paris.lutece.portal.service.message.SiteMessageException
175      *             Message displayed if an exception occures
176      * @return The page content.
177      */
178     @SuppressWarnings( "unchecked" )
179     public XPage getPage( HttpServletRequest request, int nMode, Plugin plugin ) throws SiteMessageException
180     {
181         String strIdQuiz = request.getParameter( PARAMETER_ID_QUIZ );
182         String strAction = request.getParameter( QuizService.PARAMETER_ACTION );
183         XPage page = null;
184 
185         if ( StringUtils.isNotEmpty( strIdQuiz ) && StringUtils.isNumeric( strIdQuiz ) )
186         {
187             int nIdQuiz = Integer.parseInt( strIdQuiz );
188 
189             Quiz quiz = _quizService.findQuizById( nIdQuiz );
190             if ( !quiz.isEnabled( ) )
191             {
192                 return getQuizList( request.getLocale( ) );
193             }
194 
195             if ( quiz.getDisplayStepByStep( ) )
196             {
197                 // We get the position of the old step
198                 String strOldStep = request.getParameter( PARAMETER_OLD_STEP );
199                 int nOldStepId;
200                 if ( StringUtils.isNotEmpty( strOldStep ) && StringUtils.isNumeric( strOldStep ) )
201                 {
202                     nOldStepId = Integer.parseInt( strOldStep );
203                 }
204                 else
205                 {
206                     request.getSession( ).setAttribute( MARK_SCORE, 0 );
207                     request.getSession( ).setAttribute( MARK_QUESTIONS_COUNT, 0 );
208 
209                     nOldStepId = 0;
210                 }
211 
212                 if ( !StringUtils.equals( ACTION_BACK_FROM_ERROR, strAction ) )
213                 {
214                     if ( nOldStepId > 0 )
215                     {
216                         // We get responses of the user, and save them into the session
217                         Map<String, String[]> mapResponsesCurrentStep = null;
218                         if ( !StringUtils.equals( ACTION_NEXT_STEP, strAction ) )
219                         {
220                             mapResponsesCurrentStep = saveAndValidateQuizAnswers( quiz, nOldStepId,
221                                     request.getParameterMap( ), request.getLocale( ), plugin, request.getSession( true ) );
222                             // We check that the map does not contain errors
223                             String[] strError = mapResponsesCurrentStep.get( QuizService.KEY_ERROR );
224 
225                             if ( strError != null && strError.length > 0 )
226                             {
227                                 return getErrorPage( quiz.getIdQuiz( ), strError[0], nOldStepId, request.getLocale( ) );
228                             }
229                         }
230 
231                         // If we must display the result of the current step
232                         if ( quiz.getDisplayResultAfterEachStep( ) && StringUtils.equals( strAction, PARAMETER_RESULTS ) )
233                         {
234                             page = getQuizStepResults( quiz, nOldStepId, request.getLocale( ), mapResponsesCurrentStep,
235                                     request.getSession( ), plugin );
236                         }
237                     }
238                     else
239                     {
240                         // this is the first step of the quiz, so we remove any answers to quiz made by the user
241                         resetUserAnswers( request.getSession( ) );
242                     }
243                 }
244 
245                 if ( page == null )
246                 {
247                     // Otherwise, we display the next step
248                     page = getQuizNextStep( quiz, nOldStepId, request );
249                     if ( page == null )
250                     {
251                         page = getQuizResults( quiz, request.getLocale( ), getUserAnswers( request.getSession( ) ),
252                                 plugin );
253                     }
254                 }
255             }
256             else
257             {
258                 if ( strAction != null && strAction.equals( PARAMETER_RESULTS ) )
259                 {
260                     page = getQuizResults( quiz, request.getLocale( ), request.getParameterMap( ), plugin );
261                 }
262                 else
263                 {
264                     page = getQuizPage( nIdQuiz, request.getLocale( ) );
265                 }
266             }
267         }
268         else
269         {
270             page = getQuizList( request.getLocale( ) );
271         }
272 
273         return page;
274     }
275 
276     /**
277      * Get the quiz list
278      * @param locale The locale
279      * @return The XPage
280      */
281     protected XPage getQuizList( Locale locale )
282     {
283         XPage page = new XPage( );
284         Map<String, Object> model = _quizService.getQuizList( );
285         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_QUIZ_LIST, locale, model );
286         page.setContent( template.getHtml( ) );
287         page.setTitle( I18nService.getLocalizedString( PROPERTY_QUIZ_LIST_PAGE_TITLE, locale ) );
288         page.setPathLabel( I18nService.getLocalizedString( PROPERTY_QUIZ_LIST_PAGE_PATH, locale ) );
289 
290         return page;
291     }
292 
293     /**
294      * Gets the quiz page
295      * @param nQuizId The quiz Id
296      * @param locale The current locale
297      * @return The XPage
298      */
299     protected XPage getQuizPage( int nQuizId, Locale locale )
300     {
301         XPage page = new XPage( );
302         Map<String, Object> model = _quizService.getQuiz( nQuizId );
303         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_QUESTIONS_LIST, locale, model );
304         page.setContent( template.getHtml( ) );
305 
306         setQuizProperties( (Quiz) model.get( QuizService.KEY_QUIZ ), page, model, locale );
307 
308         return page;
309     }
310 
311     /**
312      * Get the next step of the quiz
313      * @param quiz The quiz to display
314      * @param nOldStepId The id of the last displayed step of the quiz, or 0 if
315      *            no step was displayed
316      * @param request The request
317      * @return The XPage to display
318      */
319     protected XPage getQuizNextStep( Quiz quiz, int nOldStepId, HttpServletRequest request )
320     {
321         XPage page = new XPage( );
322         Map<String, Object> model = _quizService.getQuizNextStep( quiz, nOldStepId );
323         // If the model is null, then there is no more step to display
324         if ( model == null )
325         {
326             return null;
327         }
328 
329         Quiz quizModel = (Quiz) ( _quizService.getQuiz( quiz.getIdQuiz( ) ).get( QuizService.KEY_QUIZ ) );
330 
331         QuestionGroup group = (QuestionGroup) model.get( MARK_GROUP );
332 
333         boolean bDisplayScore = group.getDisplayScore( );
334         Plugin plugin = PluginService.getPlugin( QuizService.PLUGIN_NAME );
335         int nTotalQuestion = (Integer) request.getSession( ).getAttribute( MARK_QUESTIONS_COUNT );
336         int nIdLastQuizGroup = QuestionGroupHome.findLastByQuiz( quiz.getIdQuiz( ), plugin );
337         if ( !bDisplayScore )
338         {
339             // If there is no group that will display the result, then the last group must display it
340             if ( !QuestionGroupHome.hasGroupDisplayScore( group.getIdQuiz( ), plugin ) )
341             {
342                 int nSizeQuiz = quizModel.getQuestions( ).size( );
343                 bDisplayScore = nTotalQuestion == nSizeQuiz && nIdLastQuizGroup == group.getIdGroup( );
344             }
345         }
346 
347         if ( bDisplayScore )
348         {
349             // The quiz is over
350             int nScore = (Integer) request.getSession( ).getAttribute( MARK_SCORE );
351 
352             String strMessage = I18nService.getLocalizedString( PROPERTY_MSG_MANY_GOOD_ANSWERS, request.getLocale( ) );
353 
354             switch ( nScore )
355             {
356             case 0:
357                 strMessage = I18nService.getLocalizedString( PROPERTY_MSG_NO_GOOD_ANSWER, request.getLocale( ) );
358 
359                 break;
360 
361             case 1:
362                 strMessage = I18nService.getLocalizedString( PROPERTY_MSG_ONE_GOOD_ANSWER, request.getLocale( ) );
363 
364                 break;
365 
366             default:
367                 break;
368             }
369 
370             Object[] args = { nScore, nTotalQuestion };
371             String strScoreMessage = MessageFormat.format( strMessage, args );
372             model.put( MARK_SCORE_MESSAGE, strScoreMessage );
373             _quizService.processEndOfQuiz( quiz, "" + nScore, getUserAnswers( request.getSession( ) ) );
374             resetUserAnswers( request.getSession( ) );
375         }
376 
377         model.put( MARK_IS_LAST_GROUP, nIdLastQuizGroup == group.getIdGroup( ) );
378 
379         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_QUESTIONS_LIST_STEP, request.getLocale( ),
380                 model );
381         page.setContent( template.getHtml( ) );
382 
383         setQuizProperties( quiz, page, model, request.getLocale( ) );
384 
385         return page;
386     }
387 
388     /**
389      * Return The Answers list
390      * @param quiz The quiz
391      * @param locale The current locale
392      * @param mapParameters request parameters as a map
393      * @param plugin the plugin
394      * @return The XPage
395      */
396     protected XPage getQuizResults( Quiz quiz, Locale locale, Map<String, String[]> mapParameters, Plugin plugin )
397     {
398         XPage page = new XPage( );
399 
400         Map<String, Object> model;
401 
402         if ( "PROFIL".equals( quiz.getTypeQuiz( ) ) )
403         {
404             model = _quizService.calculateQuizProfile( quiz.getIdQuiz( ), mapParameters, locale );
405         }
406         else
407         {
408             model = _quizService.getResults( quiz.getIdQuiz( ), mapParameters, locale );
409         }
410 
411         String strError = (String) model.get( QuizService.KEY_ERROR );
412 
413         if ( strError != null )
414         {
415             return getErrorPage( quiz.getIdQuiz( ), strError, 0, locale );
416         }
417 
418         _quizService.processEndOfQuiz( quiz, "" + model.get( MARK_SCORE ), mapParameters );
419 
420         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_QUIZ_RESULTS, locale, model );
421 
422         page.setContent( template.getHtml( ) );
423 
424         setQuizResultProperties( quiz, page, model, locale );
425 
426         return page;
427     }
428 
429     /**
430      * Return The Answers list for the given step
431      * @param quiz The quiz
432      * @param nIdStep The id of the submitted step
433      * @param locale The current locale
434      * @param mapResponsesCurrentStep Responses of the current step
435      * @param session The session
436      * @param plugin the plugin
437      * @return The XPage
438      */
439     protected XPage getQuizStepResults( Quiz quiz, int nIdStep, Locale locale,
440             Map<String, String[]> mapResponsesCurrentStep, HttpSession session, Plugin plugin )
441     {
442         XPage page = new XPage( );
443 
444         Map<String, Object> model;
445         if ( "PROFIL".equals( quiz.getTypeQuiz( ) ) )
446         {
447             model = _quizService.calculateQuizStepProfile( quiz, nIdStep, mapResponsesCurrentStep, locale, plugin );
448         }
449         else
450         {
451             model = _quizService.getStepResults( quiz, nIdStep, mapResponsesCurrentStep, locale, plugin );
452 
453             if ( model != null )
454             {
455                 int nNewScore = (Integer) model.get( MARK_SCORE );
456                 int nOldScore = (Integer) session.getAttribute( MARK_SCORE );
457                 int nScore = nNewScore + nOldScore;
458 
459                 int nTotalNewQuestion = (Integer) model.get( MARK_QUESTIONS_COUNT );
460                 int nTotalOldQuestion = (Integer) session.getAttribute( MARK_QUESTIONS_COUNT );
461                 int nTotalQuestion = nTotalNewQuestion + nTotalOldQuestion;
462 
463                 session.setAttribute( MARK_SCORE, nScore );
464                 session.setAttribute( MARK_QUESTIONS_COUNT, nTotalQuestion );
465 
466                 String strMessage = I18nService.getLocalizedString( PROPERTY_MSG_MANY_GOOD_ANSWERS, locale );
467 
468                 switch ( nScore )
469                 {
470                 case 0:
471                     strMessage = I18nService.getLocalizedString( PROPERTY_MSG_NO_GOOD_ANSWER, locale );
472 
473                     break;
474 
475                 case 1:
476                     strMessage = I18nService.getLocalizedString( PROPERTY_MSG_ONE_GOOD_ANSWER, locale );
477 
478                     break;
479 
480                 default:
481                     break;
482                 }
483 
484                 Object[] args = { nScore, nTotalQuestion };
485                 String strScoreMessage = MessageFormat.format( strMessage, args );
486                 model.put( MARK_SCORE, nScore );
487                 model.put( MARK_SCORE_MESSAGE, strScoreMessage );
488 
489             }
490         }
491 
492         if ( model == null )
493         {
494             return null;
495         }
496 
497         model.put( PARAMETER_OLD_STEP, nIdStep );
498 
499         // If there is no next step
500         if ( QuestionGroupHome.getGroupByPosition( quiz.getIdQuiz( ), nIdStep + 1, plugin ) == null )
501         {
502             model.put( MARK_HAS_NEXT_STEP, Boolean.FALSE );
503             _quizService.processEndOfQuiz( quiz, "" + model.get( MARK_SCORE ), getUserAnswers( session ) );
504         }
505         else
506         {
507             model.put( MARK_HAS_NEXT_STEP, Boolean.TRUE );
508         }
509 
510         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_QUIZ_RESULTS_STEP, locale, model );
511 
512         page.setContent( template.getHtml( ) );
513 
514         setQuizResultProperties( quiz, page, model, locale );
515 
516         return page;
517     }
518 
519     /**
520      * Returns an error page
521      * @param nIdQuiz The id of the quiz
522      * @param strError The error message
523      * @param nStepToRedirect The id of the step to redirect the user to, or 0
524      *            to redirect the user to the start of the quiz
525      * @param locale The current locale
526      * @return The XPage
527      */
528     protected XPage getErrorPage( int nIdQuiz, String strError, int nStepToRedirect, Locale locale )
529     {
530         XPage page = new XPage( );
531         Map<String, Object> model = new HashMap<String, Object>( );
532         model.put( MARK_ERROR, strError );
533         model.put( MARK_ID_QUIZ, Integer.toString( nIdQuiz ) );
534         if ( nStepToRedirect > 1 )
535         {
536             model.put( PARAMETER_OLD_STEP, nStepToRedirect - 1 );
537         }
538 
539         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_QUIZ_ERROR, locale, model );
540 
541         page.setContent( template.getHtml( ) );
542 
543         String strPath = I18nService.getLocalizedString( PROPERTY_QUIZ_ERROR_PAGE_PATH, locale );
544         String strTitle = I18nService.getLocalizedString( PROPERTY_QUIZ_ERROR_PAGE_TITLE, locale );
545         page.setPathLabel( strPath );
546         page.setTitle( strTitle );
547 
548         return page;
549     }
550 
551     /**
552      * Save answers of a given step of a quiz into the session. If an answer is
553      * missing, then return an error message in the result map
554      * @param quiz The quiz
555      * @param nIdStep The id of the step to validate
556      * @param mapParameters The map of HTTP parameters
557      * @param locale The locale
558      * @param plugin The plugin
559      * @param session the session
560      * @return A map containing associations between question keys and answers
561      */
562     @SuppressWarnings( "unchecked" )
563     private Map<String, String[]> saveAndValidateQuizAnswers( Quiz quiz, int nIdStep,
564             Map<String, String[]> mapParameters, Locale locale, Plugin plugin, HttpSession session )
565     {
566         Map<String, String[]> mapUserAnswers = _quizService.getUserAnswersForGroup( quiz.getIdQuiz( ), nIdStep,
567                 mapParameters, locale, plugin );
568         Map<String, String[]> mapOldAnswers = (Map<String, String[]>) session.getAttribute( SESSION_KEY_QUIZ_STEP );
569         if ( mapOldAnswers != null )
570         {
571             mapOldAnswers.putAll( mapUserAnswers );
572         }
573         else
574         {
575             session.setAttribute( SESSION_KEY_QUIZ_STEP, mapUserAnswers );
576         }
577         return mapUserAnswers;
578     }
579 
580     /**
581      * Get the answers of a user stored in session
582      * @param session The session
583      * @return A map containing answers to questions of a quiz
584      */
585     @SuppressWarnings( "unchecked" )
586     private Map<String, String[]> getUserAnswers( HttpSession session )
587     {
588         return (Map<String, String[]>) session.getAttribute( SESSION_KEY_QUIZ_STEP );
589     }
590 
591     /**
592      * Set the properties of the XPage to display a quiz
593      * @param quiz The quiz displayed by the XPage
594      * @param page The XPage to display
595      * @param model The model
596      * @param locale The locale
597      */
598     private void setQuizProperties( Quiz quiz, XPage page, Map<String, Object> model, Locale locale )
599     {
600         String strPath = I18nService.getLocalizedString( PROPERTY_QUIZ_PAGE_PATH, locale );
601         String strTitle = I18nService.getLocalizedString( PROPERTY_QUIZ_PAGE_TITLE, locale );
602         Object[] args = { quiz.getName( ) };
603         page.setPathLabel( MessageFormat.format( strPath, args ) );
604         page.setTitle( MessageFormat.format( strTitle, args ) );
605     }
606 
607     /**
608      * Remove any answers of quiz made by the user
609      * @param session The session
610      */
611     private void resetUserAnswers( HttpSession session )
612     {
613         session.removeAttribute( SESSION_KEY_QUIZ_STEP );
614     }
615 
616     /**
617      * Set the properties of the XPage to display a quiz result
618      * @param quiz The quiz displayed by the XPage
619      * @param page The XPage to display
620      * @param model The model
621      * @param locale The locale
622      */
623     private void setQuizResultProperties( Quiz quiz, XPage page, Map<String, Object> model, Locale locale )
624     {
625         String strPath = I18nService.getLocalizedString( PROPERTY_QUIZ_RESULTS_PAGE_PATH, locale );
626         String strTitle = I18nService.getLocalizedString( PROPERTY_QUIZ_RESULTS_PAGE_TITLE, locale );
627         Object[] args = { quiz.getName( ) };
628         page.setPathLabel( MessageFormat.format( strPath, args ) );
629         page.setTitle( MessageFormat.format( strTitle, args ) );
630     }
631 }