View Javadoc
1   /*
2    * Copyright (c) 2002-2017, 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.directory.web.action;
35  
36  import fr.paris.lutece.plugins.directory.business.Directory;
37  import fr.paris.lutece.plugins.directory.business.IEntry;
38  import fr.paris.lutece.plugins.directory.business.Record;
39  import fr.paris.lutece.plugins.directory.service.record.IRecordService;
40  import fr.paris.lutece.plugins.directory.service.record.RecordService;
41  import fr.paris.lutece.plugins.directory.utils.DirectoryUtils;
42  import fr.paris.lutece.plugins.workflowcore.business.state.State;
43  import fr.paris.lutece.plugins.workflowcore.service.action.ActionService;
44  import fr.paris.lutece.plugins.workflowcore.service.action.IActionService;
45  import fr.paris.lutece.portal.business.user.AdminUser;
46  import fr.paris.lutece.portal.service.i18n.I18nService;
47  import fr.paris.lutece.portal.service.plugin.Plugin;
48  import fr.paris.lutece.portal.service.spring.SpringContextService;
49  import fr.paris.lutece.portal.service.util.AppLogService;
50  import fr.paris.lutece.portal.service.workflow.WorkflowService;
51  
52  import org.apache.commons.lang.StringUtils;
53  
54  import java.util.ArrayList;
55  import java.util.Collection;
56  import java.util.HashMap;
57  import java.util.List;
58  import java.util.Locale;
59  import java.util.Map;
60  
61  import javax.servlet.http.HttpServletRequest;
62  
63  /**
64   *
65   * DirectoryActionResult
66   *
67   */
68  public class DirectoryActionResult
69  {
70      // MARKS
71      private static final String MARK_RECORD = "record";
72      private static final String MARK_WORKFLOW_STATE = "workflow_state";
73      private static final String MARK_MAP_ID_ENTRY_LIST_RECORD_FIELD = "map_id_entry_list_record_field";
74      private static final String MARK_LIST_SUCCESS_RECORDS = "list_success_records";
75      private static final String MARK_LIST_FAIL_RECORDS = "list_fail_records";
76      private static final String MARK_MAP_FAIL_RECORD_CAUSES = "map_fail_record_causes";
77  
78      // VARIABLES
79      private List<Integer> _listIdsSuccessRecord;
80      private Map<String, String> _mapFailRecords;
81  
82      /**
83       * Do process the workflow action
84       * 
85       * @param nIdDirectory
86       *            the id directory
87       * @param nIdAction
88       *            the id action
89       * @param listIdsDirectoryRecord
90       *            the list of ids record to execute the action
91       * @param plugin
92       *            the plugin
93       * @param locale
94       *            the locale
95       * @param request
96       *            the HTTP request
97       */
98      public void doProcessAction( int nIdDirectory, int nIdAction, String [ ] listIdsDirectoryRecord, Plugin plugin, Locale locale, HttpServletRequest request )
99      {
100         _listIdsSuccessRecord = new ArrayList<Integer>( );
101         _mapFailRecords = new HashMap<String, String>( );
102 
103         for ( String strIdDirectoryRecord : listIdsDirectoryRecord )
104         {
105             int nIdRecord = DirectoryUtils.convertStringToInt( strIdDirectoryRecord );
106 
107             // Get the id action to execute : it may not be the one given in the parameter, but one
108             // of the linked actions
109             int nIdActionToExecute = getIdActionToExecute( nIdDirectory, nIdAction, nIdRecord, request );
110 
111             // If nIdActionToExecute == -1, then there are no actions that can be executed to the record
112             if ( nIdActionToExecute != DirectoryUtils.CONSTANT_ID_NULL )
113             {
114                 IRecordService recordService = SpringContextService.getBean( RecordService.BEAN_SERVICE );
115                 boolean bHasSucceed = false;
116 
117                 try
118                 {
119                     WorkflowService.getInstance( ).doProcessAction( nIdRecord, Record.WORKFLOW_RESOURCE_TYPE, nIdActionToExecute, nIdDirectory, request,
120                             locale, false );
121                     bHasSucceed = true;
122                 }
123                 catch( Exception e )
124                 {
125                     AppLogService.error( "Error processing action for id record '" + nIdRecord + "' - cause : " + e.getMessage( ), e );
126                     _mapFailRecords.put( strIdDirectoryRecord, e.getMessage( ) );
127                 }
128 
129                 if ( bHasSucceed )
130                 {
131                     _listIdsSuccessRecord.add( nIdRecord );
132 
133                     // Update record modification date
134                     Record record = recordService.findByPrimaryKey( nIdRecord, plugin );
135                     recordService.update( record, plugin );
136                 }
137             }
138             else
139             {
140                 String strMessage = I18nService.getLocalizedString( DirectoryUtils.MESSAGE_RECORD_INVALID_STATE, locale );
141                 _mapFailRecords.put( strIdDirectoryRecord, strMessage );
142             }
143         }
144     }
145 
146     /**
147      * Do save the task form
148      * 
149      * @param nIdDirectory
150      *            the id directory
151      * @param nIdAction
152      *            the id action
153      * @param listIdsDirectoryRecord
154      *            the list of id records
155      * @param plugin
156      *            the plugin
157      * @param locale
158      *            the locale
159      * @param request
160      *            the HTTP request
161      * @return an error message if there is an error, null otherwise
162      */
163     public String doSaveTaskForm( int nIdDirectory, int nIdAction, String [ ] listIdsDirectoryRecord, Plugin plugin, Locale locale, HttpServletRequest request )
164     {
165         _listIdsSuccessRecord = new ArrayList<Integer>( );
166         _mapFailRecords = new HashMap<String, String>( );
167 
168         for ( String strIdDirectoryRecord : listIdsDirectoryRecord )
169         {
170             int nIdRecord = DirectoryUtils.convertStringToInt( strIdDirectoryRecord );
171 
172             if ( WorkflowService.getInstance( ).canProcessAction( nIdRecord, Record.WORKFLOW_RESOURCE_TYPE, nIdAction, nIdDirectory, request, false ) )
173             {
174                 boolean bHasSucceed = false;
175 
176                 try
177                 {
178                     String strError = WorkflowService.getInstance( ).doSaveTasksForm( nIdRecord, Record.WORKFLOW_RESOURCE_TYPE, nIdAction, nIdDirectory,
179                             request, locale );
180 
181                     if ( strError != null )
182                     {
183                         return strError;
184                     }
185 
186                     bHasSucceed = true;
187                 }
188                 catch( Exception e )
189                 {
190                     String strExceptionError = buildErrorMessage( e );
191                     AppLogService.error( "Error processing action for id record '" + nIdRecord + "' - cause : " + strExceptionError, e );
192                     _mapFailRecords.put( strIdDirectoryRecord, strExceptionError );
193                 }
194 
195                 if ( bHasSucceed )
196                 {
197                     _listIdsSuccessRecord.add( nIdRecord );
198 
199                     IRecordService recordService = SpringContextService.getBean( RecordService.BEAN_SERVICE );
200 
201                     // Update record modification date
202                     Record record = recordService.findByPrimaryKey( nIdRecord, plugin );
203                     recordService.update( record, plugin );
204                 }
205             }
206             else
207             {
208                 String strMessage = I18nService.getLocalizedString( DirectoryUtils.MESSAGE_RECORD_INVALID_STATE, locale );
209                 _mapFailRecords.put( strIdDirectoryRecord, strMessage );
210             }
211         }
212 
213         return null;
214     }
215 
216     /**
217      * Fill the model with the success and fail records
218      * 
219      * @param model
220      *            the model to fill
221      * @param listEntries
222      *            the list of entries
223      * @param plugin
224      *            the plugin
225      * @param user
226      *            the current user
227      * @param directory
228      *            the directory
229      */
230     public void fillModel( Map<String, Object> model, List<IEntry> listEntries, Plugin plugin, AdminUser user, Directory directory )
231     {
232         IRecordService recordService = SpringContextService.getBean( RecordService.BEAN_SERVICE );
233 
234         // Add the success records to the model
235         if ( ( _listIdsSuccessRecord != null ) && !_listIdsSuccessRecord.isEmpty( ) )
236         {
237             List<Record> listRecords = recordService.loadListByListId( _listIdsSuccessRecord, plugin );
238             List<Map<String, Object>> listMapRecords = new ArrayList<Map<String, Object>>( _listIdsSuccessRecord.size( ) );
239 
240             for ( Record record : listRecords )
241             {
242                 Map<String, Object> mapRecord = new HashMap<String, Object>( );
243                 mapRecord.put( MARK_RECORD, record );
244                 mapRecord.put( MARK_MAP_ID_ENTRY_LIST_RECORD_FIELD,
245                         DirectoryUtils.getMapIdEntryListRecordField( listEntries, record.getIdRecord( ), plugin, false ) );
246 
247                 WorkflowService workflowService = WorkflowService.getInstance( );
248                 State state = workflowService.getState( record.getIdRecord( ), Record.WORKFLOW_RESOURCE_TYPE, directory.getIdWorkflow( ),
249                         Integer.valueOf( directory.getIdDirectory( ) ) );
250                 mapRecord.put( MARK_WORKFLOW_STATE, state );
251                 listMapRecords.add( mapRecord );
252             }
253 
254             model.put( MARK_LIST_SUCCESS_RECORDS, listMapRecords );
255         }
256 
257         // Add the fail records to the model
258         if ( ( _mapFailRecords != null ) && !_mapFailRecords.isEmpty( ) )
259         {
260             List<Integer> listIdsFailRecord = new ArrayList<Integer>( );
261 
262             for ( String strIdRecord : _mapFailRecords.keySet( ) )
263             {
264                 listIdsFailRecord.add( DirectoryUtils.convertStringToInt( strIdRecord ) );
265             }
266 
267             List<Record> listRecords = recordService.loadListByListId( listIdsFailRecord, plugin );
268             List<Map<String, Object>> listMapRecords = new ArrayList<Map<String, Object>>( listIdsFailRecord.size( ) );
269 
270             for ( Record record : listRecords )
271             {
272                 Map<String, Object> mapRecord = new HashMap<String, Object>( );
273                 mapRecord.put( MARK_RECORD, record );
274                 mapRecord.put( MARK_MAP_ID_ENTRY_LIST_RECORD_FIELD,
275                         DirectoryUtils.getMapIdEntryListRecordField( listEntries, record.getIdRecord( ), plugin, false ) );
276 
277                 WorkflowService workflowService = WorkflowService.getInstance( );
278                 State state = workflowService.getState( record.getIdRecord( ), Record.WORKFLOW_RESOURCE_TYPE, directory.getIdWorkflow( ),
279                         Integer.valueOf( directory.getIdDirectory( ) ) );
280                 mapRecord.put( MARK_WORKFLOW_STATE, state );
281                 listMapRecords.add( mapRecord );
282             }
283 
284             model.put( MARK_LIST_FAIL_RECORDS, listMapRecords );
285         }
286 
287         model.put( MARK_MAP_FAIL_RECORD_CAUSES, _mapFailRecords );
288     }
289 
290     /**
291      * Build the error message for action results
292      * 
293      * @param e
294      *            the exception
295      * @return the error message
296      */
297     private String buildErrorMessage( Exception e )
298     {
299         String strError = e.getMessage( );
300 
301         if ( StringUtils.isBlank( strError ) && ( e.getStackTrace( ) != null ) && ( e.getStackTrace( ).length > 0 ) )
302         {
303             StringBuilder sbError = new StringBuilder( );
304 
305             for ( StackTraceElement ele : e.getStackTrace( ) )
306             {
307                 sbError.append( ele.toString( ) );
308                 sbError.append( "\n" );
309             }
310 
311             strError = sbError.toString( );
312         }
313 
314         return strError;
315     }
316 
317     /**
318      * Get the ID action to execute. It may not be the one given in the parameters, but one of the linked actions of the given ID action.
319      * 
320      * @param nIdDirectory
321      *            the id directory
322      * @param nIdAction
323      *            the id action
324      * @param nIdRecord
325      *            the id record
326      * @param request
327      *            the HTTP request
328      * @return the ID action to execute
329      */
330     private int getIdActionToExecute( int nIdDirectory, int nIdAction, int nIdRecord, HttpServletRequest request )
331     {
332         if ( WorkflowService.getInstance( ).canProcessAction( nIdRecord, Record.WORKFLOW_RESOURCE_TYPE, nIdAction, nIdDirectory, request, false ) )
333         {
334             return nIdAction;
335         }
336 
337         IActionService actionService = SpringContextService.getBean( ActionService.BEAN_SERVICE );
338         Collection<Integer> listIdsLinkedAction = actionService.getListIdsLinkedAction( nIdAction );
339 
340         if ( ( listIdsLinkedAction != null ) && !listIdsLinkedAction.isEmpty( ) )
341         {
342             for ( int nIdLinkedAction : listIdsLinkedAction )
343             {
344                 if ( WorkflowService.getInstance( ).canProcessAction( nIdRecord, Record.WORKFLOW_RESOURCE_TYPE, nIdLinkedAction, nIdDirectory, request, false ) )
345                 {
346                     return nIdLinkedAction;
347                 }
348             }
349         }
350 
351         return DirectoryUtils.CONSTANT_ID_NULL;
352     }
353 }