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.appointment.service;
35  
36  import java.io.Serializable;
37  import java.util.ArrayList;
38  import java.util.List;
39  import java.util.Locale;
40  import java.util.Map;
41  
42  import javax.servlet.http.HttpServletRequest;
43  
44  import org.apache.commons.collections.CollectionUtils;
45  
46  import fr.paris.lutece.plugins.appointment.business.form.Form;
47  import fr.paris.lutece.plugins.appointment.web.AppointmentApp;
48  import fr.paris.lutece.plugins.appointment.web.dto.AppointmentDTO;
49  import fr.paris.lutece.plugins.appointment.web.dto.AppointmentFormDTO;
50  import fr.paris.lutece.plugins.genericattributes.business.Entry;
51  import fr.paris.lutece.plugins.genericattributes.business.EntryFilter;
52  import fr.paris.lutece.plugins.genericattributes.business.EntryHome;
53  import fr.paris.lutece.plugins.genericattributes.business.Field;
54  import fr.paris.lutece.plugins.genericattributes.business.FieldHome;
55  import fr.paris.lutece.plugins.genericattributes.business.GenericAttributeError;
56  import fr.paris.lutece.plugins.genericattributes.business.Response;
57  import fr.paris.lutece.plugins.genericattributes.service.entrytype.AbstractEntryTypeUpload;
58  import fr.paris.lutece.plugins.genericattributes.service.entrytype.EntryTypeServiceManager;
59  import fr.paris.lutece.plugins.genericattributes.service.entrytype.IEntryTypeService;
60  import fr.paris.lutece.portal.service.content.XPageAppService;
61  import fr.paris.lutece.portal.service.spring.SpringContextService;
62  import fr.paris.lutece.portal.service.template.AppTemplateService;
63  import fr.paris.lutece.portal.service.util.AppPathService;
64  import fr.paris.lutece.portal.service.util.RemovalListenerService;
65  import fr.paris.lutece.portal.util.mvc.utils.MVCUtils;
66  import fr.paris.lutece.util.ReferenceList;
67  import fr.paris.lutece.util.html.HtmlTemplate;
68  import fr.paris.lutece.util.url.UrlItem;
69  
70  /**
71   * Service to manage entries
72   * 
73   * @author Laurent Payen
74   *
75   */
76  public final class EntryService extends RemovalListenerService implements Serializable
77  {
78      /**
79       * Name of the bean of this service
80       */
81      public static final String BEAN_NAME = "appointment.entryService";
82      private static final long serialVersionUID = -5378918040356139703L;
83  
84      private static final String MARK_LOCALE = "locale";
85      private static final String MARK_ENTRY = "entry";
86      private static final String MARK_ENTRY_LIST = "entry_list";
87      private static final String MARK_ENTRY_TYPE_LIST = "entry_type_list";
88      private static final String MARK_GROUP_ENTRY_LIST = "entry_group_list";
89      private static final String MARK_LIST_ORDER_FIRST_LEVEL = "listOrderFirstLevel";
90      private static final String MARK_STR_LIST_CHILDREN = "str_list_entry_children";
91      private static final String MARK_FIELD = "field";
92      private static final String MARK_LIST_RESPONSES = "list_responses";
93      private static final String MARK_UPLOAD_HANDLER = "uploadHandler";
94  
95      private static final String PARAMETER_ID_FORM = "id_form";
96      private static final String PREFIX_ATTRIBUTE = "attribute";
97  
98      // Templates
99      private static final String TEMPLATE_DIV_CONDITIONAL_ENTRY = "skin/plugins/appointment/html_code_div_conditional_entry.html";
100 
101     private static final String SESSION_NOT_VALIDATED_APPOINTMENT = "appointment.appointmentFormService.notValidatedAppointment";
102 
103     /**
104      * Get an instance of the service
105      * 
106      * @return An instance of the service
107      */
108     public static EntryService getService( )
109     {
110         return SpringContextService.getBean( BEAN_NAME );
111     }
112 
113     /**
114      * Build an entry filter with static parameter
115      * 
116      * @param nIdForm
117      *            the Form Id
118      * @return the entry filter
119      */
120     public static EntryFilter buildEntryFilter( int nIdForm )
121     {
122         EntryFilter filter = new EntryFilter( );
123         filter.setIdResource( nIdForm );
124         filter.setResourceType( AppointmentFormDTO.RESOURCE_TYPE );
125         filter.setEntryParentNull( EntryFilter.FILTER_TRUE );
126         filter.setFieldDependNull( EntryFilter.FILTER_TRUE );
127         filter.setIdIsComment( EntryFilter.FILTER_FALSE );
128         filter.setIsOnlyDisplayInBack( EntryFilter.FILTER_FALSE );
129         return filter;
130     }
131 
132     /**
133      * Change the attribute's order to a greater one (move down in the list)
134      * 
135      * @param nOrderToSet
136      *            the new order for the attribute
137      * @param entryToChangeOrder
138      *            the attribute which will change
139      */
140     public void moveDownEntryOrder( int nOrderToSet, Entry entryToChangeOrder )
141     {
142         if ( entryToChangeOrder.getParent( ) == null )
143         {
144             int nNbChild = 0;
145             int nNewOrder = 0;
146 
147             EntryFilter filter = new EntryFilter( );
148             filter.setIdResource( entryToChangeOrder.getIdResource( ) );
149             filter.setResourceType( Form.RESOURCE_TYPE );
150             filter.setEntryParentNull( EntryFilter.FILTER_TRUE );
151             filter.setFieldDependNull( EntryFilter.FILTER_TRUE );
152 
153             List<Entry> listEntryFirstLevel = EntryHome.findEntriesWithoutParent( entryToChangeOrder.getIdResource( ), entryToChangeOrder.getResourceType( ) );
154 
155             List<Integer> orderFirstLevel = new ArrayList<Integer>( );
156             initOrderFirstLevel( listEntryFirstLevel, orderFirstLevel );
157 
158             Integer nbChildEntryToChangeOrder = 0;
159 
160             if ( entryToChangeOrder.getChildren( ) != null )
161             {
162                 nbChildEntryToChangeOrder = entryToChangeOrder.getChildren( ).size( );
163             }
164 
165             for ( Entry entry : listEntryFirstLevel )
166             {
167                 for ( int i = 0; i < orderFirstLevel.size( ); i++ )
168                 {
169                     if ( ( orderFirstLevel.get( i ).equals( Integer.valueOf( entry.getPosition( ) ) ) )
170                             && ( entry.getPosition( ) > entryToChangeOrder.getPosition( ) ) && ( entry.getPosition( ) <= nOrderToSet ) )
171                     {
172                         if ( nNbChild == 0 )
173                         {
174                             nNewOrder = orderFirstLevel.get( i - 1 );
175 
176                             if ( !orderFirstLevel.get( i - 1 ).equals( Integer.valueOf( entryToChangeOrder.getPosition( ) ) ) )
177                             {
178                                 nNewOrder -= nbChildEntryToChangeOrder;
179                             }
180                         }
181                         else
182                         {
183                             nNewOrder += ( nNbChild + 1 );
184                         }
185 
186                         entry.setPosition( nNewOrder );
187                         EntryHome.update( entry );
188                         nNbChild = 0;
189 
190                         if ( entry.getChildren( ) != null )
191                         {
192                             for ( Entry child : entry.getChildren( ) )
193                             {
194                                 nNbChild++;
195                                 child.setPosition( nNewOrder + nNbChild );
196                                 EntryHome.update( child );
197                             }
198                         }
199                     }
200                 }
201             }
202 
203             entryToChangeOrder.setPosition( nNewOrder + nNbChild + 1 );
204             EntryHome.update( entryToChangeOrder );
205             nNbChild = 0;
206 
207             for ( Entry child : entryToChangeOrder.getChildren( ) )
208             {
209                 nNbChild++;
210                 child.setPosition( entryToChangeOrder.getPosition( ) + nNbChild );
211                 EntryHome.update( child );
212             }
213         }
214         else
215         {
216             EntryFilter filter = new EntryFilter( );
217             filter.setIdResource( entryToChangeOrder.getIdResource( ) );
218             filter.setResourceType( Form.RESOURCE_TYPE );
219             filter.setFieldDependNull( EntryFilter.FILTER_TRUE );
220 
221             List<Entry> listAllEntry = EntryHome.getEntryList( filter );
222 
223             for ( Entry entry : listAllEntry )
224             {
225                 if ( ( entry.getPosition( ) > entryToChangeOrder.getPosition( ) ) && ( entry.getPosition( ) <= nOrderToSet ) )
226                 {
227                     entry.setPosition( entry.getPosition( ) - 1 );
228                     EntryHome.update( entry );
229                 }
230             }
231 
232             entryToChangeOrder.setPosition( nOrderToSet );
233             EntryHome.update( entryToChangeOrder );
234         }
235     }
236 
237     /**
238      * Change the attribute's order to a lower one (move up in the list)
239      * 
240      * @param nOrderToSet
241      *            the new order for the attribute
242      * @param entryToChangeOrder
243      *            the attribute which will change
244      */
245     public void moveUpEntryOrder( int nOrderToSet, Entry entryToChangeOrder )
246     {
247         EntryFilter filter = new EntryFilter( );
248         filter.setIdResource( entryToChangeOrder.getIdResource( ) );
249         filter.setResourceType( Form.RESOURCE_TYPE );
250         filter.setFieldDependNull( EntryFilter.FILTER_TRUE );
251 
252         if ( entryToChangeOrder.getParent( ) == null )
253         {
254             filter.setEntryParentNull( EntryFilter.FILTER_TRUE );
255 
256             List<Integer> orderFirstLevel = new ArrayList<Integer>( );
257 
258             int nNbChild = 0;
259             int nNewOrder = nOrderToSet;
260             int nEntryToMoveOrder = entryToChangeOrder.getPosition( );
261 
262             List<Entry> listEntryFirstLevel = EntryHome.findEntriesWithoutParent( entryToChangeOrder.getIdResource( ), entryToChangeOrder.getResourceType( ) );
263             // the list of all the orders in the first level
264             initOrderFirstLevel( listEntryFirstLevel, orderFirstLevel );
265 
266             for ( Entry entry : listEntryFirstLevel )
267             {
268                 Integer entryInitialPosition = entry.getPosition( );
269 
270                 for ( int i = 0; i < orderFirstLevel.size( ); i++ )
271                 {
272                     if ( ( orderFirstLevel.get( i ).equals( entryInitialPosition ) ) && ( entryInitialPosition < nEntryToMoveOrder )
273                             && ( entryInitialPosition >= nOrderToSet ) )
274                     {
275                         if ( entryToChangeOrder.getPosition( ) == nEntryToMoveOrder )
276                         {
277                             entryToChangeOrder.setPosition( nNewOrder );
278                             EntryHome.update( entryToChangeOrder );
279 
280                             for ( Entry child : entryToChangeOrder.getChildren( ) )
281                             {
282                                 nNbChild++;
283                                 child.setPosition( entryToChangeOrder.getPosition( ) + nNbChild );
284                                 EntryHome.update( child );
285                             }
286                         }
287 
288                         nNewOrder = nNewOrder + nNbChild + 1;
289                         entry.setPosition( nNewOrder );
290                         EntryHome.update( entry );
291                         nNbChild = 0;
292 
293                         for ( Entry child : entry.getChildren( ) )
294                         {
295                             nNbChild++;
296                             child.setPosition( nNewOrder + nNbChild );
297                             EntryHome.update( child );
298                         }
299                     }
300                 }
301             }
302         }
303         else
304         {
305             List<Entry> listAllEntry = EntryHome.getEntryList( filter );
306 
307             for ( Entry entry : listAllEntry )
308             {
309                 if ( ( entry.getPosition( ) < entryToChangeOrder.getPosition( ) ) && ( entry.getPosition( ) >= nOrderToSet ) )
310                 {
311                     entry.setPosition( entry.getPosition( ) + 1 );
312                     EntryHome.update( entry );
313                 }
314             }
315 
316             entryToChangeOrder.setPosition( nOrderToSet );
317             EntryHome.update( entryToChangeOrder );
318         }
319     }
320 
321     /**
322      * Move EntryToMove into entryGroup
323      * 
324      * @param entryToMove
325      *            the entry which will be moved
326      * @param entryGroup
327      *            the entry group
328      */
329     public void moveEntryIntoGroup( Entry entryToMove, Entry entryGroup )
330     {
331         if ( ( entryToMove != null ) && ( entryGroup != null ) )
332         {
333             // If the entry already has a parent, we must remove it before
334             // adding it to a new one
335             if ( entryToMove.getParent( ) != null )
336             {
337                 moveOutEntryFromGroup( entryToMove );
338             }
339 
340             int nPosition;
341 
342             if ( entryToMove.getPosition( ) < entryGroup.getPosition( ) )
343             {
344                 nPosition = entryGroup.getPosition( );
345                 moveDownEntryOrder( nPosition, entryToMove );
346             }
347             else
348             {
349                 nPosition = entryGroup.getPosition( ) + entryGroup.getChildren( ).size( ) + 1;
350                 moveUpEntryOrder( nPosition, entryToMove );
351             }
352 
353             entryToMove.setParent( entryGroup );
354             EntryHome.update( entryToMove );
355         }
356     }
357 
358     /**
359      * Remove an entry from a group
360      * 
361      * @param entryToMove
362      *            the entry to remove from a group
363      */
364     public void moveOutEntryFromGroup( Entry entryToMove )
365     {
366         Entry parent = EntryHome.findByPrimaryKey( entryToMove.getParent( ).getIdEntry( ) );
367 
368         // The new position of the entry is the position of the group plus the
369         // number of entries in the group (including this entry)
370         moveDownEntryOrder( parent.getPosition( ) + parent.getChildren( ).size( ), entryToMove );
371         entryToMove.setParent( null );
372         EntryHome.update( entryToMove );
373     }
374 
375     /**
376      * Init the list of the attribute's orders (first level only)
377      * 
378      * @param listEntryFirstLevel
379      *            the list of all the attributes of the first level
380      * @param orderFirstLevel
381      *            the list to set
382      */
383     private void initOrderFirstLevel( List<Entry> listEntryFirstLevel, List<Integer> orderFirstLevel )
384     {
385         for ( Entry entry : listEntryFirstLevel )
386         {
387             orderFirstLevel.add( entry.getPosition( ) );
388         }
389     }
390 
391     /**
392      * Remove every entries associated with a given appointment form
393      * 
394      * @param nIdForm
395      *            The id of the appointment to remove entries of
396      */
397     public void removeEntriesByIdAppointmentForm( int nIdForm )
398     {
399         EntryFilter entryFilter = new EntryFilter( );
400         entryFilter.setIdResource( nIdForm );
401         entryFilter.setResourceType( Form.RESOURCE_TYPE );
402         entryFilter.setEntryParentNull( EntryFilter.FILTER_TRUE );
403         entryFilter.setFieldDependNull( EntryFilter.FILTER_TRUE );
404 
405         List<Entry> listEntry = EntryHome.getEntryList( entryFilter );
406 
407         for ( Entry entry : listEntry )
408         {
409             EntryHome.remove( entry.getIdEntry( ) );
410         }
411     }
412 
413     /**
414      * Add the entries to the model
415      * 
416      * @param nIdForm
417      *            The form Id
418      * @param model
419      *            the model
420      */
421     public static void addListEntryToModel( int nIdForm, Map<String, Object> model )
422     {
423         EntryFilter entryFilter = new EntryFilter( );
424         entryFilter.setIdResource( nIdForm );
425         entryFilter.setResourceType( AppointmentFormDTO.RESOURCE_TYPE );
426         entryFilter.setEntryParentNull( EntryFilter.FILTER_TRUE );
427         entryFilter.setFieldDependNull( EntryFilter.FILTER_TRUE );
428         List<Entry> listEntryFirstLevel = EntryHome.getEntryList( entryFilter );
429         List<Entry> listEntry = new ArrayList<Entry>( listEntryFirstLevel.size( ) );
430         List<Integer> listOrderFirstLevel = new ArrayList<Integer>( listEntryFirstLevel.size( ) );
431         for ( Entry entry : listEntryFirstLevel )
432         {
433             listEntry.add( entry );
434             listOrderFirstLevel.add( listEntry.size( ) );
435             if ( entry.getEntryType( ).getGroup( ) )
436             {
437                 entryFilter = new EntryFilter( );
438                 entryFilter.setIdResource( nIdForm );
439                 entryFilter.setResourceType( AppointmentFormDTO.RESOURCE_TYPE );
440                 entryFilter.setFieldDependNull( EntryFilter.FILTER_TRUE );
441                 entryFilter.setIdEntryParent( entry.getIdEntry( ) );
442                 List<Entry> listEntryGroup = EntryHome.getEntryList( entryFilter );
443                 entry.setChildren( listEntryGroup );
444                 listEntry.addAll( listEntryGroup );
445             }
446         }
447         model.put( MARK_GROUP_ENTRY_LIST, getRefListGroups( nIdForm ) );
448         model.put( MARK_ENTRY_TYPE_LIST, EntryTypeService.getInstance( ).getEntryTypeReferenceList( ) );
449         model.put( MARK_ENTRY_LIST, listEntry );
450         model.put( MARK_LIST_ORDER_FIRST_LEVEL, listOrderFirstLevel );
451     }
452 
453     /**
454      * Find all the entries (with its fields) of a form
455      * 
456      * @param nIdForm
457      *            the form Id
458      * @return a list of all the entries
459      */
460     public static List<Entry> findListEntry( int nIdForm )
461     {
462         List<Entry> listEntries = new ArrayList<>( );
463         EntryFilter entryFilter = new EntryFilter( );
464         entryFilter.setIdResource( nIdForm );
465         entryFilter.setResourceType( AppointmentFormDTO.RESOURCE_TYPE );
466         List<Entry> listEntriesLight = EntryHome.getEntryList( entryFilter );
467         if ( CollectionUtils.isNotEmpty( listEntriesLight ) )
468         {
469             for ( Entry entryLight : listEntriesLight )
470             {
471                 listEntries.add( EntryHome.findByPrimaryKey( entryLight.getIdEntry( ) ) );
472             }
473         }
474         return listEntries;
475     }
476 
477     /**
478      * Get the reference list of groups
479      * 
480      * @param nIdForm
481      *            the id of the appointment form
482      * @return The reference list of groups of the given form
483      */
484     private static ReferenceList getRefListGroups( int nIdForm )
485     {
486         EntryFilter entryFilter = new EntryFilter( );
487         entryFilter.setIdResource( nIdForm );
488         entryFilter.setResourceType( AppointmentFormDTO.RESOURCE_TYPE );
489         entryFilter.setIdIsGroup( 1 );
490         List<Entry> listEntry = EntryHome.getEntryList( entryFilter );
491         ReferenceList refListGroups = new ReferenceList( );
492         for ( Entry entry : listEntry )
493         {
494             refListGroups.addItem( entry.getIdEntry( ), entry.getTitle( ) );
495         }
496         return refListGroups;
497     }
498 
499     /**
500      * Get the html part of the additional entry of the form
501      * 
502      * @param nIdEntry
503      *            the entry id
504      * @param stringBuffer
505      *            the string buffer
506      * @param locale
507      * @param bDisplayFront
508      * @param request
509      */
510     public static void getHtmlEntry( Map<String, Object> model, int nIdEntry, StringBuffer stringBuffer, Locale locale, boolean bDisplayFront,
511             HttpServletRequest request )
512     {
513         StringBuffer strConditionalQuestionStringBuffer = null;
514         HtmlTemplate template;
515         Entry entry = EntryHome.findByPrimaryKey( nIdEntry );
516         if ( entry.getEntryType( ).getGroup( ) )
517         {
518             StringBuffer strGroupStringBuffer = new StringBuffer( );
519             for ( Entry entryChild : entry.getChildren( ) )
520             {
521                 getHtmlEntry( model, entryChild.getIdEntry( ), strGroupStringBuffer, locale, bDisplayFront, request );
522             }
523             model.put( MARK_STR_LIST_CHILDREN, strGroupStringBuffer.toString( ) );
524         }
525         else
526         {
527             if ( entry.getNumberConditionalQuestion( ) != 0 )
528             {
529                 for ( Field field : entry.getFields( ) )
530                 {
531                     field.setConditionalQuestions( FieldHome.findByPrimaryKey( field.getIdField( ) ).getConditionalQuestions( ) );
532                 }
533             }
534         }
535         if ( entry.getNumberConditionalQuestion( ) != 0 )
536         {
537             strConditionalQuestionStringBuffer = new StringBuffer( );
538             for ( Field field : entry.getFields( ) )
539             {
540                 if ( CollectionUtils.isNotEmpty( field.getConditionalQuestions( ) ) )
541                 {
542                     StringBuffer strGroupStringBuffer = new StringBuffer( );
543                     for ( Entry entryConditional : field.getConditionalQuestions( ) )
544                     {
545                         getHtmlEntry( model, entryConditional.getIdEntry( ), strGroupStringBuffer, locale, bDisplayFront, request );
546                     }
547                     model.put( MARK_STR_LIST_CHILDREN, strGroupStringBuffer.toString( ) );
548                     model.put( MARK_FIELD, field );
549                     template = AppTemplateService.getTemplate( TEMPLATE_DIV_CONDITIONAL_ENTRY, locale, model );
550                     strConditionalQuestionStringBuffer.append( template.getHtml( ) );
551                 }
552             }
553             model.put( MARK_STR_LIST_CHILDREN, strConditionalQuestionStringBuffer.toString( ) );
554         }
555         model.put( MARK_ENTRY, entry );
556         model.put( MARK_LOCALE, locale );
557         if ( request != null )
558         {
559             AppointmentDTO appointmentDTO = (AppointmentDTO) request.getSession( ).getAttribute( SESSION_NOT_VALIDATED_APPOINTMENT );
560             if ( ( appointmentDTO != null ) && ( appointmentDTO.getMapResponsesByIdEntry( ) != null ) )
561             {
562                 List<Response> listResponses = appointmentDTO.getMapResponsesByIdEntry( ).get( entry.getIdEntry( ) );
563                 model.put( MARK_LIST_RESPONSES, listResponses );
564             }
565         }
566         IEntryTypeService entryTypeService = EntryTypeServiceManager.getEntryTypeService( entry );
567         // If the entry type is a file, we add the
568         if ( entryTypeService instanceof AbstractEntryTypeUpload )
569         {
570             model.put( MARK_UPLOAD_HANDLER, ( (AbstractEntryTypeUpload) entryTypeService ).getAsynchronousUploadHandler( ) );
571         }
572         template = AppTemplateService.getTemplate( entryTypeService.getTemplateHtmlForm( entry, bDisplayFront ), locale, model );
573         stringBuffer.append( template.getHtml( ) );
574     }
575 
576     /**
577      * Add to the map of the appointment the response of the additional entry of the form
578      * 
579      * @param request
580      *            the Request
581      * @param nIdEntry
582      *            the Entry Id
583      * @param locale
584      *            the Locale
585      * @param appointment
586      *            the Appointment
587      * @return the list of possible errors
588      */
589     public static List<GenericAttributeError> getResponseEntry( HttpServletRequest request, int nIdEntry, Locale locale, AppointmentDTO appointment )
590     {
591         List<Response> listResponse = new ArrayList<Response>( );
592         appointment.getMapResponsesByIdEntry( ).put( nIdEntry, listResponse );
593 
594         return getResponseEntry( request, nIdEntry, listResponse, false, locale, appointment );
595     }
596 
597     /**
598      * Add to the map of the appointment the response of the additional entry of the form
599      * 
600      * @param request
601      *            the request
602      * @param nIdEntry
603      *            the entry id
604      * @param listResponse
605      *            the list of the responses
606      * @param bResponseNull
607      *            true if the response can be null
608      * @param locale
609      *            the local
610      * @param appointment
611      *            the appointment
612      * @return a list of possible errors
613      */
614     private static List<GenericAttributeError> getResponseEntry( HttpServletRequest request, int nIdEntry, List<Response> listResponse, boolean bResponseNull,
615             Locale locale, AppointmentDTO appointment )
616     {
617         List<GenericAttributeError> listFormErrors = new ArrayList<GenericAttributeError>( );
618         Entry entry = EntryHome.findByPrimaryKey( nIdEntry );
619 
620         List<Field> listField = new ArrayList<Field>( );
621 
622         for ( Field field : entry.getFields( ) )
623         {
624             field = FieldHome.findByPrimaryKey( field.getIdField( ) );
625             listField.add( field );
626         }
627 
628         entry.setFields( listField );
629 
630         if ( entry.getEntryType( ).getGroup( ) )
631         {
632             for ( Entry entryChild : entry.getChildren( ) )
633             {
634                 List<Response> listResponseChild = new ArrayList<Response>( );
635                 appointment.getMapResponsesByIdEntry( ).put( entryChild.getIdEntry( ), listResponseChild );
636 
637                 listFormErrors.addAll( getResponseEntry( request, entryChild.getIdEntry( ), listResponseChild, false, locale, appointment ) );
638             }
639         }
640         else
641             if ( !entry.getEntryType( ).getComment( ) )
642             {
643                 GenericAttributeError formError = null;
644 
645                 if ( !bResponseNull )
646                 {
647                     formError = EntryTypeServiceManager.getEntryTypeService( entry ).getResponseData( entry, request, listResponse, locale );
648 
649                     if ( formError != null )
650                     {
651                         formError.setUrl( getEntryUrl( entry, appointment.getIdForm( ) ) );
652                     }
653                 }
654                 else
655                 {
656                     Response response = new Response( );
657                     response.setEntry( entry );
658                     listResponse.add( response );
659                 }
660 
661                 if ( formError != null )
662                 {
663                     entry.setError( formError );
664                     listFormErrors.add( formError );
665                 }
666 
667                 if ( entry.getNumberConditionalQuestion( ) != 0 )
668                 {
669                     for ( Field field : entry.getFields( ) )
670                     {
671                         boolean bIsFieldInResponseList = isFieldInTheResponseList( field.getIdField( ), listResponse );
672 
673                         for ( Entry conditionalEntry : field.getConditionalQuestions( ) )
674                         {
675                             List<Response> listResponseChild = new ArrayList<Response>( );
676                             appointment.getMapResponsesByIdEntry( ).put( conditionalEntry.getIdEntry( ), listResponseChild );
677 
678                             listFormErrors.addAll( getResponseEntry( request, conditionalEntry.getIdEntry( ), listResponseChild, !bIsFieldInResponseList,
679                                     locale, appointment ) );
680                         }
681                     }
682                 }
683             }
684 
685         return listFormErrors;
686     }
687 
688     /**
689      * Tell if the id of the field given is in the response list
690      * 
691      * @param nIdField
692      *            the id of the field
693      * @param listResponse
694      *            the list to search in
695      * @return true if the id is in the list
696      */
697     public static Boolean isFieldInTheResponseList( int nIdField, List<Response> listResponse )
698     {
699         for ( Response response : listResponse )
700         {
701             if ( ( response.getField( ) != null ) && ( response.getField( ).getIdField( ) == nIdField ) )
702             {
703                 return true;
704             }
705         }
706 
707         return false;
708     }
709 
710     /**
711      * Add parameters to the url with the entry given
712      * 
713      * @param entry
714      *            the entry
715      * @param nIdform
716      *            the form id
717      * @return the url
718      */
719     public static String getEntryUrl( Entry entry, int nIdform )
720     {
721         UrlItem url = new UrlItem( AppPathService.getPortalUrl( ) );
722         url.addParameter( XPageAppService.PARAM_XPAGE_APP, AppointmentPlugin.PLUGIN_NAME );
723         url.addParameter( MVCUtils.PARAMETER_VIEW, AppointmentApp.VIEW_APPOINTMENT_FORM );
724 
725         if ( ( entry != null ) && ( entry.getIdResource( ) > 0 ) )
726         {
727             url.addParameter( PARAMETER_ID_FORM, entry.getIdResource( ) );
728             url.setAnchor( PREFIX_ATTRIBUTE + entry.getIdEntry( ) );
729         }
730 
731         return url.getUrl( );
732     }
733 
734     /**
735      * Get the list of entries filtered
736      * 
737      * @param iform
738      *            the form id
739      * @param bDisplayFront
740      *            true if it is displayed on FO
741      * @return the list of entries
742      */
743     public static List<Entry> getFilter( int iform, boolean bDisplayFront )
744     {
745         EntryFilter filter = new EntryFilter( );
746         filter.setIdResource( iform );
747         filter.setResourceType( AppointmentFormDTO.RESOURCE_TYPE );
748         filter.setEntryParentNull( EntryFilter.FILTER_TRUE );
749         filter.setFieldDependNull( EntryFilter.FILTER_TRUE );
750         if ( bDisplayFront )
751         {
752             filter.setIsOnlyDisplayInBack( EntryFilter.FILTER_FALSE );
753         }
754         List<Entry> listEntryFirstLevel = EntryHome.getEntryList( filter );
755         return listEntryFirstLevel;
756     }
757 
758 }