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.document.service.publishing;
35  
36  import fr.paris.lutece.plugins.document.business.Document;
37  import fr.paris.lutece.plugins.document.business.DocumentFilter;
38  import fr.paris.lutece.plugins.document.business.DocumentHome;
39  import fr.paris.lutece.plugins.document.business.IndexerAction;
40  import fr.paris.lutece.plugins.document.business.publication.DocumentPublication;
41  import fr.paris.lutece.plugins.document.business.publication.DocumentPublicationHome;
42  import fr.paris.lutece.plugins.document.service.DocumentPlugin;
43  import fr.paris.lutece.plugins.document.service.search.DocumentIndexer;
44  import fr.paris.lutece.plugins.document.utils.DocumentIndexerUtils;
45  import fr.paris.lutece.plugins.document.utils.IntegerUtils;
46  import fr.paris.lutece.portal.business.portlet.Portlet;
47  import fr.paris.lutece.portal.business.portlet.PortletHome;
48  import fr.paris.lutece.portal.business.portlet.PortletType;
49  import fr.paris.lutece.portal.service.plugin.Plugin;
50  import fr.paris.lutece.portal.service.plugin.PluginService;
51  import fr.paris.lutece.portal.service.search.IndexationService;
52  import fr.paris.lutece.portal.service.spring.SpringContextService;
53  
54  import java.util.ArrayList;
55  import java.util.Collection;
56  import java.util.Date;
57  import java.util.Locale;
58  
59  
60  /**
61   * Publishing service
62   */
63  public class PublishingService
64  {
65      private static PublishingServiceervice/publishing/PublishingService.html#PublishingService">PublishingService _singleton = new PublishingService(  );
66      private static PublishingEventListenersManager _manager;
67  
68      /** Creates a new instance of PublishingService */
69      private PublishingService(  )
70      {
71          _manager = SpringContextService.getBean( "document.publishingEventListenersManager" );
72      }
73  
74      /**
75       * Get the unique instance of the service
76       * @return The unique instance
77       */
78      public static PublishingService getInstance(  )
79      {
80          return _singleton;
81      }
82  
83      /**
84       * Assign {@link Document} to a {@link Portlet}
85       *
86       * @param nDocumentId The {@link Document} identifier
87       * @param nPortletId The {@link Portlet} identifier
88       */
89      public void assign( int nDocumentId, int nPortletId )
90      {
91          DocumentPublicationlication/DocumentPublication.html#DocumentPublication">DocumentPublication documentPublication = new DocumentPublication(  );
92          documentPublication.setPortletId( nPortletId );
93          documentPublication.setDocumentId( nDocumentId );
94          documentPublication.setStatus( DocumentPublication.STATUS_UNPUBLISHED );
95  
96          //FIXME LUTECE-577 : before refactoring, status value was set to null
97          documentPublication.setDocumentOrder( DocumentPublication.DOCUMENT_ORDER_DEFAULT_VALUE );
98          documentPublication.setDatePublishing( new Date(  ) );
99          DocumentPublicationHome.create( documentPublication );
100     }
101 
102     /**
103      * Publishing documents assigned to a portlet at the begin of the list
104      *
105      * @param nDocumentId the Document id
106      * @param nPortletId the portlet identifier
107      */
108     public void publish( int nDocumentId, int nPortletId )
109     {
110         // Publishing of document : set status to Published
111         DocumentPublication documentPublication = DocumentPublicationHome.findByPrimaryKey( nPortletId, nDocumentId );
112 
113         if ( documentPublication != null )
114         {
115             documentPublication.setStatus( DocumentPublication.STATUS_PUBLISHED );
116             documentPublication.setDatePublishing( new Date(  ) );
117             documentPublication.setDocumentOrder( getInstance(  ).getMaxDocumentOrderByPortletId( nPortletId ) + 1 );
118             DocumentPublicationHome.update( documentPublication );
119 
120             PublishingEventument/service/publishing/PublishingEvent.html#PublishingEvent">PublishingEvent event = new PublishingEvent( nDocumentId, nPortletId, PublishingEvent.DOCUMENT_PUBLISHED );
121 
122             _manager.notifyListeners( event );
123 
124             getInstance(  )
125                 .changeDocumentOrder( documentPublication.getDocumentId(  ), documentPublication.getPortletId(  ), 1 );
126         }
127 
128         String strIdDocument = Integer.toString( nDocumentId );
129         IndexationService.addIndexerAction( strIdDocument, DocumentIndexer.INDEXER_NAME, IndexerAction.TASK_MODIFY,
130             nPortletId );
131 
132         DocumentIndexerUtils.addIndexerAction( strIdDocument, IndexerAction.TASK_MODIFY, nPortletId );
133     }
134 
135     /**
136      * UnPublishing documents assigned to a portlet
137      *
138      * @param nDocumentId the DocumentListPortlet identifier
139      * @param nPortletId the portlet identifier
140      */
141     public void unPublish( int nDocumentId, int nPortletId )
142     {
143         // Publishing of document : set status to Unpublished
144         DocumentPublication documentPublication = DocumentPublicationHome.findByPrimaryKey( nPortletId, nDocumentId );
145 
146         // Move the document at the end of the list
147         int nNewOrder = getInstance(  ).getMaxDocumentOrderByPortletId( nPortletId );
148         getInstance(  ).changeDocumentOrder( nDocumentId, nPortletId, nNewOrder );
149 
150         if ( documentPublication != null )
151         {
152             documentPublication.setStatus( DocumentPublication.STATUS_UNPUBLISHED );
153             //FIXME LUTECE-577 : before refactoring, documentOrder value was set to null
154             documentPublication.setDocumentOrder( DocumentPublication.DOCUMENT_ORDER_DEFAULT_VALUE );
155             DocumentPublicationHome.update( documentPublication );
156 
157             PublishingEventument/service/publishing/PublishingEvent.html#PublishingEvent">PublishingEvent event = new PublishingEvent( nDocumentId, nPortletId, PublishingEvent.DOCUMENT_UNPUBLISHED );
158             _manager.notifyListeners( event );
159         }
160 
161         String strIdDocument = Integer.toString( nDocumentId );
162         IndexationService.addIndexerAction( strIdDocument + "_" + DocumentIndexer.SHORT_NAME,
163             DocumentIndexer.INDEXER_NAME, IndexerAction.TASK_DELETE, nPortletId );
164 
165         DocumentIndexerUtils.addIndexerAction( strIdDocument, IndexerAction.TASK_DELETE, nPortletId );
166     }
167 
168     /**
169      * unAssign {@link Document} to a {@link Portlet}
170      *
171      * @param nDocumentId The {@link Document} identifier
172      * @param nPortletId The {@link Portlet} identifier
173      */
174     public void unAssign( int nDocumentId, int nPortletId )
175     {
176         DocumentPublicationHome.remove( nPortletId, nDocumentId );
177     }
178 
179     /**
180      * Change the {@link Document} order in a {@link Portlet}
181      *
182      * @param nDocumentId the {@link Document} identifier
183      * @param nPortletId the {@link Portlet} identifier
184      * @param nNewOrder The new place in the list
185      */
186     public void changeDocumentOrder( int nDocumentId, int nPortletId, int nNewOrder )
187     {
188         DocumentPublication documentPublication = DocumentPublicationHome.findByPrimaryKey( nPortletId, nDocumentId );
189 
190         if ( documentPublication == null )
191         {
192             return;
193         }
194 
195         Collection<DocumentPublication> listDocumentPublication = DocumentPublicationHome.findByPortletIdAndStatus( nPortletId,
196                 DocumentPublication.STATUS_PUBLISHED );
197 
198         if ( nNewOrder < documentPublication.getDocumentOrder(  ) )
199         {
200             for ( DocumentPublication documentPublicationToUpdate : listDocumentPublication )
201             {
202                 int nDocumentToUpdateOrder = documentPublicationToUpdate.getDocumentOrder(  );
203 
204                 if ( ( nDocumentToUpdateOrder >= nNewOrder ) &&
205                         ( nDocumentToUpdateOrder < documentPublication.getDocumentOrder(  ) ) )
206                 {
207                     documentPublicationToUpdate.setDocumentOrder( nDocumentToUpdateOrder + 1 );
208                     DocumentPublicationHome.update( documentPublicationToUpdate );
209                 }
210             }
211         }
212         else if ( nNewOrder > documentPublication.getDocumentOrder(  ) )
213         {
214             for ( DocumentPublication documentPublicationToUpdate : listDocumentPublication )
215             {
216                 int nDocumentToUpdateOrder = documentPublicationToUpdate.getDocumentOrder(  );
217 
218                 if ( ( nDocumentToUpdateOrder <= nNewOrder ) &&
219                         ( nDocumentToUpdateOrder > documentPublication.getDocumentOrder(  ) ) )
220                 {
221                     documentPublicationToUpdate.setDocumentOrder( nDocumentToUpdateOrder - 1 );
222                     DocumentPublicationHome.update( documentPublicationToUpdate );
223                 }
224             }
225         }
226 
227         documentPublication.setDocumentOrder( nNewOrder );
228         DocumentPublicationHome.update( documentPublication );
229     }
230 
231     /**
232      * Check if the specified {@link Document} is published into the specified {@link Portlet}
233      * @param nDocumentId The {@link Document} identifier
234      * @param nPortletId The {@link Portlet} identifier
235      * @return True if {@link Document} is published, false else (unpublished or not assigned)
236      */
237     public boolean isPublished( int nDocumentId, int nPortletId )
238     {
239         DocumentPublication documentPublication = DocumentPublicationHome.findByPrimaryKey( nPortletId, nDocumentId );
240 
241         return ( documentPublication != null ) &&
242         ( documentPublication.getStatus(  ) == DocumentPublication.STATUS_PUBLISHED );
243     }
244 
245     /**
246      * Check if the specified {@link Document} is published into the specified {@link Portlet}
247      * @param nDocumentId The {@link Document} identifier
248      * @return True if {@link Document} is published, false else (unpublished or not assigned)
249      */
250     public boolean isPublished( int nDocumentId )
251     {
252         Collection<DocumentPublication> listDocumentPublication = DocumentPublicationHome.findByDocumentIdAndStatus( nDocumentId,
253                 DocumentPublication.STATUS_PUBLISHED );
254 
255         return ( ( listDocumentPublication.size(  ) > 0 ) );
256     }
257 
258     /**
259      * Check if the specified {@link Document} is assigned (unpublished or published) into at least one {@link Portlet}
260      * @param nDocumentId The {@link Document} identifier
261      * @return True if {@link Document} is assigned (published or unpublished), false else (not assigned)
262      */
263     public boolean isAssigned( int nDocumentId )
264     {
265         Collection<DocumentPublication> listDocumentPublication = DocumentPublicationHome.findByDocumentId( nDocumentId );
266 
267         return ( listDocumentPublication.size(  ) > 0 );
268     }
269 
270     /**
271      * Check if the specified {@link Document} is assigned (unpublished or published) into the specified {@link Portlet}
272      * @param nDocumentId The {@link Document} identifier
273      * @param nPortletId The {@link Portlet} identifier
274      * @return True if {@link Document} is assigned (published or unpublished), false else (not assigned)
275      */
276     public boolean isAssigned( int nDocumentId, int nPortletId )
277     {
278         DocumentPublication documentPublication = DocumentPublicationHome.findByPrimaryKey( nPortletId, nDocumentId );
279 
280         return ( documentPublication != null );
281     }
282 
283     /**
284      * Return a {@link DocumentPublication} from a {@link Portlet} identifier and {@link Document} identifier
285      * @param nPortletId the {@link Portlet} identifier
286      * @param nDocumentId the {@link Document} identifier
287      * @return a {@link DocumentPublication} or null if no object match
288      */
289     public DocumentPublication getDocumentPublication( int nPortletId, int nDocumentId )
290     {
291         return DocumentPublicationHome.findByPrimaryKey( nPortletId, nDocumentId );
292     }
293 
294     /**
295      * Returns a {@link Collection} of {@link Document} objects from a {@link Portlet} identifier
296      * {@link Document} can be assigned or published.
297      * @param nPortletId the {@link Portlet} identifier
298      * @return a {@link Collection} of {@link Document} objects
299      */
300     public Collection<Document> getAssignedDocumentsByPortletId( int nPortletId )
301     {
302         Collection<DocumentPublication> listDocumentPublications = DocumentPublicationHome.findByPortletId( nPortletId );
303         Collection<Document> listDocuments = new ArrayList<Document>(  );
304 
305         for ( DocumentPublication documentPublication : listDocumentPublications )
306         {
307             //FIXME LUTECE-577 : use a single call to DocumentHome, but be careful to the list order !
308             listDocuments.add( DocumentHome.findByPrimaryKeyWithoutBinaries( documentPublication.getDocumentId(  ) ) );
309         }
310 
311         //FIXME LUTECE-577 : the list was order by document_order ASC
312         return listDocuments;
313     }
314 
315     /**
316      * Loads the list of the documents whose type is the same as the one specified in parameter
317      * Return published documents from a specified portlet
318      *
319      * @param nPortletId the portlet  identifier
320      * @return the list of the document in form of a List
321      */
322     public Collection<Document> getPublishedDocumentsByPortletId( int nPortletId )
323     {
324         Collection<DocumentPublication> listDocumentPublication = DocumentPublicationHome.findByPortletIdAndStatus( nPortletId,
325                 DocumentPublication.STATUS_PUBLISHED );
326         Collection<Document> listDocuments = new ArrayList<Document>(  );
327 
328         for ( DocumentPublication documentPublication : listDocumentPublication )
329         {
330             listDocuments.add( DocumentHome.findByPrimaryKeyWithoutBinaries( documentPublication.getDocumentId(  ) ) );
331         }
332 
333         return listDocuments;
334     }
335 
336     /**
337      * Get the first valid document published in a portlet or null if there are none
338      * @param nPortletId the portlet  identifier
339      * @return The document
340      */
341     public Document getFirstValidPublishedDocument( int nPortletId )
342     {
343         Collection<DocumentPublication> listDocumentPublication = DocumentPublicationHome.findByPortletIdAndStatus( nPortletId,
344                 DocumentPublication.STATUS_PUBLISHED );
345 
346         for ( DocumentPublication documentPublication : listDocumentPublication )
347         {
348             Document document = DocumentHome.findByPrimaryKeyWithoutBinaries( documentPublication.getDocumentId(  ) );
349 
350             if ( document.isValid(  ) )
351             {
352                 return document;
353             }
354         }
355 
356         return null;
357     }
358 
359     /**
360      * Loads the list of the documents whose filter and date publication is specified
361      * Return published documents since the publication date. The is also filtered with the documentFilter
362      *
363      * @param datePublishing The start publication date
364      * @param documentFilter The filter for the published documents. The filter can be null or empty. The array of Ids will not be taked in account.
365      * @param locale The locale is used to get the list of documents with the findByFilter method
366      * @return the list of the document in form of a List. return null if datePublishing is null
367      */
368     public Collection<Document> getPublishedDocumentsSinceDate( Date datePublishing, DocumentFilter documentFilter,
369         Locale locale )
370     {
371         if ( datePublishing == null )
372         {
373             return null;
374         }
375 
376         Collection<DocumentPublication> listDocumentPublication = DocumentPublicationHome.findSinceDatePublishingAndStatus( datePublishing,
377                 DocumentPublication.STATUS_PUBLISHED );
378 
379         if ( ( listDocumentPublication == null ) || ( listDocumentPublication.size(  ) == 0 ) )
380         {
381             return new ArrayList<Document>(  );
382         }
383 
384         int[] arrayIds = new int[listDocumentPublication.size(  )];
385         int i = 0;
386         DocumentFilter publishedDocumentFilter = documentFilter;
387 
388         if ( publishedDocumentFilter == null )
389         {
390             publishedDocumentFilter = new DocumentFilter(  );
391         }
392 
393         for ( DocumentPublication documentPublication : listDocumentPublication )
394         {
395             arrayIds[i++] = documentPublication.getDocumentId(  );
396         }
397 
398         publishedDocumentFilter.setIds( arrayIds );
399 
400         Collection<Document> listDocuments = DocumentHome.findByFilter( publishedDocumentFilter, locale );
401 
402         return listDocuments;
403     }
404 
405     /**
406      * Loads the list of the portlets whoes contain Document specified by id
407      *
408      * @param strDocumentId the document identifier
409      * @return the {@link Collection} of the portlets
410      */
411     public Collection<Portlet> getPortletsByDocumentId( String strDocumentId )
412     {
413         Collection<DocumentPublication> listDocumentPublication = DocumentPublicationHome.findByDocumentId( IntegerUtils.convert( 
414                     strDocumentId ) );
415         Collection<Portlet> listPortlets = new ArrayList<Portlet>(  );
416 
417         for ( DocumentPublication documentPublication : listDocumentPublication )
418         {
419             listPortlets.add( PortletHome.findByPrimaryKey( documentPublication.getPortletId(  ) ) );
420         }
421 
422         return listPortlets;
423     }
424 
425     /**
426      * Loads the list of portlets who contain published documents
427      *
428      * @return the {@link Collection} of the portlets
429      */
430     public Collection<Portlet> getPublishedPortlets(  )
431     {
432         Plugin plugin = PluginService.getPlugin( DocumentPlugin.PLUGIN_NAME );
433         Collection<Portlet> listPortletsAll = new ArrayList<Portlet>(  );
434         Collection<Portlet> listPortlets = new ArrayList<Portlet>(  );
435 
436         for ( PortletType portletType : plugin.getPortletTypes(  ) )
437         {
438             listPortletsAll.addAll( PortletHome.findByType( portletType.getId(  ) ) );
439         }
440 
441         for ( Portlet portlet : listPortletsAll )
442         {
443             if ( ( DocumentPublicationHome.findByPortletId( portlet.getId(  ) ).size(  ) > 0 ) &&
444                     ( portlet.getStatus(  ) == Portlet.STATUS_PUBLISHED ) )
445             {
446                 listPortlets.add( portlet );
447             }
448         }
449 
450         return listPortlets;
451     }
452 
453     /**
454      * Get the max document order from a {@link Portlet} id
455      * @param nPortletId the {@link Portlet} identifer
456      * @return The max document order
457      */
458     public int getMaxDocumentOrderByPortletId( int nPortletId )
459     {
460         return DocumentPublicationHome.findMaxDocumentOrderByPortletId( nPortletId );
461     }
462 }