KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ofbiz > workflow > impl > WfActivityImpl


1 /*
2  * $Id: WfActivityImpl.java 5462 2005-08-05 18:35:48Z jonesde $
3  *
4  * Copyright (c) 2001, 2002 The Open For Business Project - www.ofbiz.org
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
21  * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
22  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  */

25 package org.ofbiz.workflow.impl;
26
27 import java.util.ArrayList JavaDoc;
28 import java.util.Calendar JavaDoc;
29 import java.util.Collection JavaDoc;
30 import java.util.Date JavaDoc;
31 import java.util.HashMap JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import java.util.List JavaDoc;
34 import java.util.Map JavaDoc;
35 import java.util.Set JavaDoc;
36
37 import org.ofbiz.base.util.BshUtil;
38 import org.ofbiz.base.util.Debug;
39 import org.ofbiz.base.util.StringUtil;
40 import org.ofbiz.base.util.UtilDateTime;
41 import org.ofbiz.base.util.UtilMisc;
42 import org.ofbiz.entity.GenericDelegator;
43 import org.ofbiz.entity.GenericEntityException;
44 import org.ofbiz.entity.GenericValue;
45 import org.ofbiz.entity.util.EntityTypeUtil;
46 import org.ofbiz.entity.util.EntityUtil;
47 import org.ofbiz.service.DispatchContext;
48 import org.ofbiz.service.GenericServiceException;
49 import org.ofbiz.service.LocalDispatcher;
50 import org.ofbiz.service.ModelService;
51 import org.ofbiz.workflow.AlreadyRunning;
52 import org.ofbiz.workflow.CannotComplete;
53 import org.ofbiz.workflow.CannotResume;
54 import org.ofbiz.workflow.CannotStart;
55 import org.ofbiz.workflow.CannotStop;
56 import org.ofbiz.workflow.InvalidData;
57 import org.ofbiz.workflow.InvalidState;
58 import org.ofbiz.workflow.NotRunning;
59 import org.ofbiz.workflow.NotSuspended;
60 import org.ofbiz.workflow.ResultNotAvailable;
61 import org.ofbiz.workflow.TransitionNotAllowed;
62 import org.ofbiz.workflow.WfActivity;
63 import org.ofbiz.workflow.WfAssignment;
64 import org.ofbiz.workflow.WfException;
65 import org.ofbiz.workflow.WfFactory;
66 import org.ofbiz.workflow.WfProcess;
67 import org.ofbiz.workflow.WfResource;
68
69 /**
70  * WfActivityImpl - Workflow Activity Object implementation
71  *
72  * @author <a HREF="mailto:jaz@ofbiz.org">Andy Zeneski</a>
73  * @author David Ostrovsky (d.ostrovsky@gmx.de)
74  * @author Oswin Ondarza and Manuel Soto
75  * @version $Rev: 5462 $
76  * @since 2.0
77  */

78 public class WfActivityImpl extends WfExecutionObjectImpl implements WfActivity {
79
80     public static final String JavaDoc module = WfActivityImpl.class.getName();
81     
82     private static final int CHECK_ASSIGN = 1;
83     private static final int CHECK_COMPLETE = 2;
84
85     protected String JavaDoc processId = null;
86
87     public WfActivityImpl(GenericValue value, String JavaDoc processId) throws WfException {
88         super(value, processId);
89         this.processId = processId;
90         init();
91     }
92
93     public WfActivityImpl(GenericDelegator delegator, String JavaDoc workEffortId) throws WfException {
94         super(delegator, workEffortId);
95         if (activityId == null || activityId.length() == 0)
96             throw new WfException("Execution object is not of type WfActivity");
97         this.processId = getRuntimeObject().getString("workEffortParentId");
98     }
99
100     private void init() throws WfException {
101         GenericValue valueObject = getDefinitionObject();
102         
103         // set the activity context
104
this.setProcessContext(container().contextKey());
105         
106         // parse the descriptions
107
this.parseDescriptions(this.processContext());
108
109         // check for inheritPriority attribute
110
boolean inheritPriority = valueObject.getBoolean("inheritPriority").booleanValue() || false;
111
112         if (inheritPriority) {
113             GenericValue runTime = getRuntimeObject();
114             Map JavaDoc context = processContext();
115
116             if (context.containsKey("previousActivity")) {
117                 String JavaDoc previousActivity = (String JavaDoc) context.get("previousActivity");
118                 WfActivity pAct = WfFactory.getWfActivity(getDelegator(), previousActivity);
119
120                 if (pAct != null) {
121                     try {
122                         runTime.set("priority", new Long JavaDoc(pAct.priority()));
123                         runTime.store();
124                     } catch (GenericEntityException e) {
125                         throw new WfException(e.getMessage(), e);
126                     }
127                 }
128             }
129         }
130         
131         GenericValue performer = null;
132         if (valueObject.get("performerParticipantId") != null) {
133             try {
134                 performer = valueObject.getRelatedOne("PerformerWorkflowParticipant");
135                 if (performer == null) {
136                     Map JavaDoc performerFields = UtilMisc.toMap("packageId", valueObject.getString("packageId"),
137                             "packageVersion", valueObject.getString("packageVersion"), "processId", "_NA_",
138                             "processVersion", "_NA_", "participantId", valueObject.getString("performerParticipantId"));
139                     performer = delegator.findByPrimaryKey("WorkflowParticipant", performerFields);
140                 }
141             } catch (GenericEntityException e) {
142                 throw new WfException(e.getMessage(), e);
143             }
144         }
145         if (performer != null)
146             createAssignments(performer);
147             
148         boolean limitAfterStart = valueObject.getBoolean("limitAfterStart").booleanValue();
149
150         if (Debug.verboseOn()) {
151             Debug.logVerbose("[WfActivity.init]: limitAfterStart - " + limitAfterStart, module);
152         }
153         if (!limitAfterStart && valueObject.get("limitService") != null && !valueObject.getString("limitService").equals("")) {
154             Debug.logVerbose("[WfActivity.init]: limit service is not after start, setting up now.", module);
155             setLimitService();
156         }
157     }
158
159     private void createAssignments(GenericValue currentPerformer) throws WfException {
160         GenericValue valueObject = getDefinitionObject();
161         GenericValue performer = checkPerformer(currentPerformer);
162         boolean assignAll = false;
163
164         if (valueObject.get("acceptAllAssignments") != null) {
165             assignAll = valueObject.getBoolean("acceptAllAssignments").booleanValue();
166         }
167         
168         // first check for single assignment
169
if (!assignAll) {
170             if (performer != null) {
171                 Debug.logVerbose("[WfActivity.createAssignments] : (S) Single assignment", module);
172                 assign(WfFactory.getWfResource(performer), false);
173             }
174         }
175
176         // check for a party group
177
else if (performer.get("partyId") != null && !performer.getString("partyId").equals("_NA_")) {
178             GenericValue partyType = null;
179             GenericValue groupType = null;
180
181             try {
182                 Map JavaDoc fields1 = UtilMisc.toMap("partyId", performer.getString("partyId"));
183                 GenericValue v1 = getDelegator().findByPrimaryKey("Party", fields1);
184
185                 partyType = v1.getRelatedOne("PartyType");
186                 Map JavaDoc fields2 = UtilMisc.toMap("partyTypeId", "PARTY_GROUP");
187                 groupType = getDelegator().findByPrimaryKeyCache("PartyType", fields2);
188             } catch (GenericEntityException e) {
189                 throw new WfException(e.getMessage(), e);
190             }
191             if (EntityTypeUtil.isType(partyType, groupType)) {
192                 // party is a group
193
Collection JavaDoc partyRelations = null;
194                 try {
195                     Map JavaDoc fields = UtilMisc.toMap("partyIdFrom", performer.getString("partyId"),
196                             "partyRelationshipTypeId", "GROUP_ROLLUP");
197                     partyRelations = getDelegator().findByAnd("PartyRelationship", fields);
198                 } catch (GenericEntityException e) {
199                     throw new WfException(e.getMessage(), e);
200                 }
201
202                 // make assignments for these parties
203
Debug.logVerbose("[WfActivity.createAssignments] : Group assignment", module);
204                 Iterator JavaDoc i = partyRelations.iterator();
205
206                 while (i.hasNext()) {
207                     GenericValue value = (GenericValue) i.next();
208                     assign(
209                         WfFactory.getWfResource(getDelegator(), null, null, value.getString("partyIdTo"), null),
210                         true);
211                 }
212             } else {
213                 // not a group
214
Debug.logVerbose("[WfActivity.createAssignments] : (G) Single assignment", module);
215                 assign(WfFactory.getWfResource(performer), false);
216             }
217         }
218         
219         // check for role types
220
else if (performer.get("roleTypeId") != null && !performer.getString("roleTypeId").equals("_NA_")) {
221             Collection JavaDoc partyRoles = null;
222
223             try {
224                 Map JavaDoc fields = UtilMisc.toMap("roleTypeId", performer.getString("roleTypeId"));
225                 partyRoles = getDelegator().findByAnd("PartyRole", fields);
226             } catch (GenericEntityException e) {
227                 throw new WfException(e.getMessage(), e);
228             }
229
230             // loop through the roles and create assignments
231
Debug.logVerbose("[WfActivity.createAssignments] : Role assignment", module);
232             Iterator JavaDoc i = partyRoles.iterator();
233
234             while (i.hasNext()) {
235                 GenericValue value = (GenericValue) i.next();
236                 assign(WfFactory.getWfResource(value.getDelegator(), null, null, value.getString("partyId"), null), true);
237             }
238         }
239     }
240
241     private List JavaDoc getAssignments() throws WfException {
242         List JavaDoc assignments = new ArrayList JavaDoc();
243         List JavaDoc assignList = this.getAllAssignments();
244             
245         if (assignList == null)
246             return assignments;
247         
248         Iterator JavaDoc i = assignList.iterator();
249         while (i.hasNext()) {
250             GenericValue value = (GenericValue) i.next();
251             String JavaDoc party = value.getString("partyId");
252             String JavaDoc role = value.getString("roleTypeId");
253             String JavaDoc status = value.getString("statusId");
254             java.sql.Timestamp JavaDoc from = value.getTimestamp("fromDate");
255
256             if (status.equals("CAL_SENT") || status.equals("CAL_ACCEPTED") || status.equals("CAL_TENTATIVE"))
257                 assignments.add(WfFactory.getWfAssignment(getDelegator(), runtimeKey(), party, role, from));
258         }
259         if (Debug.verboseOn()) Debug.logVerbose("Found [" + assignments.size() + "] assignment(s)", module);
260         return assignments;
261     }
262     
263     private List JavaDoc getAllAssignments() throws WfException {
264         List JavaDoc assignList = null;
265         try {
266             assignList = getDelegator().findByAnd("WorkEffortPartyAssignment", UtilMisc.toMap("workEffortId", runtimeKey()));
267         } catch (GenericEntityException e) {
268             throw new WfException(e.getMessage(), e);
269         }
270         
271         if (assignList != null) {
272             assignList = EntityUtil.filterByDate(assignList);
273         } else {
274             return new ArrayList JavaDoc();
275         }
276         return assignList;
277     }
278
279     // create a new assignment
280
private WfAssignment assign(WfResource resource, boolean append) throws WfException {
281         if (!append) {
282             Iterator JavaDoc ai = getIteratorAssignment();
283             while (ai.hasNext()) {
284                 WfAssignment a = (WfAssignment) ai.next();
285                 a.remove();
286             }
287         }
288
289         WfAssignment assign = WfFactory.getWfAssignment(this, resource, null, true);
290         return assign;
291     }
292
293     // check the performer: dynamic; defined partyId/roleTypeId
294
private GenericValue checkPerformer(GenericValue performer) throws WfException {
295         GenericValue newPerformer = GenericValue.create(performer);
296         Map JavaDoc context = processContext();
297         
298         String JavaDoc performerType = performer.getString("participantTypeId");
299         String JavaDoc partyId = performer.getString("partyId");
300         String JavaDoc roleTypeId = performer.getString("roleTypeId");
301         
302         // check for dynamic party
303
if (partyId != null && partyId.trim().toLowerCase().startsWith("expr:")) {
304             if (Debug.verboseOn()) Debug.logVerbose("Dynamic performer: Found a party expression", module);
305             Object JavaDoc value = null;
306             try {
307                 value = BshUtil.eval(partyId.trim().substring(5).trim(), context);
308             } catch (bsh.EvalError e) {
309                 throw new WfException("Bsh evaluation error occurred.", e);
310             }
311             if (value != null) {
312                 if (value instanceof String JavaDoc) {
313                     newPerformer.set("partyId", value);
314                 } else {
315                     throw new WfException("Expression did not return a String");
316                 }
317             }
318         }
319         
320         // check for dynamic role
321
if (roleTypeId != null && roleTypeId.trim().toLowerCase().startsWith("expr:")) {
322             if (Debug.verboseOn()) Debug.logVerbose("Dynamic performer: Found a role expression", module);
323             Object JavaDoc value = null;
324             try {
325                 value = BshUtil.eval(roleTypeId.trim().substring(5).trim(), context);
326             } catch (bsh.EvalError e) {
327                 throw new WfException("Bsh evaluation error occurred.", e);
328             }
329             if (value != null) {
330                 if (value instanceof String JavaDoc) {
331                     newPerformer.set("roleTypeId", value);
332                 } else {
333                     throw new WfException("Expression did not return a String");
334                 }
335             }
336         }
337         
338         // check for un-defined party
339
if (performerType.equals("HUMAN") || performerType.equals("ORGANIZATIONAL_UNIT")) {
340             if (partyId == null) {
341                 newPerformer.set("partyId", performer.getString("participantId"));
342             }
343         }
344         
345         // check for un-defined role
346
if (performerType.equals("ROLE")) {
347             if (roleTypeId == null) {
348                 newPerformer.set("roleTypeId", performer.getString("participantId"));
349             }
350         }
351                                 
352         return newPerformer;
353     }
354
355     /**
356      * @see org.ofbiz.workflow.WfActivity#activate()
357      */

358     public void activate() throws WfException, CannotStart, AlreadyRunning {
359         // make sure we aren't already running
360
if (this.state().equals("open.running"))
361             throw new AlreadyRunning();
362
363         // check the start mode
364
String JavaDoc mode = getDefinitionObject().getString("startModeEnumId");
365
366         if (mode == null) {
367             throw new WfException("Start mode cannot be null");
368         }
369
370         if (mode.equals("WAM_AUTOMATIC")) {
371             Debug.logVerbose("Activity start mode is AUTO", module);
372             Iterator JavaDoc i = getIteratorAssignment();
373             while (i.hasNext())
374                  ((WfAssignment) i.next()).changeStatus("CAL_ACCEPTED"); // accept all assignments (AUTO)
375
Debug.logVerbose("All assignments accepted, starting activity: " + this.runtimeKey(), module);
376             startActivity();
377         } else if (howManyAssignment() > 0 && checkAssignStatus(CHECK_ASSIGN)) {
378             Debug.logVerbose("Starting activity: " + this.runtimeKey(), module);
379             startActivity();
380         }
381     }
382
383     /**
384      * @see org.ofbiz.workflow.WfActivity#complete()
385      */

386     public void complete() throws WfException, CannotComplete {
387         // check to make sure all assignements are complete
388
if (howManyAssignment() > 0 && !checkAssignStatus(CHECK_COMPLETE))
389             throw new CannotComplete("All assignments have not been completed");
390         try {
391             container().receiveResults(this, result());
392         } catch (InvalidData e) {
393             throw new WfException("Invalid result data was passed", e);
394         }
395         try {
396             changeState("closed.completed");
397             GenericValue activityWe = getRuntimeObject();
398             activityWe.set("actualCompletionDate", UtilDateTime.nowTimestamp());
399             activityWe.store();
400         } catch (InvalidState is) {
401             throw new WfException("Invalid WF State", is);
402         } catch (TransitionNotAllowed tna) {
403             throw new WfException(tna.getMessage(), tna);
404         } catch (GenericEntityException gee) {
405             throw new WfException(gee.getMessage(), gee);
406         }
407
408         container().activityComplete(this);
409     }
410     
411     /**
412      * @see org.ofbiz.workflow.WfExecutionObject#resume()
413      */

414     public void resume() throws WfException, CannotResume, NotRunning, NotSuspended {
415         super.resume();
416         try {
417             Debug.logVerbose("Checking to see if we can complete the activity", module);
418             this.checkComplete();
419         } catch (CannotComplete e) {
420             throw new CannotResume("Attempt to complete activity failed", e);
421         }
422     }
423     
424     /**
425      * @see org.ofbiz.workflow.WfExecutionObject#abort()
426      */

427     public void abort() throws WfException, CannotStop, NotRunning {
428         super.abort();
429         
430         // cancel the active assignments
431
Iterator JavaDoc assignments = this.getAssignments().iterator();
432         while (assignments.hasNext()) {
433             WfAssignment assignment = (WfAssignment) assignments.next();
434             assignment.changeStatus("CAL_CANCELLED");
435         }
436     }
437
438     /**
439      * @see org.ofbiz.workflow.WfActivity#isMemberOfAssignment(org.ofbiz.workflow.WfAssignment)
440      */

441     public boolean isMemberOfAssignment(WfAssignment member) throws WfException {
442         return getAssignments().contains(member);
443     }
444
445     /**
446      * @see org.ofbiz.workflow.WfActivity#container()
447      */

448     public WfProcess container() throws WfException {
449         return WfFactory.getWfProcess(delegator, processId);
450     }
451    
452     /**
453      * @see org.ofbiz.workflow.WfActivity#setResult(java.util.Map)
454      */

455     public void setResult(Map JavaDoc newResult) throws WfException, InvalidData {
456         if (newResult != null && newResult.size() > 0) {
457             if (Debug.verboseOn())
458                 Debug.logVerbose(
459                     "[WfActivity.setResult]: putting (" + newResult.size() + ") keys into context.",
460                     module);
461             Map JavaDoc context = processContext();
462             context.putAll(newResult);
463             setSerializedData(context);
464         }
465     }
466
467     /**
468      * @see org.ofbiz.workflow.WfActivity#howManyAssignment()
469      */

470     public int howManyAssignment() throws WfException {
471         return getAssignments().size();
472     }
473
474     /**
475      * @see org.ofbiz.workflow.WfActivity#result()
476      */

477     public Map JavaDoc result() throws WfException, ResultNotAvailable {
478         // Get the results from the signature.
479
Map JavaDoc resultSig = container().manager().resultSignature();
480         Map JavaDoc results = new HashMap JavaDoc();
481         Map JavaDoc context = processContext();
482
483         if (resultSig != null) {
484             Set JavaDoc resultKeys = resultSig.keySet();
485             Iterator JavaDoc i = resultKeys.iterator();
486
487             while (i.hasNext()) {
488                 Object JavaDoc key = i.next();
489                 if (context.containsKey(key))
490                     results.put(key, context.get(key));
491             }
492         }
493         return results;
494     }
495
496     /**
497      * @see org.ofbiz.workflow.WfActivity#getSequenceAssignment(int)
498      */

499     public List JavaDoc getSequenceAssignment(int maxNumber) throws WfException {
500         if (maxNumber > 0)
501             return getAssignments().subList(0, (maxNumber - 1));
502         return getAssignments();
503     }
504
505     /**
506      * @see org.ofbiz.workflow.WfActivity#getIteratorAssignment()
507      */

508     public Iterator JavaDoc getIteratorAssignment() throws WfException {
509         return getAssignments().iterator();
510     }
511
512     /**
513      * @see org.ofbiz.workflow.impl.WfExecutionObjectImpl#executionObjectType()
514      */

515     public String JavaDoc executionObjectType() {
516         return "WfActivity";
517     }
518
519     // Checks to see if we can complete
520
private void checkComplete() throws WfException, CannotComplete {
521         String JavaDoc mode = getDefinitionObject().getString("finishModeEnumId");
522
523         if (mode == null)
524             throw new CannotComplete("Finish mode cannot be null");
525
526         // Default mode is MANUAL -- only finish if we are automatic
527
if (mode.equals("WAM_AUTOMATIC")) {
528             // check and make sure we are not suspended
529
if (state().equals("open.running")) {
530                 // set the status of the assignments
531
Iterator JavaDoc i = getIteratorAssignment();
532                 while (i.hasNext())
533                     ((WfAssignment) i.next()).changeStatus("CAL_COMPLETED");
534                 this.complete();
535             }
536         }
537     }
538
539     // Checks the staus of all assignments
540
// type 1 -> accept status
541
// type 2 -> complete status
542
private boolean checkAssignStatus(int type) throws WfException {
543         boolean acceptAll = false;
544         boolean completeAll = false;
545         GenericValue valueObject = getDefinitionObject();
546
547         if (valueObject.get("acceptAllAssignments") != null)
548             acceptAll = valueObject.getBoolean("acceptAllAssignments").booleanValue();
549         if (valueObject.get("completeAllAssignments") != null)
550             completeAll = valueObject.getBoolean("completeAllAssignments").booleanValue();
551
552         List JavaDoc validStatus = null;
553
554         if (type == CHECK_ASSIGN)
555             validStatus = UtilMisc.toList("CAL_ACCEPTED", "CAL_COMPLETED", "CAL_DELEGATED");
556         else if (type == CHECK_COMPLETE)
557             validStatus = UtilMisc.toList("CAL_COMPLETED", "CAL_DELEGATED");
558         else
559             throw new WfException("Invalid status type");
560
561         boolean foundOne = false;
562
563         List JavaDoc assignList = this.getAllAssignments();
564         Iterator JavaDoc i = assignList.iterator();
565
566         while (i.hasNext()) {
567             GenericValue value = (GenericValue) i.next();
568             String JavaDoc party = value.getString("partyId");
569             String JavaDoc role = value.getString("roleTypeId");
570             String JavaDoc status = value.getString("statusId");
571             java.sql.Timestamp JavaDoc from = value.getTimestamp("fromDate");
572             WfAssignment a = WfFactory.getWfAssignment(getDelegator(), runtimeKey(), party, role, from);
573
574             if (validStatus.contains(a.status())) {
575                 // if we find one set this to true
576
foundOne = true;
577             } else {
578                 // if we must completeAll / assignAll and this one fails return false
579
if ((type == CHECK_COMPLETE && completeAll) || (type == CHECK_ASSIGN && acceptAll))
580                     return false;
581             }
582         }
583         
584         // we are here only if all are done, or complete/assign is false; so if not false we are done
585
if ((type == CHECK_COMPLETE && completeAll) || (type == CHECK_ASSIGN && acceptAll)) {
586             return true;
587         } else {
588             // if not all done, we don't require all, so use that foundOne stored above
589
Debug.logVerbose("[checkAssignStatus] : need only one assignment to pass", module);
590             if (foundOne)
591                 return true;
592             Debug.logVerbose("[checkAssignStatus] : found no assignment(s)", module);
593             return false;
594         }
595     }
596
597     // Starts or activates this automatic activity
598
private void startActivity() throws WfException, CannotStart {
599         try {
600             changeState("open.running");
601         } catch (InvalidState is) {
602             throw new CannotStart(is.getMessage(), is);
603         } catch (TransitionNotAllowed tna) {
604             throw new CannotStart(tna.getMessage(), tna);
605         }
606         // check the limit service
607
boolean limitAfterStart = getDefinitionObject().getBoolean("limitAfterStart").booleanValue();
608
609         if (limitAfterStart
610             && getDefinitionObject().get("limitService") != null
611             && !getDefinitionObject().getString("limitService").equals("")) {
612             Debug.logVerbose("[WfActivity.init]: limit service is after start, setting up now.", module);
613             setLimitService();
614         }
615
616         // set the new previousActivity
617
Map JavaDoc context = processContext();
618
619         context.put("previousActivity", workEffortId);
620         this.setProcessContext(context);
621
622         // set the actualStartDate
623
try {
624             GenericValue v = getRuntimeObject();
625             v.set("actualStartDate", UtilDateTime.nowTimestamp());
626             v.store();
627         } catch (GenericEntityException e) {
628             Debug.logWarning("Could not set 'actualStartDate'.", module);
629             e.printStackTrace();
630         }
631
632         // get the type of this activity
633
String JavaDoc type = getDefinitionObject().getString("activityTypeEnumId");
634
635         if (type == null)
636             throw new WfException("Illegal activity type");
637
638         WfActivityAbstractImplementation executor = WfActivityImplementationFact.getConcretImplementation(type, this);
639         executor.run();
640         this.setResult(executor.getResult());
641         if (executor.isComplete())
642             this.checkComplete();
643     }
644
645     // schedule the limit service to run
646
private void setLimitService() throws WfException {
647         LocalDispatcher dispatcher = getDispatcher();
648
649        
650         DispatchContext dctx = dispatcher.getDispatchContext();
651         String JavaDoc limitService = getDefinitionObject().getString("limitService");
652         ModelService service = null;
653
654         try {
655             service = dctx.getModelService(limitService);
656             Debug.logVerbose("[WfActivity.setLimitService] : Found service model.", module);
657         } catch (GenericServiceException e) {
658             Debug.logError(e, "[WfActivity.setLimitService] : Cannot get service model.", module);
659         }
660         if (service == null) {
661             Debug.logWarning("[WfActivity.setLimitService] : Cannot determine limit service, ignoring.", module);
662             return;
663         }
664
665         // make the limit service context
666
List JavaDoc inList = new ArrayList JavaDoc(service.getInParamNames());
667         String JavaDoc inParams = StringUtil.join(inList, ",");
668         
669         Map JavaDoc serviceContext = actualContext(inParams, null, null, true);
670         Debug.logVerbose("Setting limit service with context: " + serviceContext, module);
671
672         Double JavaDoc timeLimit = null;
673
674         if (getDefinitionObject().get("timeLimit") != null)
675             timeLimit = getDefinitionObject().getDouble("timeLimit");
676         if (timeLimit == null)
677             return;
678
679         String JavaDoc durationUOM = null;
680
681         if (container().getDefinitionObject().getString("durationUomId") != null)
682             durationUOM = container().getDefinitionObject().getString("durationUomId");
683         if (durationUOM == null)
684             return;
685
686         char durChar = durationUOM.charAt(0);
687         Calendar JavaDoc cal = Calendar.getInstance();
688
689         cal.setTime(new Date JavaDoc());
690         switch (durChar) {
691             case 'Y' :
692                 cal.add(Calendar.YEAR, timeLimit.intValue());
693                 break;
694
695             case 'M' :
696                 cal.add(Calendar.MONTH, timeLimit.intValue());
697                 break;
698
699             case 'D' :
700                 cal.add(Calendar.DATE, timeLimit.intValue());
701                 break;
702
703             case 'h' :
704                 cal.add(Calendar.HOUR, timeLimit.intValue());
705                 break;
706
707             case 'm' :
708                 cal.add(Calendar.MINUTE, timeLimit.intValue());
709                 break;
710
711             case 's' :
712                 cal.add(Calendar.SECOND, timeLimit.intValue());
713                 break;
714
715             default :
716                 throw new WfException("Invalid duration unit");
717         }
718
719         long startTime = cal.getTime().getTime();
720         Map JavaDoc context = new HashMap JavaDoc();
721
722         context.put("serviceName", limitService);
723         context.put("serviceContext", serviceContext);
724         context.put("workEffortId", runtimeKey());
725
726         try {
727             dispatcher.schedule("wfLimitInvoker", context, startTime); // yes we are hard coded!
728
} catch (GenericServiceException e) {
729             throw new WfException(e.getMessage(), e);
730         }
731         if (Debug.verboseOn()) {
732             Debug.logVerbose("[WfActivity.setLimitService]: Set limit service (" + limitService + " ) to run at " + startTime, module);
733         }
734     }
735
736     Map JavaDoc actualContext(String JavaDoc actualParameters, String JavaDoc extendedAttr, List JavaDoc serviceSignature, boolean ignoreUnknown) throws WfException {
737         Map JavaDoc actualContext = new HashMap JavaDoc();
738         Map JavaDoc context = processContext();
739
740         // extended attributes take priority over context attributes
741
Map JavaDoc extendedAttributes = StringUtil.strToMap(extendedAttr);
742
743         if (extendedAttributes != null && extendedAttributes.size() > 0) {
744             context.putAll(extendedAttributes);
745         }
746
747         // setup some internal buffer parameters
748
GenericValue userLogin = null;
749
750         if (context.containsKey("runAsUser")) {
751             userLogin = getUserLogin((String JavaDoc) context.get("runAsUser"));
752             actualContext.put("userLogin", userLogin);
753         } else if (context.containsKey("workflowOwnerId")) {
754             userLogin = getUserLogin((String JavaDoc) context.get("workflowOwnerId"));
755         }
756
757         // some static context values
758
context.put("userLogin", userLogin);
759         context.put("workEffortId", runtimeKey());
760         if (howManyAssignment() == 1) {
761             Debug.logVerbose("Single assignment; getting assignment info.", module);
762             List JavaDoc assignments = getAssignments();
763             WfAssignment assign = (WfAssignment) assignments.iterator().next();
764             WfResource res = assign.assignee();
765             context.put("assignedPartyId", res.resourcePartyId());
766             context.put("assignedRoleTypeId", res.resourceRoleId());
767         }
768                         
769         // first we will pull out the values from the context for the actual parameters
770
if (actualParameters != null) {
771             List JavaDoc params = StringUtil.split(actualParameters, ",");
772             Iterator JavaDoc i = params.iterator();
773
774             while (i.hasNext()) {
775                 Object JavaDoc key = i.next();
776                 String JavaDoc keyStr = (String JavaDoc) key;
777                 
778                 if (keyStr != null && keyStr.trim().toLowerCase().startsWith("expr:")) {
779                     // check for bsh expressions; this does not place values into the context
780
try {
781                         BshUtil.eval(keyStr.trim().substring(5).trim(), context);
782                     } catch (bsh.EvalError e) {
783                         throw new WfException("Bsh evaluation error.", e);
784                     }
785                 } else if (keyStr != null && keyStr.trim().toLowerCase().startsWith("name:")) {
786                     // name mapping of context values
787
List JavaDoc couple = StringUtil.split(keyStr.trim().substring(5).trim(), "=");
788                     String JavaDoc mName = (String JavaDoc) couple.get(0); // mapped name
789
String JavaDoc cName = (String JavaDoc) couple.get(1); // context name
790

791                     // trim out blank space
792
if (mName != null) mName = mName.trim();
793                     if (cName != null) cName = cName.trim();
794                                                            
795                     if (mName != null && cName != null && context.containsKey(cName)) {
796                         actualContext.put(mName, context.get(cName));
797                     }
798                 } else if (context.containsKey(key)) {
799                     // direct assignment from context
800
actualContext.put(key, context.get(key));
801                 } else if (!actualContext.containsKey(key) && !ignoreUnknown) {
802                     throw new WfException("Context does not contain the key: '" + (String JavaDoc) key + "'");
803                 }
804             }
805         }
806         
807         // the serviceSignature should not limit which parameters are in the actualContext
808
// so instead we will use this signature to pull out values so they do not all have to be defined
809
if (serviceSignature != null) {
810             Iterator JavaDoc si = serviceSignature.iterator();
811             while (si.hasNext()) {
812                 Object JavaDoc key = si.next();
813                 String JavaDoc keyStr = (String JavaDoc) key;
814                 if (!actualContext.containsKey(key) && context.containsKey(key)) {
815                     actualContext.put(keyStr, context.get(keyStr));
816                 }
817             }
818         }
819         return actualContext;
820     }
821
822     // Gets a UserLogin object for service invocation
823
// This allows a workflow to invoke a service as a specific user
824
private GenericValue getUserLogin(String JavaDoc userId) throws WfException {
825         GenericValue userLogin = null;
826         try {
827             userLogin = getDelegator().findByPrimaryKey("UserLogin", UtilMisc.toMap("userLoginId", userId));
828         } catch (GenericEntityException e) {
829             throw new WfException(e.getMessage(), e);
830         }
831         return userLogin;
832     }
833 }
834
Popular Tags