View Javadoc
1   /*
2    * Copyright (c) 2002-2020, 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.directories.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  import javax.servlet.http.HttpServletRequest;
42  import fr.paris.lutece.plugins.genericattributes.business.Entry;
43  import fr.paris.lutece.plugins.genericattributes.business.EntryFilter;
44  import fr.paris.lutece.plugins.genericattributes.business.EntryHome;
45  import fr.paris.lutece.plugins.genericattributes.business.Field;
46  import fr.paris.lutece.plugins.genericattributes.business.FieldHome;
47  import fr.paris.lutece.plugins.genericattributes.service.entrytype.AbstractEntryTypeUpload;
48  import fr.paris.lutece.plugins.genericattributes.service.entrytype.EntryTypeServiceManager;
49  import fr.paris.lutece.plugins.genericattributes.service.entrytype.IEntryTypeService;
50  import fr.paris.lutece.portal.service.admin.AdminUserService;
51  import fr.paris.lutece.portal.service.spring.SpringContextService;
52  import fr.paris.lutece.portal.service.template.AppTemplateService;
53  import fr.paris.lutece.portal.service.util.RemovalListenerService;
54  import fr.paris.lutece.util.ReferenceList;
55  import fr.paris.lutece.util.html.HtmlTemplate;
56  
57  /**
58   * Service to manage entries.
59   * 
60   * @author
61   */
62  public final class EntryService extends RemovalListenerService implements Serializable
63  {
64      /** Name of the bean of this service. */
65      public static final String BEAN_NAME = "directories.entryService";
66      private static final long serialVersionUID = -5378918040356139703L;
67      private static final String MARK_ENTRY_LIST = "entry_list";
68      private static final String MARK_ENTRY_TYPE_LIST = "entry_type_list";
69      private static final String MARK_GROUP_ENTRY_LIST = "entry_group_list";
70      private static final String MARK_LIST_ORDER_FIRST_LEVEL = "listOrderFirstLevel";
71      private static final String MARK_LOCALE = "locale";
72      private static final String MARK_ENTRY = "entry";
73      private static final String RESOURCE_TYPE = "DIRECTORIES";
74      private static final String MARK_UPLOAD_HANDLER = "uploadHandler";
75      private static final String MARK_ENTRY_TYPE_SERVICE = "entryTypeService";
76  
77      /**
78       * Get an instance of the service.
79       * 
80       * @return An instance of the service
81       */
82      public static EntryService getService( )
83      {
84          return SpringContextService.getBean( BEAN_NAME );
85      }
86  
87      /**
88       * Get the html part of the additional entry of the form.
89       * 
90       * @param nIdEntry
91       *            the entry id
92       * @param stringBuffer
93       *            the string buffer
94       * @param locale
95       * @param bDisplayFront
96       */
97      public static void getHtmlEntry( Map<String, Object> model, int nIdEntry, StringBuilder strBuilder, Locale locale, boolean bDisplayFront )
98      {
99          HtmlTemplate template;
100         Entry entry = EntryHome.findByPrimaryKey( nIdEntry );
101         List<Field> listField = new ArrayList<>( entry.getFields( ).size( ) );
102         for ( Field field : entry.getFields( ) )
103         {
104             field = FieldHome.findByPrimaryKey( field.getIdField( ) );
105             listField.add( field );
106         }
107         entry.setFields( listField );
108         model.put( MARK_ENTRY, entry );
109         model.put( MARK_LOCALE, locale );
110         IEntryTypeService entryTypeService = EntryTypeServiceManager.getEntryTypeService( entry );
111         // If the entry type is a file, we add the
112         if ( entryTypeService instanceof AbstractEntryTypeUpload )
113         {
114             model.put( MARK_UPLOAD_HANDLER, ( (AbstractEntryTypeUpload) entryTypeService ).getAsynchronousUploadHandler( ) );
115         }
116         template = AppTemplateService.getTemplate( entryTypeService.getTemplateHtmlForm( entry, bDisplayFront ), locale, model );
117         strBuilder.append( template.getHtml( ) );
118     }
119 
120     /**
121      * Get the html part of the additional entry of the form.
122      * 
123      * @param nIdEntry
124      *            the entry id
125      * @param StringBuilder
126      *            the string buffer
127      * @param locale
128      * @param bDisplayFront
129      */
130     public static void getHtmlEntryReadOnly( Map<String, Object> model, int nIdEntry, StringBuilder strBuilder, Locale locale, boolean bDisplayFront )
131     {
132         HtmlTemplate template;
133         Entry entry = EntryHome.findByPrimaryKey( nIdEntry );
134         List<Field> listField = new ArrayList<>( entry.getFields( ).size( ) );
135         for ( Field field : entry.getFields( ) )
136         {
137             field = FieldHome.findByPrimaryKey( field.getIdField( ) );
138             listField.add( field );
139         }
140         entry.setFields( listField );
141         model.put( MARK_ENTRY, entry );
142         model.put( MARK_LOCALE, locale );
143         IEntryTypeService entryTypeService = EntryTypeServiceManager.getEntryTypeService( entry );
144         model.put( MARK_ENTRY_TYPE_SERVICE, entryTypeService );
145 
146         // If the entry type is a file, we add the
147         if ( entryTypeService instanceof AbstractEntryTypeUpload )
148         {
149             model.put( MARK_UPLOAD_HANDLER, ( (AbstractEntryTypeUpload) entryTypeService ).getAsynchronousUploadHandler( ) );
150         }
151         template = AppTemplateService.getTemplate( entryTypeService.getTemplateEntryReadOnly( bDisplayFront ), locale, model );
152         strBuilder.append( template.getHtml( ) );
153     }
154 
155     /**
156      * Add the entries to the model.
157      * 
158      * @param nIdDirectory
159      *            The form Id
160      * @param model
161      *            the model
162      */
163     public static void addListEntryToModel( Map<String, Object> model, int nIdDirectory )
164     {
165         EntryFilter entryFilter = new EntryFilter( );
166         entryFilter.setIdResource( nIdDirectory );
167         entryFilter.setResourceType( RESOURCE_TYPE );
168         entryFilter.setEntryParentNull( EntryFilter.FILTER_TRUE );
169         entryFilter.setFieldDependNull( EntryFilter.FILTER_TRUE );
170         List<Entry> listEntryFirstLevel = EntryHome.getEntryList( entryFilter );
171         List<Entry> listEntry = new ArrayList<>( listEntryFirstLevel.size( ) );
172         List<Integer> listOrderFirstLevel = new ArrayList<>( listEntryFirstLevel.size( ) );
173         for ( Entry entry : listEntryFirstLevel )
174         {
175             listEntry.add( entry );
176             listOrderFirstLevel.add( listEntry.size( ) );
177             if ( entry.getEntryType( ).getGroup( ) )
178             {
179                 entryFilter = new EntryFilter( );
180                 entryFilter.setIdResource( nIdDirectory );
181                 entryFilter.setResourceType( RESOURCE_TYPE );
182                 entryFilter.setFieldDependNull( EntryFilter.FILTER_TRUE );
183                 entryFilter.setIdEntryParent( entry.getIdEntry( ) );
184                 List<Entry> listEntryGroup = EntryHome.getEntryList( entryFilter );
185                 entry.setChildren( listEntryGroup );
186                 listEntry.addAll( listEntryGroup );
187             }
188         }
189         model.put( MARK_GROUP_ENTRY_LIST, getRefListGroups( nIdDirectory ) );
190         model.put( MARK_ENTRY_TYPE_LIST, EntryTypeService.getInstance( ).getEntryTypeReferenceList( ) );
191         model.put( MARK_ENTRY_LIST, listEntry );
192         model.put( MARK_LIST_ORDER_FIRST_LEVEL, listOrderFirstLevel );
193     }
194 
195     /**
196      * Get the reference list of groups.
197      * 
198      * @param nIdDirectory
199      *            the id of the directories form
200      * @return The reference list of groups of the given form
201      */
202     private static ReferenceList getRefListGroups( int nIdDirectory )
203     {
204         EntryFilter entryFilter = new EntryFilter( );
205         entryFilter.setIdResource( nIdDirectory );
206         entryFilter.setResourceType( RESOURCE_TYPE );
207         entryFilter.setIdIsGroup( 1 );
208         List<Entry> listEntry = EntryHome.getEntryList( entryFilter );
209         ReferenceList refListGroups = new ReferenceList( );
210         for ( Entry entry : listEntry )
211         {
212             refListGroups.addItem( entry.getIdEntry( ), entry.getTitle( ) );
213         }
214         return refListGroups;
215     }
216 
217     /**
218      * Change the attribute's order to a greater one (move down in the list).
219      * 
220      * @param nOrderToSet
221      *            the new order for the attribute
222      * @param entryToChangeOrder
223      *            the attribute which will change
224      */
225     public void moveDownEntryOrder( int nOrderToSet, Entry entryToChangeOrder )
226     {
227         if ( entryToChangeOrder.getParent( ) == null )
228         {
229             int nNbChild = 0;
230             int nNewOrder = 0;
231             EntryFilter filter = new EntryFilter( );
232             filter.setIdResource( entryToChangeOrder.getIdResource( ) );
233             filter.setResourceType( RESOURCE_TYPE );
234             filter.setEntryParentNull( EntryFilter.FILTER_TRUE );
235             filter.setFieldDependNull( EntryFilter.FILTER_TRUE );
236             List<Entry> listEntryFirstLevel = EntryHome.findEntriesWithoutParent( entryToChangeOrder.getIdResource( ), entryToChangeOrder.getResourceType( ) );
237             List<Integer> orderFirstLevel = new ArrayList<>( );
238             initOrderFirstLevel( listEntryFirstLevel, orderFirstLevel );
239             Integer nbChildEntryToChangeOrder = 0;
240             if ( entryToChangeOrder.getChildren( ) != null )
241             {
242                 nbChildEntryToChangeOrder = entryToChangeOrder.getChildren( ).size( );
243             }
244             for ( Entry entry : listEntryFirstLevel )
245             {
246                 for ( int i = 0; i < orderFirstLevel.size( ); i++ )
247                 {
248                     if ( orderFirstLevel.get( i ).equals( Integer.valueOf( entry.getPosition( ) ) ) && entry.getPosition( ) > entryToChangeOrder.getPosition( )
249                             && entry.getPosition( ) <= nOrderToSet )
250                     {
251                         if ( nNbChild == 0 )
252                         {
253                             nNewOrder = orderFirstLevel.get( i - 1 );
254                             if ( !orderFirstLevel.get( i - 1 ).equals( Integer.valueOf( entryToChangeOrder.getPosition( ) ) ) )
255                             {
256                                 nNewOrder -= nbChildEntryToChangeOrder;
257                             }
258                         }
259                         else
260                         {
261                             nNewOrder += nNbChild + 1;
262                         }
263                         entry.setPosition( nNewOrder );
264                         EntryHome.update( entry );
265                         nNbChild = 0;
266                         if ( entry.getChildren( ) != null )
267                         {
268                             for ( Entry child : entry.getChildren( ) )
269                             {
270                                 nNbChild++;
271                                 child.setPosition( nNewOrder + nNbChild );
272                                 EntryHome.update( child );
273                             }
274                         }
275                     }
276                 }
277             }
278             entryToChangeOrder.setPosition( nNewOrder + nNbChild + 1 );
279             EntryHome.update( entryToChangeOrder );
280             nNbChild = 0;
281             for ( Entry child : entryToChangeOrder.getChildren( ) )
282             {
283                 nNbChild++;
284                 child.setPosition( entryToChangeOrder.getPosition( ) + nNbChild );
285                 EntryHome.update( child );
286             }
287         }
288         else
289         {
290             EntryFilter filter = new EntryFilter( );
291             filter.setIdResource( entryToChangeOrder.getIdResource( ) );
292             filter.setResourceType( RESOURCE_TYPE );
293             filter.setFieldDependNull( EntryFilter.FILTER_TRUE );
294             List<Entry> listAllEntry = EntryHome.getEntryList( filter );
295             for ( Entry entry : listAllEntry )
296             {
297                 if ( entry.getPosition( ) > entryToChangeOrder.getPosition( ) && entry.getPosition( ) <= nOrderToSet )
298                 {
299                     entry.setPosition( entry.getPosition( ) - 1 );
300                     EntryHome.update( entry );
301                 }
302             }
303             entryToChangeOrder.setPosition( nOrderToSet );
304             EntryHome.update( entryToChangeOrder );
305         }
306     }
307 
308     /**
309      * Change the attribute's order to a lower one (move up in the list).
310      * 
311      * @param nOrderToSet
312      *            the new order for the attribute
313      * @param entryToChangeOrder
314      *            the attribute which will change
315      */
316     public void moveUpEntryOrder( int nOrderToSet, Entry entryToChangeOrder )
317     {
318         EntryFilter filter = new EntryFilter( );
319         filter.setIdResource( entryToChangeOrder.getIdResource( ) );
320         filter.setResourceType( RESOURCE_TYPE );
321         filter.setFieldDependNull( EntryFilter.FILTER_TRUE );
322         if ( entryToChangeOrder.getParent( ) == null )
323         {
324             filter.setEntryParentNull( EntryFilter.FILTER_TRUE );
325             List<Integer> orderFirstLevel = new ArrayList<>( );
326             int nNbChild = 0;
327             int nNewOrder = nOrderToSet;
328             int nEntryToMoveOrder = entryToChangeOrder.getPosition( );
329             List<Entry> listEntryFirstLevel = EntryHome.findEntriesWithoutParent( entryToChangeOrder.getIdResource( ), entryToChangeOrder.getResourceType( ) );
330             // the list of all the orders in the first level
331             initOrderFirstLevel( listEntryFirstLevel, orderFirstLevel );
332             for ( Entry entry : listEntryFirstLevel )
333             {
334                 Integer entryInitialPosition = entry.getPosition( );
335                 for ( int i = 0; i < orderFirstLevel.size( ); i++ )
336                 {
337                     if ( orderFirstLevel.get( i ).equals( entryInitialPosition ) && entryInitialPosition < nEntryToMoveOrder
338                             && entryInitialPosition >= nOrderToSet )
339                     {
340                         if ( entryToChangeOrder.getPosition( ) == nEntryToMoveOrder )
341                         {
342                             entryToChangeOrder.setPosition( nNewOrder );
343                             EntryHome.update( entryToChangeOrder );
344                             for ( Entry child : entryToChangeOrder.getChildren( ) )
345                             {
346                                 nNbChild++;
347                                 child.setPosition( entryToChangeOrder.getPosition( ) + nNbChild );
348                                 EntryHome.update( child );
349                             }
350                         }
351                         nNewOrder = nNewOrder + nNbChild + 1;
352                         entry.setPosition( nNewOrder );
353                         EntryHome.update( entry );
354                         nNbChild = 0;
355                         for ( Entry child : entry.getChildren( ) )
356                         {
357                             nNbChild++;
358                             child.setPosition( nNewOrder + nNbChild );
359                             EntryHome.update( child );
360                         }
361                     }
362                 }
363             }
364         }
365         else
366         {
367             List<Entry> listAllEntry = EntryHome.getEntryList( filter );
368             for ( Entry entry : listAllEntry )
369             {
370                 if ( entry.getPosition( ) < entryToChangeOrder.getPosition( ) && entry.getPosition( ) >= nOrderToSet )
371                 {
372                     entry.setPosition( entry.getPosition( ) + 1 );
373                     EntryHome.update( entry );
374                 }
375             }
376             entryToChangeOrder.setPosition( nOrderToSet );
377             EntryHome.update( entryToChangeOrder );
378         }
379     }
380 
381     /**
382      * Init the list of the attribute's orders (first level only).
383      * 
384      * @param listEntryFirstLevel
385      *            the list of all the attributes of the first level
386      * @param orderFirstLevel
387      *            the list to set
388      */
389     private void initOrderFirstLevel( List<Entry> listEntryFirstLevel, List<Integer> orderFirstLevel )
390     {
391         for ( Entry entry : listEntryFirstLevel )
392         {
393             orderFirstLevel.add( entry.getPosition( ) );
394         }
395     }
396 
397     /**
398      * Move EntryToMove into entryGroup.
399      * 
400      * @param entryToMove
401      *            the entry which will be moved
402      * @param entryGroup
403      *            the entry group
404      */
405     public void moveEntryIntoGroup( Entry entryToMove, Entry entryGroup )
406     {
407         if ( entryToMove != null && entryGroup != null )
408         {
409             // If the entry already has a parent, we must remove it before
410             // adding it to a new one
411             if ( entryToMove.getParent( ) != null )
412             {
413                 moveOutEntryFromGroup( entryToMove );
414             }
415             int nPosition;
416             if ( entryToMove.getPosition( ) < entryGroup.getPosition( ) )
417             {
418                 nPosition = entryGroup.getPosition( );
419                 moveDownEntryOrder( nPosition, entryToMove );
420             }
421             else
422             {
423                 nPosition = entryGroup.getPosition( ) + entryGroup.getChildren( ).size( ) + 1;
424                 moveUpEntryOrder( nPosition, entryToMove );
425             }
426             entryToMove.setParent( entryGroup );
427             EntryHome.update( entryToMove );
428         }
429     }
430 
431     /**
432      * Remove an entry from a group.
433      * 
434      * @param entryToMove
435      *            the entry to remove from a group
436      */
437     public void moveOutEntryFromGroup( Entry entryToMove )
438     {
439         Entry parent = EntryHome.findByPrimaryKey( entryToMove.getParent( ).getIdEntry( ) );
440         // The new position of the entry is the position of the group plus the
441         // number of entries in the group (including this entry)
442         moveDownEntryOrder( parent.getPosition( ) + parent.getChildren( ).size( ), entryToMove );
443         entryToMove.setParent( null );
444         EntryHome.update( entryToMove );
445     }
446 
447     /**
448      * Get the list of directory entries.
449      * 
450      * @param nIdDirectory
451      *            the directory id
452      * @param bDisplayFront
453      *            true if it is displayed on FO
454      * @return the list of entries
455      */
456     public static List<Entry> getDirectoryEntryList( int nIdDirectory, boolean bDisplayFront )
457     {
458         EntryFilter filter = new EntryFilter( );
459         filter.setIdResource( nIdDirectory );
460         filter.setResourceType( RESOURCE_TYPE );
461         filter.setEntryParentNull( EntryFilter.FILTER_TRUE );
462         filter.setFieldDependNull( EntryFilter.FILTER_TRUE );
463         if ( bDisplayFront )
464         {
465             filter.setIsOnlyDisplayInBack( EntryFilter.FILTER_FALSE );
466         }
467         List<Entry> listEntry = EntryHome.getEntryList( filter );
468         getEntryFields( listEntry );
469         return listEntry;
470     }
471 
472     /**
473      * Get the list of directory entries filtered by type.
474      * 
475      * @param nIdEntryType
476      *            The Id of EntryType
477      * @param nIdDirectory
478      *            The id of Directory
479      * @return the list of entries
480      */
481     public static List<Entry> getEntryListFromType( int nIdEntryType, int nIdDirectory )
482     {
483         EntryFilter filter = new EntryFilter( );
484         filter.setIdEntryType( nIdEntryType );
485         filter.setIdResource( nIdDirectory );
486         return EntryHome.getEntryList( filter );
487     }
488 
489     /**
490      * Create or Modify entry
491      * 
492      * @param entry
493      *            The entry
494      * @param request
495      *            The Request
496      * @return The errors
497      */
498     public static String doCreateOrModifyEntry( Entry entry, HttpServletRequest request )
499     {
500         return EntryTypeServiceManager.getEntryTypeService( entry ).getRequestData( entry, request, AdminUserService.getLocale( request ) );
501     }
502 
503     /**
504      * fill entries fields
505      * 
506      * @param listEntry
507      *            The entry list to feed
508      */
509     private static void getEntryFields( List<Entry> listEntry )
510     {
511         for ( Entry entry : listEntry )
512         {
513             List<Field> listField = new ArrayList<>( );
514             for ( Field field : EntryHome.findByPrimaryKey( entry.getIdEntry( ) ).getFields( ) )
515             {
516                 field = FieldHome.findByPrimaryKey( field.getIdField( ) );
517                 listField.add( field );
518             }
519             entry.setFields( listField );
520         }
521     }
522 
523 }