Skip to content

Commit

Permalink
synced changes from adamsmj/yawl
Browse files Browse the repository at this point in the history
  • Loading branch information
adamsmj committed Jul 16, 2024
1 parent eb4c4fa commit 20f5005
Show file tree
Hide file tree
Showing 8 changed files with 259 additions and 40 deletions.
6 changes: 6 additions & 0 deletions build/build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2843,6 +2843,8 @@
org/yawlfoundation/yawl/elements/YAttributeMap.class
org/yawlfoundation/yawl/elements/YVerifiable.class
org/yawlfoundation/yawl/elements/YNetElement.class
org/yawlfoundation/yawl/elements/data/YParameter.class
org/yawlfoundation/yawl/elements/data/YVariable.class
org/yawlfoundation/yawl/elements/e2wfoj/*
org/yawlfoundation/yawl/engine/YSpecificationID.class
org/yawlfoundation/yawl/engine/YNetData.class
Expand All @@ -2861,10 +2863,12 @@
org/yawlfoundation/yawl/exceptions/*
org/yawlfoundation/yawl/logging/YLogDataItem.class
org/yawlfoundation/yawl/logging/YLogDataItemList.class
org/yawlfoundation/yawl/resourcing/codelets/*
org/yawlfoundation/yawl/util/DynamicValue.class
org/yawlfoundation/yawl/util/JDOMUtil.class
org/yawlfoundation/yawl/util/YNetElementDocoParser.class
org/yawlfoundation/yawl/util/SaxonErrorListener.class
org/yawlfoundation/yawl/util/SaxonUtil.class
org/yawlfoundation/yawl/util/PluginLoaderUtil.class
org/yawlfoundation/yawl/util/YVerificationHandler.class
org/yawlfoundation/yawl/util/YPluginLoader.class
Expand All @@ -2878,6 +2882,8 @@
value="${app.version} ${TODAY}"/>
</manifest>
</jar>
<copy todir="${build.dir}/jar"
file="${output.dir}/yawlstateless-${app.version}.jar"/>
</target>


Expand Down
168 changes: 151 additions & 17 deletions src/org/yawlfoundation/yawl/stateless/YStatelessEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
*/
public class YStatelessEngine {


private final YEngine _engine;
private YCaseMonitor _caseMonitor; // watches for idle cases

Expand Down Expand Up @@ -334,9 +335,16 @@ public void resumeCase(YNetRunner runner)
*/
public YWorkItem suspendWorkItem(YWorkItem workItem) throws YStateException {
checkIsLoadedCase(workItem, "suspend work item");
return _engine.suspendWorkItem(workItem);
try {
return _engine.suspendWorkItem(workItem);
}
catch (Exception e) {
resumeCaseIdleTimer(workItem);
throw e;
}
}


/**
* Resume a suspended work item
* @param workItem the work item to suspend
Expand All @@ -345,19 +353,33 @@ public YWorkItem suspendWorkItem(YWorkItem workItem) throws YStateException {
*/
public YWorkItem unsuspendWorkItem(YWorkItem workItem) throws YStateException {
checkIsLoadedCase(workItem, "unsuspend work item");
return _engine.unsuspendWorkItem(workItem) ;
try {
return _engine.unsuspendWorkItem(workItem) ;
}
catch (Exception e) {
resumeCaseIdleTimer(workItem);
throw e;
}
}


/**
* Roll back a work item from executing to enabled
* @param workItem the work item to roll back
* @throws YStateException
* @throws YStateException if the item cannot be rolled back
*/
public void rollbackWorkItem(YWorkItem workItem) throws YStateException {
public YWorkItem rollbackWorkItem(YWorkItem workItem) throws YStateException {
checkIsLoadedCase(workItem, "rollback work item");
_engine.rollbackWorkItem(workItem);
try {
return _engine.rollbackWorkItem(workItem);
}
catch (Exception e) {
resumeCaseIdleTimer(workItem);
throw e;
}
}


/**
* Complete a currently executing work item
Expand All @@ -370,13 +392,20 @@ public void rollbackWorkItem(YWorkItem workItem) throws YStateException {
* @throws YQueryException if the data extraction query is malformed
* @throws YDataStateException if the data state cannot be initialised
*/
public void completeWorkItem(YWorkItem workItem, String data,
public YWorkItem completeWorkItem(YWorkItem workItem, String data,
String logPredicate, WorkItemCompletion completionType )
throws YEngineStateException, YStateException, YQueryException, YDataStateException {
checkIsLoadedCase(workItem, "complete work item");
_engine.completeWorkItem(workItem, data, logPredicate, completionType);
try {
return _engine.completeWorkItem(workItem, data, logPredicate, completionType);
}
catch (Exception e) {
resumeCaseIdleTimer(workItem);
throw e;
}
}


/**
* Complete a currently executing work item
* @param workItem the work item to complete
Expand All @@ -387,11 +416,17 @@ public void completeWorkItem(YWorkItem workItem, String data,
* @throws YQueryException if the data extraction query is malformed
* @throws YDataStateException if the data state cannot be initialised
*/
public void completeWorkItem(YWorkItem workItem, String data,
public YWorkItem completeWorkItem(YWorkItem workItem, String data,
String logPredicate)
throws YEngineStateException, YStateException, YQueryException, YDataStateException {
checkIsLoadedCase(workItem, "complete work item");
_engine.completeWorkItem(workItem, data, logPredicate, WorkItemCompletion.Normal);
try {
return _engine.completeWorkItem(workItem, data, logPredicate, WorkItemCompletion.Normal);
}
catch (Exception e) {
resumeCaseIdleTimer(workItem);
throw e;
}
}


Expand All @@ -406,9 +441,16 @@ public void completeWorkItem(YWorkItem workItem, String data,
public YWorkItem startWorkItem(YWorkItem workItem)
throws YEngineStateException, YStateException, YQueryException, YDataStateException {
checkIsLoadedCase(workItem, "start work item");
return _engine.startWorkItem(workItem);
try {
return _engine.startWorkItem(workItem);
}
catch (Exception e) {
resumeCaseIdleTimer(workItem);
throw e;
}
}


/**
* Skip an enabled work item (immediately completes)
* @param workItem the work item to skip
Expand All @@ -420,7 +462,13 @@ public YWorkItem startWorkItem(YWorkItem workItem)
public YWorkItem skipWorkItem(YWorkItem workItem)
throws YEngineStateException, YStateException, YQueryException, YDataStateException {
checkIsLoadedCase(workItem, "skip work item");
return _engine.skipWorkItem(workItem);
try {
return _engine.skipWorkItem(workItem);
}
catch (Exception e) {
resumeCaseIdleTimer(workItem);
throw e;
}
}


Expand All @@ -436,7 +484,13 @@ public YWorkItem skipWorkItem(YWorkItem workItem)
public YWorkItem createNewInstance(YWorkItem workItem, String paramValueForMICreation)
throws YStateException {
checkIsLoadedCase(workItem, "create new work item instance");
return _engine.createNewInstance(workItem, paramValueForMICreation);
try {
return _engine.createNewInstance(workItem, paramValueForMICreation);
}
catch (Exception e) {
resumeCaseIdleTimer(workItem);
throw e;
}
}


Expand All @@ -449,7 +503,7 @@ public YWorkItem createNewInstance(YWorkItem workItem, String paramValueForMICre
* or if current number of instances is not less than the maxInstances
* for the task.
*/
public void checkElegibilityToAddInstances(YWorkItem workItem) throws YStateException {
public void checkEligibilityToAddInstances(YWorkItem workItem) throws YStateException {
_engine.checkEligibilityToAddInstances(workItem);
}

Expand All @@ -475,7 +529,7 @@ public String unloadCase(YIdentifier caseID) throws YStateException {
throw new YStateException("This engine is not monitoring idle cases");
}
YCase yCase = _caseMonitor.unloadCase(caseID); // notnull guaranteed
yCase.cancelWorkItemTimers();
yCase.removeWorkItemTimers();
String caseXML = yCase.marshal(); // ditto
_engine.getAnnouncer().announceCaseEvent(
new YCaseEvent(YEventType.CASE_UNLOADED, yCase.getRunner()));
Expand Down Expand Up @@ -507,6 +561,8 @@ public String marshalCase(YNetRunner runner) throws YStateException {
*/
public YNetRunner restoreCase(String caseXML) throws YSyntaxException, YStateException {
List<YNetRunner> runners = new YCaseImporter().unmarshal(caseXML, _engine.getAnnouncer());

// collect events and identify 'top' net runner in the runner hierarchy
List<YEvent> events = new ArrayList<>();
YNetRunner topRunner = null;
for (YNetRunner runner : runners) {
Expand All @@ -516,33 +572,111 @@ public YNetRunner restoreCase(String caseXML) throws YSyntaxException, YStateExc
}
}
if (topRunner == null) throw new YStateException("Failed to restore case runner");
events.add(0, new YCaseEvent(YEventType.CASE_RESTORED, topRunner));

// add the 'restored' event to the list of generated events
YCaseEvent restoredEvent = new YCaseEvent(YEventType.CASE_RESTORED, topRunner);
events.add(0, restoredEvent);

// ensure case is added to the case monitor
if (isCaseMonitoringEnabled()) {
_caseMonitor.addCase(restoredEvent);
}

_engine.getAnnouncer().announceEvents(events);
return topRunner;
}


/**
* Check if the engine is currently executing code for a monitored case of which this
* workitem is a member.
* @param workItem the workitem to check
* @return true if case monitoring is enabled and the case is currently in idle
* state (i.e. it has no current executing code associated with it), or false if
* case monitoring is enabled and there is code executing for the case.
* @throws YStateException when the case is unknown to the engine, or when case
* monitoring is disabled for the engine
*/
public boolean isIdleCase(YWorkItem workItem) throws YStateException {
return isIdleCase(workItem.getNetRunner().getTopRunner().getCaseID());
}


/**
* Check if the engine is currently executing code for a monitored case of which
* this net runner is a member.
* @param runner the net runner to check
* @return true if case monitoring is enabled and the case is currently in idle
* state (i.e. it has no current executing code associated with it), or false if
* case monitoring is enabled and there is code executing for the case.
* @throws YStateException when the case is unknown to the engine, or when case
* monitoring is disabled for the engine
*/
public boolean isIdleCase(YNetRunner runner) throws YStateException {
return isIdleCase(runner.getTopRunner().getCaseID());
}


/**
* Check if the engine is currently executing code for a monitored case.
* @param caseID the id of the case to check
* @return true if case monitoring is enabled and the case is currently in idle
* state (i.e. it has no current executing code associated with it), or false if
* case monitoring is enabled and there is code executing for the case.
* @throws YStateException when the case is unknown to the engine, or when case
* monitoring is disabled for the engine
*/
public boolean isIdleCase(YIdentifier caseID) throws YStateException {
if (isCaseMonitoringEnabled()) {
if (_caseMonitor.hasCase(caseID)) {
return _caseMonitor.isIdleCase(caseID);
}
else {
throw new YStateException(String.format("Case '%s' is unknown" +
" to this engine - perhaps it has been unloaded?", caseID));
}
}
else throw new YStateException("Case monitoring is disabled for this engine");
}

/**
* Throws a YStateException if cases are being monitored AND the case is unknown to
* this engine
* @param caseID the id of the case to check
* @param errMsg to be inserted if an exception is thrown
* @throws YStateException if the condition described above evaluates to true
*/
private void isLoadedCase(YIdentifier caseID, String errMsg) throws YStateException {
private boolean isLoadedCase(YIdentifier caseID, String errMsg) throws YStateException {
if (isCaseMonitoringEnabled() && ! _caseMonitor.hasCase(caseID)) {
throw new YStateException(String.format("Unable to %s; case '%s' is unknown" +
" to this engine - perhaps it has been unloaded?", errMsg, caseID));
}
return true;
}


private void checkIsLoadedCase(YWorkItem item, String msg) throws YStateException {
isLoadedCase(item.getNetRunner().getTopRunner().getCaseID(), msg);
YIdentifier caseID = item.getNetRunner().getTopRunner().getCaseID();
if (isCaseMonitoringEnabled() && isLoadedCase(caseID, msg)) {

// pause any idle timer while the workitem action is processed
_caseMonitor.pauseIdleTimer(caseID);
}
}


private void checkIsLoadedCase(YNetRunner runner, String msg) throws YStateException {
isLoadedCase(runner.getTopRunner().getCaseID(), msg);
}


// for all successful workitem method completions above, timer will resume.
// this is called from catch blocks above for cases when an exception is thrown.
private void resumeCaseIdleTimer(YWorkItem workItem) {
if (isCaseMonitoringEnabled()) {
YIdentifier caseID = workItem.getNetRunner().getTopRunner().getCaseID();
_caseMonitor.resumeIdleTimer(caseID);
}
}

}
12 changes: 9 additions & 3 deletions src/org/yawlfoundation/yawl/stateless/engine/YEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ private YWorkItem startFiredWorkItem(YNetRunner netRunner, YWorkItem workItem)
* 'force' (forced completion) or 'fail' (forced fail) completion
* @throws YStateException
*/
public void completeWorkItem(YWorkItem workItem, String data, String logPredicate,
public YWorkItem completeWorkItem(YWorkItem workItem, String data, String logPredicate,
WorkItemCompletion completionType)
throws YStateException, YDataStateException, YQueryException, YEngineStateException{
if (_logger.isDebugEnabled()) {
Expand Down Expand Up @@ -469,6 +469,8 @@ public void completeWorkItem(YWorkItem workItem, String data, String logPredicat
// }

_logger.debug("<-- completeWorkItem");

return workItem;
}


Expand Down Expand Up @@ -687,7 +689,7 @@ public YWorkItem unsuspendWorkItem(YWorkItem workItem) throws YStateException {


// rolls back a workitem from executing to fired
public void rollbackWorkItem(YWorkItem workItem) throws YStateException {
public YWorkItem rollbackWorkItem(YWorkItem workItem) throws YStateException {
if ((workItem != null) && workItem.getStatus().equals(YWorkItemStatus.statusExecuting)) {
workItem.rollBackStatus();
YNetRunner netRunner = workItem.getTask().getNetRunner().getRunnerWithID(
Expand All @@ -699,10 +701,12 @@ public void rollbackWorkItem(YWorkItem workItem) throws YStateException {
}
}
else throw new YStateException("Work Item[" + workItem.getIDString() + "] not found.");

return workItem;
}


public void cancelWorkItem(YNetRunner caseRunner, YWorkItem workItem) throws YStateException {
public YWorkItem cancelWorkItem(YNetRunner caseRunner, YWorkItem workItem) throws YStateException {
try {
if ((workItem != null) && workItem.getStatus().equals(YWorkItemStatus.statusExecuting)) {
YNetRunner runner = caseRunner.getRunnerWithID(workItem.getCaseID().getParent());
Expand All @@ -721,6 +725,8 @@ public void cancelWorkItem(YNetRunner caseRunner, YWorkItem workItem) throws YSt
catch (Exception e) {
throw new YStateException("Failure whilst cancelling workitem: " + e.getMessage());
}

return workItem;
}


Expand Down
Loading

0 comments on commit 20f5005

Please sign in to comment.