View Javadoc
1   /*
2    * Copyright (c) 2002-2023, City of Paris
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright notice
10   *     and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright notice
13   *     and the following disclaimer in the documentation and/or other materials
14   *     provided with the distribution.
15   *
16   *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17   *     contributors may be used to endorse or promote products derived from
18   *     this software without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   *
32   * License 1.0
33   */
34  package fr.paris.lutece.plugins.appointment.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_FO = "skin/plugins/appointment/html_code_div_conditional_entry.html";
100     private static final String TEMPLATE_DIV_CONDITIONAL_ENTRY_BO = "admin/plugins/appointment/html_code_div_conditional_entry.html";
101 
102     /**
103      * Get an instance of the service
104      * 
105      * @return An instance of the service
106      */
107     public static EntryService getService( )
108     {
109         return SpringContextService.getBean( BEAN_NAME );
110     }
111 
112     /**
113      * Build an entry filter with static parameter
114      * 
115      * @param nIdForm
116      *            the Form Id
117      * @return the entry filter
118      */
119     public static EntryFilter buildEntryFilter( int nIdForm )
120     {
121         EntryFilter filter = new EntryFilter( );
122         filter.setIdResource( nIdForm );
123         filter.setResourceType( AppointmentFormDTO.RESOURCE_TYPE );
124         filter.setEntryParentNull( EntryFilter.FILTER_TRUE );
125         filter.setFieldDependNull( EntryFilter.FILTER_TRUE );
126         filter.setIdIsComment( EntryFilter.FILTER_FALSE );
127         filter.setIsOnlyDisplayInBack( EntryFilter.FILTER_FALSE );
128         return filter;
129     }
130 
131     /**
132      * Change the attribute's order to a greater one (move down in the list)
133      * 
134      * @param nOrderToSet
135      *            the new order for the attribute
136      * @param entryToChangeOrder
137      *            the attribute which will change
138      */
139     public void moveDownEntryOrder( int nOrderToSet, Entry entryToChangeOrder )
140     {
141         if ( entryToChangeOrder.getParent( ) == null )
142         {
143             int nNbChild = 0;
144             int nNewOrder = 0;
145 
146             EntryFilter filter = new EntryFilter( );
147             filter.setIdResource( entryToChangeOrder.getIdResource( ) );
148             filter.setResourceType( Form.RESOURCE_TYPE );
149             filter.setEntryParentNull( EntryFilter.FILTER_TRUE );
150             filter.setFieldDependNull( EntryFilter.FILTER_TRUE );
151 
152             List<Entry> listEntryFirstLevel = EntryHome.findEntriesWithoutParent( entryToChangeOrder.getIdResource( ), entryToChangeOrder.getResourceType( ) );
153 
154             List<Integer> orderFirstLevel = new ArrayList<>( );
155             initOrderFirstLevel( listEntryFirstLevel, orderFirstLevel );
156 
157             Integer nbChildEntryToChangeOrder = 0;
158 
159             if ( entryToChangeOrder.getChildren( ) != null )
160             {
161                 nbChildEntryToChangeOrder = entryToChangeOrder.getChildren( ).size( );
162             }
163 
164             for ( Entry entry : listEntryFirstLevel )
165             {
166                 for ( int i = 0; i < orderFirstLevel.size( ); i++ )
167                 {
168                     if ( ( orderFirstLevel.get( i ).equals( Integer.valueOf( entry.getPosition( ) ) ) )
169                             && ( entry.getPosition( ) > entryToChangeOrder.getPosition( ) ) && ( entry.getPosition( ) <= nOrderToSet ) )
170                     {
171                         if ( nNbChild == 0 )
172                         {
173                             nNewOrder = orderFirstLevel.get( i - 1 );
174 
175                             if ( !orderFirstLevel.get( i - 1 ).equals( Integer.valueOf( entryToChangeOrder.getPosition( ) ) ) )
176                             {
177                                 nNewOrder -= nbChildEntryToChangeOrder;
178                             }
179                         }
180                         else
181                         {
182                             nNewOrder += ( nNbChild + 1 );
183                         }
184 
185                         entry.setPosition( nNewOrder );
186                         EntryHome.update( entry );
187                         nNbChild = 0;
188 
189                         if ( entry.getChildren( ) != null )
190                         {
191                             for ( Entry child : entry.getChildren( ) )
192                             {
193                                 nNbChild++;
194                                 child.setPosition( nNewOrder + nNbChild );
195                                 EntryHome.update( child );
196                             }
197                         }
198                     }
199                 }
200             }
201 
202             entryToChangeOrder.setPosition( nNewOrder + nNbChild + 1 );
203             EntryHome.update( entryToChangeOrder );
204             nNbChild = 0;
205 
206             for ( Entry child : entryToChangeOrder.getChildren( ) )
207             {
208                 nNbChild++;
209                 child.setPosition( entryToChangeOrder.getPosition( ) + nNbChild );
210                 EntryHome.update( child );
211             }
212         }
213         else
214         {
215             EntryFilter filter = new EntryFilter( );
216             filter.setIdResource( entryToChangeOrder.getIdResource( ) );
217             filter.setResourceType( Form.RESOURCE_TYPE );
218             filter.setFieldDependNull( EntryFilter.FILTER_TRUE );
219 
220             List<Entry> listAllEntry = EntryHome.getEntryList( filter );
221 
222             for ( Entry entry : listAllEntry )
223             {
224                 if ( ( entry.getPosition( ) > entryToChangeOrder.getPosition( ) ) && ( entry.getPosition( ) <= nOrderToSet ) )
225                 {
226                     entry.setPosition( entry.getPosition( ) - 1 );
227                     EntryHome.update( entry );
228                 }
229             }
230 
231             entryToChangeOrder.setPosition( nOrderToSet );
232             EntryHome.update( entryToChangeOrder );
233         }
234     }
235 
236     /**
237      * Change the attribute's order to a lower one (move up in the list)
238      * 
239      * @param nOrderToSet
240      *            the new order for the attribute
241      * @param entryToChangeOrder
242      *            the attribute which will change
243      */
244     public void moveUpEntryOrder( int nOrderToSet, Entry entryToChangeOrder )
245     {
246         EntryFilter filter = new EntryFilter( );
247         filter.setIdResource( entryToChangeOrder.getIdResource( ) );
248         filter.setResourceType( Form.RESOURCE_TYPE );
249         filter.setFieldDependNull( EntryFilter.FILTER_TRUE );
250 
251         if ( entryToChangeOrder.getParent( ) == null )
252         {
253             filter.setEntryParentNull( EntryFilter.FILTER_TRUE );
254 
255             List<Integer> orderFirstLevel = new ArrayList<>( );
256 
257             int nNbChild = 0;
258             int nNewOrder = nOrderToSet;
259             int nEntryToMoveOrder = entryToChangeOrder.getPosition( );
260 
261             List<Entry> listEntryFirstLevel = EntryHome.findEntriesWithoutParent( entryToChangeOrder.getIdResource( ), entryToChangeOrder.getResourceType( ) );
262             // the list of all the orders in the first level
263             initOrderFirstLevel( listEntryFirstLevel, orderFirstLevel );
264 
265             for ( Entry entry : listEntryFirstLevel )
266             {
267                 Integer entryInitialPosition = entry.getPosition( );
268 
269                 for ( int i = 0; i < orderFirstLevel.size( ); i++ )
270                 {
271                     if ( ( orderFirstLevel.get( i ).equals( entryInitialPosition ) ) && ( entryInitialPosition < nEntryToMoveOrder )
272                             && ( entryInitialPosition >= nOrderToSet ) )
273                     {
274                         if ( entryToChangeOrder.getPosition( ) == nEntryToMoveOrder )
275                         {
276                             entryToChangeOrder.setPosition( nNewOrder );
277                             EntryHome.update( entryToChangeOrder );
278 
279                             for ( Entry child : entryToChangeOrder.getChildren( ) )
280                             {
281                                 nNbChild++;
282                                 child.setPosition( entryToChangeOrder.getPosition( ) + nNbChild );
283                                 EntryHome.update( child );
284                             }
285                         }
286 
287                         nNewOrder = nNewOrder + nNbChild + 1;
288                         entry.setPosition( nNewOrder );
289                         EntryHome.update( entry );
290                         nNbChild = 0;
291 
292                         for ( Entry child : entry.getChildren( ) )
293                         {
294                             nNbChild++;
295                             child.setPosition( nNewOrder + nNbChild );
296                             EntryHome.update( child );
297                         }
298                     }
299                 }
300             }
301         }
302         else
303         {
304             List<Entry> listAllEntry = EntryHome.getEntryList( filter );
305 
306             for ( Entry entry : listAllEntry )
307             {
308                 if ( ( entry.getPosition( ) < entryToChangeOrder.getPosition( ) ) && ( entry.getPosition( ) >= nOrderToSet ) )
309                 {
310                     entry.setPosition( entry.getPosition( ) + 1 );
311                     EntryHome.update( entry );
312                 }
313             }
314 
315             entryToChangeOrder.setPosition( nOrderToSet );
316             EntryHome.update( entryToChangeOrder );
317         }
318     }
319 
320     /**
321      * Move EntryToMove into entryGroup
322      * 
323      * @param entryToMove
324      *            the entry which will be moved
325      * @param entryGroup
326      *            the entry group
327      */
328     public void moveEntryIntoGroup( Entry entryToMove, Entry entryGroup )
329     {
330         if ( ( entryToMove != null ) && ( entryGroup != null ) )
331         {
332             // If the entry already has a parent, we must remove it before
333             // adding it to a new one
334             if ( entryToMove.getParent( ) != null )
335             {
336                 moveOutEntryFromGroup( entryToMove );
337             }
338 
339             int nPosition;
340 
341             if ( entryToMove.getPosition( ) < entryGroup.getPosition( ) )
342             {
343                 nPosition = entryGroup.getPosition( );
344                 moveDownEntryOrder( nPosition, entryToMove );
345             }
346             else
347             {
348                 nPosition = entryGroup.getPosition( ) + entryGroup.getChildren( ).size( ) + 1;
349                 moveUpEntryOrder( nPosition, entryToMove );
350             }
351 
352             entryToMove.setParent( entryGroup );
353             EntryHome.update( entryToMove );
354         }
355     }
356 
357     /**
358      * Remove an entry from a group
359      * 
360      * @param entryToMove
361      *            the entry to remove from a group
362      */
363     public void moveOutEntryFromGroup( Entry entryToMove )
364     {
365         Entry parent = EntryHome.findByPrimaryKey( entryToMove.getParent( ).getIdEntry( ) );
366 
367         // The new position of the entry is the position of the group plus the
368         // number of entries in the group (including this entry)
369         moveDownEntryOrder( parent.getPosition( ) + parent.getChildren( ).size( ), entryToMove );
370         entryToMove.setParent( null );
371         EntryHome.update( entryToMove );
372     }
373 
374     /**
375      * Init the list of the attribute's orders (first level only)
376      * 
377      * @param listEntryFirstLevel
378      *            the list of all the attributes of the first level
379      * @param orderFirstLevel
380      *            the list to set
381      */
382     private void initOrderFirstLevel( List<Entry> listEntryFirstLevel, List<Integer> orderFirstLevel )
383     {
384         for ( Entry entry : listEntryFirstLevel )
385         {
386             orderFirstLevel.add( entry.getPosition( ) );
387         }
388     }
389 
390     /**
391      * Remove every entries associated with a given appointment form
392      * 
393      * @param nIdForm
394      *            The id of the appointment to remove entries of
395      */
396     public void removeEntriesByIdAppointmentForm( int nIdForm )
397     {
398         EntryFilter entryFilter = new EntryFilter( );
399         entryFilter.setIdResource( nIdForm );
400         entryFilter.setResourceType( Form.RESOURCE_TYPE );
401         entryFilter.setEntryParentNull( EntryFilter.FILTER_TRUE );
402         entryFilter.setFieldDependNull( EntryFilter.FILTER_TRUE );
403 
404         List<Entry> listEntry = EntryHome.getEntryList( entryFilter );
405 
406         for ( Entry entry : listEntry )
407         {
408             EntryHome.remove( entry.getIdEntry( ) );
409         }
410     }
411 
412     /**
413      * Add the entries to the model
414      * 
415      * @param nIdForm
416      *            The form Id
417      * @param model
418      *            the model
419      */
420     public static void addListEntryToModel( int nIdForm, Map<String, Object> model )
421     {
422         EntryFilter entryFilter = new EntryFilter( );
423         entryFilter.setIdResource( nIdForm );
424         entryFilter.setResourceType( AppointmentFormDTO.RESOURCE_TYPE );
425         entryFilter.setEntryParentNull( EntryFilter.FILTER_TRUE );
426         entryFilter.setFieldDependNull( EntryFilter.FILTER_TRUE );
427         List<Entry> listEntryFirstLevel = EntryHome.getEntryList( entryFilter );
428         List<Entry> listEntry = new ArrayList<>( listEntryFirstLevel.size( ) );
429         List<Integer> listOrderFirstLevel = new ArrayList<>( listEntryFirstLevel.size( ) );
430         for ( Entry entry : listEntryFirstLevel )
431         {
432             listEntry.add( entry );
433             listOrderFirstLevel.add( listEntry.size( ) );
434             if ( Boolean.TRUE.equals( entry.getEntryType( ).getGroup( ) ) )
435             {
436                 entryFilter = new EntryFilter( );
437                 entryFilter.setIdResource( nIdForm );
438                 entryFilter.setResourceType( AppointmentFormDTO.RESOURCE_TYPE );
439                 entryFilter.setFieldDependNull( EntryFilter.FILTER_TRUE );
440                 entryFilter.setIdEntryParent( entry.getIdEntry( ) );
441                 List<Entry> listEntryGroup = EntryHome.getEntryList( entryFilter );
442                 entry.setChildren( listEntryGroup );
443                 listEntry.addAll( listEntryGroup );
444             }
445         }
446         for ( Entry entry : listEntry )
447         {
448             entry.setFields( FieldHome.getFieldListByIdEntry( entry.getIdEntry( ) ) );
449         }
450         model.put( MARK_GROUP_ENTRY_LIST, getRefListGroups( nIdForm ) );
451         model.put( MARK_ENTRY_TYPE_LIST, EntryTypeService.getInstance( ).getEntryTypeReferenceList( ) );
452         model.put( MARK_ENTRY_LIST, listEntry );
453         model.put( MARK_LIST_ORDER_FIRST_LEVEL, listOrderFirstLevel );
454     }
455 
456     /**
457      * Find all the entries (with its fields) of a form
458      * 
459      * @param nIdForm
460      *            the form Id
461      * @return a list of all the entries
462      */
463     public static List<Entry> findListEntry( int nIdForm )
464     {
465         List<Entry> listEntries = new ArrayList<>( );
466         EntryFilter entryFilter = new EntryFilter( );
467         entryFilter.setIdResource( nIdForm );
468         entryFilter.setResourceType( AppointmentFormDTO.RESOURCE_TYPE );
469         List<Entry> listEntriesLight = EntryHome.getEntryList( entryFilter );
470         if ( CollectionUtils.isNotEmpty( listEntriesLight ) )
471         {
472             for ( Entry entryLight : listEntriesLight )
473             {
474                 listEntries.add( EntryHome.findByPrimaryKey( entryLight.getIdEntry( ) ) );
475             }
476         }
477         return listEntries;
478     }
479 
480     /**
481      * Get the reference list of groups
482      * 
483      * @param nIdForm
484      *            the id of the appointment form
485      * @return The reference list of groups of the given form
486      */
487     private static ReferenceList getRefListGroups( int nIdForm )
488     {
489         EntryFilter entryFilter = new EntryFilter( );
490         entryFilter.setIdResource( nIdForm );
491         entryFilter.setResourceType( AppointmentFormDTO.RESOURCE_TYPE );
492         entryFilter.setIdIsGroup( 1 );
493         List<Entry> listEntry = EntryHome.getEntryList( entryFilter );
494         ReferenceList refListGroups = new ReferenceList( );
495         for ( Entry entry : listEntry )
496         {
497             refListGroups.addItem( entry.getIdEntry( ), entry.getTitle( ) );
498         }
499         return refListGroups;
500     }
501 
502     /**
503      * Get the html part of the additional entry of the form
504      * 
505      * @param nIdEntry
506      *            the entry id
507      * @param stringBuffer
508      *            the string buffer
509      * @param locale
510      * @param bDisplayFront
511      * @param request
512      */
513     public static void getHtmlEntry( Map<String, Object> model, int nIdEntry, StringBuilder stringBuffer, Locale locale, boolean bDisplayFront,
514             AppointmentDTO appointmentDTO )
515     {
516         StringBuilder strConditionalQuestionStringBuffer = null;
517         HtmlTemplate template;
518         Entry entry = EntryHome.findByPrimaryKey( nIdEntry );
519         Field disabledField = entry.getFieldByCode( IEntryTypeService.FIELD_DISABLED );
520         if ( disabledField != null && !Boolean.parseBoolean( disabledField.getValue( ) ) )
521         {
522             if ( Boolean.TRUE.equals( entry.getEntryType( ).getGroup( ) ) )
523             {
524                 StringBuilder strGroupStringBuffer = new StringBuilder( );
525                 for ( Entry entryChild : entry.getChildren( ) )
526                 {
527                     getHtmlEntry( model, entryChild.getIdEntry( ), strGroupStringBuffer, locale, bDisplayFront, appointmentDTO );
528                 }
529                 model.put( MARK_STR_LIST_CHILDREN, strGroupStringBuffer.toString( ) );
530             }
531             else
532             {
533                 if ( entry.getNumberConditionalQuestion( ) != 0 )
534                 {
535                     for ( Field field : entry.getFields( ) )
536                     {
537                         field.setConditionalQuestions( FieldHome.findByPrimaryKey( field.getIdField( ) ).getConditionalQuestions( ) );
538                     }
539                 }
540             }
541             if ( entry.getNumberConditionalQuestion( ) != 0 )
542             {
543                 strConditionalQuestionStringBuffer = new StringBuilder( );
544                 for ( Field field : entry.getFields( ) )
545                 {
546                     if ( CollectionUtils.isNotEmpty( field.getConditionalQuestions( ) ) )
547                     {
548                         StringBuilder strGroupStringBuffer = new StringBuilder( );
549                         for ( Entry entryConditional : field.getConditionalQuestions( ) )
550                         {
551                             getHtmlEntry( model, entryConditional.getIdEntry( ), strGroupStringBuffer, locale, bDisplayFront, appointmentDTO );
552                         }
553                         model.put( MARK_STR_LIST_CHILDREN, strGroupStringBuffer.toString( ) );
554                         model.put( MARK_FIELD, field );
555                         String templateDivConditionalEntry = bDisplayFront ? TEMPLATE_DIV_CONDITIONAL_ENTRY_FO : TEMPLATE_DIV_CONDITIONAL_ENTRY_BO;
556                         template = AppTemplateService.getTemplate( templateDivConditionalEntry, locale, model );
557                         strConditionalQuestionStringBuffer.append( template.getHtml( ) );
558                     }
559                 }
560                 model.put( MARK_STR_LIST_CHILDREN, strConditionalQuestionStringBuffer.toString( ) );
561             }
562             model.put( MARK_ENTRY, entry );
563             model.put( MARK_LOCALE, locale );
564             if ( ( appointmentDTO != null ) && (appointmentDTO.getMapResponsesByIdEntry( ) != null ) )
565             {
566                 List<Response> listResponses = appointmentDTO.getMapResponsesByIdEntry( ).get( entry.getIdEntry( ) );
567                 model.put( MARK_LIST_RESPONSES, listResponses );
568 
569             }
570             IEntryTypeService entryTypeService = EntryTypeServiceManager.getEntryTypeService( entry );
571             // If the entry type is a file, we add the
572             if ( entryTypeService instanceof AbstractEntryTypeUpload )
573             {
574                 model.put( MARK_UPLOAD_HANDLER, ( ( AbstractEntryTypeUpload ) entryTypeService ).getAsynchronousUploadHandler( ) );
575             }
576             template = AppTemplateService.getTemplate( entryTypeService.getTemplateHtmlForm( entry, bDisplayFront ), locale, model );
577             stringBuffer.append( template.getHtml( ) );
578         }
579     }
580 
581     /**
582      * Add to the map of the appointment the response of the additional entry of the form
583      * 
584      * @param request
585      *            the Request
586      * @param nIdEntry
587      *            the Entry Id
588      * @param locale
589      *            the Locale
590      * @param appointment
591      *            the Appointment
592      * @return the list of possible errors
593      */
594     public static List<GenericAttributeError> getResponseEntry( HttpServletRequest request, int nIdEntry, Locale locale, AppointmentDTO appointment )
595     {
596         List<Response> listResponse = new ArrayList<>( );
597         appointment.getMapResponsesByIdEntry( ).put( nIdEntry, listResponse );
598 
599         return getResponseEntry( request, nIdEntry, listResponse, false, locale, appointment );
600     }
601 
602     /**
603      * Add to the map of the appointment the response of the additional entry of the form
604      * 
605      * @param request
606      *            the request
607      * @param nIdEntry
608      *            the entry id
609      * @param listResponse
610      *            the list of the responses
611      * @param bResponseNull
612      *            true if the response can be null
613      * @param locale
614      *            the local
615      * @param appointment
616      *            the appointment
617      * @return a list of possible errors
618      */
619     private static List<GenericAttributeError> getResponseEntry( HttpServletRequest request, int nIdEntry, List<Response> listResponse, boolean bResponseNull,
620             Locale locale, AppointmentDTO appointment )
621     {
622         List<GenericAttributeError> listFormErrors = new ArrayList<>( );
623         Entry entry = EntryHome.findByPrimaryKey( nIdEntry );
624 
625         List<Field> listField = new ArrayList<>( );
626 
627         for ( Field field : entry.getFields( ) )
628         {
629             field = FieldHome.findByPrimaryKey( field.getIdField( ) );
630             listField.add( field );
631         }
632 
633         entry.setFields( listField );
634 
635         Field disabledField = entry.getFieldByCode( IEntryTypeService.FIELD_DISABLED );
636         if ( disabledField != null && !Boolean.parseBoolean( disabledField.getValue( ) ) )
637         {
638             if ( Boolean.TRUE.equals( entry.getEntryType( ).getGroup( ) ) )
639             {
640                 for ( Entry entryChild : entry.getChildren( ) )
641                 {
642                     List<Response> listResponseChild = new ArrayList<>( );
643                     appointment.getMapResponsesByIdEntry( ).put( entryChild.getIdEntry( ), listResponseChild );
644 
645                     listFormErrors.addAll( getResponseEntry( request, entryChild.getIdEntry( ), listResponseChild, false, locale, appointment ) );
646                 }
647             }
648             else
649                 if ( !Boolean.TRUE.equals( entry.getEntryType( ).getComment( ) ) )
650                 {
651                     GenericAttributeError formError = null;
652 
653                     if ( !bResponseNull )
654                     {
655                         formError = EntryTypeServiceManager.getEntryTypeService( entry ).getResponseData( entry, request, listResponse, locale );
656 
657                         if ( formError != null )
658                         {
659                             formError.setUrl( getEntryUrl( entry ) );
660                         }
661                     }
662                     else
663                     {
664                         Response response = new Response( );
665                         response.setEntry( entry );
666                         listResponse.add( response );
667                     }
668 
669                     if ( formError != null )
670                     {
671                         entry.setError( formError );
672                         listFormErrors.add( formError );
673                     }
674 
675                     if ( entry.getNumberConditionalQuestion( ) != 0 )
676                     {
677                         for ( Field field : entry.getFields( ) )
678                         {
679                             boolean bIsFieldInResponseList = isFieldInTheResponseList( field.getIdField( ), listResponse );
680 
681                             for ( Entry conditionalEntry : field.getConditionalQuestions( ) )
682                             {
683                                 List<Response> listResponseChild = new ArrayList<>( );
684                                 appointment.getMapResponsesByIdEntry( ).put( conditionalEntry.getIdEntry( ), listResponseChild );
685 
686                                 listFormErrors.addAll( getResponseEntry( request, conditionalEntry.getIdEntry( ), listResponseChild, !bIsFieldInResponseList,
687                                         locale, appointment ) );
688                             }
689                         }
690                     }
691                 }
692         }
693         return listFormErrors;
694     }
695 
696     /**
697      * Tell if the id of the field given is in the response list
698      * 
699      * @param nIdField
700      *            the id of the field
701      * @param listResponse
702      *            the list to search in
703      * @return true if the id is in the list
704      */
705     public static Boolean isFieldInTheResponseList( int nIdField, List<Response> listResponse )
706     {
707         for ( Response response : listResponse )
708         {
709             if ( ( response.getField( ) != null ) && ( response.getField( ).getIdField( ) == nIdField ) )
710             {
711                 return true;
712             }
713         }
714 
715         return false;
716     }
717 
718     /**
719      * Add parameters to the url with the entry given
720      * 
721      * @param entry
722      *            the entry
723      * @return the url
724      */
725     public static String getEntryUrl( Entry entry )
726     {
727         UrlItem url = new UrlItem( AppPathService.getPortalUrl( ) );
728         url.addParameter( XPageAppService.PARAM_XPAGE_APP, AppointmentPlugin.PLUGIN_NAME );
729         url.addParameter( MVCUtils.PARAMETER_VIEW, AppointmentApp.VIEW_APPOINTMENT_FORM );
730 
731         if ( ( entry != null ) && ( entry.getIdResource( ) > 0 ) )
732         {
733             url.addParameter( PARAMETER_ID_FORM, entry.getIdResource( ) );
734             url.setAnchor( PREFIX_ATTRIBUTE + entry.getIdEntry( ) );
735         }
736 
737         return url.getUrl( );
738     }
739 
740     /**
741      * Get the list of entries filtered
742      * 
743      * @param iform
744      *            the form id
745      * @param bDisplayFront
746      *            true if it is displayed on FO
747      * @return the list of entries
748      */
749     public static List<Entry> getFilter( int iform, boolean bDisplayFront )
750     {
751         EntryFilter filter = new EntryFilter( );
752         filter.setIdResource( iform );
753         filter.setResourceType( AppointmentFormDTO.RESOURCE_TYPE );
754         filter.setEntryParentNull( EntryFilter.FILTER_TRUE );
755         filter.setFieldDependNull( EntryFilter.FILTER_TRUE );
756         if ( bDisplayFront )
757         {
758             filter.setIsOnlyDisplayInBack( EntryFilter.FILTER_FALSE );
759         }
760         return EntryHome.getEntryList( filter );
761     }
762 
763 }