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.portal.service.workflow;
35  
36  import fr.paris.lutece.plugins.workflowcore.business.action.Action;
37  import fr.paris.lutece.plugins.workflowcore.business.state.State;
38  import fr.paris.lutece.plugins.workflowcore.service.workflow.IWorkflowService;
39  import fr.paris.lutece.portal.business.user.AdminUser;
40  import fr.paris.lutece.portal.service.plugin.PluginService;
41  import fr.paris.lutece.portal.service.spring.SpringContextService;
42  import fr.paris.lutece.portal.service.util.AppException;
43  import fr.paris.lutece.portal.service.util.AppLogService;
44  import fr.paris.lutece.util.ReferenceList;
45  import fr.paris.lutece.util.sql.TransactionManager;
46  
47  import org.apache.commons.lang.StringUtils;
48  
49  import org.springframework.beans.factory.BeanDefinitionStoreException;
50  import org.springframework.beans.factory.CannotLoadBeanClassException;
51  import org.springframework.beans.factory.NoSuchBeanDefinitionException;
52  
53  import java.util.Collection;
54  import java.util.List;
55  import java.util.Locale;
56  import java.util.Map;
57  
58  import javax.servlet.http.HttpServletRequest;
59  
60  
61  /**
62   *
63   * WorkflowService
64   *
65   */
66  public final class WorkflowService
67  {
68      private static final String PLUGIN_WORKFLOW_NAME = "workflow";
69      private static final String BEAN_WORKFLOW_PROVIDER = "workflow.workflowProvider";
70      private static volatile WorkflowService _singleton;
71      private boolean _bServiceAvailable = true;
72      private IWorkflowService _service;
73      private IWorkflowProvider _provider;
74  
75      /**
76       * Private constructor
77       */
78      private WorkflowService(  )
79      {
80          try
81          {
82              _service = SpringContextService.getBean( fr.paris.lutece.plugins.workflowcore.service.workflow.WorkflowService.BEAN_SERVICE );
83              _provider = SpringContextService.getBean( BEAN_WORKFLOW_PROVIDER );
84              _bServiceAvailable = ( _service != null ) && ( _provider != null );
85          }
86          catch ( BeanDefinitionStoreException e )
87          {
88              _bServiceAvailable = false;
89          }
90          catch ( NoSuchBeanDefinitionException e )
91          {
92              _bServiceAvailable = false;
93          }
94          catch ( CannotLoadBeanClassException e )
95          {
96              _bServiceAvailable = false;
97          }
98      }
99  
100     /**
101      * Returns the unique instance of the service
102      * @return The instance of the service
103      */
104     public static WorkflowService getInstance(  )
105     {
106         if ( _singleton == null )
107         {
108             _singleton = new WorkflowService(  );
109         }
110 
111         return _singleton;
112     }
113 
114     /**
115      * Check if the workflow service is available.
116      * To be available, the following conditions must be verified :
117      * <ul>
118      * <li>the Bean service is not null</li>
119      * <li>the plugin-workflow must be enable</li>
120      * </ul>
121      * @return true if the workflow service is available
122      */
123     public boolean isAvailable(  )
124     {
125         // LUTECE-1273 : Condition ( _service != null && _provider != null ) in case the plugin-workflow is removed from a webapp  
126         return _bServiceAvailable && ( _service != null ) && ( _provider != null ) &&
127         PluginService.isPluginEnable( PLUGIN_WORKFLOW_NAME );
128     }
129 
130     /**
131      * returns a list of actions possible for a given document based on the
132      * status
133      * of the document in the workflow and the user role
134      * @param nIdResource the document id
135      * @param strResourceType the document type
136      * @param user the adminUser
137      * @param nIdWorkflow the workflow id
138      * @return a list of Action
139      */
140     public Collection<Action> getActions( int nIdResource, String strResourceType, int nIdWorkflow, AdminUser user )
141     {
142         if ( isAvailable(  ) )
143         {
144             Collection<Action> listActions = _service.getActions( nIdResource, strResourceType, nIdWorkflow );
145 
146             return _provider.getActions( listActions, user );
147         }
148 
149         return null;
150     }
151 
152     /**
153      * returns a list of actions possible for a given document based on the
154      * status
155      * of the document in the workflow and the user role
156      * @param listIdResource the list of resource id
157      * @param strResourceType the document type
158      * @param nIdExternalParentId the external parent identifier
159      * @param nIdWorkflow the workflow id
160      * @param user the adminUser
161      * @return a list of Action
162      */
163     public Map<Integer, List<Action>> getActions( List<Integer> listIdResource, String strResourceType,
164         Integer nIdExternalParentId, int nIdWorkflow, AdminUser user )
165     {
166         if ( isAvailable(  ) )
167         {
168             Map<Integer, List<Action>> mapActions = _service.getActions( listIdResource, strResourceType,
169                     nIdExternalParentId, nIdWorkflow );
170 
171             return _provider.getActions( mapActions, user );
172         }
173 
174         return null;
175     }
176 
177     /**
178      * return true if a form is associate to the action
179      *
180      * @param nIdAction the action id
181      * @param locale the loacle
182      * @return true if a form is associate to the action
183      */
184     public boolean isDisplayTasksForm( int nIdAction, Locale locale )
185     {
186         return isAvailable(  ) ? _service.isDisplayTasksForm( nIdAction, locale ) : false;
187     }
188 
189     /**
190      * Proceed action given in parameter
191      * @param nIdResource the resource id
192      * @param strResourceType the resource type
193      * @param nIdAction the action id
194      * @param nExternalParentId the external parent id
195      * @param request the request
196      * @param locale locale
197      * @param bIsAutomatic Is automatic
198      */
199     public void doProcessAction( int nIdResource, String strResourceType, int nIdAction, Integer nExternalParentId,
200         HttpServletRequest request, Locale locale, boolean bIsAutomatic )
201     {
202         if ( isAvailable(  ) &&
203                 canProcessAction( nIdResource, strResourceType, nIdAction, nExternalParentId, request, bIsAutomatic ) )
204         {
205             TransactionManager.beginTransaction( null );
206 
207             try
208             {
209                 String strUserAccessCode = bIsAutomatic ? null : _provider.getUserAccessCode( request );
210                 _service.doProcessAction( nIdResource, strResourceType, nIdAction, nExternalParentId, request, locale,
211                     bIsAutomatic, strUserAccessCode );
212                 TransactionManager.commitTransaction( null );
213             }
214             catch ( Exception e )
215             {
216                 TransactionManager.rollBack( null );
217                 throw new AppException( e.getMessage(  ), e );
218             }
219         }
220     }
221 
222     /**
223      * returns the actions history performed on a resource
224      * @param nIdResource the resource id
225      * @param strResourceType the resource type
226      * @param request the request
227      * @param nIdWorkflow the workflow id
228      * @param locale the locale
229      * @return the history of actions performed on a resource
230      */
231     public String getDisplayDocumentHistory( int nIdResource, String strResourceType, int nIdWorkflow,
232         HttpServletRequest request, Locale locale )
233     {
234         return isAvailable(  )
235         ? _provider.getDisplayDocumentHistory( nIdResource, strResourceType, nIdWorkflow, request, locale ) : null;
236     }
237 
238     /**
239      * returns the actions history performed on a resource
240      * @param nIdResource the resource id
241      * @param strResourceType the resource type
242      * @param request the request
243      * @param nIdWorkflow the workflow id
244      * @param locale the locale
245      * @param strTemplate The template
246      * @return the history of actions performed on a resource
247      */
248     @Deprecated   
249     public String getDisplayDocumentHistory( int nIdResource, String strResourceType, int nIdWorkflow,
250         HttpServletRequest request, Locale locale, String strTemplate )
251     {
252         if( ! isAvailable() )
253         {
254             return null;
255         }
256         try
257         {
258             return _provider.getDisplayDocumentHistory( nIdResource, strResourceType, nIdWorkflow, request, locale, strTemplate );
259         }
260         catch( NoSuchMethodError ex )
261         {
262             AppLogService.error( "You are using a too old Workflow provider version. Please upgrade.");
263             return _provider.getDisplayDocumentHistory( nIdResource, strResourceType, nIdWorkflow, request, locale );
264         }
265     }
266 
267     /**
268      * returns the actions history performed on a resource
269      * @param nIdResource the resource id
270      * @param strResourceType the resource type
271      * @param request the request
272      * @param nIdWorkflow the workflow id
273      * @param locale the locale
274      * @param model The model to add to the default model
275      * @param strTemplate The template
276      * @return the history of actions performed on a resource
277      */
278     public String getDisplayDocumentHistory( int nIdResource, String strResourceType, int nIdWorkflow,
279         HttpServletRequest request, Locale locale, Map<String, Object> model, String strTemplate )
280     {
281         if( ! isAvailable() )
282         {
283             return null;
284         }
285         try
286         {
287             return _provider.getDisplayDocumentHistory( nIdResource, strResourceType, nIdWorkflow, request, locale, model, strTemplate );
288         }
289         catch( NoSuchMethodError ex )
290         {
291             AppLogService.error( "You are using a too old Workflow provider version. Please upgrade.");
292             return _provider.getDisplayDocumentHistory( nIdResource, strResourceType, nIdWorkflow, request, locale );
293         }
294     }
295 
296     /**
297      * returns a xml wich contains the actions history performed on a resource
298      * @param nIdResource the resource id
299      * @param strResourceType the resource type
300      * @param request the request
301      * @param nIdWorkflow the workflow id
302      * @param locale the locale
303      * @return a xml wich contains the history of actions performed on a
304      *         resource
305      */
306     public String getDocumentHistoryXml( int nIdResource, String strResourceType, int nIdWorkflow,
307         HttpServletRequest request, Locale locale )
308     {
309         return isAvailable(  )
310         ? _provider.getDocumentHistoryXml( nIdResource, strResourceType, nIdWorkflow, request, locale ) : null;
311     }
312 
313     /**
314      * Perform the information on the various tasks associated with the given
315      * action specified in parameter
316      * @param nIdResource the resource id
317      * @param strResourceType the resource type
318      * @param nExternalParentId the external parent id
319      * @param request the request
320      * @param nIdAction the action id
321      * @param locale the locale
322      * @return null if there is no error in the task form
323      *         else return the error message url
324      */
325     public String doSaveTasksForm( int nIdResource, String strResourceType, int nIdAction, Integer nExternalParentId,
326         HttpServletRequest request, Locale locale )
327     {
328         if ( isAvailable(  ) )
329         {
330             String strError = _provider.doValidateTasksForm( nIdResource, strResourceType, nIdAction, request, locale );
331 
332             if ( StringUtils.isNotBlank( strError ) )
333             {
334                 return strError;
335             }
336 
337             doProcessAction( nIdResource, strResourceType, nIdAction, nExternalParentId, request, locale, false );
338         }
339 
340         return null;
341     }
342 
343     /**
344      * Get the list of ids of resources of a given type that are in a given
345      * state
346      * @param nIdState The id of the state of resources to get
347      * @param strResourceType The type of resources to get
348      * @return The list of resources matching both given state id and resource
349      *         given. Return an empty list if no resource was found, or if the
350      *         state does not exist.
351      */
352     public List<Integer> getResourceIdListByIdState( int nIdState, String strResourceType )
353     {
354         if ( isAvailable(  ) )
355         {
356             return _service.getResourceIdListByIdState( nIdState, strResourceType );
357         }
358 
359         return null;
360     }
361 
362     /**
363      * Remove in every workflows the resource specified in parameter
364      * @param nIdResource the resource id
365      * @param strResourceType the resource type
366      */
367     public void doRemoveWorkFlowResource( int nIdResource, String strResourceType )
368     {
369         if ( isAvailable(  ) )
370         {
371             TransactionManager.beginTransaction( null );
372 
373             try
374             {
375                 _service.doRemoveWorkFlowResource( nIdResource, strResourceType );
376                 TransactionManager.commitTransaction( null );
377             }
378             catch ( Exception e )
379             {
380                 TransactionManager.rollBack( null );
381                 throw new AppException( e.getMessage(  ), e );
382             }
383         }
384     }
385 
386     /**
387      * Remove list of resource workflow by list id
388      * @param lListIdResource list of id resource
389      * @param strResourceType the ressource type
390      * @param nIdWorflow the workflow id
391      */
392     public void doRemoveWorkFlowResourceByListId( List<Integer> lListIdResource, String strResourceType,
393         Integer nIdWorflow )
394     {
395         if ( isAvailable(  ) )
396         {
397             TransactionManager.beginTransaction( null );
398 
399             try
400             {
401                 _service.doRemoveWorkFlowResourceByListId( lListIdResource, strResourceType, nIdWorflow );
402                 TransactionManager.commitTransaction( null );
403             }
404             catch ( Exception e )
405             {
406                 TransactionManager.rollBack( null );
407                 throw new AppException( e.getMessage(  ), e );
408             }
409         }
410     }
411 
412     /**
413      * returns the tasks form
414      * @param nIdResource the document id
415      * @param strResourceType the document type
416      * @param request the request
417      * @param nIdAction the action id
418      * @param locale the locale
419      * @return the tasks form associated to the action
420      *
421      */
422     public String getDisplayTasksForm( int nIdResource, String strResourceType, int nIdAction,
423         HttpServletRequest request, Locale locale )
424     {
425         return isAvailable(  )
426         ? _provider.getDisplayTasksForm( nIdResource, strResourceType, nIdAction, request, locale ) : null;
427     }
428 
429     /**
430      * Check that a given user is allowed to view a resource depending the state
431      * of the resource
432      * @param nIdResource the document id
433      * @param strResourceType the document type
434      * @param user the AdminUser
435      * @param nIdWorkflow the workflow id
436      * @return a list of Action
437      */
438     public boolean isAuthorized( int nIdResource, String strResourceType, int nIdWorkflow, AdminUser user )
439     {
440         return isAvailable(  ) && _provider.isAuthorized( nIdResource, strResourceType, nIdWorkflow, user );
441     }
442 
443     /**
444      * Get all authorized resource Id
445      * @param strResourceType the resource type
446      * @param nIdWorkflow the workflow id
447      * @param nIdWorkflowState The workflow state id or -1 for all workflow
448      *            states
449      * @param nExternalParentId The external parent id
450      * @param user the AdminUser
451      * @return a list resource id
452      */
453     public List<Integer> getAuthorizedResourceList( String strResourceType, int nIdWorkflow, int nIdWorkflowState,
454         Integer nExternalParentId, AdminUser user )
455     {
456         return isAvailable(  )
457         ? _provider.getAuthorizedResourceList( strResourceType, nIdWorkflow, nIdWorkflowState, nExternalParentId, user )
458         : null;
459     }
460 
461     /**
462      * Get all authorized resource Id by list of state
463      * @param strResourceType the resource type
464      * @param nIdWorkflow the workflow id
465      * @param lListIdWorkflowState The workflow state <b>id or null</b> for all
466      *            workflow states
467      * @param nExternalParentId the externbal parent identifier
468      * @param user the AdminUser
469      * @return a list resource id
470      */
471     public List<Integer> getAuthorizedResourceList( String strResourceType, int nIdWorkflow,
472         List<Integer> lListIdWorkflowState, Integer nExternalParentId, AdminUser user )
473     {
474         return isAvailable(  )
475         ? _provider.getAuthorizedResourceList( strResourceType, nIdWorkflow, lListIdWorkflowState, nExternalParentId,
476             user ) : null;
477     }
478 
479     /**
480      * return a reference list which contains a list enabled workflow
481      * @param user the AdminUser
482      * @param locale the locale
483      * @return a reference list which contains a list enabled workflow
484      */
485     public ReferenceList getWorkflowsEnabled( AdminUser user, Locale locale )
486     {
487         return isAvailable(  ) ? _provider.getWorkflowsEnabled( user, locale ) : null;
488     }
489 
490     /**
491      * returns all state of a given workflow
492      * @param user the adminUser
493      * @param nIdWorkflow the workflow id
494      * @return the state of a given document
495      */
496     public Collection<State> getAllStateByWorkflow( int nIdWorkflow, AdminUser user )
497     {
498         if ( isAvailable(  ) )
499         {
500             Collection<State> listStates = _service.getAllStateByWorkflow( nIdWorkflow );
501 
502             return _provider.getAllStateByWorkflow( listStates, user );
503         }
504 
505         return null;
506     }
507 
508     /**
509      * returns the state of a given document
510      * of the document in the workflow and the user role
511      * @param nIdResource the document id
512      * @param strResourceType the document type
513      * @param nIdWorkflow the workflow id
514      * @param nIdExternalParentId the external parent id
515      * @return the state of a given document
516      */
517     public State getState( int nIdResource, String strResourceType, int nIdWorkflow, Integer nIdExternalParentId )
518     {
519         if ( isAvailable(  ) )
520         {
521             State state = null;
522             TransactionManager.beginTransaction( null );
523 
524             try
525             {
526                 state = _service.getState( nIdResource, strResourceType, nIdWorkflow, nIdExternalParentId );
527                 TransactionManager.commitTransaction( null );
528             }
529             catch ( Exception e )
530             {
531                 TransactionManager.rollBack( null );
532                 throw new AppException( e.getMessage(  ), e );
533             }
534 
535             return state;
536         }
537 
538         return null;
539     }
540 
541     /**
542      * Execute action automatic
543      * @param nIdResource the document id
544      * @param strResourceType the document type
545      * @param nIdWorkflow the workflow id
546      * @param nExternalParentId the external parent id
547      */
548     public void executeActionAutomatic( int nIdResource, String strResourceType, int nIdWorkflow,
549         Integer nExternalParentId )
550     {
551         if ( isAvailable(  ) )
552         {
553             TransactionManager.beginTransaction( null );
554 
555             try
556             {
557                 _service.executeActionAutomatic( nIdResource, strResourceType, nIdWorkflow, nExternalParentId );
558                 TransactionManager.commitTransaction( null );
559             }
560             catch ( Exception e )
561             {
562                 TransactionManager.rollBack( null );
563                 throw new AppException( e.getMessage(  ), e );
564             }
565         }
566     }
567 
568     /**
569      * Get the list of mass actions from a given id workflow
570      * @param nIdWorkflow the id workflow
571      * @return the list of mass actions
572      */
573     public List<Action> getMassActions( int nIdWorkflow )
574     {
575         return isAvailable(  ) ? _service.getMassActions( nIdWorkflow ) : null;
576     }
577 
578     /**
579      * Check if the action can be proceed for the given resource
580      * @param nIdResource the id resource
581      * @param strResourceType the resource type
582      * @param nIdAction the id action
583      * @param nExternalParentId the external parent id
584      * @param request the HTTP request
585      * @param bIsAutomatic is automatic action
586      * @return true if the action can proceed, false otherwise
587      */
588     public boolean canProcessAction( int nIdResource, String strResourceType, int nIdAction, Integer nExternalParentId,
589         HttpServletRequest request, boolean bIsAutomatic )
590     {
591         if ( isAvailable(  ) )
592         {
593             if ( _service.canProcessAction( nIdResource, strResourceType, nIdAction, nExternalParentId ) )
594             {
595                 if ( bIsAutomatic )
596                 {
597                     return true;
598                 }
599 
600                 return _provider.canProcessAction( nIdAction, request );
601             }
602         }
603 
604         return false;
605     }
606 
607     /**
608      * Proceed automatic reflexive actions of state given in parameter. This
609      * method should be called anytime a service changed the state of a resource
610      * without proceeding a workflow action
611      * @param nIdResource the resource id
612      * @param strResourceType the resource type
613      * @param nIdState the state of the resource id
614      * @param nIdExternalParent the external parent id*
615      * @param locale locale
616      */
617     public void doProcessAutomaticReflexiveActions( int nIdResource, String strResourceType, int nIdState,
618         Integer nIdExternalParent, Locale locale )
619     {
620         if ( isAvailable(  ) )
621         {
622             TransactionManager.beginTransaction( null );
623 
624             try
625             {
626                 _service.doProcessAutomaticReflexiveActions( nIdResource, strResourceType, nIdState, nIdExternalParent,
627                     locale );
628                 TransactionManager.commitTransaction( null );
629             }
630             catch ( Exception e )
631             {
632                 TransactionManager.rollBack( null );
633                 throw new AppException( e.getMessage(  ), e );
634             }
635         }
636     }
637 }