View Javadoc
1   /*
2    * Copyright (c) 2002-2025, 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.notificationstore.business;
35  
36  import fr.paris.lutece.plugins.grubusiness.business.demand.Demand;
37  import fr.paris.lutece.plugins.grubusiness.business.demand.TemporaryStatus;
38  import fr.paris.lutece.plugins.grubusiness.business.notification.EnumNotificationType;
39  import fr.paris.lutece.plugins.grubusiness.business.notification.Notification;
40  import fr.paris.lutece.plugins.grubusiness.business.web.rs.EnumGenericStatus;
41  import fr.paris.lutece.plugins.notificationstore.service.NotificationStorePlugin;
42  import fr.paris.lutece.plugins.notificationstore.service.TemporaryStatusService;
43  import fr.paris.lutece.plugins.notificationstore.utils.NotificationStoreConstants;
44  import fr.paris.lutece.plugins.notificationstore.utils.NotificationStoreUtils;
45  import fr.paris.lutece.portal.business.file.File;
46  import fr.paris.lutece.portal.business.physicalfile.PhysicalFile;
47  import fr.paris.lutece.portal.service.file.FileService;
48  import fr.paris.lutece.portal.service.file.FileServiceException;
49  import fr.paris.lutece.portal.service.plugin.Plugin;
50  import fr.paris.lutece.portal.service.spring.SpringContextService;
51  import fr.paris.lutece.portal.service.util.AppLogService;
52  import fr.paris.lutece.portal.service.util.AppPropertiesService;
53  import fr.paris.lutece.util.string.StringUtil;
54  
55  import java.io.IOException;
56  import java.nio.charset.StandardCharsets;
57  import java.util.ArrayList;
58  import java.util.Date;
59  import java.util.List;
60  import java.util.Optional;
61  
62  import javax.ws.rs.core.MediaType;
63  
64  import org.apache.commons.collections.CollectionUtils;
65  import org.apache.commons.lang3.StringUtils;
66  
67  import com.fasterxml.jackson.core.JsonProcessingException;
68  import com.fasterxml.jackson.databind.ObjectMapper;
69  
70  /**
71   * This class provides instances management methods (create, find, ...) for NotificationContent objects
72   */
73  
74  public final class NotificationContentHome
75  {
76  
77      // Static variable pointed at the DAO instance
78  
79      private static INotificationContentDAO../fr/paris/lutece/plugins/notificationstore/business/INotificationContentDAO.html#INotificationContentDAO">INotificationContentDAO _dao = (INotificationContentDAO) SpringContextService.getBean( "notificationstore.notificationContentDao" );
80  
81      /**
82       * Private constructor - this class need not be instantiated
83       */
84  
85      private NotificationContentHome( )
86      {
87      }
88  
89      /**
90       * Create an instance of the notificationContent class
91       * 
92       * @param notificationContent
93       *            The instance of the NotificationContent which contains the informations to store
94       * @param plugin
95       *            the Plugin
96       * @return The instance of notificationContent which has been created with its primary key.
97       */
98  
99      public static NotificationContent/../../fr/paris/lutece/plugins/notificationstore/business/NotificationContent.html#NotificationContent">NotificationContent create( NotificationContent notificationContent )
100     {
101         _dao.insert( notificationContent, NotificationStorePlugin.getPlugin( ) );
102 
103         return notificationContent;
104     }
105 
106     /**
107      * Create an instance of the notificationContent class
108      * 
109      * @param notificationContent
110      *            The instance of the NotificationContent which contains the informations to store
111      * @param plugin
112      *            the Plugin
113      * @return The instance of notificationContent which has been created with its primary key.
114      */
115 
116     public static List<NotificationContent> create( Notification notification )
117     {
118         List<NotificationContent> listNotificationContent = getListNotificationContent( notification );
119         for ( NotificationContent content : listNotificationContent )
120         {
121             _dao.insert( content, NotificationStorePlugin.getPlugin( ) );
122         }
123 
124         return listNotificationContent;
125     }
126 
127     /**
128      * Update of the notificationContent which is specified in parameter
129      * 
130      * @param notificationContent
131      *            The instance of the NotificationContent which contains the data to store
132      * @param plugin
133      *            the Plugin
134      * @return The instance of the notificationContent which has been updated
135      */
136 
137     public static NotificationContent/../../fr/paris/lutece/plugins/notificationstore/business/NotificationContent.html#NotificationContent">NotificationContent update( NotificationContent notificationContent )
138     {
139         _dao.store( notificationContent, NotificationStorePlugin.getPlugin( ) );
140 
141         return notificationContent;
142     }
143 
144     /**
145      * Update the record in the table
146      * 
147      * @param nNewStatusId
148      *            the new status id
149      * @param nTemporaryStatusId
150      *            This nTemporaryStatusId is allows to filter on the notifications to be updated
151      */
152 
153     public static void updateStatusId( int nNewStatusId, int nTemporaryStatusId )
154     {
155         _dao.updateStatusId( nNewStatusId, nTemporaryStatusId, NotificationStorePlugin.getPlugin( ) );
156     }
157 
158     /**
159      * Remove the notificationContent whose identifier is specified in parameter
160      * 
161      * @param nNotificationContentId
162      *            The notificationContent Id
163      * @param plugin
164      *            the Plugin
165      */
166 
167     public static void remove( int nNotificationContentId )
168     {
169         _dao.delete( nNotificationContentId, NotificationStorePlugin.getPlugin( ) );
170     }
171 
172     ///////////////////////////////////////////////////////////////////////////
173     // Finders
174 
175     /**
176      * Returns an instance of a notificationContent whose identifier is specified in parameter
177      * 
178      * @param nKey
179      *            The notificationContent primary key
180      * @param plugin
181      *            the Plugin
182      * @return an instance of NotificationContent
183      */
184 
185     public static NotificationContent findByPrimaryKey( int nKey )
186     {
187         return _dao.load( nKey, NotificationStorePlugin.getPlugin( ) );
188     }
189 
190     /**
191      * Load the data of all the notificationContent objects and returns them in form of a list
192      * 
193      * @return the list which contains the data of all the notificationContent objects
194      */
195 
196     public static List<NotificationContent> getNotificationContentsList( )
197     {
198         return _dao.selectNotificationContentsList( NotificationStorePlugin.getPlugin( ) );
199     }
200 
201     /**
202      * Load the data by id notification and returns them in form of a list
203      * 
204      * @param nIdNotification
205      *            the id notification
206      * @return the list which contains the data by id notification
207      */
208 
209     public static List<NotificationContent> getNotificationContentsByIdNotification( int nIdNotification )
210     {
211         return _dao.selectNotificationContentsByIdNotification( nIdNotification, NotificationStorePlugin.getPlugin( ) );
212     }
213 
214     /**
215      * Load the data by id notification and notification type
216      * 
217      * @param nIdNotification
218      *            the id notification
219      * @return the list which contains the data by id notification
220      */
221 
222     public static List<NotificationContent> getNotificationContentsByIdAndTypeNotification( int nIdNotification,
223             List<EnumNotificationType> listNotificationType )
224     {
225         return _dao.selectNotificationContentsByIdAndTypeNotification( nIdNotification, listNotificationType, NotificationStorePlugin.getPlugin( ) );
226     }
227 
228     private static List<NotificationContent> getListNotificationContent( Notification notification )
229     {
230         List<NotificationContent> listNotificationContent = new ArrayList<>( );
231 
232         try
233         {
234             ObjectMapper mapperr = NotificationStoreUtils.getMapper( );
235             Demand demand = notification.getDemand( );
236 
237             if ( notification.getSmsNotification( ) != null )
238             {
239                 listNotificationContent.add(
240                         initNotificationContent( notification, EnumNotificationType.SMS, mapperr.writeValueAsString( notification.getSmsNotification( ) ) ) );
241             }
242 
243             if ( notification.getBackofficeNotification( ) != null )
244             {
245                 listNotificationContent.add( initNotificationContent( notification, EnumNotificationType.BACKOFFICE,
246                         mapperr.writeValueAsString( notification.getBackofficeNotification( ) ) ) );
247             }
248 
249             if ( CollectionUtils.isNotEmpty( notification.getBroadcastEmail( ) ) )
250             {
251                 listNotificationContent.add( initNotificationContent( notification, EnumNotificationType.BROADCAST_EMAIL,
252                         mapperr.writeValueAsString( notification.getBroadcastEmail( ) ) ) );
253             }
254 
255             if ( notification.getMyDashboardNotification( ) != null )
256             {
257                 NotificationContent notificationContent = initNotificationContent( notification, EnumNotificationType.MYDASHBOARD,
258                         mapperr.writeValueAsString( notification.getMyDashboardNotification( ) ) );
259                 listNotificationContent.add( notificationContent );
260                 // Update demand status only for mydashboard notification
261                 demand.setStatusId( notificationContent.getStatusId( ) );
262             }
263 
264             if ( notification.getEmailNotification( ) != null )
265             {
266                 listNotificationContent.add( initNotificationContent( notification, EnumNotificationType.CUSTOMER_EMAIL,
267                         mapperr.writeValueAsString( notification.getEmailNotification( ) ) ) );
268             }
269             // Update modify date of demand
270             demand.setModifyDate( new Date( ).getTime( ) );
271             DemandHome.update( demand );
272 
273         }
274         catch( JsonProcessingException e )
275         {
276             AppLogService.error( "Error while writing JSON of notification", e );
277         }
278         catch( IOException e )
279         {
280             AppLogService.error( "Error while compressing or writing JSON of notification", e );
281         }
282 
283         return listNotificationContent;
284     }
285 
286     /**
287      * Initialization of notification content and retrieval of temporary and generic status
288      * 
289      * @param nNotificationId
290      * @param notificationType
291      * @param strNotificationContent
292      * @throws IOException
293      */
294     private static NotificationContent initNotificationContent( Notification notification, EnumNotificationType notificationType,
295             String strNotificationContent ) throws IOException
296     {
297         NotificationContentss/NotificationContent.html#NotificationContent">NotificationContent notificationContent = new NotificationContent( );
298         notificationContent.setIdNotification( notification.getId( ) );
299         notificationContent.setNotificationType( notificationType.name( ) );
300         notificationContent.setFileKey( saveContentInFileStore( notification, notificationType, strNotificationContent ) );
301         notificationContent.setFileStore( NotificationStoreConstants.FILE_STORE_PROVIDER );
302 
303         // Calculate status
304         Integer nStatusId = getStatusGenericId( notification, EnumNotificationType.MYDASHBOARD );
305         notificationContent.setStatusId( nStatusId );
306         notificationContent.setIdTemporaryStatus( -1 );
307 
308         // If no generic status found.
309         if ( nStatusId == -1 )
310         {
311             notificationContent.setIdTemporaryStatus( getTemporaryStatusId( notification, EnumNotificationType.MYDASHBOARD ) );
312         }
313 
314         return notificationContent;
315     }
316 
317     /**
318      * Save notification content in file store
319      * 
320      * @param notification
321      * @param notificationType
322      * @param strNotificationContent
323      * @return file id
324      * @throws IOException
325      */
326     private static String saveContentInFileStore( Notification notification, EnumNotificationType notificationType, String strNotificationContent )
327             throws IOException
328     {
329         strNotificationContent = strNotificationContent.replaceAll( NotificationStoreConstants.CHARECTER_REGEXP_FILTER, "" );
330 
331         // Convert notification content to bytes
332         byte [ ] bytes;
333 
334         if ( AppPropertiesService.getPropertyBoolean( NotificationStoreConstants.PROPERTY_COMPRESS_NOTIFICATION, false ) )
335         {
336             bytes = StringUtil.compress( strNotificationContent );
337         }
338         else
339         {
340             bytes = strNotificationContent.getBytes( StandardCharsets.UTF_8 );
341         }
342 
343         // Create file
344         File file = new File( );
345         file.setTitle(
346                 notification.getDemand( ).getId( ) + "_" + notificationType.name( ) + "_" + notification.getDemand( ).getCustomer( ).getConnectionId( ) );
347         file.setSize( bytes.length );
348         file.setMimeType( MediaType.APPLICATION_JSON );
349 
350         PhysicalFile physiqueFile = new PhysicalFile( );
351         physiqueFile.setValue( bytes );
352 
353         file.setPhysicalFile( physiqueFile );
354 
355         try
356         {
357             // Save file
358             return FileService.getInstance( ).getFileStoreServiceProvider( NotificationStoreConstants.FILE_STORE_PROVIDER ).storeFile( file );
359 
360         }
361         catch( FileServiceException e )
362         {
363             AppLogService.error( "An error occurred while saving the notification content, demand_id {}", notification.getDemand( ).getId( ), e.getMessage( ) );
364         }
365         return StringUtils.EMPTY;
366     }
367 
368     /**
369      * Get status for mydashboard notification
370      * 
371      * @param notification
372      */
373     private static Integer getStatusGenericId( Notification notification, EnumNotificationType statusType )
374     {
375         if ( EnumNotificationType.MYDASHBOARD.equals( statusType ) && notification.getMyDashboardNotification( ) != null )
376         {
377             if ( EnumGenericStatus.exists( notification.getMyDashboardNotification( ).getStatusId( ) ) )
378             {
379                 return notification.getMyDashboardNotification( ).getStatusId( );
380             }
381             else
382             {
383                 Optional<TemporaryStatus> status = TemporaryStatusService.getInstance( )
384                         .findByStatus( notification.getMyDashboardNotification( ).getStatusText( ) );
385                 if ( status.isPresent( ) && status.get( ).getGenericStatus( ) != null )
386                 {
387                     return status.get( ).getGenericStatus( ).getStatusId( );
388                 }
389                 return -1;
390             }
391         }
392 
393         return -1;
394     }
395 
396     /**
397      * Returns the id of the temporary status if it exists, otherwise we create it
398      * 
399      * @param notification
400      * @param statusType
401      * @return temporary status id
402      */
403     private static Integer getTemporaryStatusId( Notification notification, EnumNotificationType statusType )
404     {
405         if ( EnumNotificationType.MYDASHBOARD.equals( statusType ) && notification.getMyDashboardNotification( ) != null )
406         {
407             Optional<TemporaryStatus> status = TemporaryStatusService.getInstance( )
408                     .findByStatus( notification.getMyDashboardNotification( ).getStatusText( ) );
409 
410             if ( status.isPresent( ) )
411             {
412                 return status.get( ).getId( );
413             }
414             else
415             {
416                 // Create temporary status if not exist
417                 TemporaryStatus newStatus = new TemporaryStatus( );
418                 newStatus.setStatus( notification.getMyDashboardNotification( ).getStatusText( ) );
419 
420                 newStatus = TemporaryStatusService.getInstance( ).create( newStatus );
421 
422                 return newStatus.getId( );
423             }
424         }
425         return -1;
426     }
427 
428 }