From 30cd736670a579985890d8c2dfe363bacbad7568 Mon Sep 17 00:00:00 2001 From: Andrew Branson Date: Sun, 27 Oct 2013 00:27:24 +0200 Subject: Beta? --- .../com/c2kernel/lifecycle/ActivitySlotDef.java | 10 ++++-- .../java/com/c2kernel/lifecycle/AndSplitDef.java | 2 +- .../com/c2kernel/lifecycle/WfCastorHashMap.java | 6 ++-- .../com/c2kernel/lifecycle/instance/Activity.java | 34 ++++++++++++++---- .../lifecycle/instance/CompositeActivity.java | 11 ++++-- .../com/c2kernel/lifecycle/instance/OrSplit.java | 2 +- .../com/c2kernel/lifecycle/instance/WfVertex.java | 6 ++-- .../com/c2kernel/lifecycle/instance/XOrSplit.java | 2 +- .../instance/predefined/PredefinedStep.java | 10 ++++-- .../lifecycle/instance/stateMachine/State.java | 5 +++ .../instance/stateMachine/StateMachine.java | 41 ++++++++++++++-------- .../instance/stateMachine/Transition.java | 21 ++++++++--- src/main/java/com/c2kernel/process/Bootstrap.java | 4 +++ .../java/com/c2kernel/utils/StateMachineCache.java | 1 + 14 files changed, 113 insertions(+), 42 deletions(-) (limited to 'src/main/java') diff --git a/src/main/java/com/c2kernel/lifecycle/ActivitySlotDef.java b/src/main/java/com/c2kernel/lifecycle/ActivitySlotDef.java index f2cabaa..9a3819b 100644 --- a/src/main/java/com/c2kernel/lifecycle/ActivitySlotDef.java +++ b/src/main/java/com/c2kernel/lifecycle/ActivitySlotDef.java @@ -39,7 +39,7 @@ public class ActivitySlotDef extends WfVertexDef public ActivitySlotDef() { getProperties().put("Name", ""); - getProperties().put("Version", "last"); + getProperties().put("Version", 0); } public ActivityDef getTheActivityDef() throws ObjectNotFoundException, InvalidDataException @@ -142,9 +142,13 @@ public class ActivitySlotDef extends WfVertexDef { return (String) getProperties().get("Name"); } - public int getActVersion() + public int getActVersion() throws InvalidDataException { - return (Integer) getProperties().get("Version"); + Object verObj = getProperties().get("Version"); + if (verObj instanceof Integer) + return (Integer)verObj; + else + throw new InvalidDataException("Version string was not an integer", ""); } @Override diff --git a/src/main/java/com/c2kernel/lifecycle/AndSplitDef.java b/src/main/java/com/c2kernel/lifecycle/AndSplitDef.java index af87b18..014fecc 100644 --- a/src/main/java/com/c2kernel/lifecycle/AndSplitDef.java +++ b/src/main/java/com/c2kernel/lifecycle/AndSplitDef.java @@ -20,7 +20,7 @@ public class AndSplitDef extends WfVertexDef { mErrors = new Vector(0, 1); getProperties().put("RoutingScriptName", ""); - getProperties().put("RoutingScriptVersion", ""); + getProperties().put("RoutingScriptVersion", -1); } /** diff --git a/src/main/java/com/c2kernel/lifecycle/WfCastorHashMap.java b/src/main/java/com/c2kernel/lifecycle/WfCastorHashMap.java index e47fdc6..a52fcfe 100644 --- a/src/main/java/com/c2kernel/lifecycle/WfCastorHashMap.java +++ b/src/main/java/com/c2kernel/lifecycle/WfCastorHashMap.java @@ -17,11 +17,11 @@ public class WfCastorHashMap extends CastorHashMap put("Agent Role", ""); put("Agent Name", ""); put("SchemaType", ""); - put("SchemaVersion", ""); + put("SchemaVersion", -1); put("ScriptName", ""); - put("ScriptVersion", ""); + put("ScriptVersion", -1); put("StateMachineName", "Default"); - put("StateMachineVersion", "0"); + put("StateMachineVersion", 0); put("Viewpoint", ""); } } diff --git a/src/main/java/com/c2kernel/lifecycle/instance/Activity.java b/src/main/java/com/c2kernel/lifecycle/instance/Activity.java index 182882c..a386194 100644 --- a/src/main/java/com/c2kernel/lifecycle/instance/Activity.java +++ b/src/main/java/com/c2kernel/lifecycle/instance/Activity.java @@ -30,6 +30,7 @@ import com.c2kernel.process.Gateway; import com.c2kernel.utils.DateUtility; import com.c2kernel.utils.LocalObjectLoader; import com.c2kernel.utils.Logger; +import com.c2kernel.utils.Resource; /** * @version $Revision: 1.222 $ $Date: 2005/10/05 07:39:37 $ * @author $Author: abranson $ @@ -54,11 +55,16 @@ public class Activity extends WfVertex { super(); setProperties(new WfCastorHashMap()); + getProperties().put("StateMachineName", getDefaultSMName()); mErrors = new Vector(0, 1); mStateDate = new GTimeStamp(); DateUtility.setToNow(mStateDate); } + protected String getDefaultSMName() { + return "Default"; + } + /** add the activity which id is idNext as next of the current one */ void addNext(String idNext) { @@ -76,25 +82,39 @@ public class Activity extends WfVertex public StateMachine getStateMachine() throws InvalidDataException { if (machine == null) { String name = (String)getProperties().get("StateMachineName"); - String version = (String)getProperties().get("StateMachineVersion"); + Integer version = (Integer)getProperties().get("StateMachineVersion"); try { - machine = LocalObjectLoader.getStateMachine(name, Integer.parseInt(version)); + machine = LocalObjectLoader.getStateMachine(name, version); } catch (ObjectNotFoundException ex) { + if (name.equals(getDefaultSMName()) && version == 0) { // default state machine not imported yet. Fake it. + try { + String marshalledSM = Resource.getTextResource(null, "boot/SM/"+getDefaultSMName()+".xml"); + StateMachine bootstrap = (StateMachine)Gateway.getMarshaller().unmarshall(marshalledSM); + bootstrap.validate(); + machine = bootstrap; + return bootstrap; + } catch (Exception ex2) { + Logger.error(ex2); + throw new InvalidDataException("Could not bootstrap default state machine from resources.", ""); + } + } Logger.error(ex); - throw new InvalidDataException("Error loading state machine '"+name+"' v"+version); + throw new InvalidDataException("Error loading state machine '"+name+"' v"+version, ""); } } return machine; } /** return the current State of the State machine (Used in Serialisation) */ - public int getState() + public int getState() throws InvalidDataException { + if (state == -1) + state = getStateMachine().getInitialStateCode(); return state; } public String getStateName() throws InvalidDataException { - return getStateMachine().getState(state).getName(); + return getStateMachine().getState(getState()).getName(); } /** Sets a new State */ @@ -104,7 +124,7 @@ public class Activity extends WfVertex } public boolean isFinished() throws InvalidDataException { - return getStateMachine().getState(state).isFinished(); + return getStateMachine().getState(getState()).isFinished(); } @@ -350,7 +370,7 @@ public class Activity extends WfVertex Logger.debug(8, getPath() + " run " + getState()); if (!getActive()) setActive(true); - boolean finished = getStateMachine().getState(state).isFinished(); + boolean finished = getStateMachine().getState(getState()).isFinished(); if (finished) { runNext(agent, itemSysKey); diff --git a/src/main/java/com/c2kernel/lifecycle/instance/CompositeActivity.java b/src/main/java/com/c2kernel/lifecycle/instance/CompositeActivity.java index 2f475c7..f9ab0fe 100644 --- a/src/main/java/com/c2kernel/lifecycle/instance/CompositeActivity.java +++ b/src/main/java/com/c2kernel/lifecycle/instance/CompositeActivity.java @@ -21,8 +21,7 @@ import com.c2kernel.utils.Logger; public class CompositeActivity extends Activity { - public static final int START = 0; - public static final int COMPLETE = 1; + /* * -------------------------------------------- * ----------------CONSTRUCTOR----------------- @@ -34,6 +33,14 @@ public class CompositeActivity extends Activity setChildrenGraphModel(new GraphModel(new WfVertexOutlineCreator())); setIsComposite(true); } + + // State machine + public static final int START = 0; + public static final int COMPLETE = 1; + @Override + protected String getDefaultSMName() { + return "CompositeActivity"; + } @Override public void setChildrenGraphModel(GraphModel childrenGraph) { diff --git a/src/main/java/com/c2kernel/lifecycle/instance/OrSplit.java b/src/main/java/com/c2kernel/lifecycle/instance/OrSplit.java index cadf3a0..89f5ad2 100644 --- a/src/main/java/com/c2kernel/lifecycle/instance/OrSplit.java +++ b/src/main/java/com/c2kernel/lifecycle/instance/OrSplit.java @@ -24,7 +24,7 @@ public class OrSplit extends Split { String nexts; String scriptName = (String) getProperties().get("RoutingScriptName"); - String scriptVersion = (String) getProperties().get("RoutingScriptVersion"); + Integer scriptVersion = (Integer) getProperties().get("RoutingScriptVersion"); try { nexts = this.evaluateScript(scriptName, scriptVersion, itemSysKey).toString(); } catch (ScriptingEngineException e) { diff --git a/src/main/java/com/c2kernel/lifecycle/instance/WfVertex.java b/src/main/java/com/c2kernel/lifecycle/instance/WfVertex.java index 271e8df..9ed5c8a 100644 --- a/src/main/java/com/c2kernel/lifecycle/instance/WfVertex.java +++ b/src/main/java/com/c2kernel/lifecycle/instance/WfVertex.java @@ -112,7 +112,7 @@ public abstract class WfVertex extends GraphableVertex */ public abstract Next addNext(WfVertex vertex); - protected Object evaluateScript(String scriptName, String scriptVersion, int itemSysKey) throws ScriptingEngineException + protected Object evaluateScript(String scriptName, int scriptVersion, int itemSysKey) throws ScriptingEngineException { try @@ -172,14 +172,14 @@ public abstract class WfVertex extends GraphableVertex } } - private static Script getScript(String name, String version) throws ScriptingEngineException + private static Script getScript(String name, int version) throws ScriptingEngineException { if (name == null || name.length() == 0) throw new ScriptingEngineException("Script name is empty"); Script script; try { - script = new Script(name, Integer.parseInt(version)); + script = new Script(name, version); } catch (NumberFormatException e) { // version not valid diff --git a/src/main/java/com/c2kernel/lifecycle/instance/XOrSplit.java b/src/main/java/com/c2kernel/lifecycle/instance/XOrSplit.java index 164fabc..a74a939 100644 --- a/src/main/java/com/c2kernel/lifecycle/instance/XOrSplit.java +++ b/src/main/java/com/c2kernel/lifecycle/instance/XOrSplit.java @@ -33,7 +33,7 @@ public class XOrSplit extends Split ArrayList nextsToFollow = new ArrayList(); String nexts; String scriptName = (String) getProperties().get("RoutingScriptName"); - String scriptVersion = (String) getProperties().get("RoutingScriptVersion"); + int scriptVersion = (Integer) getProperties().get("RoutingScriptVersion"); try { nexts = this.evaluateScript(scriptName, scriptVersion, itemSysKey).toString(); } catch (ScriptingEngineException e) { diff --git a/src/main/java/com/c2kernel/lifecycle/instance/predefined/PredefinedStep.java b/src/main/java/com/c2kernel/lifecycle/instance/predefined/PredefinedStep.java index 5369cb2..3cf73ba 100644 --- a/src/main/java/com/c2kernel/lifecycle/instance/predefined/PredefinedStep.java +++ b/src/main/java/com/c2kernel/lifecycle/instance/predefined/PredefinedStep.java @@ -24,8 +24,7 @@ public abstract class PredefinedStep extends Activity /******************************************************************************************************************************************************************************************************************************************************************************************************* * predefined Steps are always Active, and have only one transition subclasses could override this method (if necessary) ******************************************************************************************************************************************************************************************************************************************************************************************************/ - public static final int DONE = 0; - public static final int AVAILABLE = 0; + private boolean isPredefined = false; @Override public boolean getActive() @@ -35,6 +34,13 @@ public abstract class PredefinedStep extends Activity else return super.getActive(); } + + public static final int DONE = 0; + public static final int AVAILABLE = 0; + @Override + protected String getDefaultSMName() { + return "PredefinedStep"; + } @Override public String getErrors() diff --git a/src/main/java/com/c2kernel/lifecycle/instance/stateMachine/State.java b/src/main/java/com/c2kernel/lifecycle/instance/stateMachine/State.java index 0325656..fd712f4 100644 --- a/src/main/java/com/c2kernel/lifecycle/instance/stateMachine/State.java +++ b/src/main/java/com/c2kernel/lifecycle/instance/stateMachine/State.java @@ -19,6 +19,11 @@ public class State implements Serializable { public String getName() { return name; } + + @Override + public String toString() { + return id+": "+name; + } public void setName(String name) { this.name = name; diff --git a/src/main/java/com/c2kernel/lifecycle/instance/stateMachine/StateMachine.java b/src/main/java/com/c2kernel/lifecycle/instance/stateMachine/StateMachine.java index 1506701..3896ac5 100644 --- a/src/main/java/com/c2kernel/lifecycle/instance/stateMachine/StateMachine.java +++ b/src/main/java/com/c2kernel/lifecycle/instance/stateMachine/StateMachine.java @@ -6,6 +6,7 @@ import java.util.HashMap; import java.util.Map; import com.c2kernel.common.AccessRightsException; +import com.c2kernel.common.InvalidDataException; import com.c2kernel.common.InvalidTransitionException; import com.c2kernel.common.ObjectNotFoundException; import com.c2kernel.lifecycle.instance.Activity; @@ -20,7 +21,6 @@ public class StateMachine implements DescriptionObject private ArrayList states; private ArrayList transitions; - private final HashMap stateNames; private final HashMap stateCodes; private final HashMap transitionCodes; @@ -31,32 +31,41 @@ public class StateMachine implements DescriptionObject public StateMachine() { states = new ArrayList(); transitions = new ArrayList(); - stateNames = new HashMap(); stateCodes = new HashMap(); transitionCodes = new HashMap(); } public void setStates(ArrayList newStates) { - - isCoherent = true; this.states = newStates; - stateNames.clear(); - - for (State state : states) - stateNames.put(state.getName(), state); - - for (Transition trans : transitions) - isCoherent &= trans.resolveStates(stateNames); - + validate(); } public void setTransitions(ArrayList newTransitions) { this.transitions = newTransitions; + validate(); + } + + public void validate() { + stateCodes.clear(); transitionCodes.clear(); + isCoherent = true; + + for (State state : states) { + Logger.debug(6, "State "+state.id+": "+state.name); + stateCodes.put(state.getId(), state); + } + + if (stateCodes.containsKey(initialStateCode)) + initialState = stateCodes.get(initialStateCode); + else + isCoherent = false; for (Transition trans : transitions) { + Logger.debug(6, "Transition "+trans.id+": "+trans.name); transitionCodes.put(trans.getId(), trans); + isCoherent &= trans.resolveStates(stateCodes); } + } public ArrayList getStates() { @@ -112,7 +121,7 @@ public class StateMachine implements DescriptionObject return stateCodes.get(stateID); } - public Map getPossibleTransitions(Activity act, AgentPath agent) throws ObjectNotFoundException { + public Map getPossibleTransitions(Activity act, AgentPath agent) throws ObjectNotFoundException, InvalidDataException { HashMap returnList = new HashMap(); State currentState = getState(act.getState()); for (Integer transCode : currentState.getPossibleTransitionIds()) { @@ -128,7 +137,7 @@ public class StateMachine implements DescriptionObject return returnList; } - public State traverse(Activity act, Transition transition, AgentPath agent) throws InvalidTransitionException, AccessRightsException, ObjectNotFoundException { + public State traverse(Activity act, Transition transition, AgentPath agent) throws InvalidTransitionException, AccessRightsException, ObjectNotFoundException, InvalidDataException { State currentState = getState(act.getState()); if (transition.originState.equals(currentState)) { transition.getPerformingRole(act, agent); @@ -139,5 +148,9 @@ public class StateMachine implements DescriptionObject } + public boolean isCoherent() { + return isCoherent; + } + } \ No newline at end of file diff --git a/src/main/java/com/c2kernel/lifecycle/instance/stateMachine/Transition.java b/src/main/java/com/c2kernel/lifecycle/instance/stateMachine/Transition.java index 01ede5a..e7bcba9 100644 --- a/src/main/java/com/c2kernel/lifecycle/instance/stateMachine/Transition.java +++ b/src/main/java/com/c2kernel/lifecycle/instance/stateMachine/Transition.java @@ -2,6 +2,8 @@ package com.c2kernel.lifecycle.instance.stateMachine; import java.io.Serializable; import java.util.HashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import com.c2kernel.common.AccessRightsException; import com.c2kernel.common.InvalidDataException; @@ -13,6 +15,7 @@ import com.c2kernel.persistency.outcome.Schema; import com.c2kernel.process.Gateway; import com.c2kernel.utils.CastorHashMap; import com.c2kernel.utils.LocalObjectLoader; +import com.c2kernel.utils.Logger; public class Transition implements Serializable { @@ -127,7 +130,7 @@ public class Transition implements Serializable { this.reservation = reservation; } - protected boolean resolveStates(HashMap states) { + protected boolean resolveStates(HashMap states) { boolean allFound = true; if (states.keySet().contains(originStateId)) { originState = states.get(originStateId); @@ -232,9 +235,17 @@ public class Transition implements Serializable { private static String resolveValue(String key, CastorHashMap props) { if (key==null) return null; - if (key.startsWith("$")) - return (String)props.get(key.substring(1)); - return key; + String result = key; + Pattern propField = Pattern.compile("\\$\\{(.+?)\\}"); + Matcher propMatcher = propField.matcher(result); + while (propMatcher.find()) { + String propName = propMatcher.group(1); + Object propValue = props.get(propName); + Logger.debug("Replacing Property "+propName+" as "+propValue); + String propValString = propValue==null?"":propValue.toString(); + result = result.replace("${"+propName+"}", propValString); + } + return result; } public boolean isEnabled(CastorHashMap props) { @@ -255,7 +266,7 @@ public class Transition implements Serializable { return LocalObjectLoader.getSchema(resolveValue(outcome.schemaName, actProps), Integer.parseInt(resolveValue(outcome.schemaVersion, actProps))); } catch (NumberFormatException ex) { - throw new InvalidDataException("Bad schema version number: "+outcome.schemaVersion+" ("+resolveValue(outcome.schemaVersion, actProps)); + throw new InvalidDataException("Bad schema version number: "+outcome.schemaVersion+" ("+resolveValue(outcome.schemaVersion, actProps), ""); } else return null; diff --git a/src/main/java/com/c2kernel/process/Bootstrap.java b/src/main/java/com/c2kernel/process/Bootstrap.java index b334d59..b37cc8a 100644 --- a/src/main/java/com/c2kernel/process/Bootstrap.java +++ b/src/main/java/com/c2kernel/process/Bootstrap.java @@ -209,6 +209,8 @@ public class Bootstrap return new DomainPath("/desc/Script/"); if (type.equals("OD")) return new DomainPath("/desc/OutcomeDesc/"); + if (type.equals("SM")) + return new DomainPath("/desc/StateMachine"); throw new Exception("Unknown bootstrap item type: "+type); } @@ -221,6 +223,8 @@ public class Bootstrap return "Schema"; if (type.equals("SC")) return "Script"; + if (type.equals("SM")) + return "StateMachine"; throw new Exception("Unknown bootstrap item type: "+type); } diff --git a/src/main/java/com/c2kernel/utils/StateMachineCache.java b/src/main/java/com/c2kernel/utils/StateMachineCache.java index 371df4d..d48d718 100644 --- a/src/main/java/com/c2kernel/utils/StateMachineCache.java +++ b/src/main/java/com/c2kernel/utils/StateMachineCache.java @@ -33,6 +33,7 @@ public class StateMachineCache extends DescriptionObjectCache { } try { thisStateMachine = (StateMachine)Gateway.getMarshaller().unmarshall(marshalledSM); + thisStateMachine.validate(); } catch (Exception ex) { Logger.error(ex); throw new InvalidDataException("Could not unmarshall State Machine '"+name+"' v"+version+": "+ex.getMessage(), ""); -- cgit v1.2.3