KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > repo > action > ActionServiceImpl


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.repo.action;
18
19 import java.io.Serializable JavaDoc;
20 import java.util.ArrayList JavaDoc;
21 import java.util.Date JavaDoc;
22 import java.util.HashMap JavaDoc;
23 import java.util.HashSet JavaDoc;
24 import java.util.List JavaDoc;
25 import java.util.Map JavaDoc;
26 import java.util.Set JavaDoc;
27
28 import org.alfresco.model.ContentModel;
29 import org.alfresco.repo.action.evaluator.ActionConditionEvaluator;
30 import org.alfresco.repo.action.executer.ActionExecuter;
31 import org.alfresco.repo.security.authentication.AuthenticationComponent;
32 import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
33 import org.alfresco.service.cmr.action.Action;
34 import org.alfresco.service.cmr.action.ActionCondition;
35 import org.alfresco.service.cmr.action.ActionConditionDefinition;
36 import org.alfresco.service.cmr.action.ActionDefinition;
37 import org.alfresco.service.cmr.action.ActionService;
38 import org.alfresco.service.cmr.action.ActionServiceException;
39 import org.alfresco.service.cmr.action.CompositeAction;
40 import org.alfresco.service.cmr.action.ParameterizedItem;
41 import org.alfresco.service.cmr.repository.ChildAssociationRef;
42 import org.alfresco.service.cmr.repository.NodeRef;
43 import org.alfresco.service.cmr.repository.NodeService;
44 import org.alfresco.service.cmr.search.SearchService;
45 import org.alfresco.service.namespace.DynamicNamespacePrefixResolver;
46 import org.alfresco.service.namespace.NamespaceService;
47 import org.alfresco.service.namespace.QName;
48 import org.alfresco.service.namespace.RegexQNamePattern;
49 import org.alfresco.util.GUID;
50 import org.apache.commons.logging.Log;
51 import org.apache.commons.logging.LogFactory;
52 import org.springframework.beans.BeansException;
53 import org.springframework.context.ApplicationContext;
54 import org.springframework.context.ApplicationContextAware;
55
56 /**
57  * Action service implementation
58  *
59  * @author Roy Wetherall
60  */

61 public class ActionServiceImpl implements ActionService, RuntimeActionService, ApplicationContextAware
62 {
63     /**
64      * Transaction resource name
65      */

66     private static final String JavaDoc POST_TRANSACTION_PENDING_ACTIONS = "postTransactionPendingActions";
67     
68     /**
69      * Error message
70      */

71     private static final String JavaDoc ERR_FAIL = "The action failed to execute due to an error.";
72
73     /** Action assoc name */
74     private static final QName ASSOC_NAME_ACTIONS = QName.createQName(ActionModel.ACTION_MODEL_URI, "actions");
75     
76     /**
77      * The logger
78      */

79     private static Log logger = LogFactory.getLog(ActionServiceImpl.class);
80     
81     /**
82      * Thread local containing the current action chain
83      */

84     ThreadLocal JavaDoc<Set JavaDoc<String JavaDoc>> currentActionChain = new ThreadLocal JavaDoc<Set JavaDoc<String JavaDoc>>();
85     
86     /**
87      * The application context
88      */

89     private ApplicationContext applicationContext;
90
91     /**
92      * The node service
93      */

94     private NodeService nodeService;
95     
96     /**
97      * The search service
98      */

99     private SearchService searchService;
100     
101     /** The authentication component */
102     private AuthenticationComponent authenticationComponent;
103     
104     /**
105      * The asynchronous action execution queue
106      */

107     private AsynchronousActionExecutionQueue asynchronousActionExecutionQueue;
108     
109     /**
110      * Action transaction listener
111      */

112     private ActionTransactionListener transactionListener = new ActionTransactionListener(this);
113     
114     /**
115      * All the condition definitions currently registered
116      */

117     private Map JavaDoc<String JavaDoc, ActionConditionDefinition> conditionDefinitions = new HashMap JavaDoc<String JavaDoc, ActionConditionDefinition>();
118     
119     /**
120      * All the action definitions currently registered
121      */

122     private Map JavaDoc<String JavaDoc, ActionDefinition> actionDefinitions = new HashMap JavaDoc<String JavaDoc, ActionDefinition>();
123     
124     /**
125      * Set the application context
126      *
127      * @param applicationContext the application context
128      */

129     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
130     {
131         this.applicationContext = applicationContext;
132     }
133
134     /**
135      * Set the node service
136      *
137      * @param nodeService the node service
138      */

139     public void setNodeService(NodeService nodeService)
140     {
141         this.nodeService = nodeService;
142     }
143     
144     /**
145      * Set the search service
146      *
147      * @param searchService the search service
148      */

149     public void setSearchService(SearchService searchService)
150     {
151         this.searchService = searchService;
152     }
153     
154     /**
155      * Set the authentication component
156      *
157      * @param authenticationComponent the authentication component
158      */

159     public void setAuthenticationComponent(AuthenticationComponent authenticationComponent)
160     {
161         this.authenticationComponent = authenticationComponent;
162     }
163     
164     /**
165      * Set the asynchronous action execution queue
166      *
167      * @param asynchronousActionExecutionQueue the asynchronous action execution queue
168      */

169     public void setAsynchronousActionExecutionQueue(
170             AsynchronousActionExecutionQueue asynchronousActionExecutionQueue)
171     {
172         this.asynchronousActionExecutionQueue = asynchronousActionExecutionQueue;
173     }
174     
175     /**
176      * Get the asychronous action execution queue
177      *
178      * @return the asynchronous action execution queue
179      */

180     public AsynchronousActionExecutionQueue getAsynchronousActionExecutionQueue()
181     {
182         return asynchronousActionExecutionQueue;
183     }
184     
185     /**
186      * Gets the saved action folder reference
187      *
188      * @param nodeRef the node reference
189      * @return the node reference
190      */

191     private NodeRef getSavedActionFolderRef(NodeRef nodeRef)
192     {
193         List JavaDoc<ChildAssociationRef> assocs = this.nodeService.getChildAssocs(
194                 nodeRef,
195                 RegexQNamePattern.MATCH_ALL,
196                 ActionModel.ASSOC_ACTION_FOLDER);
197         if (assocs.size() != 1)
198         {
199             throw new ActionServiceException("Unable to retrieve the saved action folder reference.");
200         }
201         
202         return assocs.get(0).getChildRef();
203     }
204     
205     /**
206      * @see org.alfresco.service.cmr.action.ActionService#getActionDefinition(java.lang.String)
207      */

208     public ActionDefinition getActionDefinition(String JavaDoc name)
209     {
210         return this.actionDefinitions.get(name);
211     }
212
213     /**
214      * @see org.alfresco.service.cmr.action.ActionService#getActionDefinitions()
215      */

216     public List JavaDoc<ActionDefinition> getActionDefinitions()
217     {
218         return new ArrayList JavaDoc<ActionDefinition>(this.actionDefinitions.values());
219     }
220
221     /**
222      * @see org.alfresco.service.cmr.action.ActionService#getActionConditionDefinition(java.lang.String)
223      */

224     public ActionConditionDefinition getActionConditionDefinition(String JavaDoc name)
225     {
226         return this.conditionDefinitions.get(name);
227     }
228
229     /**
230      * @see org.alfresco.service.cmr.action.ActionService#getActionConditionDefinitions()
231      */

232     public List JavaDoc<ActionConditionDefinition> getActionConditionDefinitions()
233     {
234         return new ArrayList JavaDoc<ActionConditionDefinition>(this.conditionDefinitions.values());
235     }
236
237     /**
238      * @see org.alfresco.service.cmr.action.ActionService#createActionCondition(java.lang.String)
239      */

240     public ActionCondition createActionCondition(String JavaDoc name)
241     {
242         return new ActionConditionImpl(GUID.generate(), name);
243     }
244
245     /**
246      * @see org.alfresco.service.cmr.action.ActionService#createActionCondition(java.lang.String, java.util.Map)
247      */

248     public ActionCondition createActionCondition(String JavaDoc name, Map JavaDoc<String JavaDoc, Serializable JavaDoc> params)
249     {
250         ActionCondition condition = createActionCondition(name);
251         condition.setParameterValues(params);
252         return condition;
253     }
254
255     /**
256      * @see org.alfresco.service.cmr.action.ActionService#createAction()
257      */

258     public Action createAction(String JavaDoc name)
259     {
260         return new ActionImpl(GUID.generate(),name, null);
261     }
262     
263     /**
264      * @see org.alfresco.service.cmr.action.ActionService#createAction(java.lang.String, java.util.Map)
265      */

266     public Action createAction(String JavaDoc name, Map JavaDoc<String JavaDoc, Serializable JavaDoc> params)
267     {
268         Action action = createAction(name);
269         action.setParameterValues(params);
270         return action;
271     }
272
273     /**
274      * @see org.alfresco.service.cmr.action.ActionService#createCompositeAction()
275      */

276     public CompositeAction createCompositeAction()
277     {
278         return new CompositeActionImpl(GUID.generate(), null);
279     }
280
281     /**
282      * @see org.alfresco.service.cmr.action.ActionService#evaluateAction(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef)
283      */

284     public boolean evaluateAction(Action action, NodeRef actionedUponNodeRef)
285     {
286         boolean result = true;
287         
288         if (action.hasActionConditions() == true)
289         {
290             List JavaDoc<ActionCondition> actionConditions = action.getActionConditions();
291             for (ActionCondition condition : actionConditions)
292             {
293                 result = result && evaluateActionCondition(condition, actionedUponNodeRef);
294             }
295         }
296         
297         return result;
298     }
299     
300     /**
301      * @see org.alfresco.service.cmr.action.ActionService#evaluateActionCondition(org.alfresco.service.cmr.action.ActionCondition, org.alfresco.service.cmr.repository.NodeRef)
302      */

303     public boolean evaluateActionCondition(ActionCondition condition, NodeRef actionedUponNodeRef)
304     {
305         boolean result = false;
306
307         // Evaluate the condition
308
ActionConditionEvaluator evaluator = (ActionConditionEvaluator)this.applicationContext.getBean(condition.getActionConditionDefinitionName());
309         result = evaluator.evaluate(condition, actionedUponNodeRef);
310         
311         return result;
312     }
313     
314     /**
315      * @see org.alfresco.service.cmr.action.ActionService#executeAction(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef, boolean)
316      */

317     public void executeAction(Action action, NodeRef actionedUponNodeRef, boolean checkConditions)
318     {
319         executeAction(action, actionedUponNodeRef, checkConditions, action.getExecuteAsychronously());
320     }
321     
322     /**
323      * @see org.alfresco.service.cmr.action.ActionService#executeAction(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef, boolean)
324      */

325     public void executeAction(Action action, NodeRef actionedUponNodeRef, boolean checkConditions, boolean executeAsychronously)
326     {
327         Set JavaDoc<String JavaDoc> actionChain = this.currentActionChain.get();
328         
329         if (executeAsychronously == false)
330         {
331             executeActionImpl(action, actionedUponNodeRef, checkConditions, false, actionChain);
332         }
333         else
334         {
335             // Add to the post transaction pending action list
336
addPostTransactionPendingAction(action, actionedUponNodeRef, checkConditions, actionChain);
337         }
338     }
339
340     /**
341      * @see org.alfresco.repo.action.RuntimeActionService#executeActionImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef, boolean, org.alfresco.service.cmr.repository.NodeRef)
342      */

343     public void executeActionImpl(
344             Action action,
345             NodeRef actionedUponNodeRef,
346             boolean checkConditions,
347             boolean executedAsynchronously,
348             Set JavaDoc<String JavaDoc> actionChain)
349     {
350         if (logger.isDebugEnabled() == true)
351         {
352             StringBuilder JavaDoc builder = new StringBuilder JavaDoc("Exceute action impl action chain = ");
353             if (actionChain == null)
354             {
355                 builder.append("null");
356             }
357             else
358             {
359                 for (String JavaDoc value : actionChain)
360                 {
361                     builder.append(value).append(" ");
362                 }
363             }
364             logger.debug(builder.toString());
365             logger.debug("Current action = " + action.getId());
366         }
367         
368         // get the current user early in case the process fails and we are unable to do it later
369
String JavaDoc currentUserName = this.authenticationComponent.getCurrentUserName();
370         
371         if (actionChain == null || actionChain.contains(action.getId()) == false)
372         {
373             if (logger.isDebugEnabled() == true)
374             {
375                 logger.debug("Doing executeActionImpl");
376             }
377             
378             try
379             {
380                 Set JavaDoc<String JavaDoc> origActionChain = null;
381                 
382                 if (actionChain == null)
383                 {
384                     actionChain = new HashSet JavaDoc<String JavaDoc>();
385                 }
386                 else
387                 {
388                     origActionChain = new HashSet JavaDoc<String JavaDoc>(actionChain);
389                 }
390                 actionChain.add(action.getId());
391                 this.currentActionChain.set(actionChain);
392                 
393                 if (logger.isDebugEnabled() == true)
394                 {
395                     logger.debug("Adding " + action.getId() + " to action chain.");
396                 }
397                 
398                 try
399                 {
400                     // Check and execute now
401
if (checkConditions == false || evaluateAction(action, actionedUponNodeRef) == true)
402                     {
403                         // Execute the action
404
directActionExecution(action, actionedUponNodeRef);
405                     }
406                 }
407                 finally
408                 {
409                     if (origActionChain == null)
410                     {
411                         this.currentActionChain.remove();
412                     }
413                     else
414                     {
415                         this.currentActionChain.set(origActionChain);
416                     }
417                     
418                     if (logger.isDebugEnabled() == true)
419                     {
420                         logger.debug("Resetting the action chain.");
421                     }
422                 }
423             }
424             catch (Throwable JavaDoc exception)
425             {
426                 // Log the exception
427
logger.error(
428                             "An error was encountered whilst executing the action '" + action.getActionDefinitionName() + "'.",
429                             exception);
430                 
431                 if (executedAsynchronously == true)
432                 {
433                     // If one is specified, queue the compensating action ready for execution
434
Action compensatingAction = action.getCompensatingAction();
435                     if (compensatingAction != null)
436                     {
437                         // Set the current user
438
((ActionImpl)compensatingAction).setRunAsUser(currentUserName);
439                         
440                         // Queue the compensating action ready for execution
441
this.asynchronousActionExecutionQueue.executeAction(this, compensatingAction, actionedUponNodeRef, false, null);
442                     }
443                 }
444                     
445                 // Rethrow the exception
446
if (exception instanceof RuntimeException JavaDoc)
447                 {
448                     throw (RuntimeException JavaDoc)exception;
449                 }
450                 else
451                 {
452                     throw new ActionServiceException(ERR_FAIL, exception);
453                 }
454                 
455             }
456         }
457     }
458
459     /**
460      * @see org.alfresco.repo.action.RuntimeActionService#directActionExecution(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef)
461      */

462     public void directActionExecution(Action action, NodeRef actionedUponNodeRef)
463     {
464         // Debug output
465
if (logger.isDebugEnabled() == true)
466         {
467             logger.debug("The action is being executed as the user: " + this.authenticationComponent.getCurrentUserName());
468         }
469         
470         // Get the action executer and execute
471
ActionExecuter executer = (ActionExecuter)this.applicationContext.getBean(action.getActionDefinitionName());
472         executer.execute(action, actionedUponNodeRef);
473     }
474
475     /**
476      * @see org.alfresco.service.cmr.action.ActionService#executeAction(org.alfresco.service.cmr.action.Action, NodeRef)
477      */

478     public void executeAction(Action action, NodeRef actionedUponNodeRef)
479     {
480         executeAction(action, actionedUponNodeRef, true);
481     }
482
483     /**
484      * @see org.alfresco.repo.action.RuntimeActionService#registerActionConditionEvaluator(org.alfresco.repo.action.evaluator.ActionConditionEvaluator)
485      */

486     public void registerActionConditionEvaluator(ActionConditionEvaluator actionConditionEvaluator)
487     {
488         ActionConditionDefinition cond = actionConditionEvaluator.getActionConditionDefintion();
489         this.conditionDefinitions.put(cond.getName(), cond);
490     }
491
492     /**
493      * @see org.alfresco.repo.action.RuntimeActionService#registerActionExecuter(org.alfresco.repo.action.executer.ActionExecuter)
494      */

495     public void registerActionExecuter(ActionExecuter actionExecuter)
496     {
497         ActionDefinition action = actionExecuter.getActionDefinition();
498         this.actionDefinitions.put(action.getName(), action);
499     }
500     
501     /**
502      * Gets the action node ref from the action id
503      *
504      * @param nodeRef the node reference
505      * @param actionId the acition id
506      * @return the action node reference
507      */

508     private NodeRef getActionNodeRefFromId(NodeRef nodeRef, String JavaDoc actionId)
509     {
510         NodeRef result = null;
511         
512         if (this.nodeService.hasAspect(nodeRef, ActionModel.ASPECT_ACTIONS) == true)
513         {
514             DynamicNamespacePrefixResolver namespacePrefixResolver = new DynamicNamespacePrefixResolver();
515             namespacePrefixResolver.registerNamespace(NamespaceService.SYSTEM_MODEL_PREFIX, NamespaceService.SYSTEM_MODEL_1_0_URI);
516             
517             List JavaDoc<NodeRef> nodeRefs = searchService.selectNodes(
518                     getSavedActionFolderRef(nodeRef),
519                     "*[@sys:" + ContentModel.PROP_NODE_UUID.getLocalName() + "='" + actionId + "']",
520                     null,
521                     namespacePrefixResolver,
522                     false);
523             if (nodeRefs.size() != 0)
524             {
525                 result = nodeRefs.get(0);
526             }
527         }
528         
529         return result;
530     }
531
532     /**
533      * @see org.alfresco.service.cmr.action.ActionService#saveAction(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.action.Action)
534      */

535     public void saveAction(NodeRef nodeRef, Action action)
536     {
537         NodeRef actionNodeRef = getActionNodeRefFromId(nodeRef, action.getId());
538         if (actionNodeRef == null)
539         {
540             if (this.nodeService.hasAspect(nodeRef, ActionModel.ASPECT_ACTIONS) == false)
541             {
542                 // Apply the actionable aspect
543
this.nodeService.addAspect(nodeRef, ActionModel.ASPECT_ACTIONS, null);
544             }
545                 
546             Map JavaDoc<QName, Serializable JavaDoc> props = new HashMap JavaDoc<QName, Serializable JavaDoc>(2);
547             props.put(ActionModel.PROP_DEFINITION_NAME, action.getActionDefinitionName());
548             props.put(ContentModel.PROP_NODE_UUID, action.getId());
549             
550             QName actionType = ActionModel.TYPE_ACTION;
551             if(action instanceof CompositeAction)
552             {
553                 actionType = ActionModel.TYPE_COMPOSITE_ACTION;
554             }
555             
556             // Create the action node
557
actionNodeRef = this.nodeService.createNode(
558                     getSavedActionFolderRef(nodeRef),
559                     ContentModel.ASSOC_CONTAINS,
560                     ASSOC_NAME_ACTIONS,
561                     actionType,
562                     props).getChildRef();
563             
564             // Update the created details
565
((ActionImpl)action).setCreator((String JavaDoc)this.nodeService.getProperty(actionNodeRef, ContentModel.PROP_CREATOR));
566             ((ActionImpl)action).setCreatedDate((Date JavaDoc)this.nodeService.getProperty(actionNodeRef, ContentModel.PROP_CREATED));
567         }
568         
569         saveActionImpl(nodeRef, actionNodeRef, action);
570     }
571     
572     /**
573      * @see org.alfresco.repo.action.RuntimeActionService#saveActionImpl(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.action.Action)
574      */

575     public void saveActionImpl(NodeRef owningNodeRef, NodeRef actionNodeRef, Action action)
576     {
577         // Set the owning node ref
578
((ActionImpl)action).setOwningNodeRef(owningNodeRef);
579         
580         // Save action properties
581
saveActionProperties(actionNodeRef, action);
582         
583         // Update the parameters of the action
584
saveParameters(actionNodeRef, action);
585         
586         // Update the conditions of the action
587
saveConditions(actionNodeRef, action);
588         
589         if (action instanceof CompositeAction)
590         {
591             // Update composite action
592
saveActions(actionNodeRef, (CompositeAction)action);
593         }
594         
595         // Update the modified details
596
((ActionImpl)action).setModifier((String JavaDoc)this.nodeService.getProperty(actionNodeRef, ContentModel.PROP_MODIFIER));
597         ((ActionImpl)action).setModifiedDate((Date JavaDoc)this.nodeService.getProperty(actionNodeRef, ContentModel.PROP_MODIFIED));
598     }
599
600     /**
601      * Save the action property values
602      *
603      * @param actionNodeRef the action node reference
604      * @param action the action
605      */

606     private void saveActionProperties(NodeRef actionNodeRef, Action action)
607     {
608         // Update the action property values
609
Map JavaDoc<QName, Serializable JavaDoc> props = this.nodeService.getProperties(actionNodeRef);
610         props.put(ActionModel.PROP_ACTION_TITLE, action.getTitle());
611         props.put(ActionModel.PROP_ACTION_DESCRIPTION, action.getDescription());
612         props.put(ActionModel.PROP_EXECUTE_ASYNCHRONOUSLY, action.getExecuteAsychronously());
613         this.nodeService.setProperties(actionNodeRef, props);
614         
615         // Update the compensating action (model should enforce the singularity of this association)
616
Action compensatingAction = action.getCompensatingAction();
617         List JavaDoc<ChildAssociationRef> assocs = this.nodeService.getChildAssocs(actionNodeRef, RegexQNamePattern.MATCH_ALL, ActionModel.ASSOC_COMPENSATING_ACTION);
618         if (assocs.size() == 0)
619         {
620             if (compensatingAction != null)
621             {
622                 Map JavaDoc<QName, Serializable JavaDoc> props2 = new HashMap JavaDoc<QName, Serializable JavaDoc>(2);
623                 props2.put(ActionModel.PROP_DEFINITION_NAME, compensatingAction.getActionDefinitionName());
624                 props2.put(ContentModel.PROP_NODE_UUID, compensatingAction.getId());
625                 
626                 NodeRef compensatingActionNodeRef = this.nodeService.createNode(
627                         actionNodeRef,
628                         ActionModel.ASSOC_COMPENSATING_ACTION,
629                         ActionModel.ASSOC_COMPENSATING_ACTION,
630                         ActionModel.TYPE_ACTION,
631                         props2).getChildRef();
632                 
633                 saveActionImpl(compensatingAction.getOwningNodeRef(), compensatingActionNodeRef, compensatingAction);
634             }
635         }
636         else
637         {
638             ChildAssociationRef assoc = assocs.get(0);
639             if (compensatingAction == null)
640             {
641                 this.nodeService.removeChild(actionNodeRef, assoc.getChildRef());
642             }
643             else
644             {
645                 saveActionImpl(compensatingAction.getOwningNodeRef(), assoc.getChildRef(), compensatingAction);
646             }
647         }
648     }
649
650     /**
651      * Save the actions of a composite action
652      *
653      * @param compositeActionNodeRef the node reference of the coposite action
654      * @param compositeAction the composite action
655      */

656     private void saveActions(NodeRef compositeActionNodeRef, CompositeAction compositeAction)
657     {
658         // TODO Need a way of sorting the order of the actions
659

660         Map JavaDoc<String JavaDoc, Action> idToAction = new HashMap JavaDoc<String JavaDoc, Action>();
661         List JavaDoc<String JavaDoc> orderedIds = new ArrayList JavaDoc<String JavaDoc>();
662         for (Action action : compositeAction.getActions())
663         {
664             idToAction.put(action.getId(), action);
665             orderedIds.add(action.getId());
666         }
667         
668         List JavaDoc<ChildAssociationRef> actionRefs = this.nodeService.getChildAssocs(compositeActionNodeRef, RegexQNamePattern.MATCH_ALL, ActionModel.ASSOC_ACTIONS);
669         for (ChildAssociationRef actionRef : actionRefs)
670         {
671             NodeRef actionNodeRef = actionRef.getChildRef();
672             if (idToAction.containsKey(actionNodeRef.getId()) == false)
673             {
674                 // Delete the action
675
this.nodeService.removeChild(compositeActionNodeRef, actionNodeRef);
676             }
677             else
678             {
679                 // Update the action
680
Action action = idToAction.get(actionNodeRef.getId());
681                 saveActionImpl(action.getOwningNodeRef(), actionNodeRef, action);
682                 orderedIds.remove(actionNodeRef.getId());
683             }
684             
685         }
686         
687         // Create the actions remaining
688
for (String JavaDoc actionId : orderedIds)
689         {
690             Action action = idToAction.get(actionId);
691             
692             Map JavaDoc<QName, Serializable JavaDoc> props = new HashMap JavaDoc<QName, Serializable JavaDoc>(2);
693             props.put(ActionModel.PROP_DEFINITION_NAME, action.getActionDefinitionName());
694             props.put(ContentModel.PROP_NODE_UUID, action.getId());
695             
696             NodeRef actionNodeRef = this.nodeService.createNode(
697                     compositeActionNodeRef,
698                     ActionModel.ASSOC_ACTIONS,
699                     ActionModel.ASSOC_ACTIONS,
700                     ActionModel.TYPE_ACTION,
701                     props).getChildRef();
702             
703             saveActionImpl(action.getOwningNodeRef(), actionNodeRef, action);
704         }
705     }
706
707     /**
708      * Saves the conditions associated with an action
709      *
710      * @param actionNodeRef the action node reference
711      * @param action the action
712      */

713     private void saveConditions(NodeRef actionNodeRef, Action action)
714     {
715         // TODO Need a way of sorting out the order of the conditions
716

717         Map JavaDoc<String JavaDoc, ActionCondition> idToCondition = new HashMap JavaDoc<String JavaDoc, ActionCondition>();
718         List JavaDoc<String JavaDoc> orderedIds = new ArrayList JavaDoc<String JavaDoc>();
719         for (ActionCondition actionCondition : action.getActionConditions())
720         {
721             idToCondition.put(actionCondition.getId(), actionCondition);
722             orderedIds.add(actionCondition.getId());
723         }
724         
725         List JavaDoc<ChildAssociationRef> conditionRefs = this.nodeService.getChildAssocs(actionNodeRef, RegexQNamePattern.MATCH_ALL, ActionModel.ASSOC_CONDITIONS);
726         for (ChildAssociationRef conditionRef : conditionRefs)
727         {
728             NodeRef conditionNodeRef = conditionRef.getChildRef();
729             if (idToCondition.containsKey(conditionNodeRef.getId()) == false)
730             {
731                 // Delete the condition
732
this.nodeService.removeChild(actionNodeRef, conditionNodeRef);
733             }
734             else
735             {
736                 saveConditionProperties(conditionNodeRef, idToCondition.get(conditionNodeRef.getId()));
737                 
738                 // Update the conditions parameters
739
saveParameters(conditionNodeRef, idToCondition.get(conditionNodeRef.getId()));
740                 orderedIds.remove(conditionNodeRef.getId());
741             }
742             
743         }
744         
745         // Create the conditions remaining
746
for (String JavaDoc nextId : orderedIds)
747         {
748             ActionCondition actionCondition = idToCondition.get(nextId);
749             Map JavaDoc<QName, Serializable JavaDoc> props = new HashMap JavaDoc<QName, Serializable JavaDoc>(2);
750             props.put(ActionModel.PROP_DEFINITION_NAME, actionCondition.getActionConditionDefinitionName());
751             props.put(ContentModel.PROP_NODE_UUID, actionCondition.getId());
752             
753             NodeRef conditionNodeRef = this.nodeService.createNode(
754                     actionNodeRef,
755                     ActionModel.ASSOC_CONDITIONS,
756                     ActionModel.ASSOC_CONDITIONS,
757                     ActionModel.TYPE_ACTION_CONDITION,
758                     props).getChildRef();
759             
760             saveConditionProperties(conditionNodeRef, actionCondition);
761             saveParameters(conditionNodeRef, actionCondition);
762         }
763     }
764
765     /**
766      * Save the condition properties
767      *
768      * @param conditionNodeRef
769      * @param condition
770      */

771     private void saveConditionProperties(NodeRef conditionNodeRef, ActionCondition condition)
772     {
773         this.nodeService.setProperty(conditionNodeRef, ActionModel.PROP_CONDITION_INVERT, condition.getInvertCondition());
774         
775     }
776
777     /**
778      * Saves the parameters associated with an action or condition
779      *
780      * @param parameterizedNodeRef the parameterized item node reference
781      * @param item the parameterized item
782      */

783     private void saveParameters(NodeRef parameterizedNodeRef, ParameterizedItem item)
784     {
785         Map JavaDoc<String JavaDoc, Serializable JavaDoc> parameterMap = new HashMap JavaDoc<String JavaDoc, Serializable JavaDoc>();
786         parameterMap.putAll(item.getParameterValues());
787         
788         List JavaDoc<ChildAssociationRef> parameters = this.nodeService.getChildAssocs(parameterizedNodeRef, RegexQNamePattern.MATCH_ALL, ActionModel.ASSOC_PARAMETERS);
789         for (ChildAssociationRef ref : parameters)
790         {
791             NodeRef paramNodeRef = ref.getChildRef();
792             Map JavaDoc<QName, Serializable JavaDoc> nodeRefParameterMap = this.nodeService.getProperties(paramNodeRef);
793             String JavaDoc paramName = (String JavaDoc)nodeRefParameterMap.get(ActionModel.PROP_PARAMETER_NAME);
794             if (parameterMap.containsKey(paramName) == false)
795             {
796                 // Delete parameter from node ref
797
this.nodeService.removeChild(parameterizedNodeRef, paramNodeRef);
798             }
799             else
800             {
801                 // Update the parameter value
802
nodeRefParameterMap.put(ActionModel.PROP_PARAMETER_VALUE, parameterMap.get(paramName));
803                 this.nodeService.setProperties(paramNodeRef, nodeRefParameterMap);
804                 parameterMap.remove(paramName);
805             }
806         }
807         
808         // Add any remaing parameters
809
for (Map.Entry JavaDoc<String JavaDoc, Serializable JavaDoc> entry : parameterMap.entrySet())
810         {
811             Map JavaDoc<QName, Serializable JavaDoc> nodeRefProperties = new HashMap JavaDoc<QName, Serializable JavaDoc>(2);
812             nodeRefProperties.put(ActionModel.PROP_PARAMETER_NAME, entry.getKey());
813             nodeRefProperties.put(ActionModel.PROP_PARAMETER_VALUE, entry.getValue());
814             
815             this.nodeService.createNode(
816                     parameterizedNodeRef,
817                     ActionModel.ASSOC_PARAMETERS,
818                     ActionModel.ASSOC_PARAMETERS,
819                     ActionModel.TYPE_ACTION_PARAMETER,
820                     nodeRefProperties);
821         }
822     }
823
824     /**
825      * @see org.alfresco.service.cmr.action.ActionService#getActions(org.alfresco.service.cmr.repository.NodeRef)
826      */

827     public List JavaDoc<Action> getActions(NodeRef nodeRef)
828     {
829         List JavaDoc<Action> result = new ArrayList JavaDoc<Action>();
830         
831         if (this.nodeService.exists(nodeRef) == true &&
832             this.nodeService.hasAspect(nodeRef, ActionModel.ASPECT_ACTIONS) == true)
833         {
834             List JavaDoc<ChildAssociationRef> actions = this.nodeService.getChildAssocs(
835                                                     getSavedActionFolderRef(nodeRef),
836                                                     RegexQNamePattern.MATCH_ALL, ASSOC_NAME_ACTIONS);
837             for (ChildAssociationRef action : actions)
838             {
839                 NodeRef actionNodeRef = action.getChildRef();
840                 result.add(createAction(nodeRef, actionNodeRef));
841             }
842         }
843         
844         return result;
845     }
846
847     /**
848      * Create an action from the action node reference
849      *
850      * @param actionNodeRef the action node reference
851      * @return the action
852      */

853     private Action createAction(NodeRef owningNodeRef, NodeRef actionNodeRef)
854     {
855         Action result = null;
856         
857         Map JavaDoc<QName, Serializable JavaDoc> properties = this.nodeService.getProperties(actionNodeRef);
858         
859         QName actionType = this.nodeService.getType(actionNodeRef);
860         if (ActionModel.TYPE_COMPOSITE_ACTION.equals(actionType) == true)
861         {
862             // Create a composite action
863
result = new CompositeActionImpl(actionNodeRef.getId(), owningNodeRef);
864             populateCompositeAction(actionNodeRef, (CompositeAction)result);
865         }
866         else
867         {
868             // Create an action
869
result = new ActionImpl(actionNodeRef.getId(), (String JavaDoc)properties.get(ActionModel.PROP_DEFINITION_NAME), owningNodeRef);
870             populateAction(actionNodeRef, result);
871         }
872         
873         return result;
874     }
875
876     /**
877      * Populate the details of the action from the node reference
878      *
879      * @param actionNodeRef the action node reference
880      * @param action the action
881      */

882     private void populateAction(NodeRef actionNodeRef, Action action)
883     {
884         // Populate the action properties
885
populateActionProperties(actionNodeRef, action);
886         
887         // Set the parameters
888
populateParameters(actionNodeRef, action);
889         
890         // Set the conditions
891
List JavaDoc<ChildAssociationRef> conditions = this.nodeService.getChildAssocs(actionNodeRef, RegexQNamePattern.MATCH_ALL, ActionModel.ASSOC_CONDITIONS);
892         for (ChildAssociationRef condition : conditions)
893         {
894             NodeRef conditionNodeRef = condition.getChildRef();
895             action.addActionCondition(createActionCondition(conditionNodeRef));
896         }
897     }
898
899     /**
900      * Populates the action properties from the node reference
901      *
902      * @param actionNodeRef the action node reference
903      * @param action the action
904      */

905     private void populateActionProperties(NodeRef actionNodeRef, Action action)
906     {
907         Map JavaDoc<QName, Serializable JavaDoc> props = this.nodeService.getProperties(actionNodeRef);
908         
909         action.setTitle((String JavaDoc)props.get(ActionModel.PROP_ACTION_TITLE));
910         action.setDescription((String JavaDoc)props.get(ActionModel.PROP_ACTION_DESCRIPTION));
911         
912         boolean value = false;
913         Boolean JavaDoc executeAsynchronously = (Boolean JavaDoc)props.get(ActionModel.PROP_EXECUTE_ASYNCHRONOUSLY);
914         if (executeAsynchronously != null)
915         {
916             value = executeAsynchronously.booleanValue();
917         }
918         action.setExecuteAsynchronously(value);
919         
920         ((ActionImpl)action).setCreator((String JavaDoc)props.get(ContentModel.PROP_CREATOR));
921         ((ActionImpl)action).setCreatedDate((Date JavaDoc)props.get(ContentModel.PROP_CREATED));
922         ((ActionImpl)action).setModifier((String JavaDoc)props.get(ContentModel.PROP_MODIFIER));
923         ((ActionImpl)action).setModifiedDate((Date JavaDoc)props.get(ContentModel.PROP_MODIFIED));
924         
925         // Get the compensating action
926
List JavaDoc<ChildAssociationRef> assocs = this.nodeService.getChildAssocs(actionNodeRef, RegexQNamePattern.MATCH_ALL, ActionModel.ASSOC_COMPENSATING_ACTION);
927         if (assocs.size() != 0)
928         {
929             Action compensatingAction = createAction(action.getOwningNodeRef(), assocs.get(0).getChildRef());
930             action.setCompensatingAction(compensatingAction);
931         }
932     }
933
934     /**
935      * Populate the parameteres of a parameterized item from the parameterized item node reference
936      *
937      * @param parameterizedItemNodeRef the parameterized item node reference
938      * @param parameterizedItem the parameterized item
939      */

940     private void populateParameters(NodeRef parameterizedItemNodeRef, ParameterizedItem parameterizedItem)
941     {
942         List JavaDoc<ChildAssociationRef> parameters = this.nodeService.getChildAssocs(parameterizedItemNodeRef, RegexQNamePattern.MATCH_ALL, ActionModel.ASSOC_PARAMETERS);
943         for (ChildAssociationRef parameter : parameters)
944         {
945             NodeRef parameterNodeRef = parameter.getChildRef();
946             Map JavaDoc<QName, Serializable JavaDoc> properties = this.nodeService.getProperties(parameterNodeRef);
947             parameterizedItem.setParameterValue(
948                     (String JavaDoc)properties.get(ActionModel.PROP_PARAMETER_NAME),
949                     properties.get(ActionModel.PROP_PARAMETER_VALUE));
950         }
951     }
952     
953     /**
954      * Creates an action condition from an action condition node reference
955      *
956      * @param conditionNodeRef the condition node reference
957      * @return the action condition
958      */

959     private ActionCondition createActionCondition(NodeRef conditionNodeRef)
960     {
961         Map JavaDoc<QName, Serializable JavaDoc> properties = this.nodeService.getProperties(conditionNodeRef);
962         ActionCondition condition = new ActionConditionImpl(conditionNodeRef.getId(), (String JavaDoc)properties.get(ActionModel.PROP_DEFINITION_NAME));
963         
964         boolean value = false;
965         Boolean JavaDoc invert = (Boolean JavaDoc)this.nodeService.getProperty(conditionNodeRef, ActionModel.PROP_CONDITION_INVERT);
966         if (invert != null)
967         {
968             value = invert.booleanValue();
969         }
970         condition.setInvertCondition(value);
971         
972         populateParameters(conditionNodeRef, condition);
973         return condition;
974     }
975
976     /**
977      * Populates a composite action from a composite action node reference
978      *
979      * @param compositeNodeRef the composite action node reference
980      * @param compositeAction the composite action
981      */

982     public void populateCompositeAction(NodeRef compositeNodeRef, CompositeAction compositeAction)
983     {
984         populateAction(compositeNodeRef, compositeAction);
985         
986         List JavaDoc<ChildAssociationRef> actions = this.nodeService.getChildAssocs(compositeNodeRef, RegexQNamePattern.MATCH_ALL, ActionModel.ASSOC_ACTIONS);
987         for (ChildAssociationRef action : actions)
988         {
989             NodeRef actionNodeRef = action.getChildRef();
990             compositeAction.addAction(createAction(compositeAction.getOwningNodeRef(), actionNodeRef));
991         }
992     }
993
994     /**
995      * @see org.alfresco.service.cmr.action.ActionService#getAction(org.alfresco.service.cmr.repository.NodeRef, java.lang.String)
996      */

997     public Action getAction(NodeRef nodeRef, String JavaDoc actionId)
998     {
999         Action result = null;
1000        
1001        if (this.nodeService.exists(nodeRef) == true &&
1002            this.nodeService.hasAspect(nodeRef, ActionModel.ASPECT_ACTIONS) == true)
1003        {
1004            NodeRef actionNodeRef = getActionNodeRefFromId(nodeRef, actionId);
1005            if (actionNodeRef != null)
1006            {
1007                result = createAction(nodeRef, actionNodeRef);
1008            }
1009        }
1010        
1011        return result;
1012    }
1013
1014    /**
1015     * @see org.alfresco.service.cmr.action.ActionService#removeAction(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.action.Action)
1016     */

1017    public void removeAction(NodeRef nodeRef, Action action)
1018    {
1019        if (this.nodeService.exists(nodeRef) == true &&
1020            this.nodeService.hasAspect(nodeRef, ActionModel.ASPECT_ACTIONS) == true)
1021        {
1022            NodeRef actionNodeRef = getActionNodeRefFromId(nodeRef, action.getId());
1023            if (actionNodeRef != null)
1024            {
1025                this.nodeService.removeChild(getSavedActionFolderRef(nodeRef), actionNodeRef);
1026            }
1027        }
1028    }
1029
1030    /**
1031     * @see org.alfresco.service.cmr.action.ActionService#removeAllActions(org.alfresco.service.cmr.repository.NodeRef)
1032     */

1033    public void removeAllActions(NodeRef nodeRef)
1034    {
1035        if (this.nodeService.exists(nodeRef) == true &&
1036            this.nodeService.hasAspect(nodeRef, ActionModel.ASPECT_ACTIONS) == true)
1037        {
1038            List JavaDoc<ChildAssociationRef> actions = new ArrayList JavaDoc<ChildAssociationRef>(this.nodeService.getChildAssocs(getSavedActionFolderRef(nodeRef), RegexQNamePattern.MATCH_ALL, ASSOC_NAME_ACTIONS));
1039            for (ChildAssociationRef action : actions)
1040            {
1041                this.nodeService.removeChild(getSavedActionFolderRef(nodeRef), action.getChildRef());
1042            }
1043        }
1044    }
1045    
1046    /**
1047     * Add a pending action to the list to be queued for execution once the transaction is completed.
1048     *
1049     * @param action the action
1050     * @param actionedUponNodeRef the actioned upon node reference
1051     * @param checkConditions indicates whether to check the conditions before execution
1052     */

1053    @SuppressWarnings JavaDoc("unchecked")
1054    private void addPostTransactionPendingAction(
1055            Action action,
1056            NodeRef actionedUponNodeRef,
1057            boolean checkConditions,
1058            Set JavaDoc<String JavaDoc> actionChain)
1059    {
1060        if (logger.isDebugEnabled() == true)
1061        {
1062            StringBuilder JavaDoc builder = new StringBuilder JavaDoc("addPostTransactionPendingAction action chain = ");
1063            if (actionChain == null)
1064            {
1065                builder.append("null");
1066            }
1067            else
1068            {
1069                for (String JavaDoc value : actionChain)
1070                {
1071                    builder.append(value).append(" ");
1072                }
1073            }
1074            logger.debug(builder.toString());
1075            logger.debug("Current action = " + action.getId());
1076        }
1077        
1078        // Don't continue if the action is already in the action chain
1079
if (actionChain == null || actionChain.contains(action.getId()) == false)
1080        {
1081            if (logger.isDebugEnabled() == true)
1082            {
1083                logger.debug("Doing addPostTransactionPendingAction");
1084            }
1085            
1086            // Set the run as user to the current user
1087
if (logger.isDebugEnabled() == true)
1088            {
1089                logger.debug("The current user is: " + this.authenticationComponent.getCurrentUserName());
1090            }
1091            ((ActionImpl)action).setRunAsUser(this.authenticationComponent.getCurrentUserName());
1092            
1093            // Ensure that the transaction listener is bound to the transaction
1094
AlfrescoTransactionSupport.bindListener(this.transactionListener);
1095            
1096            // Add the pending action to the transaction resource
1097
List JavaDoc<PendingAction> pendingActions = (List JavaDoc<PendingAction>)AlfrescoTransactionSupport.getResource(POST_TRANSACTION_PENDING_ACTIONS);
1098            if (pendingActions == null)
1099            {
1100                pendingActions = new ArrayList JavaDoc<PendingAction>();
1101                AlfrescoTransactionSupport.bindResource(POST_TRANSACTION_PENDING_ACTIONS, pendingActions);
1102            }
1103            
1104            // Check that action has only been added to the list once
1105
PendingAction pendingAction = new PendingAction(action, actionedUponNodeRef, checkConditions, actionChain);
1106            if (pendingActions.contains(pendingAction) == false)
1107            {
1108                pendingActions.add(pendingAction);
1109            }
1110        }
1111    }
1112    
1113    /**
1114     * @see org.alfresco.repo.action.RuntimeActionService#getPostTransactionPendingActions()
1115     */

1116    @SuppressWarnings JavaDoc("unchecked")
1117    public List JavaDoc<PendingAction> getPostTransactionPendingActions()
1118    {
1119        return (List JavaDoc<PendingAction>)AlfrescoTransactionSupport.getResource(POST_TRANSACTION_PENDING_ACTIONS);
1120    }
1121    
1122    /**
1123     * Pending action details class
1124     */

1125    public class PendingAction
1126    {
1127        /**
1128         * The action
1129         */

1130        private Action action;
1131        
1132        /**
1133         * The actioned upon node reference
1134         */

1135        private NodeRef actionedUponNodeRef;
1136        
1137        /**
1138         * Indicates whether the conditions should be checked before the action is executed
1139         */

1140        private boolean checkConditions;
1141        
1142        private Set JavaDoc<String JavaDoc> actionChain;
1143        
1144        /**
1145         * Constructor
1146         *
1147         * @param action the action
1148         * @param actionedUponNodeRef the actioned upon node reference
1149         * @param checkConditions indicated whether the conditions need to be checked
1150         */

1151        public PendingAction(Action action, NodeRef actionedUponNodeRef, boolean checkConditions, Set JavaDoc<String JavaDoc> actionChain)
1152        {
1153            this.action = action;
1154            this.actionedUponNodeRef = actionedUponNodeRef;
1155            this.checkConditions = checkConditions;
1156            this.actionChain = actionChain;
1157        }
1158        
1159        /**
1160         * Get the action
1161         *
1162         * @return the action
1163         */

1164        public Action getAction()
1165        {
1166            return action;
1167        }
1168        
1169        /**
1170         * Get the actioned upon node reference
1171         *
1172         * @return the actioned upon node reference
1173         */

1174        public NodeRef getActionedUponNodeRef()
1175        {
1176            return actionedUponNodeRef;
1177        }
1178        
1179        /**
1180         * Get the check conditions value
1181         *
1182         * @return indicates whether the condition should be checked
1183         */

1184        public boolean getCheckConditions()
1185        {
1186            return this.checkConditions;
1187        }
1188        
1189        public Set JavaDoc<String JavaDoc> getActionChain()
1190        {
1191            return this.actionChain;
1192        }
1193        
1194        /**
1195         * @see java.lang.Object#hashCode()
1196         */

1197        @Override JavaDoc
1198        public int hashCode()
1199        {
1200            int hashCode = 37 * this.actionedUponNodeRef.hashCode();
1201            hashCode += 37 * this.action.hashCode();
1202            return hashCode;
1203        }
1204        
1205        /**
1206         * @see java.lang.Object#equals(java.lang.Object)
1207         */

1208        @Override JavaDoc
1209        public boolean equals(Object JavaDoc obj)
1210        {
1211            if (this == obj)
1212            {
1213                return true;
1214            }
1215            if (obj instanceof PendingAction)
1216            {
1217                PendingAction that = (PendingAction) obj;
1218                return (this.action.equals(that.action) && this.actionedUponNodeRef.equals(that.actionedUponNodeRef));
1219            }
1220            else
1221            {
1222                return false;
1223            }
1224        }
1225    }
1226}
1227
Popular Tags