001: /*
002: * $Id: WfExecutionObjectImpl.java,v 1.6 2003/09/02 02:17:15 ajzeneski Exp $
003: *
004: * Copyright (c) 2001, 2002 The Open For Business Project - www.ofbiz.org
005: *
006: * Permission is hereby granted, free of charge, to any person obtaining a
007: * copy of this software and associated documentation files (the "Software"),
008: * to deal in the Software without restriction, including without limitation
009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
010: * and/or sell copies of the Software, and to permit persons to whom the
011: * Software is furnished to do so, subject to the following conditions:
012: *
013: * The above copyright notice and this permission notice shall be included
014: * in all copies or substantial portions of the Software.
015: *
016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
023: *
024: */
025: package org.ofbiz.workflow.impl;
026:
027: import java.io.FileNotFoundException;
028: import java.io.IOException;
029: import java.sql.Timestamp;
030: import java.util.ArrayList;
031: import java.util.Arrays;
032: import java.util.Date;
033: import java.util.HashMap;
034: import java.util.Iterator;
035: import java.util.List;
036: import java.util.Map;
037:
038: import org.ofbiz.base.util.BshUtil;
039: import org.ofbiz.base.util.Debug;
040: import org.ofbiz.base.util.FlexibleStringExpander;
041: import org.ofbiz.base.util.ObjectType;
042: import org.ofbiz.base.util.UtilMisc;
043: import org.ofbiz.entity.GenericDelegator;
044: import org.ofbiz.entity.GenericEntityException;
045: import org.ofbiz.entity.GenericValue;
046: import org.ofbiz.entity.serialize.SerializeException;
047: import org.ofbiz.entity.serialize.XmlSerializer;
048: import org.ofbiz.service.DispatchContext;
049: import org.ofbiz.service.GenericDispatcher;
050: import org.ofbiz.service.GenericServiceException;
051: import org.ofbiz.service.LocalDispatcher;
052: import org.ofbiz.workflow.AlreadySuspended;
053: import org.ofbiz.workflow.CannotResume;
054: import org.ofbiz.workflow.CannotStop;
055: import org.ofbiz.workflow.CannotSuspend;
056: import org.ofbiz.workflow.EvaluationException;
057: import org.ofbiz.workflow.HistoryNotAvailable;
058: import org.ofbiz.workflow.InvalidData;
059: import org.ofbiz.workflow.InvalidState;
060: import org.ofbiz.workflow.NotRunning;
061: import org.ofbiz.workflow.NotSuspended;
062: import org.ofbiz.workflow.TransitionCondition;
063: import org.ofbiz.workflow.TransitionNotAllowed;
064: import org.ofbiz.workflow.UpdateNotAllowed;
065: import org.ofbiz.workflow.WfException;
066: import org.ofbiz.workflow.WfExecutionObject;
067: import org.ofbiz.workflow.WfUtil;
068:
069: /**
070: * WfExecutionObjectImpl - Workflow Execution Object implementation
071: *
072: * @author <a href="mailto:jaz@ofbiz.org">Andy Zeneski</a>
073: * @author David Ostrovsky (d.ostrovsky@gmx.de)
074: * @version $Revision: 1.6 $
075: * @since 2.0
076: */
077: public abstract class WfExecutionObjectImpl implements
078: WfExecutionObject {
079:
080: public static final String module = WfExecutionObjectImpl.class
081: .getName();
082: public static final String dispatcherName = "WFDispatcher";
083:
084: protected String packageId = null;
085: protected String packageVersion = null;
086: protected String processId = null;
087: protected String processVersion = null;
088: protected String activityId = null;
089: protected String workEffortId = null;
090: protected GenericDelegator delegator = null;
091: protected List history = null;
092:
093: public WfExecutionObjectImpl(GenericValue valueObject,
094: String parentId) throws WfException {
095: this .packageId = valueObject.getString("packageId");
096: this .packageVersion = valueObject.getString("packageVersion");
097: this .processId = valueObject.getString("processId");
098: this .processVersion = valueObject.getString("processVersion");
099: if (valueObject.getEntityName().equals("WorkflowActivity")) {
100: this .activityId = valueObject.getString("activityId");
101: } else {
102: this .activityId = null;
103: }
104: this .delegator = valueObject.getDelegator();
105: createRuntime(parentId);
106: }
107:
108: public WfExecutionObjectImpl(GenericDelegator delegator,
109: String workEffortId) throws WfException {
110: this .delegator = delegator;
111: this .workEffortId = workEffortId;
112: this .packageId = getRuntimeObject().getString(
113: "workflowPackageId");
114: this .packageVersion = getRuntimeObject().getString(
115: "workflowPackageVersion");
116: this .processId = getRuntimeObject().getString(
117: "workflowProcessId");
118: this .processVersion = getRuntimeObject().getString(
119: "workflowProcessVersion");
120: this .activityId = getRuntimeObject().getString(
121: "workflowActivityId");
122: this .history = null;
123: if (Debug.verboseOn())
124: Debug.logVerbose(" Package ID: " + packageId + " V: "
125: + packageVersion, module);
126: if (Debug.verboseOn())
127: Debug.logVerbose(" Process ID: " + processId + " V: "
128: + processVersion, module);
129: if (Debug.verboseOn())
130: Debug.logVerbose("Activity ID: " + activityId, module);
131: }
132:
133: // creates the stored runtime workeffort data.
134: private void createRuntime(String parentId) throws WfException {
135: GenericValue valueObject = getDefinitionObject();
136: GenericValue dataObject = null;
137:
138: workEffortId = getDelegator().getNextSeqId("WorkEffort")
139: .toString();
140: Map dataMap = new HashMap();
141: String weType = activityId != null ? "ACTIVITY" : "WORK_FLOW";
142:
143: dataMap.put("workEffortId", workEffortId);
144: dataMap.put("workEffortTypeId", weType);
145: dataMap.put("workEffortParentId", parentId);
146: dataMap.put("workflowPackageId", packageId);
147: dataMap.put("workflowPackageVersion", packageVersion);
148: dataMap.put("workflowProcessId", processId);
149: dataMap.put("workflowProcessVersion", processVersion);
150: dataMap.put("workEffortName", valueObject
151: .getString("objectName"));
152: dataMap
153: .put("description", valueObject
154: .getString("description"));
155: dataMap.put("createdDate",
156: new Timestamp((new Date()).getTime()));
157: dataMap.put("estimatedStartDate", dataMap.get("createdDate"));
158: dataMap.put("lastModifiedDate", dataMap.get("createdDate"));
159: dataMap.put("priority", valueObject.getLong("objectPriority"));
160: dataMap.put("currentStatusId", WfUtil
161: .getOFBStatus("open.not_running.not_started"));
162: if (activityId != null)
163: dataMap.put("workflowActivityId", activityId);
164: if (activityId != null && parentId != null) {
165: GenericValue parentWorkEffort = getWorkEffort(parentId);
166: if (parentWorkEffort != null
167: && parentWorkEffort.get("sourceReferenceId") != null)
168: dataMap.put("sourceReferenceId", parentWorkEffort
169: .getString("sourceReferenceId"));
170: }
171:
172: try {
173: dataObject = getDelegator()
174: .makeValue("WorkEffort", dataMap);
175: getDelegator().create(dataObject);
176:
177: String objectId = activityId != null ? activityId
178: : processId;
179: if (Debug.verboseOn())
180: Debug.logVerbose("Created new runtime object ["
181: + objectId + "] (Workeffort: " + runtimeKey()
182: + ")", module);
183: } catch (GenericEntityException e) {
184: throw new WfException(e.getMessage(), e);
185: }
186: }
187:
188: protected void parseDescriptions(Map parseContext)
189: throws WfException {
190: GenericValue runtime = getRuntimeObject();
191: String name = runtime.getString("workEffortName");
192: String desc = runtime.getString("description");
193: String nameExp = FlexibleStringExpander.expandString(name,
194: parseContext);
195: String descExp = FlexibleStringExpander.expandString(desc,
196: parseContext);
197:
198: boolean changed = false;
199: if (nameExp != null && !nameExp.equals(name)) {
200: changed = true;
201: runtime.set("workEffortName", nameExp);
202: }
203: if (descExp != null && !descExp.equals(desc)) {
204: changed = true;
205: runtime.set("description", descExp);
206: }
207:
208: if (changed) {
209: try {
210: runtime.store();
211: } catch (GenericEntityException e) {
212: throw new WfException(e.getMessage(), e);
213: }
214: }
215: }
216:
217: /**
218: * @see org.ofbiz.workflow.WfExecutionObject#name()
219: */
220: public String name() throws WfException {
221: return getRuntimeObject().getString("workEffortName");
222: }
223:
224: /**
225: * @see org.ofbiz.workflow.WfExecutionObject#setName(java.lang.String)
226: */
227: public void setName(String newValue) throws WfException {
228: GenericValue dataObject = getRuntimeObject();
229:
230: try {
231: dataObject.set("workEffortName", newValue);
232: dataObject.store();
233: } catch (GenericEntityException e) {
234: throw new WfException(e.getMessage(), e);
235: }
236: }
237:
238: /**
239: * @see org.ofbiz.workflow.WfExecutionObject#setPriority(long)
240: */
241: public void setPriority(long newValue) throws WfException {
242: GenericValue dataObject = getRuntimeObject();
243:
244: try {
245: dataObject.set("priority", new Long(newValue));
246: dataObject.store();
247: } catch (GenericEntityException e) {
248: throw new WfException(e.getMessage(), e);
249: }
250: }
251:
252: /**
253: * @see org.ofbiz.workflow.WfExecutionObject#priority()
254: */
255: public long priority() throws WfException {
256: if (getRuntimeObject().get("priority") != null)
257: return getRuntimeObject().getLong("priority").longValue();
258: return 0; // change to default priority value
259: }
260:
261: /**
262: * @see org.ofbiz.workflow.WfExecutionObject#state()
263: */
264: public String state() throws WfException {
265: GenericValue statusObj = null;
266: String stateStr = null;
267:
268: try {
269: statusObj = getRuntimeObject().getRelatedOne(
270: "CurrentStatusItem");
271: } catch (GenericEntityException e) {
272: throw new WfException(e.getMessage(), e);
273: }
274: if (statusObj != null)
275: stateStr = statusObj.getString("statusCode");
276:
277: if (stateStr == null)
278: throw new WfException("Stored state is not a valid type.");
279:
280: if (Debug.verboseOn())
281: Debug.logVerbose("Current state: " + stateStr, module);
282: return stateStr;
283: }
284:
285: /**
286: * @see org.ofbiz.workflow.WfExecutionObject#validStates()
287: */
288: public List validStates() throws WfException {
289: String statesArr[] = { "open.running",
290: "open.not_running.not_started",
291: "open.not_running.suspended", "closed.completed",
292: "closed.terminated", "closed.aborted" };
293: ArrayList possibleStates = new ArrayList(Arrays
294: .asList(statesArr));
295: String currentState = state();
296:
297: if (currentState.startsWith("closed"))
298: return new ArrayList();
299: if (!currentState.startsWith("open"))
300: throw new WfException("Currently in an unknown state.");
301: if (currentState.equals("open.running")) {
302: possibleStates.remove("open.running");
303: possibleStates.remove("open.not_running.not_started");
304: return possibleStates;
305: }
306: if (currentState.equals("open.not_running.not_started")) {
307: possibleStates.remove("open.not_running.not_started");
308: possibleStates.remove("open.not_running.suspended");
309: possibleStates.remove("closed.completed");
310: possibleStates.remove("closed.terminated");
311: return possibleStates;
312: }
313: if (currentState.equals("open.not_running.suspended")) {
314: possibleStates.remove("open.not_running.suspended");
315: possibleStates.remove("open.not_running.not_started");
316: possibleStates.remove("closed.complete");
317: possibleStates.remove("closed.terminated");
318: return possibleStates;
319: }
320: return new ArrayList();
321: }
322:
323: /**
324: * @see org.ofbiz.workflow.WfExecutionObject#howManyHistory()
325: */
326: public int howManyHistory() throws WfException, HistoryNotAvailable {
327: if (history.size() < 1)
328: throw new HistoryNotAvailable();
329: return history.size();
330: }
331:
332: /**
333: * @see org.ofbiz.workflow.WfExecutionObject#abort()
334: */
335: public void abort() throws WfException, CannotStop, NotRunning {
336: Debug.logInfo("Aborting current state : " + state(), module);
337: String stateStr = "closed.aborted";
338:
339: if (!state().startsWith("open")) {
340: throw new NotRunning();
341: }
342:
343: if (!validStates().contains(stateStr)) {
344: throw new CannotStop();
345: }
346:
347: changeState(stateStr);
348: }
349:
350: /**
351: * @see org.ofbiz.workflow.WfExecutionObject#whileOpenType()
352: */
353: public List whileOpenType() throws WfException {
354: String[] list = { "running", "not_running" };
355:
356: return Arrays.asList(list);
357: }
358:
359: /**
360: * @see org.ofbiz.workflow.WfExecutionObject#whyNotRunningType()
361: */
362: public List whyNotRunningType() throws WfException {
363: String[] list = { "not_started", "suspended" };
364:
365: return Arrays.asList(list);
366: }
367:
368: /**
369: * @see org.ofbiz.workflow.WfExecutionObject#runtimeKey()
370: */
371: public String runtimeKey() throws WfException {
372: return getRuntimeObject().getString("workEffortId");
373: }
374:
375: /**
376: * @see org.ofbiz.workflow.WfExecutionObject#key()
377: */
378: public String key() throws WfException {
379: if (activityId != null)
380: return activityId;
381: else
382: return processId;
383: }
384:
385: /**
386: * @see org.ofbiz.workflow.WfExecutionObject#isMemberOfHistory(org.ofbiz.workflow.WfExecutionObject)
387: */
388: public boolean isMemberOfHistory(WfExecutionObject member)
389: throws WfException {
390: return false;
391: }
392:
393: /**
394: * @see org.ofbiz.workflow.WfExecutionObject#setProcessContext(java.util.Map)
395: */
396: public void setProcessContext(Map newValue) throws WfException,
397: InvalidData, UpdateNotAllowed {
398: setSerializedData(newValue);
399: }
400:
401: /**
402: * @see org.ofbiz.workflow.WfExecutionObject#setProcessContext(java.lang.String)
403: */
404: public void setProcessContext(String contextKey)
405: throws WfException, InvalidData, UpdateNotAllowed {
406: GenericValue dataObject = getRuntimeObject();
407:
408: try {
409: dataObject.set("runtimeDataId", contextKey);
410: dataObject.store();
411: } catch (GenericEntityException e) {
412: throw new WfException(e.getMessage(), e);
413: }
414: }
415:
416: /**
417: * @see org.ofbiz.workflow.WfExecutionObject#contextKey()
418: */
419: public String contextKey() throws WfException {
420: if (getRuntimeObject().get("runtimeDataId") == null)
421: return null;
422: else
423: return getRuntimeObject().getString("runtimeDataId");
424: }
425:
426: /**
427: * @see org.ofbiz.workflow.WfExecutionObject#processContext()
428: */
429: public Map processContext() throws WfException {
430: return getContext();
431: }
432:
433: /**
434: * @see org.ofbiz.workflow.WfExecutionObject#workflowStateType()
435: */
436: public List workflowStateType() throws WfException {
437: String[] list = { "open", "closed" };
438: return Arrays.asList(list);
439: }
440:
441: /**
442: * @see org.ofbiz.workflow.WfExecutionObject#terminate()
443: */
444: public void terminate() throws WfException, CannotStop, NotRunning {
445: String stateStr = "closed.terminated";
446:
447: if (!state().equals("open.running"))
448: throw new NotRunning();
449: if (!validStates().contains(stateStr))
450: throw new CannotStop();
451: changeState(stateStr);
452: }
453:
454: /**
455: * @see org.ofbiz.workflow.WfExecutionObject#setDescription(java.lang.String)
456: */
457: public void setDescription(String newValue) throws WfException {
458: GenericValue valueObject = getDefinitionObject();
459:
460: try {
461: valueObject.set("description", newValue);
462: valueObject.store();
463: } catch (GenericEntityException e) {
464: throw new WfException(e.getMessage(), e);
465: }
466: }
467:
468: /**
469: * @see org.ofbiz.workflow.WfExecutionObject#description()
470: */
471: public String description() throws WfException {
472: return getDefinitionObject().getString("description");
473: }
474:
475: /**
476: * @see org.ofbiz.workflow.WfExecutionObject#lastStateTime()
477: */
478: public Timestamp lastStateTime() throws WfException {
479: GenericValue dataObject = getRuntimeObject();
480:
481: if (dataObject == null
482: || dataObject.get("lastStatusUpdate") == null)
483: throw new WfException(
484: "No runtime object or status has never been set.");
485: return dataObject.getTimestamp("lastStatusUpdate");
486: }
487:
488: /**
489: * @see org.ofbiz.workflow.WfExecutionObject#getSequenceHistory(int)
490: */
491: public List getSequenceHistory(int maxNumber) throws WfException,
492: HistoryNotAvailable {
493: return history;
494: }
495:
496: /**
497: * @see org.ofbiz.workflow.WfExecutionObject#getIteratorHistory(java.lang.String, java.util.Map)
498: */
499: public Iterator getIteratorHistory(String query, Map namesInQuery)
500: throws WfException, HistoryNotAvailable {
501: return history.iterator();
502: }
503:
504: /**
505: * @see org.ofbiz.workflow.WfExecutionObject#resume()
506: */
507: public void resume() throws WfException, CannotResume, NotRunning,
508: NotSuspended {
509: if (!state().equals("open.not_running.suspended")) {
510: if (state().equals("open.not_running.not_started")) {
511: throw new NotRunning();
512: } else if (state().startsWith("closed")) {
513: throw new CannotResume();
514: } else {
515: throw new NotSuspended();
516: }
517: } else {
518: changeState("open.running");
519: }
520: }
521:
522: /**
523: * @see org.ofbiz.workflow.WfExecutionObject#howClosedType()
524: */
525: public List howClosedType() throws WfException {
526: String[] list = { "completed", "terminated", "aborted" };
527:
528: return Arrays.asList(list);
529: }
530:
531: /**
532: * @see org.ofbiz.workflow.WfExecutionObject#changeState(java.lang.String)
533: */
534: public void changeState(String newState) throws WfException,
535: InvalidState, TransitionNotAllowed {
536: // Test is transaction is allowed???
537: GenericValue dataObject = getRuntimeObject();
538:
539: if (validStates().contains(newState)) {
540: try {
541: long now = (new Date()).getTime();
542:
543: dataObject.set("currentStatusId", WfUtil
544: .getOFBStatus(newState));
545: dataObject.set("lastStatusUpdate", new Timestamp(now));
546: dataObject.store();
547: } catch (GenericEntityException e) {
548: throw new WfException(e.getMessage(), e);
549: }
550: } else {
551: throw new InvalidState();
552: }
553: }
554:
555: /**
556: * @see org.ofbiz.workflow.WfExecutionObject#suspend()
557: */
558: public void suspend() throws WfException, CannotSuspend,
559: NotRunning, AlreadySuspended {
560: changeState("open.not_running.suspended");
561: }
562:
563: /**
564: * @see org.ofbiz.workflow.WfExecutionObject#getDelegator()
565: */
566: public GenericDelegator getDelegator() throws WfException {
567: return delegator;
568: }
569:
570: /**
571: * @see org.ofbiz.workflow.WfExecutionObject#getDefinitionObject()
572: */
573: public GenericValue getDefinitionObject() throws WfException {
574: String entityName = activityId != null ? "WorkflowActivity"
575: : "WorkflowProcess";
576: GenericValue value = null;
577: Map fields = UtilMisc.toMap("packageId", packageId,
578: "packageVersion", packageVersion, "processId",
579: processId, "processVersion", processVersion);
580:
581: if (activityId != null)
582: fields.put("activityId", activityId);
583: try {
584: value = getDelegator().findByPrimaryKey(entityName, fields);
585: } catch (GenericEntityException e) {
586: throw new WfException(e.getMessage(), e);
587: }
588: return value;
589: }
590:
591: public GenericValue getRuntimeObject() throws WfException {
592: GenericValue value = null;
593:
594: try {
595: value = getDelegator().findByPrimaryKey("WorkEffort",
596: UtilMisc.toMap("workEffortId", workEffortId));
597: } catch (GenericEntityException e) {
598: throw new WfException(e.getMessage(), e);
599: }
600: return value;
601: }
602:
603: /**
604: * Getter for this type of execution object.
605: * @return String
606: */
607: public abstract String executionObjectType();
608:
609: /**
610: * Updates the runtime data entity
611: * @param field The field name of the entity (resultDataId,contextDataId)
612: * @param value The value to serialize and set
613: * @throws WfException
614: */
615: protected void setSerializedData(Map value) throws WfException,
616: InvalidData {
617: GenericValue runtimeData = null;
618: GenericValue dataObject = getRuntimeObject();
619:
620: try {
621: if (dataObject.get("runtimeDataId") == null) {
622: String seqId = getDelegator().getNextSeqId(
623: "RuntimeData").toString();
624:
625: runtimeData = getDelegator().makeValue("RuntimeData",
626: UtilMisc.toMap("runtimeDataId", seqId));
627: getDelegator().create(runtimeData);
628: dataObject.set("runtimeDataId", seqId);
629: dataObject.store();
630: } else {
631: runtimeData = dataObject.getRelatedOne("RuntimeData");
632: }
633: // String serialized = XmlSerializer.serialize(value);
634: // System.out.println(serialized);
635:
636: runtimeData.set("runtimeInfo", XmlSerializer
637: .serialize(value));
638: runtimeData.store();
639: } catch (GenericEntityException e) {
640: throw new WfException(e.getMessage(), e);
641: } catch (SerializeException e) {
642: throw new InvalidData(e.getMessage(), e);
643: } catch (FileNotFoundException e) {
644: throw new InvalidData(e.getMessage(), e);
645: } catch (IOException e) {
646: throw new InvalidData(e.getMessage(), e);
647: }
648: }
649:
650: /**
651: * Get an instance of the local dispatcher
652: * @return LocalDispatcher instance for use with this workflow
653: * @throws WfException
654: */
655: protected LocalDispatcher getDispatcher() throws WfException {
656: try {
657: return GenericDispatcher.getLocalDispatcher(dispatcherName,
658: getDelegator());
659: } catch (GenericServiceException e) {
660: throw new WfException("No workflow service dispatcher", e);
661: }
662: }
663:
664: private Map getContext() throws WfException {
665: GenericValue dataObject = getRuntimeObject();
666: String contextXML = null;
667: Map context = null;
668:
669: if (dataObject.get("runtimeDataId") == null)
670: return context;
671: try {
672: GenericValue runtimeData = dataObject
673: .getRelatedOne("RuntimeData");
674:
675: contextXML = runtimeData.getString("runtimeInfo");
676: } catch (GenericEntityException e) {
677: throw new WfException(e.getMessage(), e);
678: }
679: // De-serialize the context
680: if (contextXML != null) {
681: try {
682: context = (Map) XmlSerializer.deserialize(contextXML,
683: getDelegator());
684: } catch (SerializeException e) {
685: throw new WfException(e.getMessage(), e);
686: } catch (IOException e) {
687: throw new WfException(e.getMessage(), e);
688: } catch (Exception e) {
689: throw new WfException(e.getMessage(), e);
690: }
691: }
692: return context;
693: }
694:
695: private GenericValue getWorkEffort(String workEffortId)
696: throws WfException {
697: GenericValue we = null;
698: try {
699: we = getDelegator().findByPrimaryKey("WorkEffort",
700: UtilMisc.toMap("workEffortId", workEffortId));
701: } catch (GenericEntityException e) {
702: throw new WfException("Problem getting WorkEffort entity ("
703: + workEffortId + ")", e);
704: }
705: return we;
706: }
707:
708: /**
709: * Evaluate a condition expression using an implementation of TransitionCondition
710: * @param className The class name of the TransitionCondition implementation
711: * @param expression The expression to evaluate
712: * @return The result of the evaluation (True/False)
713: * @throws WfException
714: */
715: protected boolean evalConditionClass(String className,
716: String expression, Map context, Map attrs)
717: throws WfException {
718: // attempt to load and instance of the class
719: Object conditionObject = null;
720: try {
721: conditionObject = ObjectType.getInstance(className);
722: } catch (ClassNotFoundException e) {
723: Debug.logError(e, "Cannot load class " + className, module);
724: return false;
725: } catch (InstantiationException e) {
726: Debug.logError(e, "Cannot get instance of class "
727: + className, module);
728: return false;
729: } catch (IllegalAccessException e) {
730: Debug.logError(e, "Cannot access class " + className,
731: module);
732: return false;
733: }
734:
735: // make sure we implement the TransitionCondition interface
736: if (!ObjectType.instanceOf(conditionObject,
737: "org.ofbiz.workflow.TransitionCondition")) {
738: Debug.logError("Class " + className
739: + " is not an instance of TransitionCondition",
740: module);
741: return false;
742: }
743:
744: // cast to the interface
745: TransitionCondition cond = (TransitionCondition) conditionObject;
746:
747: // trim up the expression if it isn't empty
748: if (expression != null)
749: expression = expression.trim();
750:
751: // get a DispatchContext object to pass over to the eval
752: DispatchContext dctx = this .getDispatcher()
753: .getDispatchContext();
754:
755: // evaluate the condition
756: Boolean evaluation = null;
757: try {
758: evaluation = cond.evaluateCondition(context, attrs,
759: expression, dctx);
760: } catch (EvaluationException e) {
761: throw new WfException("Problems evaluating condition", e);
762: }
763:
764: return evaluation.booleanValue();
765: }
766:
767: /**
768: * Evaluate a condition expression using BeanShell
769: * @param expression The expression to evaluate
770: * @param context The context to use in evaluation
771: * @return The result of the evaluation (True/False)
772: * @throws WfException
773: */
774: protected boolean evalBshCondition(String expression, Map context)
775: throws WfException {
776: if (expression == null || expression.length() == 0) {
777: Debug
778: .logVerbose(
779: "Null or empty expression, returning true.",
780: module);
781: return true;
782: }
783:
784: Object o = null;
785: try {
786: o = BshUtil.eval(expression.trim(), context);
787: } catch (bsh.EvalError e) {
788: throw new WfException("Bsh evaluation error.", e);
789: }
790:
791: if (o == null)
792: return false;
793: else if (o instanceof Number)
794: return (((Number) o).doubleValue() == 0) ? false : true;
795: else
796: return (!o.toString().equalsIgnoreCase("true")) ? false
797: : true;
798: }
799: }
|