View Javadoc
1   /*
2    * Copyright (c) 2002-2014, Mairie de Paris
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright notice
10   *     and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright notice
13   *     and the following disclaimer in the documentation and/or other materials
14   *     provided with the distribution.
15   *
16   *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17   *     contributors may be used to endorse or promote products derived from
18   *     this software without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   *
32   * License 1.0
33   */
34  package fr.paris.lutece.plugins.workflow.modules.notifydirectory.service;
35  
36  import fr.paris.lutece.plugins.directory.business.Directory;
37  import fr.paris.lutece.plugins.directory.business.DirectoryHome;
38  import fr.paris.lutece.plugins.directory.business.EntryFilter;
39  import fr.paris.lutece.plugins.directory.business.EntryHome;
40  import fr.paris.lutece.plugins.directory.business.EntryTypeGeolocation;
41  import fr.paris.lutece.plugins.directory.business.File;
42  import fr.paris.lutece.plugins.directory.business.IEntry;
43  import fr.paris.lutece.plugins.directory.business.PhysicalFileHome;
44  import fr.paris.lutece.plugins.directory.business.Record;
45  import fr.paris.lutece.plugins.directory.business.RecordField;
46  import fr.paris.lutece.plugins.directory.business.RecordFieldFilter;
47  import fr.paris.lutece.plugins.directory.business.RecordFieldHome;
48  import fr.paris.lutece.plugins.directory.service.DirectoryPlugin;
49  import fr.paris.lutece.plugins.directory.utils.DirectoryUtils;
50  import fr.paris.lutece.plugins.workflow.modules.notifydirectory.business.ResourceKey;
51  import fr.paris.lutece.plugins.workflow.modules.notifydirectory.business.TaskNotifyDirectoryConfig;
52  import fr.paris.lutece.plugins.workflow.modules.notifydirectory.utils.constants.NotifyDirectoryConstants;
53  import fr.paris.lutece.plugins.workflow.service.WorkflowPlugin;
54  import fr.paris.lutece.plugins.workflow.service.security.IWorkflowUserAttributesManager;
55  import fr.paris.lutece.plugins.workflow.service.taskinfo.ITaskInfoProvider;
56  import fr.paris.lutece.plugins.workflow.service.taskinfo.TaskInfoManager;
57  import fr.paris.lutece.plugins.workflowcore.business.action.Action;
58  import fr.paris.lutece.plugins.workflowcore.business.resource.ResourceHistory;
59  import fr.paris.lutece.plugins.workflowcore.business.state.State;
60  import fr.paris.lutece.plugins.workflowcore.business.state.StateFilter;
61  import fr.paris.lutece.plugins.workflowcore.service.action.IActionService;
62  import fr.paris.lutece.plugins.workflowcore.service.config.ITaskConfigService;
63  import fr.paris.lutece.plugins.workflowcore.service.state.IStateService;
64  import fr.paris.lutece.plugins.workflowcore.service.task.ITask;
65  import fr.paris.lutece.plugins.workflowcore.service.task.ITaskService;
66  import fr.paris.lutece.portal.business.mailinglist.Recipient;
67  import fr.paris.lutece.portal.service.admin.AdminUserService;
68  import fr.paris.lutece.portal.service.i18n.I18nService;
69  import fr.paris.lutece.portal.service.mail.MailService;
70  import fr.paris.lutece.portal.service.mailinglist.AdminMailingListService;
71  import fr.paris.lutece.portal.service.plugin.Plugin;
72  import fr.paris.lutece.portal.service.plugin.PluginService;
73  import fr.paris.lutece.portal.service.security.LuteceUser;
74  import fr.paris.lutece.portal.service.template.AppTemplateService;
75  import fr.paris.lutece.portal.service.util.AppPathService;
76  import fr.paris.lutece.portal.service.util.AppPropertiesService;
77  import fr.paris.lutece.portal.service.workflow.WorkflowService;
78  import fr.paris.lutece.util.ReferenceList;
79  import fr.paris.lutece.util.mail.FileAttachment;
80  import fr.paris.lutece.util.url.UrlItem;
81  import fr.paris.lutece.util.xml.XmlUtil;
82  
83  import org.apache.commons.lang.StringUtils;
84  
85  import java.sql.Timestamp;
86  
87  import java.util.ArrayList;
88  import java.util.Calendar;
89  import java.util.Collection;
90  import java.util.GregorianCalendar;
91  import java.util.HashMap;
92  import java.util.List;
93  import java.util.Locale;
94  import java.util.Map;
95  import java.util.UUID;
96  
97  import javax.inject.Inject;
98  import javax.inject.Named;
99  
100 import javax.servlet.http.HttpServletRequest;
101 
102 
103 /**
104  *
105  * NotifyDirectoryService
106  *
107  */
108 public final class NotifyDirectoryService implements INotifyDirectoryService
109 {
110     /** The Constant BEAN_SERVICE. */
111     public static final String BEAN_SERVICE = "workflow-notifydirectory.notifyDirectoryService";
112 
113     // SERVICES
114     @Inject
115     private IActionService _actionService;
116     @Inject
117     private IStateService _stateService;
118     @Inject
119     @Named( TaskNotifyDirectoryConfigService.BEAN_SERVICE )
120     private ITaskConfigService _taskNotifyDirectoryService;
121     @Inject
122     private IWorkflowUserAttributesManager _userAttributesManager;
123     @Inject
124     private ITaskService _taskService;
125     @Inject
126     private IResourceKeyService _resourceKeyService;
127     private List<Integer> _listAcceptedEntryTypesEmailSMS;
128     private List<Integer> _listAcceptedEntryTypesUserGuid;
129     private List<Integer> _listRefusedEntryTypes;
130     private List<Integer> _listAcceptedEntryTypesFile;
131 
132     /**
133      * Private constructor
134      */
135     private NotifyDirectoryService(  )
136     {
137         // Init list accepted entry types for email
138         _listAcceptedEntryTypesEmailSMS = fillListEntryTypes( NotifyDirectoryConstants.PROPERTY_ACCEPTED_DIRECTORY_ENTRY_TYPE_EMAIL_SMS );
139 
140         // Init list accepted entry types for user guid
141         _listAcceptedEntryTypesUserGuid = fillListEntryTypes( NotifyDirectoryConstants.PROPERTY_ACCEPTED_DIRECTORY_ENTRY_TYPE_USER_GUID );
142 
143         // Init list accepted entry types for file
144         _listAcceptedEntryTypesFile = fillListEntryTypes( NotifyDirectoryConstants.PROPERTY_ACCEPTED_DIRECTORY_ENTRY_TYPE_FILE );
145 
146         // Init list refused entry types
147         _listRefusedEntryTypes = fillListEntryTypes( NotifyDirectoryConstants.PROPERTY_REFUSED_DIRECTORY_ENTRY_TYPE_USER_GUID );
148     }
149 
150     // CHECKS
151 
152     /**
153      * {@inheritDoc}
154      */
155     @Override
156     public boolean isEntryTypeEmailSMSAccepted( int nIdEntryType )
157     {
158         boolean bIsAccepted = false;
159 
160         if ( ( _listAcceptedEntryTypesEmailSMS != null ) && !_listAcceptedEntryTypesEmailSMS.isEmpty(  ) )
161         {
162             bIsAccepted = _listAcceptedEntryTypesEmailSMS.contains( nIdEntryType );
163         }
164 
165         return bIsAccepted;
166     }
167 
168     /**
169      * {@inheritDoc}
170      */
171     @Override
172     public boolean isEntryTypeUserGuidAccepted( int nIdEntryType )
173     {
174         boolean bIsAccepted = false;
175 
176         if ( ( _listAcceptedEntryTypesUserGuid != null ) && !_listAcceptedEntryTypesUserGuid.isEmpty(  ) )
177         {
178             bIsAccepted = _listAcceptedEntryTypesUserGuid.contains( nIdEntryType );
179         }
180 
181         return bIsAccepted;
182     }
183 
184     /**
185      * {@inheritDoc}
186      */
187     @Override
188     public boolean isEntryTypeFileAccepted( int nIdEntryType )
189     {
190         boolean bIsAccepted = false;
191 
192         if ( ( _listAcceptedEntryTypesFile != null ) && !_listAcceptedEntryTypesFile.isEmpty(  ) )
193         {
194             bIsAccepted = _listAcceptedEntryTypesFile.contains( nIdEntryType );
195         }
196 
197         return bIsAccepted;
198     }
199 
200     /**
201      * {@inheritDoc}
202      */
203     @Override
204     public boolean isEntryTypeRefused( int nIdEntryType )
205     {
206         boolean bIsRefused = true;
207 
208         if ( ( _listRefusedEntryTypes != null ) && !_listRefusedEntryTypes.isEmpty(  ) )
209         {
210             bIsRefused = _listRefusedEntryTypes.contains( nIdEntryType );
211         }
212 
213         return bIsRefused;
214     }
215 
216     // GETS
217 
218     /**
219      * {@inheritDoc}
220      */
221     @Override
222     public ReferenceList getListStates( int nIdAction )
223     {
224         ReferenceList referenceListStates = new ReferenceList(  );
225         Action action = _actionService.findByPrimaryKey( nIdAction );
226 
227         if ( ( action != null ) && ( action.getWorkflow(  ) != null ) )
228         {
229             StateFilter stateFilter = new StateFilter(  );
230             stateFilter.setIdWorkflow( action.getWorkflow(  ).getId(  ) );
231 
232             List<State> listStates = _stateService.getListStateByFilter( stateFilter );
233 
234             referenceListStates.addItem( DirectoryUtils.CONSTANT_ID_NULL, StringUtils.EMPTY );
235             referenceListStates.addAll( ReferenceList.convert( listStates, NotifyDirectoryConstants.ID,
236                     NotifyDirectoryConstants.NAME, true ) );
237         }
238 
239         return referenceListStates;
240     }
241 
242     /**
243      * {@inheritDoc}
244      */
245     @Override
246     public ReferenceList getListDirectories(  )
247     {
248         Plugin pluginDirectory = PluginService.getPlugin( DirectoryPlugin.PLUGIN_NAME );
249         ReferenceList listDirectories = DirectoryHome.getDirectoryList( pluginDirectory );
250         ReferenceList refenreceListDirectories = new ReferenceList(  );
251         refenreceListDirectories.addItem( DirectoryUtils.CONSTANT_ID_NULL, StringUtils.EMPTY );
252 
253         if ( listDirectories != null )
254         {
255             refenreceListDirectories.addAll( listDirectories );
256         }
257 
258         return refenreceListDirectories;
259     }
260 
261     /**
262      * {@inheritDoc}
263      */
264     @Override
265     public ReferenceList getMailingList( HttpServletRequest request )
266     {
267         ReferenceList refMailingList = new ReferenceList(  );
268         refMailingList.addItem( DirectoryUtils.CONSTANT_ID_NULL, StringUtils.EMPTY );
269         refMailingList.addAll( AdminMailingListService.getMailingLists( AdminUserService.getAdminUser( request ) ) );
270 
271         return refMailingList;
272     }
273 
274     /**
275      * {@inheritDoc}
276      */
277     @Override
278     public List<IEntry> getListEntries( int nIdTask )
279     {
280         Plugin pluginDirectory = PluginService.getPlugin( DirectoryPlugin.PLUGIN_NAME );
281 
282         TaskNotifyDirectoryConfig config = _taskNotifyDirectoryService.findByPrimaryKey( nIdTask );
283 
284         List<IEntry> listEntries = new ArrayList<IEntry>(  );
285 
286         if ( config != null )
287         {
288             EntryFilter entryFilter = new EntryFilter(  );
289             entryFilter.setIdDirectory( config.getIdDirectory(  ) );
290 
291             listEntries = EntryHome.getEntryList( entryFilter, pluginDirectory );
292         }
293 
294         return listEntries;
295     }
296 
297     /**
298      * {@inheritDoc}
299      */
300     @Override
301     public ReferenceList getListEntriesUserGuid( int nIdTask, Locale locale )
302     {
303         ReferenceList refenreceListEntries = new ReferenceList(  );
304         refenreceListEntries.addItem( DirectoryUtils.CONSTANT_ID_NULL, DirectoryUtils.EMPTY_STRING );
305 
306         for ( IEntry entry : getListEntries( nIdTask ) )
307         {
308             int nIdEntryType = entry.getEntryType(  ).getIdType(  );
309 
310             if ( isEntryTypeUserGuidAccepted( nIdEntryType ) )
311             {
312                 refenreceListEntries.addItem( entry.getPosition(  ), buildReferenceEntryToString( entry, locale ) );
313             }
314         }
315 
316         return refenreceListEntries;
317     }
318 
319     /**
320      * {@inheritDoc}
321      */
322     @Override
323     public ReferenceList getListEntriesEmailSMS( int nIdTask, Locale locale )
324     {
325         ReferenceList refenreceListEntries = new ReferenceList(  );
326         refenreceListEntries.addItem( DirectoryUtils.CONSTANT_ID_NULL, DirectoryUtils.EMPTY_STRING );
327 
328         for ( IEntry entry : getListEntries( nIdTask ) )
329         {
330             int nIdEntryType = entry.getEntryType(  ).getIdType(  );
331 
332             if ( isEntryTypeEmailSMSAccepted( nIdEntryType ) )
333             {
334                 refenreceListEntries.addItem( entry.getPosition(  ), buildReferenceEntryToString( entry, locale ) );
335             }
336         }
337 
338         return refenreceListEntries;
339     }
340 
341     /**
342      * {@inheritDoc}
343      */
344     @Override
345     public List<IEntry> getListEntriesFreemarker( int nIdTask )
346     {
347         List<IEntry> listEntries = new ArrayList<IEntry>(  );
348 
349         for ( IEntry entry : getListEntries( nIdTask ) )
350         {
351             int nIdEntryType = entry.getEntryType(  ).getIdType(  );
352 
353             if ( !isEntryTypeRefused( nIdEntryType ) )
354             {
355                 listEntries.add( entry );
356             }
357         }
358 
359         return listEntries;
360     }
361 
362     /**
363      * {@inheritDoc}
364      */
365     @Override
366     public List<IEntry> getListEntriesFile( int nIdTask, Locale locale )
367     {
368         List<IEntry> listEntries = new ArrayList<IEntry>(  );
369 
370         for ( IEntry entry : getListEntries( nIdTask ) )
371         {
372             int nIdEntryType = entry.getEntryType(  ).getIdType(  );
373 
374             if ( isEntryTypeFileAccepted( nIdEntryType ) )
375             {
376                 listEntries.add( entry );
377             }
378         }
379 
380         return listEntries;
381     }
382 
383     /**
384      * {@inheritDoc}
385      */
386     @Override
387     public String getEmail( TaskNotifyDirectoryConfig config, int nIdRecord, int nIdDirectory )
388     {
389         String strEmail = StringUtils.EMPTY;
390 
391         if ( config.isNotifyByEmail(  ) )
392         {
393             if ( config.isNotifyByUserGuid(  ) )
394             {
395                 String strUserGuid = getRecordFieldValue( config.getPositionEntryDirectoryUserGuid(  ), nIdRecord,
396                         nIdDirectory );
397                 strEmail = _userAttributesManager.getAttribute( strUserGuid, LuteceUser.BUSINESS_INFO_ONLINE_EMAIL );
398             }
399             else
400             {
401                 strEmail = getRecordFieldValue( config.getPositionEntryDirectoryEmail(  ), nIdRecord, nIdDirectory );
402             }
403         }
404 
405         return strEmail;
406     }
407 
408     /**
409      * {@inheritDoc}
410      */
411     @Override
412     public String getSMSPhoneNumber( TaskNotifyDirectoryConfig config, int nIdRecord, int nIdDirectory )
413     {
414         String strSMSPhoneNumber = StringUtils.EMPTY;
415 
416         if ( config.isNotifyBySms(  ) )
417         {
418             strSMSPhoneNumber = getRecordFieldValue( config.getPositionEntryDirectorySms(  ), nIdRecord, nIdDirectory );
419         }
420 
421         return strSMSPhoneNumber;
422     }
423 
424     /**
425      * {@inheritDoc}
426      */
427     @Override
428     public List<FileAttachment> getFilesAttachment( TaskNotifyDirectoryConfig config, int nIdRecord, int nIdDirectory )
429     {
430         List<FileAttachment> listFileAttachment = null;
431 
432         if ( ( config.getListPositionEntryFile(  ) != null ) && ( config.getListPositionEntryFile(  ).size(  ) > 0 ) )
433         {
434             listFileAttachment = new ArrayList<FileAttachment>(  );
435 
436             for ( Integer nPositionEntryFile : config.getListPositionEntryFile(  ) )
437             {
438                 List<File> listFiles = getFiles( nPositionEntryFile, nIdRecord, nIdDirectory );
439 
440                 if ( ( listFiles != null ) && !listFiles.isEmpty(  ) )
441                 {
442                     for ( File file : listFiles )
443                     {
444                         if ( ( file != null ) && ( file.getPhysicalFile(  ) != null ) )
445                         {
446                             FileAttachment fileAttachment = new FileAttachment( file.getTitle(  ),
447                                     file.getPhysicalFile(  ).getValue(  ), file.getMimeType(  ) );
448                             listFileAttachment.add( fileAttachment );
449                         }
450                     }
451                 }
452             }
453         }
454 
455         return listFileAttachment;
456     }
457 
458     /**
459      * {@inheritDoc}
460      */
461     @Override
462     public String getUserGuid( TaskNotifyDirectoryConfig config, int nIdRecord, int nIdDirectory )
463     {
464         String strUserGuid = StringUtils.EMPTY;
465 
466         if ( config.getPositionEntryDirectoryUserGuid(  ) != DirectoryUtils.CONSTANT_ID_NULL )
467         {
468             strUserGuid = getRecordFieldValue( config.getPositionEntryDirectoryUserGuid(  ), nIdRecord, nIdDirectory );
469         }
470 
471         return strUserGuid;
472     }
473 
474     /**
475      * {@inheritDoc}
476      */
477     @Override
478     public List<ITask> getListBelowTasks( ITask task, Locale locale )
479     {
480         List<ITask> listTasks = new ArrayList<ITask>(  );
481 
482         if ( task != null )
483         {
484             for ( ITask otherTask : _taskService.getListTaskByIdAction( task.getAction(  ).getId(  ), locale ) )
485             {
486                 // FIXME : When upgrading to workflow v3.0.2, change this condition to :
487                 // if ( task.getOrder(  ) <= otherTasK.getOrder(  ) )
488                 // Indeed, in workflow v3.0.1 and inferior, the task are ordered by id task
489                 if ( task.getId(  ) == otherTask.getId(  ) )
490                 {
491                     break;
492                 }
493 
494                 for ( ITaskInfoProvider provider : TaskInfoManager.getProvidersList(  ) )
495                 {
496                     if ( otherTask.getTaskType(  ).getKey(  ).equals( provider.getTaskType(  ).getKey(  ) ) )
497                     {
498                         listTasks.add( otherTask );
499 
500                         break;
501                     }
502                 }
503             }
504         }
505 
506         return listTasks;
507     }
508 
509     // OTHERS
510 
511     /**
512      * {@inheritDoc}
513      */
514     @Override
515     public void sendMessage( TaskNotifyDirectoryConfig config, String strEmail, String strSms, String strSenderEmail,
516         String strSubject, String strEmailContent, String strSMSContent, List<FileAttachment> listFileAttachment )
517     {
518         if ( config.isNotifyByEmail(  ) && StringUtils.isNotBlank( strEmail ) )
519         {
520             // Build the mail message
521             if ( ( listFileAttachment != null ) && ( listFileAttachment.size(  ) > 0 ) )
522             {
523                 MailService.sendMailMultipartHtml( strEmail, config.getRecipientsCc(  ), config.getRecipientsBcc(  ),
524                     config.getSenderName(  ), strSenderEmail, strSubject, strEmailContent, null, listFileAttachment );
525             }
526             else
527             {
528                 MailService.sendMailHtml( strEmail, config.getRecipientsCc(  ), config.getRecipientsBcc(  ),
529                     config.getSenderName(  ), strSenderEmail, strSubject, strEmailContent );
530             }
531         }
532 
533         if ( config.isNotifyBySms(  ) && StringUtils.isNotBlank( strSms ) )
534         {
535             String strServerSms = AppPropertiesService.getProperty( NotifyDirectoryConstants.PROPERTY_SERVER_SMS );
536             MailService.sendMailHtml( strSms + strServerSms, config.getSenderName(  ), strSenderEmail, strSubject,
537                 strSMSContent );
538         }
539 
540         if ( config.isNotifyByMailingList(  ) )
541         {
542             Collection<Recipient> listRecipients = AdminMailingListService.getRecipients( config.getIdMailingList(  ) );
543 
544             // Send Mail
545             for ( Recipient recipient : listRecipients )
546             {
547                 if ( ( listFileAttachment != null ) && ( listFileAttachment.size(  ) > 0 ) )
548                 {
549                     MailService.sendMailMultipartHtml( recipient.getEmail(  ), config.getRecipientsCc(  ),
550                         config.getRecipientsBcc(  ), config.getSenderName(  ), strSenderEmail, strSubject,
551                         strEmailContent, null, listFileAttachment );
552                 }
553                 else
554                 {
555                     // Build the mail message
556                     MailService.sendMailHtml( recipient.getEmail(  ), config.getSenderName(  ), strSenderEmail,
557                         strSubject, strEmailContent );
558                 }
559             }
560         }
561 
562         // If the task is not notified by email and the recipients bcc is not an
563         // empty string, then send the bcc
564         if ( !config.isNotifyByEmail(  ) &&
565                 ( StringUtils.isNotBlank( config.getRecipientsBcc(  ) ) ||
566                 StringUtils.isNotBlank( config.getRecipientsCc(  ) ) ) )
567         {
568             if ( ( listFileAttachment != null ) && ( listFileAttachment.size(  ) > 0 ) )
569             {
570                 MailService.sendMailMultipartHtml( null, config.getRecipientsCc(  ), config.getRecipientsBcc(  ),
571                     config.getSenderName(  ), strSenderEmail, strSubject, strEmailContent, null, listFileAttachment );
572             }
573             else
574             {
575                 MailService.sendMailHtml( null, config.getRecipientsCc(  ), config.getRecipientsBcc(  ),
576                     config.getSenderName(  ), strSenderEmail, strSubject, strEmailContent );
577             }
578         }
579     }
580 
581     /**
582      * {@inheritDoc}
583      */
584     @Override
585     public Map<String, Object> fillModel( TaskNotifyDirectoryConfig config, ResourceHistory resourceHistory,
586         Record record, Directory directory, HttpServletRequest request, int nIdAction, int nIdHistory )
587     {
588         Map<String, Object> model = new HashMap<String, Object>(  );
589 
590         Locale locale = getLocale( request );
591         ITask task = _taskService.findByPrimaryKey( config.getIdTask(  ), locale );
592         Plugin pluginDirectory = PluginService.getPlugin( DirectoryPlugin.PLUGIN_NAME );
593 
594         model.put( NotifyDirectoryConstants.MARK_MESSAGE, config.getMessage(  ) );
595         model.put( NotifyDirectoryConstants.MARK_DIRECTORY_TITLE, directory.getTitle(  ) );
596         model.put( NotifyDirectoryConstants.MARK_DIRECTORY_DESCRIPTION, directory.getDescription(  ) );
597 
598         RecordFieldFilter recordFieldFilter = new RecordFieldFilter(  );
599         recordFieldFilter.setIdRecord( record.getIdRecord(  ) );
600 
601         List<RecordField> listRecordField = RecordFieldHome.getRecordFieldList( recordFieldFilter, pluginDirectory );
602 
603         for ( RecordField recordField : listRecordField )
604         {
605             String strNewValue = StringUtils.EMPTY;
606 
607             if ( isEntryTypeRefused( recordField.getEntry(  ).getEntryType(  ).getIdType(  ) ) )
608             {
609                 continue;
610             }
611             else if ( recordField.getEntry(  ) instanceof fr.paris.lutece.plugins.directory.business.EntryTypeGeolocation &&
612                     ( ( recordField.getField(  ) == null ) ||
613                     StringUtils.isBlank( recordField.getField(  ).getTitle(  ) ) ||
614                     !EntryTypeGeolocation.CONSTANT_ADDRESS.equals( recordField.getField(  ).getTitle(  ) ) ) )
615             {
616                 continue;
617             }
618             else if ( ( recordField.getField(  ) != null ) && ( recordField.getField(  ).getTitle(  ) != null ) &&
619                     !( recordField.getEntry(  ) instanceof fr.paris.lutece.plugins.directory.business.EntryTypeGeolocation ) )
620             {
621                 strNewValue = recordField.getField(  ).getTitle(  );
622             }
623             else if ( recordField.getEntry(  ) instanceof fr.paris.lutece.plugins.directory.business.EntryTypeFile &&
624                     ( recordField.getFile(  ) != null ) && ( recordField.getFile(  ).getTitle(  ) != null ) )
625             {
626                 strNewValue = recordField.getFile(  ).getTitle(  );
627             }
628             else
629             {
630                 strNewValue = recordField.getEntry(  ).convertRecordFieldValueToString( recordField, locale, false,
631                         false );
632             }
633 
634             recordField.setEntry( EntryHome.findByPrimaryKey( recordField.getEntry(  ).getIdEntry(  ), pluginDirectory ) );
635 
636             String strKey = NotifyDirectoryConstants.MARK_POSITION + recordField.getEntry(  ).getPosition(  );
637             String strOldValue = ( (String) model.get( strKey ) );
638 
639             if ( StringUtils.isNotBlank( strOldValue ) && StringUtils.isNotBlank( strNewValue ) )
640             {
641                 // Add markers for message
642                 model.put( strKey, strNewValue + NotifyDirectoryConstants.COMMA + strOldValue );
643             }
644             else if ( strNewValue != null )
645             {
646                 model.put( strKey, strNewValue );
647             }
648             else
649             {
650                 model.put( strKey, StringUtils.EMPTY );
651             }
652         }
653 
654         if ( ( directory.getIdWorkflow(  ) != DirectoryUtils.CONSTANT_ID_NULL ) &&
655                 WorkflowService.getInstance(  ).isAvailable(  ) )
656         {
657             State state = WorkflowService.getInstance(  )
658                                          .getState( record.getIdRecord(  ), Record.WORKFLOW_RESOURCE_TYPE,
659                     directory.getIdWorkflow(  ), null );
660             model.put( NotifyDirectoryConstants.MARK_STATUS, state.getName(  ) );
661         }
662 
663         // Link View record
664         String strLinkViewRecordHtml = DirectoryUtils.EMPTY_STRING;
665 
666         if ( config.isViewRecord(  ) )
667         {
668             StringBuilder sbBaseUrl = new StringBuilder( getBaseUrl( request ) );
669 
670             if ( ( sbBaseUrl.length(  ) > 0 ) && !sbBaseUrl.toString(  ).endsWith( NotifyDirectoryConstants.SLASH ) )
671             {
672                 sbBaseUrl.append( NotifyDirectoryConstants.SLASH );
673             }
674 
675             sbBaseUrl.append( NotifyDirectoryConstants.JSP_DO_VISUALISATION_RECORD );
676 
677             UrlItem url = new UrlItem( sbBaseUrl.toString(  ) );
678             url.addParameter( DirectoryUtils.PARAMETER_ID_DIRECTORY, directory.getIdDirectory(  ) );
679             url.addParameter( DirectoryUtils.PARAMETER_ID_DIRECTORY_RECORD, record.getIdRecord(  ) );
680 
681             StringBuffer sbLinkHtml = new StringBuffer(  );
682             Map<String, String> mapParams = new HashMap<String, String>(  );
683             mapParams.put( NotifyDirectoryConstants.ATTRIBUTE_HREF, url.getUrl(  ) );
684             XmlUtil.beginElement( sbLinkHtml, NotifyDirectoryConstants.TAG_A, mapParams );
685             sbLinkHtml.append( config.getLabelLinkViewRecord(  ) );
686             XmlUtil.endElement( sbLinkHtml, NotifyDirectoryConstants.TAG_A );
687 
688             Map<String, Object> modelTmp = new HashMap<String, Object>(  );
689             modelTmp.put( NotifyDirectoryConstants.MARK_LINK_VIEW_RECORD, url.getUrl(  ) );
690             strLinkViewRecordHtml = AppTemplateService.getTemplateFromStringFtl( sbLinkHtml.toString(  ), locale,
691                     modelTmp ).getHtml(  );
692         }
693 
694         model.put( NotifyDirectoryConstants.MARK_LINK_VIEW_RECORD, strLinkViewRecordHtml );
695 
696         // Generate key
697         String linkHtml = DirectoryUtils.EMPTY_STRING;
698 
699         if ( config.isEmailValidation(  ) )
700         {
701             ResourceKey resourceKey = new ResourceKey(  );
702             UUID key = java.util.UUID.randomUUID(  );
703             resourceKey.setKey( key.toString(  ) );
704             resourceKey.setIdResource( record.getIdRecord(  ) );
705             resourceKey.setResourceType( resourceHistory.getResourceType(  ) );
706             resourceKey.setIdTask( config.getIdTask(  ) );
707 
708             Calendar calendar = GregorianCalendar.getInstance(  );
709             calendar.add( Calendar.DAY_OF_MONTH, config.getPeriodValidity(  ) );
710             resourceKey.setDateExpiry( new Timestamp( calendar.getTimeInMillis(  ) ) );
711             _resourceKeyService.create( resourceKey, PluginService.getPlugin( NotifyDirectoryPlugin.PLUGIN_NAME ) );
712 
713             StringBuilder sbBaseUrl = new StringBuilder( getBaseUrl( request ) );
714 
715             if ( ( sbBaseUrl.length(  ) > 0 ) && !sbBaseUrl.toString(  ).endsWith( NotifyDirectoryConstants.SLASH ) )
716             {
717                 sbBaseUrl.append( NotifyDirectoryConstants.SLASH );
718             }
719 
720             sbBaseUrl.append( AppPathService.getPortalUrl(  ) );
721 
722             UrlItem url = new UrlItem( sbBaseUrl.toString(  ) );
723             url.addParameter( NotifyDirectoryConstants.PARAMETER_PAGE, WorkflowPlugin.PLUGIN_NAME );
724             url.addParameter( NotifyDirectoryConstants.PARAMETER_KEY, key.toString(  ) );
725 
726             StringBuffer sbLinkHtml = new StringBuffer(  );
727             Map<String, String> mapParams = new HashMap<String, String>(  );
728             mapParams.put( NotifyDirectoryConstants.ATTRIBUTE_HREF, url.getUrl(  ) );
729             XmlUtil.beginElement( sbLinkHtml, NotifyDirectoryConstants.TAG_A, mapParams );
730             sbLinkHtml.append( config.getLabelLink(  ) );
731             XmlUtil.endElement( sbLinkHtml, NotifyDirectoryConstants.TAG_A );
732 
733             linkHtml = sbLinkHtml.toString(  );
734 
735             Map<String, Object> modelTmp = new HashMap<String, Object>(  );
736             modelTmp.put( NotifyDirectoryConstants.MARK_LINK, url.getUrl(  ) );
737             linkHtml = AppTemplateService.getTemplateFromStringFtl( linkHtml, locale, modelTmp ).getHtml(  );
738         }
739 
740         model.put( NotifyDirectoryConstants.MARK_LINK, linkHtml );
741 
742         // Fill user attributes
743         String strUserGuid = getUserGuid( config, record.getIdRecord(  ), directory.getIdDirectory(  ) );
744         fillModelWithUserAttributes( model, strUserGuid );
745 
746         // Fill the model with the info of other tasks
747         for ( ITask otherTask : getListBelowTasks( task, locale ) )
748         {
749             model.put( NotifyDirectoryConstants.MARK_TASK + otherTask.getId(  ),
750                 TaskInfoManager.getTaskResourceInfo( nIdHistory, otherTask.getId(  ), request ) );
751         }
752 
753         return model;
754     }
755 
756     /**
757      * {@inheritDoc}
758      */
759     @Override
760     public Locale getLocale( HttpServletRequest request )
761     {
762         Locale locale = null;
763 
764         if ( request != null )
765         {
766             locale = request.getLocale(  );
767         }
768         else
769         {
770             locale = I18nService.getDefaultLocale(  );
771         }
772 
773         return locale;
774     }
775 
776     // PRIVATE METHODS
777 
778     /**
779      * Get the record field value
780      *
781      * @param nPosition
782      *            the position of the entry
783      * @param nIdRecord
784      *            the id record
785      * @param nIdDirectory
786      *            the id directory
787      * @return the record field value
788      */
789     private String getRecordFieldValue( int nPosition, int nIdRecord, int nIdDirectory )
790     {
791         String strRecordFieldValue = StringUtils.EMPTY;
792         Plugin pluginDirectory = PluginService.getPlugin( DirectoryPlugin.PLUGIN_NAME );
793 
794         // RecordField
795         EntryFilter entryFilter = new EntryFilter(  );
796         entryFilter.setPosition( nPosition );
797         entryFilter.setIdDirectory( nIdDirectory );
798 
799         List<IEntry> listEntries = EntryHome.getEntryList( entryFilter, pluginDirectory );
800 
801         if ( ( listEntries != null ) && !listEntries.isEmpty(  ) )
802         {
803             IEntry entry = listEntries.get( 0 );
804             RecordFieldFilter recordFieldFilterEmail = new RecordFieldFilter(  );
805             recordFieldFilterEmail.setIdDirectory( nIdDirectory );
806             recordFieldFilterEmail.setIdEntry( entry.getIdEntry(  ) );
807             recordFieldFilterEmail.setIdRecord( nIdRecord );
808 
809             List<RecordField> listRecordFields = RecordFieldHome.getRecordFieldList( recordFieldFilterEmail,
810                     pluginDirectory );
811 
812             if ( ( listRecordFields != null ) && !listRecordFields.isEmpty(  ) && ( listRecordFields.get( 0 ) != null ) )
813             {
814                 RecordField recordFieldIdDemand = listRecordFields.get( 0 );
815                 strRecordFieldValue = recordFieldIdDemand.getValue(  );
816 
817                 if ( recordFieldIdDemand.getField(  ) != null )
818                 {
819                     strRecordFieldValue = recordFieldIdDemand.getField(  ).getTitle(  );
820                 }
821             }
822         }
823 
824         return strRecordFieldValue;
825     }
826 
827     /**
828      * Get the directory files
829      *
830      * @param nPosition
831      *            the position of the entry
832      * @param nIdRecord
833      *            the id record
834      * @param nIdDirectory
835      *            the id directory
836      * @return the directory file
837      */
838     private List<File> getFiles( int nPosition, int nIdRecord, int nIdDirectory )
839     {
840         Plugin pluginDirectory = PluginService.getPlugin( DirectoryPlugin.PLUGIN_NAME );
841 
842         // RecordField
843         EntryFilter entryFilter = new EntryFilter(  );
844         entryFilter.setPosition( nPosition );
845         entryFilter.setIdDirectory( nIdDirectory );
846 
847         List<IEntry> listEntries = EntryHome.getEntryList( entryFilter, pluginDirectory );
848 
849         if ( ( listEntries != null ) && !listEntries.isEmpty(  ) )
850         {
851             IEntry entry = listEntries.get( 0 );
852             RecordFieldFilter recordFieldFilter = new RecordFieldFilter(  );
853             recordFieldFilter.setIdDirectory( nIdDirectory );
854             recordFieldFilter.setIdEntry( entry.getIdEntry(  ) );
855             recordFieldFilter.setIdRecord( nIdRecord );
856 
857             List<RecordField> listRecordFields = RecordFieldHome.getRecordFieldList( recordFieldFilter, pluginDirectory );
858 
859             if ( ( listRecordFields != null ) && !listRecordFields.isEmpty(  ) && ( listRecordFields.get( 0 ) != null ) )
860             {
861                 List<File> listFiles = new ArrayList<File>(  );
862 
863                 for ( RecordField recordField : listRecordFields )
864                 {
865                     if ( entry instanceof fr.paris.lutece.plugins.directory.business.EntryTypeFile )
866                     {
867                         File file = recordField.getFile(  );
868 
869                         if ( ( file != null ) && ( file.getPhysicalFile(  ) != null ) )
870                         {
871                             file.setPhysicalFile( PhysicalFileHome.findByPrimaryKey( 
872                                     file.getPhysicalFile(  ).getIdPhysicalFile(  ), pluginDirectory ) );
873                             listFiles.add( file );
874                         }
875                     }
876                     else if ( entry instanceof fr.paris.lutece.plugins.directory.business.EntryTypeDownloadUrl )
877                     {
878                         File file = DirectoryUtils.doDownloadFile( recordField.getValue(  ) );
879 
880                         if ( file != null )
881                         {
882                             listFiles.add( file );
883                         }
884                     }
885                 }
886 
887                 return listFiles;
888             }
889         }
890 
891         return null;
892     }
893 
894     /**
895      * Get the base url
896      *
897      * @param request
898      *            the HTTP request
899      * @return the base url
900      */
901     private String getBaseUrl( HttpServletRequest request )
902     {
903         String strBaseUrl = StringUtils.EMPTY;
904 
905         if ( request != null )
906         {
907             strBaseUrl = AppPathService.getBaseUrl( request );
908         }
909         else
910         {
911             strBaseUrl = AppPropertiesService.getProperty( NotifyDirectoryConstants.PROPERTY_LUTECE_ADMIN_PROD_URL );
912 
913             if ( StringUtils.isBlank( strBaseUrl ) )
914             {
915                 strBaseUrl = AppPropertiesService.getProperty( NotifyDirectoryConstants.PROPERTY_LUTECE_BASE_URL );
916 
917                 if ( StringUtils.isBlank( strBaseUrl ) )
918                 {
919                     strBaseUrl = AppPropertiesService.getProperty( NotifyDirectoryConstants.PROPERTY_LUTECE_PROD_URL );
920                 }
921             }
922         }
923 
924         return strBaseUrl;
925     }
926 
927     /**
928      * Fills the model with user attributes
929      *
930      * @param model
931      *            the model
932      * @param strUserGuid
933      *            the user guid
934      */
935     private void fillModelWithUserAttributes( Map<String, Object> model, String strUserGuid )
936     {
937         if ( _userAttributesManager.isEnabled(  ) && StringUtils.isNotBlank( strUserGuid ) )
938         {
939             Map<String, String> mapUserAttributes = _userAttributesManager.getAttributes( strUserGuid );
940             String strFirstName = mapUserAttributes.get( LuteceUser.NAME_GIVEN );
941             String strLastName = mapUserAttributes.get( LuteceUser.NAME_FAMILY );
942             String strEmail = mapUserAttributes.get( LuteceUser.BUSINESS_INFO_ONLINE_EMAIL );
943             String strPhoneNumber = mapUserAttributes.get( LuteceUser.BUSINESS_INFO_TELECOM_TELEPHONE_NUMBER );
944 
945             model.put( NotifyDirectoryConstants.MARK_FIRST_NAME,
946                 StringUtils.isNotEmpty( strFirstName ) ? strFirstName : StringUtils.EMPTY );
947             model.put( NotifyDirectoryConstants.MARK_LAST_NAME,
948                 StringUtils.isNotEmpty( strLastName ) ? strLastName : StringUtils.EMPTY );
949             model.put( NotifyDirectoryConstants.MARK_EMAIL,
950                 StringUtils.isNotEmpty( strEmail ) ? strEmail : StringUtils.EMPTY );
951             model.put( NotifyDirectoryConstants.MARK_PHONE_NUMBER,
952                 StringUtils.isNotEmpty( strPhoneNumber ) ? strPhoneNumber : StringUtils.EMPTY );
953         }
954     }
955 
956     /**
957      * Build the reference entry into String
958      *
959      * @param entry
960      *            the entry
961      * @param locale
962      *            the Locale
963      * @return the reference entry
964      */
965     private String buildReferenceEntryToString( IEntry entry, Locale locale )
966     {
967         StringBuilder sbReferenceEntry = new StringBuilder(  );
968         sbReferenceEntry.append( entry.getPosition(  ) );
969         sbReferenceEntry.append( NotifyDirectoryConstants.SPACE + NotifyDirectoryConstants.OPEN_BRACKET );
970         sbReferenceEntry.append( entry.getTitle(  ) );
971         sbReferenceEntry.append( NotifyDirectoryConstants.SPACE + NotifyDirectoryConstants.HYPHEN +
972             NotifyDirectoryConstants.SPACE );
973         sbReferenceEntry.append( I18nService.getLocalizedString( entry.getEntryType(  ).getTitleI18nKey(  ), locale ) );
974         sbReferenceEntry.append( NotifyDirectoryConstants.CLOSED_BRACKET );
975 
976         return sbReferenceEntry.toString(  );
977     }
978 
979     /**
980      * Fill the list of entry types
981      *
982      * @param strPropertyEntryTypes
983      *            the property containing the entry types
984      * @return a list of integer
985      */
986     private static List<Integer> fillListEntryTypes( String strPropertyEntryTypes )
987     {
988         List<Integer> listEntryTypes = new ArrayList<Integer>(  );
989         String strEntryTypes = AppPropertiesService.getProperty( strPropertyEntryTypes );
990 
991         if ( StringUtils.isNotBlank( strEntryTypes ) )
992         {
993             String[] listAcceptEntryTypesForIdDemand = strEntryTypes.split( NotifyDirectoryConstants.COMMA );
994 
995             for ( String strAcceptEntryType : listAcceptEntryTypesForIdDemand )
996             {
997                 if ( StringUtils.isNotBlank( strAcceptEntryType ) && StringUtils.isNumeric( strAcceptEntryType ) )
998                 {
999                     int nAcceptedEntryType = Integer.parseInt( strAcceptEntryType );
1000                     listEntryTypes.add( nAcceptedEntryType );
1001                 }
1002             }
1003         }
1004 
1005         return listEntryTypes;
1006     }
1007 }