From 1bda9df450248cc172a7cfeedf87d4b8ed60f1ee Mon Sep 17 00:00:00 2001
From: Robert von Burg
Date: Mon, 17 Feb 2020 14:22:32 +0100
Subject: [PATCH 1/2] [WIP] Implementing Planning refactoring
---
.../strolch/agent/api/StrolchComponent.java | 4 +-
.../persistence/api/AbstractTransaction.java | 23 ++-
.../persistence/api/StrolchTransaction.java | 8 +-
.../java/li/strolch/service/api/Command.java | 11 +-
.../src/main/java/li/strolch/model/State.java | 25 ++-
.../li/strolch/model/activity/Activity.java | 21 ++
.../ArchiveExecutedActivitiesJob.java | 14 +-
.../java/li/strolch/execution/Controller.java | 70 +++++++
.../execution/EventBasedExecutionHandler.java | 182 ++++++------------
.../strolch/execution/ExecutionHandler.java | 34 ++--
.../command/ArchiveActivityCommand.java | 54 ++++++
.../command/ExecuteActivityCommand.java | 11 +-
.../command/ExecuteStoppedActionCommand.java | 10 +-
.../execution/command/ExecutionCommand.java | 5 +-
.../execution/command/PlanActionCommand.java | 5 +
.../execution/command/PlanningCommand.java | 27 +++
.../command/SetActionToClosedCommand.java | 10 +-
.../command/SetActionToCreatedCommand.java | 10 +-
.../command/SetActionToErrorCommand.java | 10 +-
.../command/SetActionToExecutedCommand.java | 10 +-
.../command/SetActionToPlannedCommand.java | 10 +-
.../command/SetActionToPlanningCommand.java | 10 +-
.../command/SetActionToStoppedCommand.java | 10 +-
.../command/SetActionToWarningCommand.java | 10 +-
.../service/SetActionStateService.java | 18 +-
.../service/SetActionToClosedService.java | 2 +-
.../service/SetActionToCreatedService.java | 2 +-
.../service/SetActionToErrorService.java | 2 +-
.../service/SetActionToExecutedService.java | 2 +-
.../service/SetActionToPlannedService.java | 2 +-
.../service/SetActionToPlanningService.java | 2 +-
.../service/SetActionToStoppedService.java | 2 +-
.../service/SetActionToWarningService.java | 2 +-
.../service/SetToExecutionService.java | 15 +-
.../StartActivityExecutionService.java | 9 +-
li.strolch.website/www.strolch.li/api.html | 1 +
li.strolch.website/www.strolch.li/blog.html | 1 +
.../www.strolch.li/development.html | 1 +
.../documentation-architecture.html | 1 +
.../documentation-components.html | 1 +
.../documentation-do-and-dont.html | 1 +
.../www.strolch.li/documentation-model.html | 1 +
.../documentation-observers.html | 1 +
.../documentation-policies.html | 1 +
.../documentation-privileges.html | 1 +
.../www.strolch.li/documentation-queries.html | 1 +
.../www.strolch.li/documentation-realms.html | 1 +
.../www.strolch.li/documentation-reports.html | 1 +
.../www.strolch.li/documentation-runtime.html | 1 +
.../documentation-searches.html | 1 +
.../documentation-services-and-commands.html | 1 +
.../documentation-transactions.html | 1 +
.../documentation-versioning.html | 1 +
.../www.strolch.li/documentation.html | 1 +
.../www.strolch.li/downloads.html | 1 +
.../www.strolch.li/history.html | 1 +
li.strolch.website/www.strolch.li/index.html | 1 +
li.strolch.website/www.strolch.li/plc.html | 109 +++++++++++
.../tutorial-configuration.html | 1 +
.../www.strolch.li/tutorial-crud-book.html | 1 +
.../www.strolch.li/tutorial-model.html | 1 +
.../www.strolch.li/tutorial.html | 1 +
62 files changed, 494 insertions(+), 283 deletions(-)
create mode 100644 li.strolch.service/src/main/java/li/strolch/execution/Controller.java
create mode 100644 li.strolch.service/src/main/java/li/strolch/execution/command/ArchiveActivityCommand.java
create mode 100644 li.strolch.website/www.strolch.li/plc.html
diff --git a/li.strolch.agent/src/main/java/li/strolch/agent/api/StrolchComponent.java b/li.strolch.agent/src/main/java/li/strolch/agent/api/StrolchComponent.java
index 49b92e978..a9b038390 100644
--- a/li.strolch.agent/src/main/java/li/strolch/agent/api/StrolchComponent.java
+++ b/li.strolch.agent/src/main/java/li/strolch/agent/api/StrolchComponent.java
@@ -425,7 +425,7 @@ public class StrolchComponent {
* @return the newly created transaction
*/
protected StrolchTransaction openTx(Certificate cert, boolean readOnly) {
- return getContainer().getRealm(cert).openTx(cert, this.getClass(), readOnly);
+ return getContainer().getRealm(cert).openTx(cert, getClass(), readOnly);
}
/**
@@ -457,7 +457,7 @@ public class StrolchComponent {
* @return the newly created transaction
*/
protected StrolchTransaction openTx(String realm, Certificate cert, boolean readOnly) {
- return getContainer().getRealm(realm).openTx(cert, this.getClass(), readOnly);
+ return getContainer().getRealm(realm).openTx(cert, getClass(), readOnly);
}
/**
diff --git a/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java b/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java
index 0114f9847..2ccb64bbd 100644
--- a/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java
+++ b/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java
@@ -416,13 +416,14 @@ public abstract class AbstractTransaction implements StrolchTransaction {
}
@Override
- public T findElement(Locator locator) throws StrolchException, ClassCastException {
+ public T findElement(Locator locator) throws StrolchModelException, ClassCastException {
return findElement(locator, false);
}
@SuppressWarnings("unchecked")
@Override
- public T findElement(Locator locator, boolean allowNull) {
+ public T findElement(Locator locator, boolean allowNull)
+ throws StrolchModelException, ClassCastException {
// Resource//
// Resource///Bag/
@@ -435,7 +436,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
if (locator.getSize() < 3) {
String msg = "The locator is invalid as it does not have at least three path elements (e.g. Resource/MyType/@id): {0}"; //$NON-NLS-1$
msg = MessageFormat.format(msg, locator.toString());
- throw new StrolchException(msg);
+ throw new StrolchModelException(msg);
}
List elements = locator.getPathElements();
@@ -454,14 +455,15 @@ public abstract class AbstractTransaction implements StrolchTransaction {
groupedParameterizedElement = getActivityBy(type, id);
break;
default:
- throw new StrolchException(MessageFormat.format("Unknown object class {0}", objectClassType)); //$NON-NLS-1$
+ throw new StrolchModelException(
+ MessageFormat.format("Unknown object class {0}", objectClassType)); //$NON-NLS-1$
}
if (groupedParameterizedElement == null) {
if (allowNull)
return null;
String msg = "No top level object could be found with locator {0}"; //$NON-NLS-1$
- throw new StrolchException(MessageFormat.format(msg, locator));
+ throw new StrolchModelException(MessageFormat.format(msg, locator));
}
if (elements.size() == 3)
@@ -477,7 +479,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
if (allowNull)
return null;
String msg = "Could not find ParameterBag for locator {0} on element {1}"; //$NON-NLS-1$
- throw new StrolchException(
+ throw new StrolchModelException(
MessageFormat.format(msg, locator, groupedParameterizedElement.getLocator()));
}
@@ -490,7 +492,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
if (allowNull)
return null;
String msg = "Could not find Parameter for locator {0} on element {1}"; //$NON-NLS-1$
- throw new StrolchException(MessageFormat.format(msg, locator, bag.getLocator()));
+ throw new StrolchModelException(MessageFormat.format(msg, locator, bag.getLocator()));
}
return (T) parameter;
@@ -498,9 +500,10 @@ public abstract class AbstractTransaction implements StrolchTransaction {
if (elements.size() != 5) {
String msg = "Missing state Id on locator {0}"; //$NON-NLS-1$
- throw new StrolchException(MessageFormat.format(msg, locator));
+ throw new StrolchModelException(MessageFormat.format(msg, locator));
}
+ @SuppressWarnings("ConstantConditions")
Resource resource = (Resource) groupedParameterizedElement;
String stateId = elements.get(4);
@@ -518,7 +521,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
if (!(element instanceof Activity)) {
String msg = "Invalid locator {0} with part {1} as not an Activity but deeper element specified"; //$NON-NLS-1$
- throw new StrolchException(MessageFormat.format(msg, locator, next));
+ throw new StrolchModelException(MessageFormat.format(msg, locator, next));
}
element = ((Activity) element).getElement(next);
@@ -531,7 +534,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
return null;
String msg = "Invalid locator {0} with part {1}"; //$NON-NLS-1$
- throw new StrolchException(MessageFormat.format(msg, locator, stateOrBagOrActivity));
+ throw new StrolchModelException(MessageFormat.format(msg, locator, stateOrBagOrActivity));
}
@Override
diff --git a/li.strolch.agent/src/main/java/li/strolch/persistence/api/StrolchTransaction.java b/li.strolch.agent/src/main/java/li/strolch/persistence/api/StrolchTransaction.java
index 9f19e18af..23d49cf74 100644
--- a/li.strolch.agent/src/main/java/li/strolch/persistence/api/StrolchTransaction.java
+++ b/li.strolch.agent/src/main/java/li/strolch/persistence/api/StrolchTransaction.java
@@ -534,11 +534,11 @@ public interface StrolchTransaction extends AutoCloseable {
* Used to find a {@link StrolchElement} by a {@link Locator}, throwing exception if the element is not found
*
*
- * @throws StrolchException
+ * @throws StrolchModelException
* if the element could not be found
* @see #findElement(Locator, boolean)
*/
- T findElement(Locator locator) throws StrolchException, ClassCastException;
+ T findElement(Locator locator) throws StrolchModelException, ClassCastException;
/**
*
@@ -565,14 +565,14 @@ public interface StrolchTransaction extends AutoCloseable {
* an inexistant {@link Resource} or an inexistand {@link Parameter} on a Resource, then a {@link StrolchException}
* is thrown
*
- * @throws StrolchException
+ * @throws StrolchModelException
* if the element could not be found and {@code allowNull} is false
* @throws ClassCastException
* if the querying code is not asking for the correct instance. Do not query a {@link Parameter} if the variable
* to which the result is to be is stored is a {@link Resource}, etc.
*/
T findElement(Locator locator, boolean allowNull)
- throws StrolchException, ClassCastException;
+ throws StrolchModelException, ClassCastException;
/**
*
Finds a parameter with the given @bagKey and @paramKey on the given @element, but if it does not exists
diff --git a/li.strolch.agent/src/main/java/li/strolch/service/api/Command.java b/li.strolch.agent/src/main/java/li/strolch/service/api/Command.java
index b6ff122ee..1bf35902a 100644
--- a/li.strolch.agent/src/main/java/li/strolch/service/api/Command.java
+++ b/li.strolch.agent/src/main/java/li/strolch/service/api/Command.java
@@ -304,11 +304,12 @@ public abstract class Command implements Restrictable {
/**
*
- * Should the transaction fail, either due to a {@link Command} throwing an exception when {@link #validate()} is
- * called, or while committing the transaction, then this method should properly undo any changes it has done. It is
- * imperative that this method does not throw further exceptions and that the state to be rolled back is remembered
- * in the Command during committing
+ * This method can be used to undo actions peformed during the command, should the TX fail. In earlier versions of
+ * Strolch this was important to undo model changes, but the model changes are only visible after a commit succeeds,
+ * so this is no longer necessary.
*
*/
- public abstract void undo();
+ public void undo() {
+ // do nothing
+ }
}
diff --git a/li.strolch.model/src/main/java/li/strolch/model/State.java b/li.strolch.model/src/main/java/li/strolch/model/State.java
index 224be9018..4f64e5f72 100644
--- a/li.strolch.model/src/main/java/li/strolch/model/State.java
+++ b/li.strolch.model/src/main/java/li/strolch/model/State.java
@@ -30,6 +30,7 @@ public enum State {
CREATED("Created"), //$NON-NLS-1$
PLANNING("Planning"), //$NON-NLS-1$
PLANNED("Planned"), //$NON-NLS-1$
+ EXECUTABLE("Executable"), //$NON-NLS-1$
EXECUTION("Execution"), //$NON-NLS-1$
WARNING("Warning"), //$NON-NLS-1$
ERROR("Error"), //$NON-NLS-1$
@@ -39,7 +40,7 @@ public enum State {
private String state;
- private State(String state) {
+ State(String state) {
this.state = state;
}
@@ -62,8 +63,8 @@ public enum State {
}
/**
- * @return true if the state is one of {@link #EXECUTION}, {@link #STOPPED}, {@link #WARNING}, {@link #ERROR} or
- * {@link #EXECUTED}
+ * @return true if the state is one of {@link #EXECUTABLE} {@link #EXECUTION}, {@link #STOPPED}, {@link #WARNING},
+ * {@link #ERROR} or {@link #EXECUTED}
*/
public boolean inExecutionPhase() {
return this == EXECUTION || this == STOPPED || this == WARNING || this == ERROR;
@@ -168,10 +169,17 @@ public enum State {
}
/**
- * @return true if {@link #CREATED} or {@link #PLANNING} or {@link #PLANNED} or {@link #EXECUTION} or {@link #STOPPED}
+ * @return true if {@link #PLANNED} or {@link #EXECUTABLE} or {@link #EXECUTION}
*/
- public boolean canSetToExecution() {
- return this == CREATED || this == PLANNING || this == PLANNED || this == EXECUTION || this == State.STOPPED;
+ public boolean isExecutable() {
+ return this == PLANNED || this == EXECUTABLE || this == EXECUTION;
+ }
+
+ /**
+ * @return true if state >= {@link #EXECUTED}
+ */
+ public boolean canNotSetToExecution() {
+ return this.compareTo(State.EXECUTED) >= 0;
}
/**
@@ -249,7 +257,7 @@ public enum State {
return WARNING;
// execution
- if (states.contains(EXECUTION))
+ if (states.contains(EXECUTABLE) || states.contains(EXECUTION))
return EXECUTION;
if (states.contains(EXECUTED) && (states.contains(CREATED) || states.contains(PLANNING) || states
.contains(PLANNED)))
@@ -275,4 +283,5 @@ public enum State {
// should never happen, unless new state is introduced
throw new IllegalStateException("Unhandled situation with states: " + states.stream().map(e -> e.state)
.collect(Collectors.joining(", ")));
- }}
+ }
+}
diff --git a/li.strolch.model/src/main/java/li/strolch/model/activity/Activity.java b/li.strolch.model/src/main/java/li/strolch/model/activity/Activity.java
index 1e8583ee2..d078b758b 100644
--- a/li.strolch.model/src/main/java/li/strolch/model/activity/Activity.java
+++ b/li.strolch.model/src/main/java/li/strolch/model/activity/Activity.java
@@ -381,6 +381,27 @@ public class Activity extends AbstractStrolchRootElement
}
}
+ public T getElementByLocator(Locator locator) {
+ DBC.PRE.assertEquals("Locator is not for this activity!", getLocator(), locator.trim(3));
+ DBC.PRE.assertTrue("Locator must have at least 5 parts", locator.getSize() >= 4);
+
+ IActivityElement element = this;
+ for (int i = 3; i < locator.getSize(); i++) {
+ String next = locator.get(i);
+
+ if (!(element instanceof Activity)) {
+ String msg = "Invalid locator {0} with part {1} as not an Activity but deeper element specified"; //$NON-NLS-1$
+ throw new StrolchModelException(MessageFormat.format(msg, locator, next));
+ }
+
+ element = ((Activity) element).getElement(next);
+ }
+
+ @SuppressWarnings("unchecked")
+ T t = (T) element;
+ return t;
+ }
+
/**
* @return the iterator for entries, which include the id as key and the {@link IActivityElement} as value
*/
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/ArchiveExecutedActivitiesJob.java b/li.strolch.service/src/main/java/li/strolch/execution/ArchiveExecutedActivitiesJob.java
index b91f9a6ee..0d8215415 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/ArchiveExecutedActivitiesJob.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/ArchiveExecutedActivitiesJob.java
@@ -3,6 +3,7 @@ package li.strolch.execution;
import java.util.concurrent.TimeUnit;
import li.strolch.agent.api.StrolchAgent;
+import li.strolch.execution.command.ArchiveActivityCommand;
import li.strolch.job.JobMode;
import li.strolch.job.StrolchJob;
import li.strolch.model.State;
@@ -23,13 +24,16 @@ public class ArchiveExecutedActivitiesJob extends StrolchJob {
@Override
protected void execute(PrivilegeContext ctx) {
- ExecutionHandler executionHandler = getComponent(ExecutionHandler.class);
-
- try (StrolchTransaction tx = openTx(ctx.getCertificate(), true)) {
+ try (StrolchTransaction tx = openTx(ctx.getCertificate())) {
tx.streamActivities().forEach(activity -> {
- if (activity.getState() == State.EXECUTED)
- executionHandler.archiveActivity(tx.getRealmName(), activity.getLocator());
+ if (activity.getState() == State.EXECUTED) {
+ ArchiveActivityCommand command = new ArchiveActivityCommand(tx);
+ command.setActivity(activity);
+ tx.addCommand(command);
+ }
});
+
+ tx.commitOnClose();
}
}
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/Controller.java b/li.strolch.service/src/main/java/li/strolch/execution/Controller.java
new file mode 100644
index 000000000..e2888d36f
--- /dev/null
+++ b/li.strolch.service/src/main/java/li/strolch/execution/Controller.java
@@ -0,0 +1,70 @@
+package li.strolch.execution;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import li.strolch.execution.command.ExecuteActivityCommand;
+import li.strolch.execution.policy.ExecutionPolicy;
+import li.strolch.model.Locator;
+import li.strolch.model.State;
+import li.strolch.model.activity.Activity;
+import li.strolch.persistence.api.StrolchTransaction;
+import li.strolch.privilege.base.PrivilegeException;
+import li.strolch.privilege.model.Certificate;
+import li.strolch.privilege.model.PrivilegeContext;
+import li.strolch.runtime.privilege.PrivilegedRunnable;
+
+public class Controller {
+
+ private ExecutionHandler executionHandler;
+ private Activity activity;
+ private Map inExecution;
+
+ public Controller(ExecutionHandler executionHandler, Activity activity) {
+ this.executionHandler = executionHandler;
+ this.activity = activity;
+ this.inExecution = new HashMap<>();
+ }
+
+ public State getState() {
+ return this.activity.getState();
+ }
+
+ public Activity getActivity() {
+ return this.activity;
+ }
+
+ public Set getInExecution() {
+ return this.inExecution.keySet();
+ }
+
+ protected StrolchTransaction openTx(Certificate cert) {
+ return this.executionHandler.openTx(cert, getClass(), false);
+ }
+
+ protected void runAsAgent(PrivilegedRunnable runnable) throws PrivilegeException, Exception {
+ this.executionHandler.runAsAgent(runnable);
+ }
+
+ private Activity refreshActivity(StrolchTransaction tx) {
+ this.activity = tx.getActivityBy(this.activity.getType(), this.activity.getId(), true);
+ return this.activity;
+ }
+
+ public void execute() {
+ try (StrolchTransaction tx = openTx(ctx.getCertificate())) {
+
+ ExecuteActivityCommand command = new ExecuteActivityCommand(tx);
+ command.setActivity(refreshActivity(tx));
+ command.validate();
+ command.doCommand();
+
+ tx.commitOnClose();
+ }
+ }
+
+ public void stop() {
+
+ }
+}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/EventBasedExecutionHandler.java b/li.strolch.service/src/main/java/li/strolch/execution/EventBasedExecutionHandler.java
index 29f8b4c18..38f2b500c 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/EventBasedExecutionHandler.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/EventBasedExecutionHandler.java
@@ -1,7 +1,9 @@
package li.strolch.execution;
+import static java.util.Collections.emptySet;
import static li.strolch.model.StrolchModelConstants.*;
import static li.strolch.runtime.StrolchConstants.SYSTEM_USER_AGENT;
+import static li.strolch.utils.collections.SynchronizedCollections.synchronizedMapOfMaps;
import java.util.*;
import java.util.concurrent.ExecutorService;
@@ -9,7 +11,6 @@ import java.util.concurrent.ExecutorService;
import li.strolch.agent.api.ComponentContainer;
import li.strolch.agent.api.ObserverEvent;
import li.strolch.execution.command.*;
-import li.strolch.execution.policy.ActivityArchivalPolicy;
import li.strolch.execution.policy.ExecutionPolicy;
import li.strolch.handler.operationslog.LogMessage;
import li.strolch.handler.operationslog.LogSeverity;
@@ -19,13 +20,11 @@ import li.strolch.model.activity.Action;
import li.strolch.model.activity.Activity;
import li.strolch.model.activity.IActivityElement;
import li.strolch.model.parameter.StringParameter;
-import li.strolch.model.policy.PolicyDef;
import li.strolch.persistence.api.StrolchTransaction;
-import li.strolch.policy.PolicyHandler;
import li.strolch.privilege.model.Certificate;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.runtime.configuration.ComponentConfiguration;
-import li.strolch.utils.collections.MapOfSets;
+import li.strolch.utils.collections.MapOfMaps;
import li.strolch.utils.dbc.DBC;
/**
@@ -36,11 +35,10 @@ import li.strolch.utils.dbc.DBC;
*/
public class EventBasedExecutionHandler extends ExecutionHandler {
- private static final String KEY_DEFAULT_ACTIVITY_ARCHIVAL = "key:DefaultActivityArchival";
private static final String PROP_RESTART_EXECUTION = "restartExecution";
private Map statesByRealm;
- private MapOfSets registeredActivities;
+ private MapOfMaps controllers;
private DelayedExecutionTimer delayedExecutionTimer;
@@ -48,11 +46,23 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
super(container, componentName);
}
+ private ExecutorService getExecutor() {
+ return getExecutorService("ExecutionHandler");
+ }
+
+ @Override
+ public Set getActiveActivitiesLocator(String realm) {
+ if (this.controllers == null)
+ return emptySet();
+ Map activities = this.controllers.getMap(realm);
+ if (activities == null)
+ return emptySet();
+ return activities.keySet();
+ }
+
@Override
public void initialize(ComponentConfiguration configuration) throws Exception {
-
- this.registeredActivities = new MapOfSets<>();
-
+ this.controllers = synchronizedMapOfMaps(new MapOfMaps<>());
super.initialize(configuration);
}
@@ -85,67 +95,34 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
super.stop();
}
- @Override
- public Set getActiveActivitiesLocator(String realm) {
- if (this.registeredActivities == null || !this.registeredActivities.containsSet(realm))
- return Collections.emptySet();
-
- synchronized (this.registeredActivities) {
- return new HashSet<>(this.registeredActivities.getSet(realm));
- }
- }
-
@Override
public void addForExecution(String realm, Activity activity) {
-
ExecutionHandlerState state = this.statesByRealm.getOrDefault(realm, ExecutionHandlerState.Running);
if (state == ExecutionHandlerState.HaltNew)
throw new IllegalStateException(
"ExecutionHandler state is " + state + ", can not add activities for execution!");
- Locator rootElemLoc = activity.getLocator();
- synchronized (this.registeredActivities) {
- this.registeredActivities.addElement(realm, rootElemLoc);
- }
-
- notifyObserverAdd(realm, activity);
- toExecution(realm, rootElemLoc);
- }
-
- @Override
- public void addForExecution(String realm, Locator activityLoc) {
-
- ExecutionHandlerState state = this.statesByRealm.getOrDefault(realm, ExecutionHandlerState.Running);
- if (state == ExecutionHandlerState.HaltNew)
- throw new IllegalStateException(
- "ExecutionHandler state is " + state + ", can not add activities for execution!");
-
- Locator rootElemLoc = activityLoc.trim(3);
- synchronized (this.registeredActivities) {
- this.registeredActivities.addElement(realm, rootElemLoc);
- }
-
- getExecutor().submit(() -> notifyObserverAdd(realm, activityLoc));
- toExecution(realm, activityLoc);
+ Controller controller = new Controller(this, activity);
+ this.controllers.addElement(realm, activity.getLocator(), controller);
+ notifyObserverAdd(realm, controller);
+ toExecution(realm, activity);
}
@Override
public void removeFromExecution(String realm, Locator activityLoc) {
Locator rootElemLoc = activityLoc.trim(3);
- synchronized (this.registeredActivities) {
- this.registeredActivities.removeElement(realm, rootElemLoc);
- }
- getExecutor().submit(() -> notifyObserverRemove(realm, activityLoc));
+ Controller controller = this.controllers.removeElement(realm, rootElemLoc);
+ if (controller != null)
+ getExecutor().submit(() -> notifyObserverRemove(realm, controller));
}
@Override
public void clearAllCurrentExecutions(String realm) {
- Set removed = this.registeredActivities.removeSet(realm);
+ Map removed = this.controllers.removeMap(realm);
getExecutor().submit(() -> notifyObserverRemove(realm, removed));
}
private void restartActivityExecution(PrivilegeContext ctx) {
-
// iterate the realms
for (String realmName : getContainer().getRealmNames()) {
reloadActivitiesInExecution(ctx, realmName);
@@ -180,7 +157,8 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
tx.update(activity);
// register for execution
- this.registeredActivities.addElement(realmName, activity.getLocator());
+ Controller controller = new Controller(this, activity);
+ this.controllers.addElement(realmName, activity.getLocator(), controller);
});
// commit changes to state
@@ -200,12 +178,12 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
return;
}
- synchronized (this.registeredActivities) {
- Set locators = this.registeredActivities.getSet(realm);
- if (locators != null) {
- for (Locator locator : locators) {
+ synchronized (this.controllers) {
+ Map controllers = this.controllers.getMap(realm);
+ if (controllers != null) {
+ for (Controller controller : controllers.values()) {
// execute async
- toExecution(realm, locator);
+ toExecution(realm, controller);
}
}
}
@@ -283,23 +261,23 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
}
@Override
- public void toExecution(String realm, Locator locator) {
+ public void toExecution(String realm, Activity activity) {
ExecutionHandlerState state = this.statesByRealm.getOrDefault(realm, ExecutionHandlerState.Running);
if (state == ExecutionHandlerState.Paused) {
- logger.warn("Ignoring execution of " + locator + " for paused realm " + realm);
+ logger.warn("Ignoring execution of " + activity.getLocator() + " for paused realm " + realm);
return;
}
getExecutor().execute(() -> {
try {
- runAsAgent(ctx -> toExecution(realm, locator, ctx));
+ runAsAgent(ctx -> toExecution(realm, activity, ctx));
} catch (Exception e) {
- logger.error("Failed to set " + locator + " to execution due to " + e.getMessage(), e);
+ logger.error("Failed to set " + activity.getLocator() + " to execution", e);
if (getContainer().hasComponent(OperationsLog.class)) {
getComponent(OperationsLog.class).addMessage(
- new LogMessage(realm, SYSTEM_USER_AGENT, locator, LogSeverity.Exception,
+ new LogMessage(realm, SYSTEM_USER_AGENT, activity.getLocator(), LogSeverity.Exception,
ResourceBundle.getBundle("strolch-service"), "execution.handler.failed.execution")
.withException(e).value("reason", e));
}
@@ -307,17 +285,11 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
});
}
- private ExecutorService getExecutor() {
- return getExecutorService("ExecutionHandler");
- }
-
@Override
public void toExecuted(String realm, Locator locator) {
getExecutor().execute(() -> {
try {
- runAsAgent(ctx -> {
- toExecuted(realm, locator, ctx);
- });
+ runAsAgent(ctx -> toExecuted(realm, locator, ctx));
} catch (Exception e) {
logger.error("Failed to set " + locator + " to executed due to " + e.getMessage(), e);
@@ -335,9 +307,7 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
public void toStopped(String realm, Locator locator) {
getExecutor().execute(() -> {
try {
- runAsAgent(ctx -> {
- toStopped(realm, locator, ctx);
- });
+ runAsAgent(ctx -> toStopped(realm, locator, ctx));
} catch (Exception e) {
logger.error("Failed to set " + locator + " to stopped due to " + e.getMessage(), e);
@@ -355,9 +325,7 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
public void toError(String realm, Locator locator) {
getExecutor().execute(() -> {
try {
- runAsAgent(ctx -> {
- toError(realm, locator, ctx);
- });
+ runAsAgent(ctx -> toError(realm, locator, ctx));
} catch (Exception e) {
logger.error("Failed to set " + locator + " to error due to " + e.getMessage(), e);
@@ -375,9 +343,7 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
public void toWarning(String realm, Locator locator) {
getExecutor().execute(() -> {
try {
- runAsAgent(ctx -> {
- toWarning(realm, locator, ctx);
- });
+ runAsAgent(ctx -> toWarning(realm, locator, ctx));
} catch (Exception e) {
logger.error("Failed to set " + locator + " to warning due to " + e.getMessage(), e);
@@ -392,42 +358,24 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
}
@Override
- public void archiveActivity(String realm, Locator activityLoc) {
+ public void archiveActivity(String realm, Activity activity) {
getExecutor().execute(() -> {
try {
runAsAgent(ctx -> {
- try (StrolchTransaction tx = openTx(realm, ctx.getCertificate(), ActivityArchivalPolicy.class,
+ try (StrolchTransaction tx = openTx(realm, ctx.getCertificate(), ArchiveActivityCommand.class,
false)) {
- tx.lock(activityLoc);
-
- Activity activity = tx.findElement(activityLoc, true);
- if (activity == null) {
- return;
- }
-
- logger.info("Activity " + activity.getLocator() + " is in state " + activity.getState());
-
- PolicyDef policyDef;
- if (activity.hasPolicyDef(ActivityArchivalPolicy.class.getSimpleName())) {
- policyDef = activity.getPolicyDef(ActivityArchivalPolicy.class.getSimpleName());
- } else {
- policyDef = PolicyDef.valueOf(ActivityArchivalPolicy.class.getSimpleName(),
- KEY_DEFAULT_ACTIVITY_ARCHIVAL);
- }
-
- PolicyHandler policyHandler = getComponent(PolicyHandler.class);
- ActivityArchivalPolicy archivalPolicy = policyHandler.getPolicy(policyDef, tx);
- archivalPolicy.archive(activity);
-
+ ArchiveActivityCommand command = new ArchiveActivityCommand(tx);
+ command.setActivityLoc(activity.getLocator());
+ tx.addCommand(command);
tx.commitOnClose();
}
});
} catch (Exception e) {
- logger.error("Failed to archive " + activityLoc + " due to " + e.getMessage(), e);
+ logger.error("Failed to archive " + activity.getLocator() + " due to " + e.getMessage(), e);
if (getContainer().hasComponent(OperationsLog.class)) {
getComponent(OperationsLog.class).addMessage(
- new LogMessage(realm, SYSTEM_USER_AGENT, activityLoc, LogSeverity.Exception,
+ new LogMessage(realm, SYSTEM_USER_AGENT, activity.getLocator(), LogSeverity.Exception,
ResourceBundle.getBundle("strolch-service"), "execution.handler.failed.archive")
.withException(e).value("reason", e));
}
@@ -596,27 +544,7 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
triggerExecution(realm);
}
- private void notifyObserverAdd(String realm, Locator activityLoc) {
- if (!getContainer().getRealm(realm).isUpdateObservers())
- return;
-
- try {
- runAsAgent(ctx -> {
- try (StrolchTransaction tx = openTx(realm, ctx.getCertificate(), true)) {
- Activity activity = tx.findElement(activityLoc, true);
- if (activity != null) {
- ObserverEvent observerEvent = new ObserverEvent();
- observerEvent.added.addElement(Tags.CONTROLLER, activity);
- getContainer().getRealm(realm).getObserverHandler().notify(observerEvent);
- }
- }
- });
- } catch (Exception e) {
- logger.error("Failed to notify observers of new controller " + activityLoc);
- }
- }
-
- private void notifyObserverAdd(String realm, Activity rootElement) {
+ private void notifyObserverAdd(String realm, Controller controller) {
if (!getContainer().getRealm(realm).isUpdateObservers())
return;
@@ -625,7 +553,7 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
getContainer().getRealm(realm).getObserverHandler().notify(observerEvent);
}
- private void notifyObserverUpdate(StrolchTransaction tx, Activity rootElement) {
+ private void notifyObserverUpdate(StrolchTransaction tx, Controller controller) {
if (!getContainer().getRealm(tx.getRealmName()).isUpdateObservers())
return;
@@ -634,7 +562,7 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
tx.getContainer().getRealm(tx.getRealmName()).getObserverHandler().notify(observerEvent);
}
- private void notifyObserverRemove(StrolchTransaction tx, Activity rootElement) {
+ private void notifyObserverRemove(StrolchTransaction tx, Controller controller) {
if (!getContainer().getRealm(tx.getRealmName()).isUpdateObservers())
return;
@@ -643,7 +571,7 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
tx.getContainer().getRealm(tx.getRealmName()).getObserverHandler().notify(observerEvent);
}
- private void notifyObserverRemove(String realm, Locator activityLoc) {
+ private void notifyObserverRemove(String realm, Controller controller) {
if (!getContainer().getRealm(realm).isUpdateObservers())
return;
@@ -663,7 +591,7 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
}
}
- private void notifyObserverRemove(String realm, Set activityLocs) {
+ private void notifyObserverRemove(String realm, Map removed) {
if (!getContainer().getRealm(realm).isUpdateObservers())
return;
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/ExecutionHandler.java b/li.strolch.service/src/main/java/li/strolch/execution/ExecutionHandler.java
index e33faca4c..b93c37478 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/ExecutionHandler.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/ExecutionHandler.java
@@ -11,8 +11,11 @@ import li.strolch.model.State;
import li.strolch.model.activity.Action;
import li.strolch.model.activity.Activity;
import li.strolch.model.activity.TimeOrdering;
+import li.strolch.persistence.api.StrolchTransaction;
+import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.model.Certificate;
import li.strolch.privilege.model.PrivilegeContext;
+import li.strolch.runtime.privilege.PrivilegedRunnable;
/**
*
@@ -41,16 +44,13 @@ public abstract class ExecutionHandler extends StrolchComponent {
public static final String PARAM_STATE = "state";
- /**
- * Registers the given {@link Locator} of an {@link Activity} for execution, and submits it for execution
- * immediately in an asynchronous manner
- *
- * @param realm
- * the realm where the {@link Activity} resides
- * @param activityLoc
- * the {@link Locator} of the {@link Activity}
- */
- public abstract void addForExecution(String realm, Locator activityLoc);
+ public StrolchTransaction openTx(Certificate cert, Class> action, boolean readOnly) {
+ return super.openTx(cert, action.getName(), readOnly);
+ }
+
+ public void runAsAgent(PrivilegedRunnable runnable) throws PrivilegeException, Exception {
+ super.runAsAgent(runnable);
+ }
/**
* Registers the given {@link Activity} for execution, and submits it for execution immediately in an asynchronous
@@ -126,10 +126,10 @@ public abstract class ExecutionHandler extends StrolchComponent {
*
* @param realm
* the realm where the activity resides
- * @param activityLoc
- * the {@link Locator} of the {@link Activity}
+ * @param activity
+ * the {@link Activity}
*/
- public abstract void archiveActivity(String realm, Locator activityLoc);
+ public abstract void archiveActivity(String realm, Activity activity);
/**
* Returns the {@link Set} of {@link Locator Locators} of {@link Activity Activities} which are registered for
@@ -157,14 +157,14 @@ public abstract class ExecutionHandler extends StrolchComponent {
public abstract DelayedExecutionTimer getDelayedExecutionTimer();
/**
- * Starts the execution of the given {@link Activity} with the given {@link Locator}
+ * Starts the execution of the given {@link Activity}
*
* @param realm
* the realm where the {@link Activity} resides
- * @param activityLoc
- * the {@link Locator} of the {@link Activity}
+ * @param activity
+ * the {@link Activity}
*/
- public abstract void toExecution(String realm, Locator activityLoc);
+ public abstract void toExecution(String realm, Activity activity);
/**
* Completes the execution of the given {@link Action} with the given {@link Locator}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/ArchiveActivityCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/ArchiveActivityCommand.java
new file mode 100644
index 000000000..1b6bcd8d4
--- /dev/null
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/ArchiveActivityCommand.java
@@ -0,0 +1,54 @@
+package li.strolch.execution.command;
+
+import li.strolch.execution.policy.ActivityArchivalPolicy;
+import li.strolch.model.Locator;
+import li.strolch.model.activity.Activity;
+import li.strolch.model.policy.PolicyDef;
+import li.strolch.persistence.api.StrolchTransaction;
+import li.strolch.policy.PolicyHandler;
+import li.strolch.service.api.Command;
+import li.strolch.utils.dbc.DBC;
+
+public class ArchiveActivityCommand extends Command {
+
+ private static final String KEY_DEFAULT_ACTIVITY_ARCHIVAL = "key:DefaultActivityArchival";
+
+ private Locator activityLoc;
+
+ public ArchiveActivityCommand(StrolchTransaction tx) {
+ super(tx);
+ }
+
+ public void setActivityLoc(Locator activityLoc) {
+ this.activityLoc = activityLoc;
+ }
+
+ @Override
+ public void validate() {
+ DBC.PRE.assertNotNull("activity can not be null!", this.activityLoc);
+ }
+
+ @Override
+ public void doCommand() {
+ tx().lock(this.activityLoc);
+
+ Activity activity = tx().getActivityBy(this.activityLoc.get(1), this.activityLoc.get(2));
+ if (activity == null) {
+ logger.error("Activity " + this.activityLoc + " does not exist anymore, can not archive!");
+ return;
+ }
+
+ logger.info("Activity " + activity.getLocator() + " is in state " + activity.getState());
+
+ PolicyDef policyDef;
+ if (activity.hasPolicyDef(ActivityArchivalPolicy.class.getSimpleName())) {
+ policyDef = activity.getPolicyDef(ActivityArchivalPolicy.class.getSimpleName());
+ } else {
+ policyDef = PolicyDef.valueOf(ActivityArchivalPolicy.class.getSimpleName(), KEY_DEFAULT_ACTIVITY_ARCHIVAL);
+ }
+
+ PolicyHandler policyHandler = getComponent(PolicyHandler.class);
+ ActivityArchivalPolicy archivalPolicy = policyHandler.getPolicy(policyDef, tx());
+ archivalPolicy.archive(activity);
+ }
+}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/ExecuteActivityCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/ExecuteActivityCommand.java
index b50b711e0..493202a4f 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/ExecuteActivityCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/ExecuteActivityCommand.java
@@ -1,6 +1,5 @@
package li.strolch.execution.command;
-import li.strolch.agent.api.ComponentContainer;
import li.strolch.model.State;
import li.strolch.model.activity.Activity;
import li.strolch.persistence.api.StrolchTransaction;
@@ -10,8 +9,8 @@ public class ExecuteActivityCommand extends ExecutionCommand {
private Activity activity;
- public ExecuteActivityCommand(ComponentContainer container, StrolchTransaction tx) {
- super(container, tx);
+ public ExecuteActivityCommand(StrolchTransaction tx) {
+ super(tx);
}
public void setActivity(Activity activity) {
@@ -21,7 +20,6 @@ public class ExecuteActivityCommand extends ExecutionCommand {
@Override
public void validate() {
DBC.PRE.assertNotNull("activity can not be null!", this.activity);
- tx().lock(this.activity.getRootElement());
}
@Override
@@ -34,9 +32,4 @@ public class ExecuteActivityCommand extends ExecutionCommand {
updateOrderState(tx(), rootElement, currentState, rootElement.getState());
}
-
- @Override
- public void undo() {
- // can't undo execution
- }
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/ExecuteStoppedActionCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/ExecuteStoppedActionCommand.java
index c72aab5c7..615dd8477 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/ExecuteStoppedActionCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/ExecuteStoppedActionCommand.java
@@ -2,7 +2,6 @@ package li.strolch.execution.command;
import java.text.MessageFormat;
-import li.strolch.agent.api.ComponentContainer;
import li.strolch.exception.StrolchException;
import li.strolch.model.State;
import li.strolch.model.activity.Action;
@@ -14,8 +13,8 @@ public class ExecuteStoppedActionCommand extends ExecutionCommand {
private Action action;
- public ExecuteStoppedActionCommand(ComponentContainer container, StrolchTransaction tx) {
- super(container, tx);
+ public ExecuteStoppedActionCommand(StrolchTransaction tx) {
+ super(tx);
}
public void setAction(Action action) {
@@ -47,9 +46,4 @@ public class ExecuteStoppedActionCommand extends ExecutionCommand {
updateOrderState(tx(), rootElement, currentState, rootElement.getState());
}
-
- @Override
- public void undo() {
- // can't undo execution
- }
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/ExecutionCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/ExecutionCommand.java
index 6fbfd12eb..f532ed989 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/ExecutionCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/ExecutionCommand.java
@@ -8,7 +8,6 @@ import static li.strolch.utils.helper.StringHelper.isEmpty;
import java.util.Iterator;
import java.util.Map.Entry;
-import li.strolch.agent.api.ComponentContainer;
import li.strolch.exception.StrolchException;
import li.strolch.execution.policy.ConfirmationPolicy;
import li.strolch.execution.policy.ExecutionPolicy;
@@ -29,8 +28,8 @@ import li.strolch.service.api.Command;
public abstract class ExecutionCommand extends Command implements TimeOrderingVisitor, IActivityElementVisitor {
- public ExecutionCommand(ComponentContainer container, StrolchTransaction tx) {
- super(container, tx);
+ public ExecutionCommand(StrolchTransaction tx) {
+ super(tx);
}
protected Locator getResourceLocator(Action action) {
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/PlanActionCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/PlanActionCommand.java
index 754fa6668..7413c604d 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/PlanActionCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/PlanActionCommand.java
@@ -72,8 +72,13 @@ public class PlanActionCommand extends PlanningCommand {
@Override
public Void visitAction(Action action) {
+
PlanningPolicy planningPolicy = tx().getPolicy(action.findPolicy(PlanningPolicy.class, NO_PLANNING));
planningPolicy.plan(action);
+
+ if (action.getState() == State.PLANNED)
+ getConfirmationPolicy(action).toPlanned(action);
+
return null;
}
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/PlanningCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/PlanningCommand.java
index b658acca4..95cc9c4f7 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/PlanningCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/PlanningCommand.java
@@ -15,14 +15,23 @@
*/
package li.strolch.execution.command;
+import static li.strolch.utils.helper.StringHelper.DASH;
+import static li.strolch.utils.helper.StringHelper.isEmpty;
+
import java.util.Iterator;
import java.util.Map.Entry;
+import li.strolch.exception.StrolchException;
+import li.strolch.execution.policy.ConfirmationPolicy;
+import li.strolch.model.Resource;
import li.strolch.model.State;
+import li.strolch.model.activity.Action;
import li.strolch.model.activity.Activity;
import li.strolch.model.activity.IActivityElement;
+import li.strolch.model.policy.PolicyDef;
import li.strolch.model.visitor.IActivityElementVisitor;
import li.strolch.persistence.api.StrolchTransaction;
+import li.strolch.policy.PolicyHandler;
import li.strolch.service.api.Command;
/**
@@ -52,4 +61,22 @@ public abstract class PlanningCommand extends Command implements IActivityElemen
}
return null;
}
+
+ protected Resource getResource(Action action) {
+ String resourceId = action.getResourceId();
+ if (isEmpty(resourceId) || resourceId.equals(DASH))
+ throw new StrolchException("No resourceId defined on action " + action.getLocator());
+ String resourceType = action.getResourceType();
+ if (isEmpty(resourceType) || resourceType.equals(DASH))
+ throw new StrolchException("No resourceType defined on action " + action.getLocator());
+
+ return tx().getResourceBy(resourceType, resourceId, true);
+ }
+
+
+ protected ConfirmationPolicy getConfirmationPolicy(Action action) {
+ Resource resource = getResource(action);
+ PolicyDef executionPolicyDef = resource.getPolicyDefs().getPolicyDef(ConfirmationPolicy.class.getSimpleName());
+ return getComponent(PolicyHandler.class).getPolicy(executionPolicyDef, tx());
+ }
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToClosedCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToClosedCommand.java
index 6b8d13a2f..97163a71d 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToClosedCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToClosedCommand.java
@@ -2,7 +2,6 @@ package li.strolch.execution.command;
import java.text.MessageFormat;
-import li.strolch.agent.api.ComponentContainer;
import li.strolch.exception.StrolchException;
import li.strolch.model.State;
import li.strolch.model.activity.Action;
@@ -14,8 +13,8 @@ public class SetActionToClosedCommand extends ExecutionCommand {
private Action action;
- public SetActionToClosedCommand(ComponentContainer container, StrolchTransaction tx) {
- super(container, tx);
+ public SetActionToClosedCommand(StrolchTransaction tx) {
+ super(tx);
}
public void setAction(Action action) {
@@ -55,9 +54,4 @@ public class SetActionToClosedCommand extends ExecutionCommand {
updateOrderState(tx(), rootElement, currentState, rootElement.getState());
}
-
- @Override
- public void undo() {
- // can not undo
- }
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToCreatedCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToCreatedCommand.java
index 9337dac9a..efdaa4107 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToCreatedCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToCreatedCommand.java
@@ -2,7 +2,6 @@ package li.strolch.execution.command;
import java.text.MessageFormat;
-import li.strolch.agent.api.ComponentContainer;
import li.strolch.exception.StrolchException;
import li.strolch.model.State;
import li.strolch.model.activity.Action;
@@ -14,8 +13,8 @@ public class SetActionToCreatedCommand extends ExecutionCommand {
private Action action;
- public SetActionToCreatedCommand(ComponentContainer container, StrolchTransaction tx) {
- super(container, tx);
+ public SetActionToCreatedCommand(StrolchTransaction tx) {
+ super(tx);
}
public void setAction(Action action) {
@@ -55,9 +54,4 @@ public class SetActionToCreatedCommand extends ExecutionCommand {
updateOrderState(tx(), rootElement, currentState, rootElement.getState());
}
-
- @Override
- public void undo() {
- // can not undo
- }
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToErrorCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToErrorCommand.java
index d5841da74..03719b85e 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToErrorCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToErrorCommand.java
@@ -2,7 +2,6 @@ package li.strolch.execution.command;
import java.text.MessageFormat;
-import li.strolch.agent.api.ComponentContainer;
import li.strolch.exception.StrolchException;
import li.strolch.model.State;
import li.strolch.model.activity.Action;
@@ -14,8 +13,8 @@ public class SetActionToErrorCommand extends ExecutionCommand {
private Action action;
- public SetActionToErrorCommand(ComponentContainer container, StrolchTransaction tx) {
- super(container, tx);
+ public SetActionToErrorCommand(StrolchTransaction tx) {
+ super(tx);
}
public void setAction(Action action) {
@@ -54,9 +53,4 @@ public class SetActionToErrorCommand extends ExecutionCommand {
updateOrderState(tx(), rootElement, currentState, rootElement.getState());
}
-
- @Override
- public void undo() {
- // can not undo
- }
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToExecutedCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToExecutedCommand.java
index 5c84facfc..ad1385614 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToExecutedCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToExecutedCommand.java
@@ -2,7 +2,6 @@ package li.strolch.execution.command;
import java.text.MessageFormat;
-import li.strolch.agent.api.ComponentContainer;
import li.strolch.exception.StrolchException;
import li.strolch.model.State;
import li.strolch.model.activity.Action;
@@ -14,8 +13,8 @@ public class SetActionToExecutedCommand extends ExecutionCommand {
private Action action;
- public SetActionToExecutedCommand(ComponentContainer container, StrolchTransaction tx) {
- super(container, tx);
+ public SetActionToExecutedCommand(StrolchTransaction tx) {
+ super(tx);
}
public void setAction(Action action) {
@@ -54,9 +53,4 @@ public class SetActionToExecutedCommand extends ExecutionCommand {
updateOrderState(tx(), rootElement, currentState, rootElement.getState());
}
-
- @Override
- public void undo() {
- // can not undo
- }
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToPlannedCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToPlannedCommand.java
index 6f17c28a9..3c91fb27e 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToPlannedCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToPlannedCommand.java
@@ -2,7 +2,6 @@ package li.strolch.execution.command;
import java.text.MessageFormat;
-import li.strolch.agent.api.ComponentContainer;
import li.strolch.exception.StrolchException;
import li.strolch.model.State;
import li.strolch.model.activity.Action;
@@ -14,8 +13,8 @@ public class SetActionToPlannedCommand extends ExecutionCommand {
private Action action;
- public SetActionToPlannedCommand(ComponentContainer container, StrolchTransaction tx) {
- super(container, tx);
+ public SetActionToPlannedCommand(StrolchTransaction tx) {
+ super(tx);
}
public void setAction(Action action) {
@@ -55,9 +54,4 @@ public class SetActionToPlannedCommand extends ExecutionCommand {
updateOrderState(tx(), rootElement, currentState, rootElement.getState());
}
-
- @Override
- public void undo() {
- // can not undo
- }
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToPlanningCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToPlanningCommand.java
index 22b02c509..1efbd211d 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToPlanningCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToPlanningCommand.java
@@ -2,7 +2,6 @@ package li.strolch.execution.command;
import java.text.MessageFormat;
-import li.strolch.agent.api.ComponentContainer;
import li.strolch.exception.StrolchException;
import li.strolch.model.State;
import li.strolch.model.activity.Action;
@@ -14,8 +13,8 @@ public class SetActionToPlanningCommand extends ExecutionCommand {
private Action action;
- public SetActionToPlanningCommand(ComponentContainer container, StrolchTransaction tx) {
- super(container, tx);
+ public SetActionToPlanningCommand(StrolchTransaction tx) {
+ super(tx);
}
public void setAction(Action action) {
@@ -55,9 +54,4 @@ public class SetActionToPlanningCommand extends ExecutionCommand {
updateOrderState(tx(), rootElement, currentState, rootElement.getState());
}
-
- @Override
- public void undo() {
- // can not undo
- }
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToStoppedCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToStoppedCommand.java
index 726023796..ccf897e36 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToStoppedCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToStoppedCommand.java
@@ -2,7 +2,6 @@ package li.strolch.execution.command;
import java.text.MessageFormat;
-import li.strolch.agent.api.ComponentContainer;
import li.strolch.exception.StrolchException;
import li.strolch.model.State;
import li.strolch.model.activity.Action;
@@ -14,8 +13,8 @@ public class SetActionToStoppedCommand extends ExecutionCommand {
private Action action;
- public SetActionToStoppedCommand(ComponentContainer container, StrolchTransaction tx) {
- super(container, tx);
+ public SetActionToStoppedCommand(StrolchTransaction tx) {
+ super(tx);
}
public void setAction(Action action) {
@@ -54,9 +53,4 @@ public class SetActionToStoppedCommand extends ExecutionCommand {
updateOrderState(tx(), rootElement, currentState, rootElement.getState());
}
-
- @Override
- public void undo() {
- // can not undo
- }
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToWarningCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToWarningCommand.java
index 74ba55d67..98fbc628c 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToWarningCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToWarningCommand.java
@@ -2,7 +2,6 @@ package li.strolch.execution.command;
import java.text.MessageFormat;
-import li.strolch.agent.api.ComponentContainer;
import li.strolch.exception.StrolchException;
import li.strolch.model.State;
import li.strolch.model.activity.Action;
@@ -14,8 +13,8 @@ public class SetActionToWarningCommand extends ExecutionCommand {
private Action action;
- public SetActionToWarningCommand(ComponentContainer container, StrolchTransaction tx) {
- super(container, tx);
+ public SetActionToWarningCommand(StrolchTransaction tx) {
+ super(tx);
}
public void setAction(Action action) {
@@ -54,9 +53,4 @@ public class SetActionToWarningCommand extends ExecutionCommand {
updateOrderState(tx(), rootElement, currentState, rootElement.getState());
}
-
- @Override
- public void undo() {
- // can not undo
- }
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/service/SetActionStateService.java b/li.strolch.service/src/main/java/li/strolch/execution/service/SetActionStateService.java
index f46a5fa03..63d82a6a5 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/service/SetActionStateService.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/service/SetActionStateService.java
@@ -42,7 +42,7 @@ public class SetActionStateService extends AbstractServiceOverview
+ *
+ * @param command
+ * the command to add
+ */
+ void add(Command command);
+
/**
* Helper method to create an {@link Audit} with the given arguments. The audit can then be saved by calling {@link
* AuditTrail#add(StrolchTransaction, Audit)}
@@ -1361,6 +1379,14 @@ public interface StrolchTransaction extends AutoCloseable {
List getOrdersByRelation(StrolchRootElement element, String refId, boolean assertExists)
throws StrolchException;
+ /**
+ * Allows to evict a {@link Locator} from the transaction's cache and object filter
+ *
+ * @param locator
+ * the locator of the object to remove from cache
+ */
+ void removeFromCache(Locator locator);
+
/**
* Returns the cached resource with the given type and id, or null if not yet fetched
*
diff --git a/li.strolch.agent/src/main/java/li/strolch/policy/StrolchPolicy.java b/li.strolch.agent/src/main/java/li/strolch/policy/StrolchPolicy.java
index 06dbc7493..a75c54e7b 100644
--- a/li.strolch.agent/src/main/java/li/strolch/policy/StrolchPolicy.java
+++ b/li.strolch.agent/src/main/java/li/strolch/policy/StrolchPolicy.java
@@ -16,20 +16,15 @@
package li.strolch.policy;
import static li.strolch.runtime.StrolchConstants.PolicyConstants.PARAM_ORDER;
-import static li.strolch.utils.helper.StringHelper.DASH;
-
-import li.strolch.model.Order;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import li.strolch.agent.api.ComponentContainer;
import li.strolch.agent.api.StrolchComponent;
-import li.strolch.exception.StrolchException;
-import li.strolch.model.Resource;
+import li.strolch.model.Order;
import li.strolch.model.activity.Action;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.service.api.Command;
-import li.strolch.utils.helper.StringHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Interface for all Strolch policies, which are instantiated by the {@link PolicyHandler}
@@ -86,30 +81,6 @@ public abstract class StrolchPolicy {
return this.tx;
}
- /**
- * Return the defined {@link Resource} on the given {@link Action}
- *
- * @param action
- * the action for which to get the {@link Resource}
- *
- * @return the {@link Resource}
- *
- * @throws IllegalArgumentException
- * if the resource is not defined on the action, i.e. fields are empty or a dash
- * @throws StrolchException
- * if the resource does not exist, which is referenced by the action
- */
- protected Resource getResource(Action action) throws IllegalArgumentException, StrolchException {
- String resourceId = action.getResourceId();
- if (StringHelper.isEmpty(resourceId) || resourceId.equals(DASH))
- throw new IllegalArgumentException("No resourceId defined on action " + action.getLocator());
- String resourceType = action.getResourceType();
- if (StringHelper.isEmpty(resourceType) || resourceType.equals(DASH))
- throw new IllegalArgumentException("No resourceType defined on action " + action.getLocator());
-
- return this.tx.getResourceBy(resourceType, resourceId, true);
- }
-
protected Order getOrder(Action action) {
return tx().getOrderByRelation(action.getRootElement(), PARAM_ORDER, true);
}
diff --git a/li.strolch.agent/src/main/java/li/strolch/runtime/StrolchConstants.java b/li.strolch.agent/src/main/java/li/strolch/runtime/StrolchConstants.java
index 24cb89455..32a126765 100644
--- a/li.strolch.agent/src/main/java/li/strolch/runtime/StrolchConstants.java
+++ b/li.strolch.agent/src/main/java/li/strolch/runtime/StrolchConstants.java
@@ -118,9 +118,12 @@ public class StrolchConstants {
public static class PolicyConstants {
public static final String TYPE_PRODUCE = "Produce";
public static final String TYPE_CONSUME = "Consume";
+ public static final String TYPE_RESERVE = "Reserve";
+ public static final String TYPE_RELEASE = "Release";
public static final String BAG_OBJECTIVES = "Objectives";
+ public static final String PARAM_RESERVED = "reserved";
public static final String PARAM_QUANTITY = "quantity";
public static final String PARAM_DURATION = "duration";
public static final String PARAM_ORDER = "order";
diff --git a/li.strolch.agent/src/test/java/li/strolch/policytest/TestNoConfirmationPolicy.java b/li.strolch.agent/src/test/java/li/strolch/policytest/TestNoConfirmationPolicy.java
index b9f551bd8..27397f9d5 100644
--- a/li.strolch.agent/src/test/java/li/strolch/policytest/TestNoConfirmationPolicy.java
+++ b/li.strolch.agent/src/test/java/li/strolch/policytest/TestNoConfirmationPolicy.java
@@ -1,12 +1,12 @@
/*
* Copyright 2015 Robert von Burg
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -32,9 +32,4 @@ public class TestNoConfirmationPolicy extends TestConfirmationPolicy {
public void confirm(Action action) {
action.setState(State.CLOSED);
}
-
- @Override
- public void undo() {
- // do nothing
- }
}
diff --git a/li.strolch.agent/src/test/java/li/strolch/policytest/TestSimplePlanningPolicy.java b/li.strolch.agent/src/test/java/li/strolch/policytest/TestSimplePlanningPolicy.java
index 0a6ad5500..bb96fa566 100644
--- a/li.strolch.agent/src/test/java/li/strolch/policytest/TestSimplePlanningPolicy.java
+++ b/li.strolch.agent/src/test/java/li/strolch/policytest/TestSimplePlanningPolicy.java
@@ -1,12 +1,12 @@
/*
* Copyright 2015 Robert von Burg
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -32,9 +32,4 @@ public class TestSimplePlanningPolicy extends TestPlanningPolicy {
public void plan(Action action) {
action.setState(State.PLANNED);
}
-
- @Override
- public void undo() {
- // do nothing
- }
}
diff --git a/li.strolch.agent/src/test/java/li/strolch/policytest/TestSimulatedExecutionPolicy.java b/li.strolch.agent/src/test/java/li/strolch/policytest/TestSimulatedExecutionPolicy.java
index 43fbfea5a..747431bd4 100644
--- a/li.strolch.agent/src/test/java/li/strolch/policytest/TestSimulatedExecutionPolicy.java
+++ b/li.strolch.agent/src/test/java/li/strolch/policytest/TestSimulatedExecutionPolicy.java
@@ -1,12 +1,12 @@
/*
* Copyright 2015 Robert von Burg
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -32,9 +32,4 @@ public class TestSimulatedExecutionPolicy extends TestExecutionPolicy {
public void execute(Action action) {
action.setState(State.EXECUTION);
}
-
- @Override
- public void undo() {
- // do nothing
- }
}
diff --git a/li.strolch.model/src/main/java/li/strolch/model/Order.java b/li.strolch.model/src/main/java/li/strolch/model/Order.java
index f7197f7f6..7a4bb3cf4 100644
--- a/li.strolch.model/src/main/java/li/strolch/model/Order.java
+++ b/li.strolch.model/src/main/java/li/strolch/model/Order.java
@@ -154,6 +154,20 @@ public class Order extends AbstractStrolchRootElement implements StrolchRootElem
return getPolicyDefs().getPolicyDef(type);
}
+ @Override
+ public PolicyDef getPolicyDef(Class> clazz, PolicyDef defaultDef) {
+ if (!hasPolicyDefs())
+ return defaultDef;
+ return getPolicyDefs().getPolicyDef(clazz.getSimpleName(), defaultDef);
+ }
+
+ @Override
+ public PolicyDef getPolicyDef(String type, PolicyDef defaultDef) {
+ if (!hasPolicyDefs())
+ return defaultDef;
+ return getPolicyDefs().getPolicyDef(type, defaultDef);
+ }
+
@Override
public boolean hasPolicyDefs() {
return this.policyDefs != null;
diff --git a/li.strolch.model/src/main/java/li/strolch/model/PolicyContainer.java b/li.strolch.model/src/main/java/li/strolch/model/PolicyContainer.java
index 2bab69cff..d61c2d5d4 100644
--- a/li.strolch.model/src/main/java/li/strolch/model/PolicyContainer.java
+++ b/li.strolch.model/src/main/java/li/strolch/model/PolicyContainer.java
@@ -20,12 +20,12 @@ public interface PolicyContainer {
* @throws StrolchPolicyException
* if no {@link PolicyDefs} are available
*/
- public PolicyDefs getPolicyDefs() throws StrolchPolicyException;
+ PolicyDefs getPolicyDefs() throws StrolchPolicyException;
/**
* @return true if this container has {@link PolicyDefs}, false if not
*/
- public boolean hasPolicyDefs();
+ boolean hasPolicyDefs();
/**
* Returns true if this container has the {@link PolicyDef} with the given type, false if not
@@ -35,7 +35,7 @@ public interface PolicyContainer {
*
* @return true if this container has the {@link PolicyDef} with the given type, false if not
*/
- public boolean hasPolicyDef(String type);
+ boolean hasPolicyDef(String type);
/**
* Returns the {@link PolicyDef} for the given type
@@ -45,7 +45,19 @@ public interface PolicyContainer {
*
* @return the policy def of the given type
*/
- public PolicyDef getPolicyDef(String type);
+ PolicyDef getPolicyDef(String type);
+
+ /**
+ * Returns the {@link PolicyDef} for the given type
+ *
+ * @param type
+ * the type of policy def to return
+ * @param defaultDef
+ * the default policy definition to return if the given type is not defined
+ *
+ * @return the policy def of the given type
+ */
+ PolicyDef getPolicyDef(String type, PolicyDef defaultDef);
/**
* Returns the {@link PolicyDef} for the given class
@@ -55,7 +67,19 @@ public interface PolicyContainer {
*
* @return the policy def of the given class
*/
- public PolicyDef getPolicyDef(Class> clazz);
+ PolicyDef getPolicyDef(Class> clazz);
+
+ /**
+ * Returns the {@link PolicyDef} for the given class
+ *
+ * @param clazz
+ * the type of policy def to return
+ * @param defaultDef
+ * the default policy definition to return if the given type is not defined
+ *
+ * @return the policy def of the given class
+ */
+ PolicyDef getPolicyDef(Class> clazz, PolicyDef defaultDef);
/**
* Set the reference to the {@link PolicyDefs}
@@ -63,5 +87,5 @@ public interface PolicyContainer {
* @param policyDefs
* the {@link PolicyDefs} to set
*/
- public void setPolicyDefs(PolicyDefs policyDefs);
+ void setPolicyDefs(PolicyDefs policyDefs);
}
diff --git a/li.strolch.model/src/main/java/li/strolch/model/Resource.java b/li.strolch.model/src/main/java/li/strolch/model/Resource.java
index 79c7f260d..0801ab1d0 100644
--- a/li.strolch.model/src/main/java/li/strolch/model/Resource.java
+++ b/li.strolch.model/src/main/java/li/strolch/model/Resource.java
@@ -252,6 +252,20 @@ public class Resource extends AbstractStrolchRootElement implements StrolchRootE
return getPolicyDefs().getPolicyDef(type);
}
+ @Override
+ public PolicyDef getPolicyDef(Class> clazz, PolicyDef defaultDef) {
+ if (!hasPolicyDefs())
+ return defaultDef;
+ return getPolicyDefs().getPolicyDef(clazz.getSimpleName(), defaultDef);
+ }
+
+ @Override
+ public PolicyDef getPolicyDef(String type, PolicyDef defaultDef) {
+ if (!hasPolicyDefs())
+ return defaultDef;
+ return getPolicyDefs().getPolicyDef(type, defaultDef);
+ }
+
@Override
public boolean hasPolicyDefs() {
return this.policyDefs != null;
diff --git a/li.strolch.model/src/main/java/li/strolch/model/State.java b/li.strolch.model/src/main/java/li/strolch/model/State.java
index 4f64e5f72..76bf0a402 100644
--- a/li.strolch.model/src/main/java/li/strolch/model/State.java
+++ b/li.strolch.model/src/main/java/li/strolch/model/State.java
@@ -168,6 +168,13 @@ public enum State {
return this == CREATED || this == PLANNING || this == PLANNED;
}
+ /**
+ * @return true if {@link #PLANNED} or {@link #EXECUTABLE} or {@link #STOPPED}
+ */
+ public boolean canSetToExecutable() {
+ return this == PLANNED || this == EXECUTABLE || this == State.STOPPED;
+ }
+
/**
* @return true if {@link #PLANNED} or {@link #EXECUTABLE} or {@link #EXECUTION}
*/
diff --git a/li.strolch.model/src/main/java/li/strolch/model/activity/Action.java b/li.strolch.model/src/main/java/li/strolch/model/activity/Action.java
index 2bfe0f7db..66bd7e946 100644
--- a/li.strolch.model/src/main/java/li/strolch/model/activity/Action.java
+++ b/li.strolch.model/src/main/java/li/strolch/model/activity/Action.java
@@ -16,6 +16,8 @@
package li.strolch.model.activity;
+import static li.strolch.utils.helper.StringHelper.isNotEmpty;
+
import java.text.MessageFormat;
import java.util.*;
@@ -142,6 +144,16 @@ public class Action extends GroupedParameterizedElement implements IActivityElem
this.resourceId = resource.getId();
}
+ public boolean hasResourceDefined() {
+ return isNotEmpty(this.resourceType) && isNotEmpty(this.resourceId);
+ }
+
+ public Locator getResourceLocator() {
+ if (!hasResourceDefined())
+ throw new IllegalStateException("Resource not set on " + getLocator());
+ return Resource.locatorFor(this.resourceType, this.resourceId);
+ }
+
/**
* Returns true if this {@link Action} contains any {@link IValueChange changes}, false if not
*
@@ -245,6 +257,20 @@ public class Action extends GroupedParameterizedElement implements IActivityElem
return getPolicyDefs().getPolicyDef(clazz.getSimpleName());
}
+ @Override
+ public PolicyDef getPolicyDef(Class> clazz, PolicyDef defaultDef) {
+ if (!hasPolicyDefs())
+ return defaultDef;
+ return getPolicyDefs().getPolicyDef(clazz.getSimpleName(), defaultDef);
+ }
+
+ @Override
+ public PolicyDef getPolicyDef(String type, PolicyDef defaultDef) {
+ if (!hasPolicyDefs())
+ return defaultDef;
+ return getPolicyDefs().getPolicyDef(type, defaultDef);
+ }
+
@Override
public boolean hasPolicyDef(String type) {
return this.policyDefs != null && policyDefs.hasPolicyDef(type);
diff --git a/li.strolch.model/src/main/java/li/strolch/model/activity/Activity.java b/li.strolch.model/src/main/java/li/strolch/model/activity/Activity.java
index d078b758b..261c18b4f 100644
--- a/li.strolch.model/src/main/java/li/strolch/model/activity/Activity.java
+++ b/li.strolch.model/src/main/java/li/strolch/model/activity/Activity.java
@@ -20,6 +20,7 @@ import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Stream;
+import li.strolch.exception.StrolchElementNotFoundException;
import li.strolch.exception.StrolchException;
import li.strolch.exception.StrolchModelException;
import li.strolch.exception.StrolchPolicyException;
@@ -395,6 +396,8 @@ public class Activity extends AbstractStrolchRootElement
}
element = ((Activity) element).getElement(next);
+ if (element == null)
+ throw new StrolchElementNotFoundException(locator + " does not exist!");
}
@SuppressWarnings("unchecked")
@@ -470,6 +473,20 @@ public class Activity extends AbstractStrolchRootElement
return getPolicyDefs().getPolicyDef(type);
}
+ @Override
+ public PolicyDef getPolicyDef(Class> clazz, PolicyDef defaultDef) {
+ if (!hasPolicyDefs())
+ return defaultDef;
+ return getPolicyDefs().getPolicyDef(clazz.getSimpleName(), defaultDef);
+ }
+
+ @Override
+ public PolicyDef getPolicyDef(String type, PolicyDef defaultDef) {
+ if (!hasPolicyDefs())
+ return defaultDef;
+ return getPolicyDefs().getPolicyDef(type, defaultDef);
+ }
+
@Override
public boolean hasPolicyDefs() {
return this.policyDefs != null;
diff --git a/li.strolch.model/src/main/java/li/strolch/model/policy/PolicyDefs.java b/li.strolch.model/src/main/java/li/strolch/model/policy/PolicyDefs.java
index f505ec87a..48cff42f2 100644
--- a/li.strolch.model/src/main/java/li/strolch/model/policy/PolicyDefs.java
+++ b/li.strolch.model/src/main/java/li/strolch/model/policy/PolicyDefs.java
@@ -55,7 +55,14 @@ public class PolicyDefs {
}
public PolicyDef getPolicyDef(String type) {
+ return getPolicyDef(type, null);
+ }
+
+ public PolicyDef getPolicyDef(String type, PolicyDef defaultDef) {
if (!this.policyDefMap.containsKey(type)) {
+ if (defaultDef != null)
+ return defaultDef;
+
throw new StrolchPolicyException(
"The PolicyDef does not exist with type " + type + " on " + this.parent.getLocator());
}
diff --git a/li.strolch.rest/src/main/java/li/strolch/rest/endpoint/ControlResource.java b/li.strolch.rest/src/main/java/li/strolch/rest/endpoint/ControlResource.java
index 127f1e722..841088d66 100644
--- a/li.strolch.rest/src/main/java/li/strolch/rest/endpoint/ControlResource.java
+++ b/li.strolch.rest/src/main/java/li/strolch/rest/endpoint/ControlResource.java
@@ -16,6 +16,7 @@ import li.strolch.execution.ExecutionHandler;
import li.strolch.execution.ExecutionHandlerState;
import li.strolch.execution.service.*;
import li.strolch.model.Locator;
+import li.strolch.model.State;
import li.strolch.model.activity.Activity;
import li.strolch.model.json.StrolchElementToJsonVisitor;
import li.strolch.persistence.api.StrolchTransaction;
@@ -133,15 +134,84 @@ public class ControlResource {
@QueryParam("locator") String locatorS, @QueryParam("state") String stateS) {
Certificate cert = (Certificate) request.getAttribute(STROLCH_CERTIFICATE);
+ State state = State.parse(stateS);
+ Locator locator = Locator.valueOf(locatorS);
- SetActionStateService svc = new SetActionStateService();
- StringMapArgument arg = svc.getArgumentInstance();
- arg.realm = realm;
- arg.map.put("locator", locatorS);
- arg.map.put("state", stateS);
+ LocatorArgument arg = new LocatorArgument();
+ arg.locator = locator;
ServiceHandler serviceHandler = RestfulStrolchComponent.getInstance().getServiceHandler();
- ServiceResult svcResult = serviceHandler.doService(cert, svc, arg);
+ ServiceResult svcResult;
+
+ switch (state) {
+ case CREATED: {
+
+ SetActionToCreatedService svc = new SetActionToCreatedService();
+ svcResult = serviceHandler.doService(cert, svc, arg);
+
+ break;
+ }
+
+ case PLANNED: {
+
+ SetActionToPlannedService svc = new SetActionToPlannedService();
+ svcResult = serviceHandler.doService(cert, svc, arg);
+
+ break;
+ }
+
+ case EXECUTION: {
+
+ ExecuteActionService svc = new ExecuteActionService();
+ svcResult = serviceHandler.doService(cert, svc, arg);
+
+ break;
+ }
+
+ case WARNING: {
+
+ SetActionToWarningService svc = new SetActionToWarningService();
+ svcResult = serviceHandler.doService(cert, svc, arg);
+
+ break;
+ }
+
+ case ERROR: {
+
+ SetActionToErrorService svc = new SetActionToErrorService();
+ svcResult = serviceHandler.doService(cert, svc, arg);
+
+ break;
+ }
+
+ case STOPPED: {
+
+ SetActionToStoppedService svc = new SetActionToStoppedService();
+ svcResult = serviceHandler.doService(cert, svc, arg);
+
+ break;
+ }
+
+ case EXECUTED: {
+
+ SetActionToExecutedService svc = new SetActionToExecutedService();
+ svcResult = serviceHandler.doService(cert, svc, arg);
+
+ break;
+ }
+
+ case CLOSED: {
+
+ SetActionToClosedService svc = new SetActionToClosedService();
+ svcResult = serviceHandler.doService(cert, svc, arg);
+
+ break;
+ }
+
+ default:
+ throw new UnsupportedOperationException("Unhandled state " + state);
+ }
+
return ResponseUtil.toResponse(svcResult);
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/ArchiveExecutedActivitiesJob.java b/li.strolch.service/src/main/java/li/strolch/execution/ArchiveExecutedActivitiesJob.java
index 0d8215415..aa978fba4 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/ArchiveExecutedActivitiesJob.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/ArchiveExecutedActivitiesJob.java
@@ -28,7 +28,7 @@ public class ArchiveExecutedActivitiesJob extends StrolchJob {
tx.streamActivities().forEach(activity -> {
if (activity.getState() == State.EXECUTED) {
ArchiveActivityCommand command = new ArchiveActivityCommand(tx);
- command.setActivity(activity);
+ command.setActivityLoc(activity.getLocator());
tx.addCommand(command);
}
});
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/Controller.java b/li.strolch.service/src/main/java/li/strolch/execution/Controller.java
index e2888d36f..f1bffd546 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/Controller.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/Controller.java
@@ -1,70 +1,331 @@
package li.strolch.execution;
+import static li.strolch.runtime.StrolchConstants.SYSTEM_USER_AGENT;
+
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
-import java.util.Set;
+import java.util.ResourceBundle;
-import li.strolch.execution.command.ExecuteActivityCommand;
+import li.strolch.agent.api.ComponentContainer;
+import li.strolch.agent.api.ObserverEvent;
+import li.strolch.agent.api.StrolchRealm;
+import li.strolch.execution.command.*;
import li.strolch.execution.policy.ExecutionPolicy;
+import li.strolch.handler.operationslog.LogMessage;
+import li.strolch.handler.operationslog.LogSeverity;
+import li.strolch.handler.operationslog.OperationsLog;
import li.strolch.model.Locator;
+import li.strolch.model.Resource;
import li.strolch.model.State;
+import li.strolch.model.Tags;
+import li.strolch.model.activity.Action;
import li.strolch.model.activity.Activity;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.model.Certificate;
-import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.runtime.privilege.PrivilegedRunnable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class Controller {
+ private static final Logger logger = LoggerFactory.getLogger(Controller.class);
+
+ private final String realm;
+ private ComponentContainer container;
private ExecutionHandler executionHandler;
+
+ private final String activityType;
+ private final String activityId;
+ private final Locator locator;
+
private Activity activity;
+
private Map inExecution;
- public Controller(ExecutionHandler executionHandler, Activity activity) {
+ public Controller(String realm, ExecutionHandler executionHandler, Activity activity) {
+ this.realm = realm;
+ this.container = executionHandler.getContainer();
this.executionHandler = executionHandler;
+ this.locator = activity.getLocator();
+ this.activityType = activity.getType();
+ this.activityId = activity.getId();
this.activity = activity;
- this.inExecution = new HashMap<>();
+ this.inExecution = Collections.synchronizedMap(new HashMap<>());
}
- public State getState() {
- return this.activity.getState();
+ public String getRealm() {
+ return this.realm;
+ }
+
+ public boolean isStopped(Locator locator) {
+ ExecutionPolicy executionPolicy = this.inExecution.get(locator);
+ return executionPolicy == null || executionPolicy.isStopped();
+ }
+
+ public Locator getLocator() {
+ return this.locator;
}
public Activity getActivity() {
return this.activity;
}
- public Set getInExecution() {
- return this.inExecution.keySet();
+ public ExecutionPolicy getExecutionPolicy(StrolchTransaction tx, Action action) {
+ ExecutionPolicy executionPolicy = this.inExecution.computeIfAbsent(action.getLocator(), e -> {
+ Resource resource = tx.getResourceFor(action, true);
+ return tx.getPolicy(resource.getPolicyDef(ExecutionPolicy.class));
+ });
+
+ // always update the TX and controller
+ executionPolicy.setController(tx, this);
+ return executionPolicy;
}
protected StrolchTransaction openTx(Certificate cert) {
- return this.executionHandler.openTx(cert, getClass(), false);
+ return this.executionHandler.openTx(this.realm, cert, getClass(), false);
}
protected void runAsAgent(PrivilegedRunnable runnable) throws PrivilegeException, Exception {
this.executionHandler.runAsAgent(runnable);
}
- private Activity refreshActivity(StrolchTransaction tx) {
- this.activity = tx.getActivityBy(this.activity.getType(), this.activity.getId(), true);
- return this.activity;
- }
-
- public void execute() {
- try (StrolchTransaction tx = openTx(ctx.getCertificate())) {
-
- ExecuteActivityCommand command = new ExecuteActivityCommand(tx);
- command.setActivity(refreshActivity(tx));
- command.validate();
- command.doCommand();
-
- tx.commitOnClose();
+ private boolean refreshActivity(StrolchTransaction tx) {
+ Activity activity = tx.getActivityBy(this.activityType, this.activityId, false);
+ if (activity == null) {
+ logger.error("Element " + this.locator + " does not exist anymore. Removing from execution");
+ this.executionHandler.removeFromExecution(this);
+ return false;
}
+
+ this.activity = activity;
+ return true;
}
- public void stop() {
+ /**
+ * Starts the execution of this {@link Activity}
+ */
+ public void execute() throws Exception {
+ boolean[] trigger = new boolean[1];
+ this.executionHandler.runAsAgent(ctx -> {
+ try (StrolchTransaction tx = openTx(ctx.getCertificate())) {
+ tx.lock(this.locator);
+ trigger[0] = execute(tx);
+ if (tx.needsCommit()) {
+ tx.commitOnClose();
+ }
+ }
+ });
+ if (trigger[0])
+ this.executionHandler.triggerExecution(this.realm);
+ }
+
+ private boolean execute(StrolchTransaction tx) {
+ if (!refreshActivity(tx))
+ return false;
+
+ if (this.activity.getState().isExecuted()) {
+ this.executionHandler.removeFromExecution(this);
+ logger.info("Archiving executed activity " + this.locator + " with state " + this.activity.getState());
+ this.executionHandler.archiveActivity(this.realm, this.activity);
+
+ return false;
+ }
+
+ ExecutionHandlerState state = this.executionHandler.getState(this.realm);
+ if (state == ExecutionHandlerState.Paused) {
+ logger.warn("Ignoring trigger for paused realm " + this.realm);
+ return false;
+ }
+
+ ExecuteActivityCommand command = new ExecuteActivityCommand(tx);
+ command.setController(this);
+ command.validate();
+ command.doCommand();
+
+ notifyObserverUpdate();
+
+ return command.needsRetriggerOfExecution();
+ }
+
+ /**
+ * Completes the execution of the given {@link Action} with the given {@link Locator}
+ *
+ * @param actionLoc
+ * the {@link Locator} of the {@link Action}
+ */
+ public void toExecuted(Locator actionLoc) throws Exception {
+ this.executionHandler.runAsAgent(ctx -> {
+ try (StrolchTransaction tx = openTx(ctx.getCertificate())) {
+ tx.lock(this.locator);
+
+ if (!refreshActivity(tx))
+ return;
+
+ Action action = this.activity.getElementByLocator(actionLoc);
+
+ // set this action to executed
+ SetActionToExecutedCommand command = new SetActionToExecutedCommand(tx);
+ command.setExecutionPolicy(getExecutionPolicy(tx, action));
+ command.setAction(action);
+ command.validate();
+ command.doCommand();
+
+ notifyObserverUpdate();
+
+ // flush so we can see the changes performed
+ tx.flush();
+
+ // now try and execute the next action(s)
+ execute(tx);
+
+ if (tx.needsCommit())
+ tx.commitOnClose();
+ }
+ });
+
+ this.executionHandler.triggerExecution(this.realm);
+ }
+
+ /**
+ * Sets the state of the {@link Action} with the given {@link Locator} to {@link State#STOPPED}
+ *
+ * @param actionLoc
+ * the {@link Locator} of the {@link Action}
+ */
+ public void toStopped(Locator actionLoc) throws Exception {
+ this.executionHandler.runAsAgent(ctx -> {
+ try (StrolchTransaction tx = openTx(ctx.getCertificate())) {
+ tx.lock(this.locator);
+
+ if (!refreshActivity(tx))
+ return;
+
+ Action action = this.activity.getElementByLocator(actionLoc);
+
+ // set this action to executed
+ SetActionToStoppedCommand command = new SetActionToStoppedCommand(tx);
+ command.setExecutionPolicy(getExecutionPolicy(tx, action));
+ command.setAction(action);
+ command.validate();
+ command.doCommand();
+
+ tx.commitOnClose();
+ }
+ });
+ }
+
+ /**
+ * Sets the state of the {@link Action} with the given {@link Locator} to {@link State#ERROR}
+ *
+ * @param actionLoc
+ * the {@link Locator} of the {@link Action}
+ */
+ public void toError(Locator actionLoc) throws Exception {
+ this.executionHandler.runAsAgent(ctx -> {
+ try (StrolchTransaction tx = openTx(ctx.getCertificate())) {
+ tx.lock(this.locator);
+
+ if (!refreshActivity(tx))
+ return;
+
+ Action action = this.activity.getElementByLocator(actionLoc);
+
+ // set this action to executed
+ SetActionToErrorCommand command = new SetActionToErrorCommand(tx);
+ command.setExecutionPolicy(getExecutionPolicy(tx, action));
+ command.setAction(action);
+ command.validate();
+ command.doCommand();
+
+ tx.commitOnClose();
+ }
+ });
+ }
+
+ /**
+ * Sets the state of the {@link Action} with the given {@link Locator} to {@link State#WARNING}
+ *
+ * @param actionLoc
+ * the {@link Locator} of the {@link Action}
+ */
+ public void toWarning(Locator actionLoc) throws Exception {
+ this.executionHandler.runAsAgent(ctx -> {
+ try (StrolchTransaction tx = openTx(ctx.getCertificate())) {
+ tx.lock(this.locator);
+
+ if (!refreshActivity(tx))
+ return;
+
+ Action action = this.activity.getElementByLocator(actionLoc);
+
+ // set this action to executed
+ SetActionToWarningCommand command = new SetActionToWarningCommand(tx);
+ command.setExecutionPolicy(getExecutionPolicy(tx, action));
+ command.setAction(action);
+ command.validate();
+ command.doCommand();
+
+ tx.commitOnClose();
+ }
+ });
+ }
+
+ /**
+ * Sets the state of the {@link Action} with the given {@link Locator} to {@link State#ERROR}
+ *
+ * @param actionLoc
+ * the {@link Locator} of the {@link Action}
+ */
+ public void asyncToError(Locator actionLoc) {
+ this.executionHandler.getExecutor().submit(() -> {
+ try {
+ toError(actionLoc);
+ } catch (Exception e) {
+ logger.error("Failed to set " + locator + " to error due to " + e.getMessage(), e);
+
+ if (this.container.hasComponent(OperationsLog.class)) {
+ this.container.getComponent(OperationsLog.class).addMessage(
+ new LogMessage(realm, SYSTEM_USER_AGENT, locator, LogSeverity.Exception,
+ ResourceBundle.getBundle("strolch-service"), "execution.handler.failed.error")
+ .withException(e).value("reason", e));
+ }
+ }
+ });
+ }
+
+ /**
+ * Sets the state of the {@link Action} with the given {@link Locator} to {@link State#WARNING}
+ *
+ * @param actionLoc
+ * the {@link Locator} of the {@link Action}
+ */
+ public void asyncToWarning(Locator actionLoc) {
+ this.executionHandler.getExecutor().submit(() -> {
+ try {
+ toWarning(actionLoc);
+ } catch (Exception e) {
+ logger.error("Failed to set " + locator + " to warning due to " + e.getMessage(), e);
+
+ if (this.container.hasComponent(OperationsLog.class)) {
+ this.container.getComponent(OperationsLog.class).addMessage(
+ new LogMessage(realm, SYSTEM_USER_AGENT, locator, LogSeverity.Exception,
+ ResourceBundle.getBundle("strolch-service"), "execution.handler.failed.warning")
+ .withException(e).value("reason", e));
+ }
+ }
+ });
+ }
+
+ private void notifyObserverUpdate() {
+ StrolchRealm realm = this.executionHandler.getContainer().getRealm(this.realm);
+ if (!realm.isUpdateObservers())
+ return;
+
+ ObserverEvent observerEvent = new ObserverEvent();
+ observerEvent.updated.addElement(Tags.CONTROLLER, this.activity);
+ realm.getObserverHandler().notify(observerEvent);
}
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/EventBasedExecutionHandler.java b/li.strolch.service/src/main/java/li/strolch/execution/EventBasedExecutionHandler.java
index 38f2b500c..4c4718f79 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/EventBasedExecutionHandler.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/EventBasedExecutionHandler.java
@@ -6,11 +6,11 @@ import static li.strolch.runtime.StrolchConstants.SYSTEM_USER_AGENT;
import static li.strolch.utils.collections.SynchronizedCollections.synchronizedMapOfMaps;
import java.util.*;
-import java.util.concurrent.ExecutorService;
import li.strolch.agent.api.ComponentContainer;
import li.strolch.agent.api.ObserverEvent;
-import li.strolch.execution.command.*;
+import li.strolch.agent.api.StrolchRealm;
+import li.strolch.execution.command.ArchiveActivityCommand;
import li.strolch.execution.policy.ExecutionPolicy;
import li.strolch.handler.operationslog.LogMessage;
import li.strolch.handler.operationslog.LogSeverity;
@@ -18,14 +18,12 @@ import li.strolch.handler.operationslog.OperationsLog;
import li.strolch.model.*;
import li.strolch.model.activity.Action;
import li.strolch.model.activity.Activity;
-import li.strolch.model.activity.IActivityElement;
import li.strolch.model.parameter.StringParameter;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.privilege.model.Certificate;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.runtime.configuration.ComponentConfiguration;
import li.strolch.utils.collections.MapOfMaps;
-import li.strolch.utils.dbc.DBC;
/**
* The event based execution handler waits for events in that the {@link ExecutionPolicy} implementations must call the
@@ -46,8 +44,14 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
super(container, componentName);
}
- private ExecutorService getExecutor() {
- return getExecutorService("ExecutionHandler");
+ @Override
+ public Controller getController(String realm, Activity activity) {
+ return this.controllers.getElement(realm, activity.getLocator());
+ }
+
+ @Override
+ public Controller getController(String realm, Locator locator) {
+ return this.controllers.getElement(realm, locator.trim(3));
}
@Override
@@ -96,16 +100,29 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
}
@Override
- public void addForExecution(String realm, Activity activity) {
+ public void toExecution(String realm, Activity activity) {
ExecutionHandlerState state = this.statesByRealm.getOrDefault(realm, ExecutionHandlerState.Running);
if (state == ExecutionHandlerState.HaltNew)
throw new IllegalStateException(
"ExecutionHandler state is " + state + ", can not add activities for execution!");
- Controller controller = new Controller(this, activity);
- this.controllers.addElement(realm, activity.getLocator(), controller);
- notifyObserverAdd(realm, controller);
- toExecution(realm, activity);
+ Controller controller = this.controllers.getElement(realm, activity.getLocator());
+ if (controller == null) {
+ controller = new Controller(realm, this, activity);
+ this.controllers.addElement(realm, activity.getLocator(), controller);
+ notifyObserverAdd(controller);
+ }
+
+ toExecution(controller);
+ }
+
+ @Override
+ public void removeFromExecution(Controller controller) {
+ logger.info("Removing controller " + controller.getLocator() + " from execution...");
+ if (this.controllers.removeElement(controller.getRealm(), controller.getLocator()) != null) {
+ logger.info("Removed controller " + controller.getLocator() + " from execution.");
+ getExecutor().submit(() -> notifyObserverRemove(controller));
+ }
}
@Override
@@ -113,7 +130,7 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
Locator rootElemLoc = activityLoc.trim(3);
Controller controller = this.controllers.removeElement(realm, rootElemLoc);
if (controller != null)
- getExecutor().submit(() -> notifyObserverRemove(realm, controller));
+ getExecutor().submit(() -> notifyObserverRemove(controller));
}
@Override
@@ -157,7 +174,7 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
tx.update(activity);
// register for execution
- Controller controller = new Controller(this, activity);
+ Controller controller = new Controller(realmName, this, activity);
this.controllers.addElement(realmName, activity.getLocator(), controller);
});
@@ -183,7 +200,7 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
if (controllers != null) {
for (Controller controller : controllers.values()) {
// execute async
- toExecution(realm, controller);
+ toExecution(controller);
}
}
}
@@ -260,24 +277,26 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
}
}
- @Override
- public void toExecution(String realm, Activity activity) {
+ private void toExecution(Controller controller) {
+ String realm = controller.getRealm();
ExecutionHandlerState state = this.statesByRealm.getOrDefault(realm, ExecutionHandlerState.Running);
if (state == ExecutionHandlerState.Paused) {
- logger.warn("Ignoring execution of " + activity.getLocator() + " for paused realm " + realm);
+ logger.warn("Ignoring execution of " + controller.getLocator() + " for paused realm " + realm);
return;
}
+ logger.info("Adding async " + controller.getLocator() + " for execution!");
+
getExecutor().execute(() -> {
try {
- runAsAgent(ctx -> toExecution(realm, activity, ctx));
+ controller.execute();
} catch (Exception e) {
- logger.error("Failed to set " + activity.getLocator() + " to execution", e);
+ logger.error("Failed to set " + controller.getLocator() + " to execution", e);
if (getContainer().hasComponent(OperationsLog.class)) {
getComponent(OperationsLog.class).addMessage(
- new LogMessage(realm, SYSTEM_USER_AGENT, activity.getLocator(), LogSeverity.Exception,
+ new LogMessage(realm, SYSTEM_USER_AGENT, controller.getLocator(), LogSeverity.Exception,
ResourceBundle.getBundle("strolch-service"), "execution.handler.failed.execution")
.withException(e).value("reason", e));
}
@@ -289,7 +308,11 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
public void toExecuted(String realm, Locator locator) {
getExecutor().execute(() -> {
try {
- runAsAgent(ctx -> toExecuted(realm, locator, ctx));
+
+ Controller controller = this.controllers.getElement(realm, locator.trim(3));
+ if (controller != null)
+ controller.toExecuted(locator);
+
} catch (Exception e) {
logger.error("Failed to set " + locator + " to executed due to " + e.getMessage(), e);
@@ -307,7 +330,11 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
public void toStopped(String realm, Locator locator) {
getExecutor().execute(() -> {
try {
- runAsAgent(ctx -> toStopped(realm, locator, ctx));
+
+ Controller controller = this.controllers.getElement(realm, locator.trim(3));
+ if (controller != null)
+ controller.toStopped(locator);
+
} catch (Exception e) {
logger.error("Failed to set " + locator + " to stopped due to " + e.getMessage(), e);
@@ -325,7 +352,11 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
public void toError(String realm, Locator locator) {
getExecutor().execute(() -> {
try {
- runAsAgent(ctx -> toError(realm, locator, ctx));
+
+ Controller controller = this.controllers.getElement(realm, locator.trim(3));
+ if (controller != null)
+ controller.toError(locator);
+
} catch (Exception e) {
logger.error("Failed to set " + locator + " to error due to " + e.getMessage(), e);
@@ -343,7 +374,11 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
public void toWarning(String realm, Locator locator) {
getExecutor().execute(() -> {
try {
- runAsAgent(ctx -> toWarning(realm, locator, ctx));
+
+ Controller controller = this.controllers.getElement(realm, locator.trim(3));
+ if (controller != null)
+ controller.toWarning(locator);
+
} catch (Exception e) {
logger.error("Failed to set " + locator + " to warning due to " + e.getMessage(), e);
@@ -383,235 +418,36 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
});
}
- private void toExecution(String realm, Locator elementLoc, PrivilegeContext ctx) {
- try (StrolchTransaction tx = openTx(realm, ctx.getCertificate(), ExecuteActivityCommand.class, false)) {
-
- Locator activityLoc = elementLoc.trim(3);
- tx.lock(activityLoc);
-
- Activity activity = tx.findElement(activityLoc, true);
- if (activity == null) {
- logger.error("Element for locator " + elementLoc + " does not exist!");
- synchronized (this.registeredActivities) {
- this.registeredActivities.removeElement(realm, activityLoc);
- }
- notifyObserverRemove(realm, activityLoc);
- return;
- }
-
- if (activity.getState().isExecuted()) {
-
- synchronized (this.registeredActivities) {
- if (!this.registeredActivities.removeElement(realm, activityLoc))
- logger.warn("Activity " + activityLoc + " already removed from registered activities!");
- }
-
- notifyObserverRemove(tx, activity);
-
- logger.info("Archiving activity " + activityLoc + " with state " + activity.getState());
- archiveActivity(realm, activity.getLocator());
-
- } else {
-
- ExecuteActivityCommand command = new ExecuteActivityCommand(getContainer(), tx);
- command.setActivity(activity);
- command.validate();
- command.doCommand();
-
- notifyObserverUpdate(tx, activity);
- tx.commitOnClose();
- }
- }
- }
-
- private void toExecuted(String realm, Locator actionLoc, PrivilegeContext ctx) {
-
- Locator activityLoc = actionLoc.trim(3);
-
- try (StrolchTransaction tx = openTx(realm, ctx.getCertificate(), SetActionToExecutedCommand.class, false)) {
-
- tx.lock(activityLoc);
-
- Action action = tx.findElement(actionLoc);
-
- // set this action to executed
- SetActionToExecutedCommand command = new SetActionToExecutedCommand(getContainer(), tx);
- command.setAction(action);
- command.validate();
- command.doCommand();
-
- notifyObserverUpdate(tx, action.getRootElement());
-
- // flush so we can see the changes performed
- tx.flush();
-
- // if the activity is now executed, remove it from the registered activities
- Activity activity = action.getRootElement().getClone(true);
- if (activity.getState().isExecuted()) {
-
- synchronized (this.registeredActivities) {
- if (!this.registeredActivities.removeElement(realm, activityLoc))
- logger.warn("Activity " + activityLoc + " already removed from registered activities!");
- }
-
- notifyObserverRemove(tx, action.getRootElement());
-
- logger.info("Archiving activity " + activityLoc + " with state " + activity.getState());
- archiveActivity(realm, activity.getLocator());
-
- } else {
-
- ExecutionHandlerState state = this.statesByRealm.getOrDefault(realm, ExecutionHandlerState.Running);
- if (state == ExecutionHandlerState.Paused) {
- logger.warn("Ignoring trigger for paused realm " + realm);
- } else {
-
- // otherwise execute any next action(s) for this action's activity
-
- ExecuteActivityCommand execCommand = new ExecuteActivityCommand(getContainer(), tx);
- execCommand.setActivity(activity);
- execCommand.validate();
- execCommand.doCommand();
-
- notifyObserverUpdate(tx, action.getRootElement());
-
- // flush so we can see the changes performed
- tx.flush();
- }
- }
-
- tx.commitOnClose();
- }
-
- // now trigger a further execution of any other activities needed execution in this realm
- triggerExecution(realm);
- }
-
- private void toWarning(String realm, Locator actionLoc, PrivilegeContext ctx) {
- try (StrolchTransaction tx = openTx(realm, ctx.getCertificate(), SetActionToExecutedCommand.class, false)) {
- Locator rootElemLoc = actionLoc.trim(3);
- tx.lock(rootElemLoc);
-
- IActivityElement elem = tx.findElement(actionLoc);
- DBC.INTERIM.assertEquals("toWarning only for Action!", Action.class, elem.getClass());
-
- SetActionToWarningCommand command = new SetActionToWarningCommand(getContainer(), tx);
- command.setAction((Action) elem);
- command.validate();
- command.doCommand();
-
- notifyObserverUpdate(tx, elem.getRootElement());
- tx.commitOnClose();
- }
- }
-
- private void toError(String realm, Locator actionLoc, PrivilegeContext ctx) {
- try (StrolchTransaction tx = openTx(realm, ctx.getCertificate(), SetActionToExecutedCommand.class, false)) {
- Locator rootElemLoc = actionLoc.trim(3);
- tx.lock(rootElemLoc);
-
- IActivityElement elem = tx.findElement(actionLoc);
- DBC.INTERIM.assertEquals("toError only for Action!", Action.class, elem.getClass());
-
- SetActionToErrorCommand command = new SetActionToErrorCommand(getContainer(), tx);
- command.setAction((Action) elem);
- command.validate();
- command.doCommand();
-
- notifyObserverUpdate(tx, elem.getRootElement());
- tx.commitOnClose();
- }
- }
-
- private void toStopped(String realm, Locator actionLoc, PrivilegeContext ctx) {
- try (StrolchTransaction tx = openTx(realm, ctx.getCertificate(), SetActionToStoppedCommand.class, false)) {
- Locator rootElemLoc = actionLoc.trim(3);
- tx.lock(rootElemLoc);
-
- IActivityElement elem = tx.findElement(actionLoc);
- DBC.INTERIM.assertEquals("toStopped only for Action!", Action.class, elem.getClass());
-
- SetActionToStoppedCommand command = new SetActionToStoppedCommand(getContainer(), tx);
- command.setAction((Action) elem);
- command.validate();
- command.doCommand();
-
- notifyObserverUpdate(tx, elem.getRootElement());
- tx.commitOnClose();
- }
-
- // now trigger a further execution of any other activities needed execution in this realm
- triggerExecution(realm);
- }
-
- private void notifyObserverAdd(String realm, Controller controller) {
- if (!getContainer().getRealm(realm).isUpdateObservers())
+ private void notifyObserverAdd(Controller controller) {
+ StrolchRealm realm = getContainer().getRealm(controller.getRealm());
+ if (!realm.isUpdateObservers())
return;
ObserverEvent observerEvent = new ObserverEvent();
- observerEvent.added.addElement(Tags.CONTROLLER, rootElement);
- getContainer().getRealm(realm).getObserverHandler().notify(observerEvent);
+ observerEvent.added.addElement(Tags.CONTROLLER, controller.getActivity());
+ realm.getObserverHandler().notify(observerEvent);
}
- private void notifyObserverUpdate(StrolchTransaction tx, Controller controller) {
- if (!getContainer().getRealm(tx.getRealmName()).isUpdateObservers())
+ private void notifyObserverRemove(Controller controller) {
+ StrolchRealm realm = getContainer().getRealm(controller.getRealm());
+ if (!realm.isUpdateObservers())
return;
ObserverEvent observerEvent = new ObserverEvent();
- observerEvent.updated.addElement(Tags.CONTROLLER, rootElement);
- tx.getContainer().getRealm(tx.getRealmName()).getObserverHandler().notify(observerEvent);
+ observerEvent.removed.addElement(Tags.CONTROLLER, controller.getActivity());
+ realm.getObserverHandler().notify(observerEvent);
}
- private void notifyObserverRemove(StrolchTransaction tx, Controller controller) {
- if (!getContainer().getRealm(tx.getRealmName()).isUpdateObservers())
+ private void notifyObserverRemove(String realmName, Map removed) {
+ StrolchRealm realm = getContainer().getRealm(realmName);
+ if (!realm.isUpdateObservers())
return;
ObserverEvent observerEvent = new ObserverEvent();
- observerEvent.removed.addElement(Tags.CONTROLLER, rootElement);
- tx.getContainer().getRealm(tx.getRealmName()).getObserverHandler().notify(observerEvent);
- }
-
- private void notifyObserverRemove(String realm, Controller controller) {
- if (!getContainer().getRealm(realm).isUpdateObservers())
- return;
-
- try {
- runAsAgent(ctx -> {
- try (StrolchTransaction tx = openTx(realm, ctx.getCertificate(), true)) {
- Activity activity = tx.findElement(activityLoc, true);
- if (activity != null) {
- ObserverEvent observerEvent = new ObserverEvent();
- observerEvent.removed.addElement(Tags.CONTROLLER, activity);
- getContainer().getRealm(realm).getObserverHandler().notify(observerEvent);
- }
- }
- });
- } catch (Exception e) {
- logger.error("Failed to notify observers of removed controller " + activityLoc);
- }
- }
-
- private void notifyObserverRemove(String realm, Map removed) {
- if (!getContainer().getRealm(realm).isUpdateObservers())
- return;
-
- try {
- runAsAgent(ctx -> {
- try (StrolchTransaction tx = openTx(realm, ctx.getCertificate(), true)) {
- ObserverEvent observerEvent = new ObserverEvent();
-
- for (Locator activityLoc : activityLocs) {
- Activity activity = tx.findElement(activityLoc, true);
- if (activity != null)
- observerEvent.removed.addElement(Tags.CONTROLLER, activity);
- }
-
- getContainer().getRealm(realm).getObserverHandler().notify(observerEvent);
- }
- });
- } catch (Exception e) {
- logger.error("Failed to notify observers of removed controllers " + activityLocs);
+ for (Controller controller : removed.values()) {
+ observerEvent.removed.addElement(Tags.CONTROLLER, controller.getActivity());
}
+ realm.getObserverHandler().notify(observerEvent);
}
@Override
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/ExecutionHandler.java b/li.strolch.service/src/main/java/li/strolch/execution/ExecutionHandler.java
index b93c37478..093a15ebc 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/ExecutionHandler.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/ExecutionHandler.java
@@ -1,6 +1,7 @@
package li.strolch.execution;
import java.util.Set;
+import java.util.concurrent.ExecutorService;
import li.strolch.agent.api.ComponentContainer;
import li.strolch.agent.api.StrolchComponent;
@@ -24,7 +25,7 @@ import li.strolch.runtime.privilege.PrivilegedRunnable;
*
*
* To start the execution of an {@link Activity} add it to the {@link ExecutionHandler} by calling {@link
- * #addForExecution(String, Activity)} or {@link #addForExecution(String, Locator)}. Actual execution is asynchronously
+ * #toExecution(String, Activity)} or {@link #toExecution(String, Activity)}. Actual execution is asynchronously
* performed and the {@link ExecutionPolicy} of the resources of the {@link Action Actions} will perform the actual
* execution.
*
@@ -44,14 +45,42 @@ public abstract class ExecutionHandler extends StrolchComponent {
public static final String PARAM_STATE = "state";
- public StrolchTransaction openTx(Certificate cert, Class> action, boolean readOnly) {
- return super.openTx(cert, action.getName(), readOnly);
+ public StrolchTransaction openTx(String realm, Certificate cert, Class> action, boolean readOnly) {
+ return super.openTx(realm, cert, action.getName(), readOnly);
}
public void runAsAgent(PrivilegedRunnable runnable) throws PrivilegeException, Exception {
super.runAsAgent(runnable);
}
+ public ExecutorService getExecutor() {
+ return getExecutorService("ExecutionHandler");
+ }
+
+ /**
+ * Returns the controller for the given realm and activity, null if it does not exist
+ *
+ * @param realm
+ * the realm for which to get the controller
+ * @param activity
+ * the activity for which to get the controller
+ *
+ * @return the controller, or null if it does not exist
+ */
+ public abstract Controller getController(String realm, Activity activity);
+
+ /**
+ * Returns the controller for the given realm and activity, null if it does not exist
+ *
+ * @param realm
+ * the realm for which to get the controller
+ * @param locator
+ * the locator of the activity for which to get the controller
+ *
+ * @return the controller, or null if it does not exist
+ */
+ public abstract Controller getController(String realm, Locator locator);
+
/**
* Registers the given {@link Activity} for execution, and submits it for execution immediately in an asynchronous
* manner
@@ -61,7 +90,15 @@ public abstract class ExecutionHandler extends StrolchComponent {
* @param activity
* the the {@link Activity}
*/
- public abstract void addForExecution(String realm, Activity activity);
+ public abstract void toExecution(String realm, Activity activity);
+
+ /**
+ * Removes the given {@link Controller} from execution, so it is not executed further
+ *
+ * @param controller
+ * the controller to remove
+ */
+ public abstract void removeFromExecution(Controller controller);
/**
* Removes the given {@link Locator} for an {@link Activity} from execution, so it is not executed further
@@ -92,7 +129,7 @@ public abstract class ExecutionHandler extends StrolchComponent {
public abstract void clearAllCurrentExecutions(String realm);
/**
- * Triggers a to execution for all registered activities in the given realm
+ * Triggers execution for all registered activities in the given realm
*
* @param realm
* the realm to trigger execution for
@@ -148,24 +185,14 @@ public abstract class ExecutionHandler extends StrolchComponent {
*
*
*
- * The {@link DelayedExecutionTimer} allows to delay the {@link #toExecuted(String, Locator)} call by a given time.
- * See the {@link DurationExecution} policy
+ * The {@link DelayedExecutionTimer} allows to delay the {@link Controller#toExecuted(Locator)} call by a given
+ * time. See the {@link DurationExecution} policy
*
*
* @return the {@link DelayedExecutionTimer}
*/
public abstract DelayedExecutionTimer getDelayedExecutionTimer();
- /**
- * Starts the execution of the given {@link Activity}
- *
- * @param realm
- * the realm where the {@link Activity} resides
- * @param activity
- * the {@link Activity}
- */
- public abstract void toExecution(String realm, Activity activity);
-
/**
* Completes the execution of the given {@link Action} with the given {@link Locator}
*
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/SimpleDurationExecutionTimer.java b/li.strolch.service/src/main/java/li/strolch/execution/SimpleDurationExecutionTimer.java
index 2c7b50b55..42cad3ec1 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/SimpleDurationExecutionTimer.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/SimpleDurationExecutionTimer.java
@@ -1,14 +1,20 @@
package li.strolch.execution;
+import static li.strolch.runtime.StrolchConstants.SYSTEM_USER_AGENT;
+
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
+import java.util.ResourceBundle;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import li.strolch.agent.api.ComponentContainer;
import li.strolch.agent.api.StrolchAgent;
+import li.strolch.handler.operationslog.LogMessage;
+import li.strolch.handler.operationslog.LogSeverity;
+import li.strolch.handler.operationslog.OperationsLog;
import li.strolch.model.Locator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -65,7 +71,22 @@ public class SimpleDurationExecutionTimer implements DelayedExecutionTimer {
this.simulationTasks.remove(locator);
ExecutionHandler executionHandler = container.getComponent(ExecutionHandler.class);
- executionHandler.toExecuted(realm, locator);
+ Controller controller = executionHandler.getController(realm, locator);
+ if (controller != null) {
+ try {
+ if (!controller.isStopped(locator))
+ controller.toExecuted(locator);
+ } catch (Exception e) {
+ logger.error("Failed to set " + locator + " to executed due to " + e.getMessage(), e);
+
+ if (this.agent.getContainer().hasComponent(OperationsLog.class)) {
+ this.agent.getContainer().getComponent(OperationsLog.class).addMessage(
+ new LogMessage(realm, SYSTEM_USER_AGENT, locator, LogSeverity.Exception,
+ ResourceBundle.getBundle("strolch-service"), "execution.handler.failed.executed")
+ .withException(e).value("reason", e));
+ }
+ }
+ }
}
private class SimulationTask implements Runnable {
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/ActionExecutionCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/ActionExecutionCommand.java
new file mode 100644
index 000000000..28e3f57fa
--- /dev/null
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/ActionExecutionCommand.java
@@ -0,0 +1,35 @@
+package li.strolch.execution.command;
+
+import li.strolch.execution.policy.ExecutionPolicy;
+import li.strolch.model.activity.Action;
+import li.strolch.persistence.api.StrolchTransaction;
+import li.strolch.utils.dbc.DBC;
+
+public abstract class ActionExecutionCommand extends BasePlanningAndExecutionCommand {
+
+ protected Action action;
+ private ExecutionPolicy executionPolicy;
+
+ public ActionExecutionCommand(StrolchTransaction tx) {
+ super(tx);
+ }
+
+ public void setAction(Action action) {
+ this.action = action;
+ }
+
+ public void setExecutionPolicy(ExecutionPolicy executionPolicy) {
+ this.executionPolicy = executionPolicy;
+ }
+
+ protected ExecutionPolicy getExecutionPolicy(Action action) {
+ if (this.executionPolicy != null)
+ return this.executionPolicy;
+ return tx().getPolicy(action.getPolicyDef(ExecutionPolicy.class));
+ }
+
+ @Override
+ public void validate() {
+ DBC.PRE.assertNotNull("action can not be null", this.action);
+ }
+}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/ArchiveActivityCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/ArchiveActivityCommand.java
index 1b6bcd8d4..6bc8dfd9d 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/ArchiveActivityCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/ArchiveActivityCommand.java
@@ -1,18 +1,17 @@
package li.strolch.execution.command;
+import static li.strolch.execution.policy.ActivityArchivalPolicy.DEFAULT_ACTIVITY_ARCHIVAL;
+
import li.strolch.execution.policy.ActivityArchivalPolicy;
import li.strolch.model.Locator;
import li.strolch.model.activity.Activity;
import li.strolch.model.policy.PolicyDef;
import li.strolch.persistence.api.StrolchTransaction;
-import li.strolch.policy.PolicyHandler;
import li.strolch.service.api.Command;
import li.strolch.utils.dbc.DBC;
public class ArchiveActivityCommand extends Command {
- private static final String KEY_DEFAULT_ACTIVITY_ARCHIVAL = "key:DefaultActivityArchival";
-
private Locator activityLoc;
public ArchiveActivityCommand(StrolchTransaction tx) {
@@ -30,8 +29,6 @@ public class ArchiveActivityCommand extends Command {
@Override
public void doCommand() {
- tx().lock(this.activityLoc);
-
Activity activity = tx().getActivityBy(this.activityLoc.get(1), this.activityLoc.get(2));
if (activity == null) {
logger.error("Activity " + this.activityLoc + " does not exist anymore, can not archive!");
@@ -40,15 +37,8 @@ public class ArchiveActivityCommand extends Command {
logger.info("Activity " + activity.getLocator() + " is in state " + activity.getState());
- PolicyDef policyDef;
- if (activity.hasPolicyDef(ActivityArchivalPolicy.class.getSimpleName())) {
- policyDef = activity.getPolicyDef(ActivityArchivalPolicy.class.getSimpleName());
- } else {
- policyDef = PolicyDef.valueOf(ActivityArchivalPolicy.class.getSimpleName(), KEY_DEFAULT_ACTIVITY_ARCHIVAL);
- }
-
- PolicyHandler policyHandler = getComponent(PolicyHandler.class);
- ActivityArchivalPolicy archivalPolicy = policyHandler.getPolicy(policyDef, tx());
+ PolicyDef policyDef = activity.getPolicyDef(ActivityArchivalPolicy.class, DEFAULT_ACTIVITY_ARCHIVAL);
+ ActivityArchivalPolicy archivalPolicy = tx().getPolicy(policyDef);
archivalPolicy.archive(activity);
}
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/AssignActionCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/AssignActionCommand.java
index bd76b5dd2..3ca2f971f 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/AssignActionCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/AssignActionCommand.java
@@ -15,8 +15,7 @@
*/
package li.strolch.execution.command;
-import static li.strolch.execution.command.ExecutionCommand.updateOrderState;
-import static li.strolch.execution.policy.NoPlanning.NO_PLANNING;
+import static li.strolch.execution.policy.NoPlanning.DEFAULT_PLANNING;
import li.strolch.execution.policy.PlanningPolicy;
import li.strolch.model.Resource;
@@ -69,14 +68,9 @@ public class AssignActionCommand extends PlanningCommand {
@Override
public void doCommand() {
- validate();
-
Activity rootElement = this.action.getRootElement();
- tx().lock(rootElement);
-
State currentState = rootElement.getState();
this.action.accept(this);
-
updateOrderState(tx(), rootElement, currentState, rootElement.getState());
}
@@ -85,7 +79,7 @@ public class AssignActionCommand extends PlanningCommand {
// unplan the action
if (action.getState() == State.PLANNED) {
- PlanningPolicy planningPolicy = tx().getPolicy(action.findPolicy(PlanningPolicy.class, NO_PLANNING));
+ PlanningPolicy planningPolicy = tx().getPolicy(action.findPolicy(PlanningPolicy.class, DEFAULT_PLANNING));
planningPolicy.unplan(action);
}
@@ -94,7 +88,7 @@ public class AssignActionCommand extends PlanningCommand {
action.setResourceType(this.targetResourceType);
// finally plan the action to the assigned resource
- PlanningPolicy planningPolicy = tx().getPolicy(action.findPolicy(PlanningPolicy.class, NO_PLANNING));
+ PlanningPolicy planningPolicy = tx().getPolicy(action.findPolicy(PlanningPolicy.class, DEFAULT_PLANNING));
planningPolicy.plan(action);
return null;
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/BasePlanningAndExecutionCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/BasePlanningAndExecutionCommand.java
new file mode 100644
index 000000000..aa8a24478
--- /dev/null
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/BasePlanningAndExecutionCommand.java
@@ -0,0 +1,63 @@
+package li.strolch.execution.command;
+
+import static li.strolch.execution.policy.ConfirmationPolicy.DEFAULT_CONFIRMATION;
+import static li.strolch.execution.policy.NoPlanning.DEFAULT_PLANNING;
+import static li.strolch.runtime.StrolchConstants.PolicyConstants.PARAM_ORDER;
+
+import li.strolch.execution.policy.ConfirmationPolicy;
+import li.strolch.execution.policy.PlanningPolicy;
+import li.strolch.model.Locator;
+import li.strolch.model.Order;
+import li.strolch.model.Resource;
+import li.strolch.model.State;
+import li.strolch.model.activity.Action;
+import li.strolch.model.activity.Activity;
+import li.strolch.model.policy.PolicyDef;
+import li.strolch.persistence.api.StrolchTransaction;
+import li.strolch.policy.PolicyHandler;
+import li.strolch.service.api.Command;
+
+public abstract class BasePlanningAndExecutionCommand extends Command {
+
+ public BasePlanningAndExecutionCommand(StrolchTransaction tx) {
+ super(tx);
+ }
+
+ protected Resource getResource(Action action) {
+ Locator resourceLocator = action.getResourceLocator();
+ return tx().getResourceBy(resourceLocator.get(1), resourceLocator.get(2), true);
+ }
+
+ protected static void updateOrderState(StrolchTransaction tx, Activity rootElement, State currentState,
+ State newState) {
+ if (currentState == newState)
+ return;
+
+ Order order = tx.getOrderByRelation(rootElement, PARAM_ORDER);
+ if (order == null) {
+ logger.warn("Did not find activity order by relation " + PARAM_ORDER + " for activity " + rootElement
+ .getLocator() + ", trying by Activity type and id");
+ order = tx.getOrderBy(rootElement.getType(), rootElement.getId());
+ if (order == null) {
+ logger.error("Could not find order by Activity type and id either, not updating order state!");
+ return;
+ }
+ }
+
+ order.setState(rootElement.getState());
+
+ tx.update(order);
+ }
+
+ protected ConfirmationPolicy getConfirmationPolicy(Action action) {
+ Resource resource = getResource(action);
+ PolicyDef executionPolicyDef = resource.getPolicyDefs()
+ .getPolicyDef(ConfirmationPolicy.class.getSimpleName(), DEFAULT_CONFIRMATION);
+ return getComponent(PolicyHandler.class).getPolicy(executionPolicyDef, tx());
+ }
+
+ protected PlanningPolicy getPlanningPolicy(Action action) {
+ PolicyDef planningPolicyDef = action.findPolicy(PlanningPolicy.class, DEFAULT_PLANNING);
+ return getComponent(PolicyHandler.class).getPolicy(planningPolicyDef, tx());
+ }
+}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/ExecuteActivityCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/ExecuteActivityCommand.java
index 493202a4f..c63593f48 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/ExecuteActivityCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/ExecuteActivityCommand.java
@@ -1,35 +1,186 @@
package li.strolch.execution.command;
+import java.util.Iterator;
+import java.util.Map.Entry;
+
+import li.strolch.execution.Controller;
+import li.strolch.execution.policy.ConfirmationPolicy;
+import li.strolch.execution.policy.ExecutionPolicy;
import li.strolch.model.State;
+import li.strolch.model.activity.Action;
import li.strolch.model.activity.Activity;
+import li.strolch.model.activity.IActivityElement;
+import li.strolch.model.activity.TimeOrderingVisitor;
+import li.strolch.model.visitor.IActivityElementVisitor;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.utils.dbc.DBC;
-public class ExecuteActivityCommand extends ExecutionCommand {
+public class ExecuteActivityCommand extends BasePlanningAndExecutionCommand
+ implements TimeOrderingVisitor, IActivityElementVisitor {
- private Activity activity;
+ private Controller controller;
+ private boolean needsRetriggerOfExecution;
public ExecuteActivityCommand(StrolchTransaction tx) {
super(tx);
}
- public void setActivity(Activity activity) {
- this.activity = activity;
+ public void setController(Controller controller) {
+ this.controller = controller;
+ }
+
+ private ExecutionPolicy getExecutionPolicy(Action action) {
+ return this.controller.getExecutionPolicy(tx(), action);
+ }
+
+ public boolean needsRetriggerOfExecution() {
+ return this.needsRetriggerOfExecution;
}
@Override
public void validate() {
- DBC.PRE.assertNotNull("activity can not be null!", this.activity);
+ DBC.PRE.assertNotNull("controller can not be null!", this.controller);
}
@Override
public void doCommand() {
- Activity rootElement = this.activity.getRootElement();
- tx().lock(rootElement);
+ Activity activity = this.controller.getActivity();
+ State currentState = activity.getState();
+ activity.accept(this);
+ updateOrderState(tx(), activity, currentState, activity.getState());
+ }
- State currentState = rootElement.getState();
- this.activity.accept(this);
+ @Override
+ public Void visitAction(Action action) {
+ execute(action);
+ return null;
+ }
- updateOrderState(tx(), rootElement, currentState, rootElement.getState());
+ public void execute(Action action) {
+
+ // first plan
+ if (action.getState().compareTo(State.PLANNED) < 0) {
+ getPlanningPolicy(action).plan(action);
+ if (action.getState() != State.PLANNED) {
+ logger.info("Action " + action.getLocator() + " was not planned, can thus not executed.");
+ return;
+ }
+ }
+
+ tx().lock(action.getResourceLocator());
+ tx().removeFromCache(action.getResourceLocator());
+
+ ConfirmationPolicy confirmationPolicy = getConfirmationPolicy(action);
+ ExecutionPolicy executionPolicy = getExecutionPolicy(action);
+
+ if (!executionPolicy.isExecutable(action)) {
+ logger.info("Action " + action.getLocator() + " is not yet executable.");
+ return;
+ }
+
+ logger.info("Action " + action.getLocator() + " is now being executed...");
+
+ // we catch all exceptions because we can't undo, thus need to set the state to ERROR in this case
+ // this is only required because we execute actions in same TX as we set to executed any previous actions
+ try {
+ executionPolicy.initialize(action);
+ executionPolicy.toExecution(action);
+ confirmationPolicy.toExecution(action);
+
+ if (action.getState() == State.EXECUTED)
+ this.needsRetriggerOfExecution = true;
+
+ } catch (Exception e) {
+ logger.error("Failed to set " + action.getLocator() + " to execution due to " + e.getMessage(), e);
+
+ try {
+ executionPolicy.stop();
+ } catch (Exception ex) {
+ logger.error("Failed to stop execution policy for " + action.getLocator(), e);
+ }
+
+ action.setState(State.ERROR);
+ tx().update(action.getRootElement());
+
+ confirmationPolicy.toError(action);
+ }
+ }
+
+ protected boolean isExecutable(IActivityElement element) {
+ State state = element.getState();
+ if (state.compareTo(State.EXECUTED) >= 0)
+ return false;
+
+ if (element instanceof Activity)
+ return true;
+
+ // not yet in execution
+ if (state.compareTo(State.EXECUTION) < 0)
+ return true;
+
+ // in stopped, means we can re-execute
+ if (state == State.STOPPED)
+ return true;
+
+ // if in ERROR, then must first be handled
+ return false;
+ }
+
+ @Override
+ public void visitSeries(Activity activity) {
+
+ if (activity.getState().compareTo(State.EXECUTED) >= 0)
+ return;
+
+ Iterator> iter = activity.elementIterator();
+ while (iter.hasNext()) {
+ IActivityElement element = iter.next().getValue();
+ State state = element.getState();
+ if (element.getState().compareTo(State.EXECUTED) >= 0)
+ continue;
+
+ // in series we can never have two Actions in execution, so if we found the action in execution, we stop
+ if (element instanceof Action //
+ && (state == State.EXECUTION //
+ || state == State.WARNING //
+ || state == State.ERROR)) {
+ break;
+ }
+
+ boolean canExecute = isExecutable(element);
+ if (canExecute) {
+ element.accept(this);
+
+ // in series we stop when the first action is set to execution
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void visitParallel(Activity activity) {
+
+ if (activity.getState().compareTo(State.EXECUTED) >= 0)
+ return;
+
+ Iterator> iter = activity.elementIterator();
+ while (iter.hasNext()) {
+ IActivityElement element = iter.next().getValue();
+ if (element.getState().isExecuted())
+ continue;
+
+ // in parallel we execute all the actions in the activity
+
+ boolean canExecute = isExecutable(element);
+ if (canExecute) {
+ element.accept(this);
+ }
+ }
+ }
+
+ @Override
+ public Void visitActivity(Activity activity) {
+ activity.getTimeOrdering().accept(this, activity);
+ return null;
}
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/ExecuteStoppedActionCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/ExecuteStoppedActionCommand.java
deleted file mode 100644
index 615dd8477..000000000
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/ExecuteStoppedActionCommand.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package li.strolch.execution.command;
-
-import java.text.MessageFormat;
-
-import li.strolch.exception.StrolchException;
-import li.strolch.model.State;
-import li.strolch.model.activity.Action;
-import li.strolch.model.activity.Activity;
-import li.strolch.persistence.api.StrolchTransaction;
-import li.strolch.utils.dbc.DBC;
-
-public class ExecuteStoppedActionCommand extends ExecutionCommand {
-
- private Action action;
-
- public ExecuteStoppedActionCommand(StrolchTransaction tx) {
- super(tx);
- }
-
- public void setAction(Action action) {
- this.action = action;
- }
-
- @Override
- public void validate() {
- DBC.PRE.assertNotNull("action can not be null", this.action);
-
- tx().lock(this.action.getRootElement());
- tx().lock(getResourceLocator(this.action));
-
- if (this.action.getState() != State.STOPPED) {
- String msg = "Action {0} is not in state " + State.STOPPED + " and can thus not be put into execution!";
- msg = MessageFormat.format(msg, this.action.getState(), State.ERROR, this.action.getLocator());
- throw new StrolchException(msg);
- }
- }
-
- @Override
- public void doCommand() {
- Activity rootElement = this.action.getRootElement();
- tx().lock(rootElement);
- tx().lock(getResourceLocator(this.action));
-
- State currentState = rootElement.getState();
- rootElement.accept(this);
-
- updateOrderState(tx(), rootElement, currentState, rootElement.getState());
- }
-}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/ExecutionCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/ExecutionCommand.java
deleted file mode 100644
index f532ed989..000000000
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/ExecutionCommand.java
+++ /dev/null
@@ -1,208 +0,0 @@
-package li.strolch.execution.command;
-
-import static li.strolch.execution.policy.NoPlanning.NO_PLANNING;
-import static li.strolch.runtime.StrolchConstants.PolicyConstants.PARAM_ORDER;
-import static li.strolch.utils.helper.StringHelper.DASH;
-import static li.strolch.utils.helper.StringHelper.isEmpty;
-
-import java.util.Iterator;
-import java.util.Map.Entry;
-
-import li.strolch.exception.StrolchException;
-import li.strolch.execution.policy.ConfirmationPolicy;
-import li.strolch.execution.policy.ExecutionPolicy;
-import li.strolch.execution.policy.PlanningPolicy;
-import li.strolch.model.Locator;
-import li.strolch.model.Order;
-import li.strolch.model.Resource;
-import li.strolch.model.State;
-import li.strolch.model.activity.Action;
-import li.strolch.model.activity.Activity;
-import li.strolch.model.activity.IActivityElement;
-import li.strolch.model.activity.TimeOrderingVisitor;
-import li.strolch.model.policy.PolicyDef;
-import li.strolch.model.visitor.IActivityElementVisitor;
-import li.strolch.persistence.api.StrolchTransaction;
-import li.strolch.policy.PolicyHandler;
-import li.strolch.service.api.Command;
-
-public abstract class ExecutionCommand extends Command implements TimeOrderingVisitor, IActivityElementVisitor {
-
- public ExecutionCommand(StrolchTransaction tx) {
- super(tx);
- }
-
- protected Locator getResourceLocator(Action action) {
- String resourceId = action.getResourceId();
- if (isEmpty(resourceId) || resourceId.equals(DASH))
- throw new StrolchException("No resourceId defined on action " + action.getLocator());
- String resourceType = action.getResourceType();
- if (isEmpty(resourceType) || resourceType.equals(DASH))
- throw new StrolchException("No resourceType defined on action " + action.getLocator());
-
- return Resource.locatorFor(resourceType, resourceId);
- }
-
- protected Resource getResource(Action action) {
- String resourceId = action.getResourceId();
- if (isEmpty(resourceId) || resourceId.equals(DASH))
- throw new StrolchException("No resourceId defined on action " + action.getLocator());
- String resourceType = action.getResourceType();
- if (isEmpty(resourceType) || resourceType.equals(DASH))
- throw new StrolchException("No resourceType defined on action " + action.getLocator());
-
- return tx().getResourceBy(resourceType, resourceId, true);
- }
-
- protected static void updateOrderState(StrolchTransaction tx, Activity rootElement, State currentState,
- State newState) {
- if (currentState == newState)
- return;
-
- Order order = tx.getOrderByRelation(rootElement, PARAM_ORDER);
- if (order == null) {
- logger.warn("Did not find activity order by relation " + PARAM_ORDER + " for activity " + rootElement
- .getLocator() + ", trying by Activity type and id");
- order = tx.getOrderBy(rootElement.getType(), rootElement.getId());
- if (order == null) {
- logger.error("Could not find order by Activity type and id either, not updating order state!");
- return;
- }
- }
-
- order.setState(rootElement.getState());
-
- tx.update(order);
- }
-
- protected ExecutionPolicy getExecutionPolicy(Action action) {
- Resource resource = getResource(action);
- PolicyDef executionPolicyDef = resource.getPolicyDefs().getPolicyDef(ExecutionPolicy.class.getSimpleName());
- return getComponent(PolicyHandler.class).getPolicy(executionPolicyDef, tx());
- }
-
- protected ConfirmationPolicy getConfirmationPolicy(Action action) {
- Resource resource = getResource(action);
- PolicyDef executionPolicyDef = resource.getPolicyDefs().getPolicyDef(ConfirmationPolicy.class.getSimpleName());
- return getComponent(PolicyHandler.class).getPolicy(executionPolicyDef, tx());
- }
-
- @Override
- public void visitSeries(Activity activity) {
-
- if (activity.getState().compareTo(State.EXECUTED) >= 0)
- return;
-
- Iterator> iter = activity.elementIterator();
- while (iter.hasNext()) {
- IActivityElement element = iter.next().getValue();
- State state = element.getState();
- if (element.getState().compareTo(State.EXECUTED) >= 0)
- continue;
-
- // in series we can never have two Actions in execution, so if we found the action in execution, we stop
- if (element instanceof Action //
- && (state == State.EXECUTION //
- || state == State.WARNING //
- || state == State.ERROR)) {
- break;
- }
-
- boolean canExecute = isExecutable(element);
- if (canExecute) {
- element.accept(this);
-
- // in series we stop when the first action is set to execution
- break;
- }
- }
- }
-
- @Override
- public void visitParallel(Activity activity) {
-
- if (activity.getState().compareTo(State.EXECUTED) >= 0)
- return;
-
- Iterator> iter = activity.elementIterator();
- while (iter.hasNext()) {
- IActivityElement element = iter.next().getValue();
- if (element.getState().isExecuted())
- continue;
-
- // in parallel we execute all the actions in the activity
-
- boolean canExecute = isExecutable(element);
- if (canExecute) {
- element.accept(this);
- }
- }
- }
-
- protected boolean isExecutable(IActivityElement element) {
- State state = element.getState();
- if (state.compareTo(State.EXECUTED) >= 0)
- return false;
-
- if (element instanceof Activity)
- return true;
-
- // not yet in execution
- if (state.compareTo(State.EXECUTION) < 0)
- return true;
-
- // in stopped, means we can re-execute
- if (state == State.STOPPED)
- return true;
-
- // if in ERROR, then must first be handled
- return false;
- }
-
- @Override
- public Void visitActivity(Activity activity) {
- activity.getTimeOrdering().accept(this, activity);
- return null;
- }
-
- @Override
- public Void visitAction(Action action) {
-
- // first plan
- if (action.getState().compareTo(State.PLANNED) < 0) {
- PlanningPolicy planningPolicy = tx().getPolicy(action.findPolicy(PlanningPolicy.class, NO_PLANNING));
- planningPolicy.plan(action);
- if (action.getState() != State.PLANNED) {
- logger.info("Action " + action.getLocator() + " was not planned, can thus not executed.");
- return null;
- }
- }
-
- ExecutionPolicy executionPolicy = getExecutionPolicy(action);
-
- tx().lock(getResourceLocator(action));
-
- if (!executionPolicy.isExecutable(action)) {
- logger.info("Action " + action.getLocator() + " is not yet executable.");
- return null;
- }
-
- logger.info("Action " + action.getLocator() + " is now being executed...");
-
- // we catch all exceptions because we can't undo, thus need to set the state to ERROR in this case
- // this is only required because we execute actions in same TX as we set to executed any previous actions
- try {
- executionPolicy.toExecution(action);
- getConfirmationPolicy(action).toExecution(action);
- } catch (Exception e) {
- logger.error("Failed to set " + action.getLocator() + " to execution due to " + e.getMessage(), e);
- action.setState(State.ERROR);
-
- tx().update(action.getRootElement());
-
- getConfirmationPolicy(action).toError(action);
- }
-
- return null;
- }
-}
\ No newline at end of file
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/PlanActionCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/PlanActionCommand.java
index 7413c604d..c68e842b5 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/PlanActionCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/PlanActionCommand.java
@@ -15,8 +15,7 @@
*/
package li.strolch.execution.command;
-import static li.strolch.execution.command.ExecutionCommand.updateOrderState;
-import static li.strolch.execution.policy.NoPlanning.NO_PLANNING;
+import static li.strolch.execution.policy.NoPlanning.DEFAULT_PLANNING;
import li.strolch.execution.policy.PlanningPolicy;
import li.strolch.model.Resource;
@@ -59,26 +58,18 @@ public class PlanActionCommand extends PlanningCommand {
@Override
public void doCommand() {
- validate();
-
Activity rootElement = this.action.getRootElement();
- tx().lock(rootElement);
-
State currentState = rootElement.getState();
this.action.accept(this);
-
updateOrderState(tx(), rootElement, currentState, rootElement.getState());
}
@Override
public Void visitAction(Action action) {
-
- PlanningPolicy planningPolicy = tx().getPolicy(action.findPolicy(PlanningPolicy.class, NO_PLANNING));
+ PlanningPolicy planningPolicy = tx().getPolicy(action.findPolicy(PlanningPolicy.class, DEFAULT_PLANNING));
planningPolicy.plan(action);
-
if (action.getState() == State.PLANNED)
getConfirmationPolicy(action).toPlanned(action);
-
return null;
}
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/PlanActivityCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/PlanActivityCommand.java
index df94ef694..7b58b67b0 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/PlanActivityCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/PlanActivityCommand.java
@@ -15,8 +15,7 @@
*/
package li.strolch.execution.command;
-import static li.strolch.execution.command.ExecutionCommand.updateOrderState;
-import static li.strolch.execution.policy.NoPlanning.NO_PLANNING;
+import static li.strolch.execution.policy.NoPlanning.DEFAULT_PLANNING;
import li.strolch.execution.policy.PlanningPolicy;
import li.strolch.model.Resource;
@@ -59,21 +58,18 @@ public class PlanActivityCommand extends PlanningCommand {
@Override
public void doCommand() {
- validate();
-
Activity rootElement = this.activity.getRootElement();
- tx().lock(rootElement);
-
State currentState = rootElement.getState();
this.activity.accept(this);
-
updateOrderState(tx(), rootElement, currentState, rootElement.getState());
}
@Override
public Void visitAction(Action action) {
- PlanningPolicy planningPolicy = tx().getPolicy(action.findPolicy(PlanningPolicy.class, NO_PLANNING));
+ PlanningPolicy planningPolicy = tx().getPolicy(action.findPolicy(PlanningPolicy.class, DEFAULT_PLANNING));
planningPolicy.plan(action);
+ if (action.getState() == State.PLANNED)
+ getConfirmationPolicy(action).toPlanned(action);
return null;
}
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/PlanningCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/PlanningCommand.java
index 95cc9c4f7..e1fde5150 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/PlanningCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/PlanningCommand.java
@@ -15,39 +15,24 @@
*/
package li.strolch.execution.command;
-import static li.strolch.utils.helper.StringHelper.DASH;
-import static li.strolch.utils.helper.StringHelper.isEmpty;
-
import java.util.Iterator;
import java.util.Map.Entry;
-import li.strolch.exception.StrolchException;
-import li.strolch.execution.policy.ConfirmationPolicy;
-import li.strolch.model.Resource;
import li.strolch.model.State;
-import li.strolch.model.activity.Action;
import li.strolch.model.activity.Activity;
import li.strolch.model.activity.IActivityElement;
-import li.strolch.model.policy.PolicyDef;
import li.strolch.model.visitor.IActivityElementVisitor;
import li.strolch.persistence.api.StrolchTransaction;
-import li.strolch.policy.PolicyHandler;
-import li.strolch.service.api.Command;
/**
* @author Martin Smock
*/
-public abstract class PlanningCommand extends Command implements IActivityElementVisitor {
+public abstract class PlanningCommand extends BasePlanningAndExecutionCommand implements IActivityElementVisitor {
public PlanningCommand(StrolchTransaction tx) {
super(tx);
}
- @Override
- public void undo() {
- // do nothing
- }
-
@Override
public Void visitActivity(Activity activity) {
if (activity.getState().compareTo(State.PLANNED) >= 0)
@@ -61,22 +46,4 @@ public abstract class PlanningCommand extends Command implements IActivityElemen
}
return null;
}
-
- protected Resource getResource(Action action) {
- String resourceId = action.getResourceId();
- if (isEmpty(resourceId) || resourceId.equals(DASH))
- throw new StrolchException("No resourceId defined on action " + action.getLocator());
- String resourceType = action.getResourceType();
- if (isEmpty(resourceType) || resourceType.equals(DASH))
- throw new StrolchException("No resourceType defined on action " + action.getLocator());
-
- return tx().getResourceBy(resourceType, resourceId, true);
- }
-
-
- protected ConfirmationPolicy getConfirmationPolicy(Action action) {
- Resource resource = getResource(action);
- PolicyDef executionPolicyDef = resource.getPolicyDefs().getPolicyDef(ConfirmationPolicy.class.getSimpleName());
- return getComponent(PolicyHandler.class).getPolicy(executionPolicyDef, tx());
- }
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToClosedCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToClosedCommand.java
index 97163a71d..d975f9c4b 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToClosedCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToClosedCommand.java
@@ -9,7 +9,7 @@ import li.strolch.model.activity.Activity;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.utils.dbc.DBC;
-public class SetActionToClosedCommand extends ExecutionCommand {
+public class SetActionToClosedCommand extends BasePlanningAndExecutionCommand {
private Action action;
@@ -25,9 +25,6 @@ public class SetActionToClosedCommand extends ExecutionCommand {
public void validate() {
DBC.PRE.assertNotNull("action can not be null", this.action);
- tx().lock(this.action.getRootElement());
- tx().lock(getResourceLocator(this.action));
-
if (!this.action.getState().canSetToClosed()) {
String msg = "Current state is {0} and can not be changed to {1} for action {2}";
msg = MessageFormat.format(msg, this.action.getState(), State.CLOSED, this.action.getLocator());
@@ -37,15 +34,12 @@ public class SetActionToClosedCommand extends ExecutionCommand {
@Override
public void doCommand() {
- Activity rootElement = this.action.getRootElement();
- tx().lock(rootElement);
- tx().lock(getResourceLocator(this.action));
-
if (this.action.getState() == State.CLOSED) {
logger.warn("Action " + this.action.getLocator() + " is already in state CLOSED! Not changing.");
return;
}
+ Activity rootElement = this.action.getRootElement();
State currentState = rootElement.getState();
this.action.setState(State.CLOSED);
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToCreatedCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToCreatedCommand.java
index efdaa4107..fc95d270a 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToCreatedCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToCreatedCommand.java
@@ -9,7 +9,7 @@ import li.strolch.model.activity.Activity;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.utils.dbc.DBC;
-public class SetActionToCreatedCommand extends ExecutionCommand {
+public class SetActionToCreatedCommand extends BasePlanningAndExecutionCommand {
private Action action;
@@ -25,9 +25,6 @@ public class SetActionToCreatedCommand extends ExecutionCommand {
public void validate() {
DBC.PRE.assertNotNull("action can not be null", this.action);
- tx().lock(this.action.getRootElement());
- tx().lock(getResourceLocator(this.action));
-
if (!this.action.getState().canSetToCreated()) {
String msg = "Current state is {0} and can not be changed to {1} for action {2}";
msg = MessageFormat.format(msg, this.action.getState(), State.CREATED, this.action.getLocator());
@@ -37,15 +34,12 @@ public class SetActionToCreatedCommand extends ExecutionCommand {
@Override
public void doCommand() {
- Activity rootElement = this.action.getRootElement();
- tx().lock(rootElement);
- tx().lock(getResourceLocator(this.action));
-
if (this.action.getState() == State.CREATED) {
logger.warn("Action " + this.action.getLocator() + " is already in state CREATED! Not changing.");
return;
}
+ Activity rootElement = this.action.getRootElement();
State currentState = rootElement.getState();
this.action.setState(State.CREATED);
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToErrorCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToErrorCommand.java
index 03719b85e..b8834fc50 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToErrorCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToErrorCommand.java
@@ -4,29 +4,18 @@ import java.text.MessageFormat;
import li.strolch.exception.StrolchException;
import li.strolch.model.State;
-import li.strolch.model.activity.Action;
import li.strolch.model.activity.Activity;
import li.strolch.persistence.api.StrolchTransaction;
-import li.strolch.utils.dbc.DBC;
-public class SetActionToErrorCommand extends ExecutionCommand {
-
- private Action action;
+public class SetActionToErrorCommand extends ActionExecutionCommand {
public SetActionToErrorCommand(StrolchTransaction tx) {
super(tx);
}
- public void setAction(Action action) {
- this.action = action;
- }
-
@Override
public void validate() {
- DBC.PRE.assertNotNull("action can not be null", this.action);
-
- tx().lock(this.action.getRootElement());
- tx().lock(getResourceLocator(this.action));
+ super.validate();
if (!this.action.getState().canSetToError()) {
String msg = "Current state is {0} and can not be changed to {1} for action {2}";
@@ -37,15 +26,12 @@ public class SetActionToErrorCommand extends ExecutionCommand {
@Override
public void doCommand() {
- Activity rootElement = this.action.getRootElement();
- tx().lock(rootElement);
- tx().lock(getResourceLocator(this.action));
-
if (this.action.getState() == State.ERROR) {
logger.warn("Action " + this.action.getLocator() + " is already in state ERROR! Not changing.");
return;
}
+ Activity rootElement = this.action.getRootElement();
State currentState = rootElement.getState();
getExecutionPolicy(this.action).toError(this.action);
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToExecutableCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToExecutableCommand.java
new file mode 100644
index 000000000..db00fe05f
--- /dev/null
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToExecutableCommand.java
@@ -0,0 +1,43 @@
+package li.strolch.execution.command;
+
+import java.text.MessageFormat;
+
+import li.strolch.exception.StrolchException;
+import li.strolch.model.State;
+import li.strolch.model.activity.Activity;
+import li.strolch.persistence.api.StrolchTransaction;
+
+public class SetActionToExecutableCommand extends ActionExecutionCommand {
+
+ public SetActionToExecutableCommand(StrolchTransaction tx) {
+ super(tx);
+ }
+
+ @Override
+ public void validate() {
+ super.validate();
+
+ if (!this.action.getState().canSetToExecutable()) {
+ String msg = "Current state is {0} and can not be changed to {1} for action {2}";
+ msg = MessageFormat.format(msg, this.action.getState(), State.EXECUTABLE, this.action.getLocator());
+ throw new StrolchException(msg);
+ }
+ }
+
+ @Override
+ public void doCommand() {
+ if (this.action.getState() == State.EXECUTABLE) {
+ logger.warn("Action " + this.action.getLocator() + " is already in state EXECUTABLE! Not changing.");
+ return;
+ }
+
+ Activity rootElement = this.action.getRootElement();
+ State currentState = rootElement.getState();
+
+ this.action.setState(State.EXECUTABLE);
+
+ getConfirmationPolicy(this.action).toExecutable(this.action);
+
+ updateOrderState(tx(), rootElement, currentState, rootElement.getState());
+ }
+}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToExecutedCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToExecutedCommand.java
index ad1385614..52e883e26 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToExecutedCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToExecutedCommand.java
@@ -4,29 +4,18 @@ import java.text.MessageFormat;
import li.strolch.exception.StrolchException;
import li.strolch.model.State;
-import li.strolch.model.activity.Action;
import li.strolch.model.activity.Activity;
import li.strolch.persistence.api.StrolchTransaction;
-import li.strolch.utils.dbc.DBC;
-public class SetActionToExecutedCommand extends ExecutionCommand {
-
- private Action action;
+public class SetActionToExecutedCommand extends ActionExecutionCommand {
public SetActionToExecutedCommand(StrolchTransaction tx) {
super(tx);
}
- public void setAction(Action action) {
- this.action = action;
- }
-
@Override
public void validate() {
- DBC.PRE.assertNotNull("action can not be null", this.action);
-
- tx().lock(this.action.getRootElement());
- tx().lock(getResourceLocator(this.action));
+ super.validate();
if (!this.action.getState().canSetToExecuted()) {
String msg = "Current state is {0} can not be changed to {1} for action {2}";
@@ -37,15 +26,12 @@ public class SetActionToExecutedCommand extends ExecutionCommand {
@Override
public void doCommand() {
- Activity rootElement = this.action.getRootElement();
- tx().lock(rootElement);
- tx().lock(getResourceLocator(this.action));
-
if (this.action.getState() == State.EXECUTED) {
logger.warn("Action " + this.action.getLocator() + " is already in state EXECUTED! Not changing.");
return;
}
+ Activity rootElement = this.action.getRootElement();
State currentState = rootElement.getState();
getExecutionPolicy(this.action).toExecuted(this.action);
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToPlannedCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToPlannedCommand.java
index 3c91fb27e..004ebe5dd 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToPlannedCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToPlannedCommand.java
@@ -9,7 +9,7 @@ import li.strolch.model.activity.Activity;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.utils.dbc.DBC;
-public class SetActionToPlannedCommand extends ExecutionCommand {
+public class SetActionToPlannedCommand extends BasePlanningAndExecutionCommand {
private Action action;
@@ -25,9 +25,6 @@ public class SetActionToPlannedCommand extends ExecutionCommand {
public void validate() {
DBC.PRE.assertNotNull("action can not be null", this.action);
- tx().lock(this.action.getRootElement());
- tx().lock(getResourceLocator(this.action));
-
if (!this.action.getState().canSetToPlanned()) {
String msg = "Current state is {0} and can not be changed to {1} for action {2}";
msg = MessageFormat.format(msg, this.action.getState(), State.PLANNED, this.action.getLocator());
@@ -37,15 +34,12 @@ public class SetActionToPlannedCommand extends ExecutionCommand {
@Override
public void doCommand() {
- Activity rootElement = this.action.getRootElement();
- tx().lock(rootElement);
- tx().lock(getResourceLocator(this.action));
-
if (this.action.getState() == State.PLANNED) {
logger.warn("Action " + this.action.getLocator() + " is already in state PLANNED! Not changing.");
return;
}
+ Activity rootElement = this.action.getRootElement();
State currentState = rootElement.getState();
this.action.setState(State.PLANNED);
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToPlanningCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToPlanningCommand.java
deleted file mode 100644
index 1efbd211d..000000000
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToPlanningCommand.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package li.strolch.execution.command;
-
-import java.text.MessageFormat;
-
-import li.strolch.exception.StrolchException;
-import li.strolch.model.State;
-import li.strolch.model.activity.Action;
-import li.strolch.model.activity.Activity;
-import li.strolch.persistence.api.StrolchTransaction;
-import li.strolch.utils.dbc.DBC;
-
-public class SetActionToPlanningCommand extends ExecutionCommand {
-
- private Action action;
-
- public SetActionToPlanningCommand(StrolchTransaction tx) {
- super(tx);
- }
-
- public void setAction(Action action) {
- this.action = action;
- }
-
- @Override
- public void validate() {
- DBC.PRE.assertNotNull("action can not be null", this.action);
-
- tx().lock(this.action.getRootElement());
- tx().lock(getResourceLocator(this.action));
-
- if (!this.action.getState().canSetToPlanning()) {
- String msg = "Current state is {0} and can not be changed to {1} for action {2}";
- msg = MessageFormat.format(msg, this.action.getState(), State.PLANNING, this.action.getLocator());
- throw new StrolchException(msg);
- }
- }
-
- @Override
- public void doCommand() {
- Activity rootElement = this.action.getRootElement();
- tx().lock(rootElement);
- tx().lock(getResourceLocator(this.action));
-
- if (this.action.getState() == State.PLANNING) {
- logger.warn("Action " + this.action.getLocator() + " is already in state PLANNING! Not changing.");
- return;
- }
-
- State currentState = rootElement.getState();
-
- this.action.setState(State.PLANNING);
-
- getConfirmationPolicy(this.action).toPlanning(this.action);
-
- updateOrderState(tx(), rootElement, currentState, rootElement.getState());
- }
-}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToStoppedCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToStoppedCommand.java
index ccf897e36..acb6fdf87 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToStoppedCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToStoppedCommand.java
@@ -4,29 +4,18 @@ import java.text.MessageFormat;
import li.strolch.exception.StrolchException;
import li.strolch.model.State;
-import li.strolch.model.activity.Action;
import li.strolch.model.activity.Activity;
import li.strolch.persistence.api.StrolchTransaction;
-import li.strolch.utils.dbc.DBC;
-public class SetActionToStoppedCommand extends ExecutionCommand {
-
- private Action action;
+public class SetActionToStoppedCommand extends ActionExecutionCommand {
public SetActionToStoppedCommand(StrolchTransaction tx) {
super(tx);
}
- public void setAction(Action action) {
- this.action = action;
- }
-
@Override
public void validate() {
- DBC.PRE.assertNotNull("action can not be null", this.action);
-
- tx().lock(this.action.getRootElement());
- tx().lock(getResourceLocator(this.action));
+ super.validate();
if (!this.action.getState().canSetToStopped()) {
String msg = "Current state is {0} and can not be changed to {1} for action {2}";
@@ -37,15 +26,12 @@ public class SetActionToStoppedCommand extends ExecutionCommand {
@Override
public void doCommand() {
- Activity rootElement = this.action.getRootElement();
- tx().lock(rootElement);
- tx().lock(getResourceLocator(this.action));
-
if (this.action.getState() == State.STOPPED) {
logger.warn("Action " + this.action.getLocator() + " is already in state STOPPED! Not changing.");
return;
}
+ Activity rootElement = this.action.getRootElement();
State currentState = rootElement.getState();
getExecutionPolicy(this.action).toStopped(this.action);
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToWarningCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToWarningCommand.java
index 98fbc628c..1c27dd5b6 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToWarningCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToWarningCommand.java
@@ -4,29 +4,18 @@ import java.text.MessageFormat;
import li.strolch.exception.StrolchException;
import li.strolch.model.State;
-import li.strolch.model.activity.Action;
import li.strolch.model.activity.Activity;
import li.strolch.persistence.api.StrolchTransaction;
-import li.strolch.utils.dbc.DBC;
-public class SetActionToWarningCommand extends ExecutionCommand {
-
- private Action action;
+public class SetActionToWarningCommand extends ActionExecutionCommand {
public SetActionToWarningCommand(StrolchTransaction tx) {
super(tx);
}
- public void setAction(Action action) {
- this.action = action;
- }
-
@Override
public void validate() {
- DBC.PRE.assertNotNull("action can not be null", this.action);
-
- tx().lock(this.action.getRootElement());
- tx().lock(getResourceLocator(this.action));
+ super.validate();
if (!this.action.getState().canSetToWarning()) {
String msg = "Current state is {0} and can not be changed to {1} for action {2}";
@@ -37,15 +26,12 @@ public class SetActionToWarningCommand extends ExecutionCommand {
@Override
public void doCommand() {
- Activity rootElement = this.action.getRootElement();
- tx().lock(rootElement);
- tx().lock(getResourceLocator(this.action));
-
if (this.action.getState() == State.WARNING) {
logger.warn("Action " + this.action.getLocator() + " is already in state WARNING! Not changing.");
return;
}
+ Activity rootElement = this.action.getRootElement();
State currentState = rootElement.getState();
getExecutionPolicy(this.action).toWarning(this.action);
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/ShiftActionCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/ShiftActionCommand.java
index 7f5108150..0e144974d 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/ShiftActionCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/ShiftActionCommand.java
@@ -15,8 +15,7 @@
*/
package li.strolch.execution.command;
-import static li.strolch.execution.command.ExecutionCommand.updateOrderState;
-import static li.strolch.execution.policy.NoPlanning.NO_PLANNING;
+import static li.strolch.execution.policy.NoPlanning.DEFAULT_PLANNING;
import java.util.List;
@@ -59,14 +58,9 @@ public class ShiftActionCommand extends PlanningCommand {
@Override
public void doCommand() {
- validate();
-
Activity rootElement = this.action.getRootElement();
- tx().lock(rootElement);
-
State currentState = rootElement.getState();
this.action.accept(this);
-
updateOrderState(tx(), rootElement, currentState, rootElement.getState());
}
@@ -75,8 +69,10 @@ public class ShiftActionCommand extends PlanningCommand {
// unplan the action
if (action.getState() == State.PLANNED) {
- PlanningPolicy planningPolicy = tx().getPolicy(action.findPolicy(PlanningPolicy.class, NO_PLANNING));
+ PlanningPolicy planningPolicy = tx().getPolicy(action.findPolicy(PlanningPolicy.class, DEFAULT_PLANNING));
planningPolicy.unplan(action);
+ if (action.getState() == State.CREATED)
+ getConfirmationPolicy(action).toCreated(action);
}
// iterate all changes and shift
@@ -86,8 +82,10 @@ public class ShiftActionCommand extends PlanningCommand {
}
// finally plan the action
- PlanningPolicy planningPolicy = tx().getPolicy(action.findPolicy(PlanningPolicy.class, NO_PLANNING));
+ PlanningPolicy planningPolicy = tx().getPolicy(action.findPolicy(PlanningPolicy.class, DEFAULT_PLANNING));
planningPolicy.plan(action);
+ if (action.getState() == State.PLANNED)
+ getConfirmationPolicy(action).toPlanned(action);
return null;
}
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/UnplanActionCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/UnplanActionCommand.java
index e210fcc63..9d158998b 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/UnplanActionCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/UnplanActionCommand.java
@@ -15,8 +15,7 @@
*/
package li.strolch.execution.command;
-import static li.strolch.execution.command.ExecutionCommand.updateOrderState;
-import static li.strolch.execution.policy.NoPlanning.NO_PLANNING;
+import static li.strolch.execution.policy.NoPlanning.DEFAULT_PLANNING;
import li.strolch.execution.policy.PlanningPolicy;
import li.strolch.model.Resource;
@@ -61,21 +60,18 @@ public class UnplanActionCommand extends PlanningCommand {
@Override
public void doCommand() {
- validate();
-
Activity rootElement = this.action.getRootElement();
- tx().lock(rootElement);
-
State currentState = rootElement.getState();
this.action.accept(this);
-
updateOrderState(tx(), rootElement, currentState, rootElement.getState());
}
@Override
public Void visitAction(Action action) {
- PlanningPolicy planningPolicy = tx().getPolicy(action.findPolicy(PlanningPolicy.class, NO_PLANNING));
+ PlanningPolicy planningPolicy = tx().getPolicy(action.findPolicy(PlanningPolicy.class, DEFAULT_PLANNING));
planningPolicy.unplan(action);
+ if (action.getState() == State.CREATED)
+ getConfirmationPolicy(action).toCreated(action);
return null;
}
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/command/UnplanActivityCommand.java b/li.strolch.service/src/main/java/li/strolch/execution/command/UnplanActivityCommand.java
index 2c9b4a6fa..8382e7af3 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/command/UnplanActivityCommand.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/command/UnplanActivityCommand.java
@@ -15,8 +15,7 @@
*/
package li.strolch.execution.command;
-import static li.strolch.execution.command.ExecutionCommand.updateOrderState;
-import static li.strolch.execution.policy.NoPlanning.NO_PLANNING;
+import static li.strolch.execution.policy.NoPlanning.DEFAULT_PLANNING;
import li.strolch.execution.policy.PlanningPolicy;
import li.strolch.model.Resource;
@@ -59,21 +58,18 @@ public class UnplanActivityCommand extends PlanningCommand {
@Override
public void doCommand() {
- validate();
-
Activity rootElement = this.activity.getRootElement();
- tx().lock(rootElement);
-
State currentState = rootElement.getState();
this.activity.accept(this);
-
updateOrderState(tx(), rootElement, currentState, rootElement.getState());
}
@Override
public Void visitAction(Action action) {
- PlanningPolicy planningPolicy = tx().getPolicy(action.findPolicy(PlanningPolicy.class, NO_PLANNING));
+ PlanningPolicy planningPolicy = tx().getPolicy(action.findPolicy(PlanningPolicy.class, DEFAULT_PLANNING));
planningPolicy.unplan(action);
+ if (action.getState() == State.CREATED)
+ getConfirmationPolicy(action).toCreated(action);
return null;
}
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/policy/ActivityArchivalPolicy.java b/li.strolch.service/src/main/java/li/strolch/execution/policy/ActivityArchivalPolicy.java
index dff3989ef..7a417b56c 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/policy/ActivityArchivalPolicy.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/policy/ActivityArchivalPolicy.java
@@ -2,6 +2,7 @@ package li.strolch.execution.policy;
import li.strolch.model.State;
import li.strolch.model.activity.Activity;
+import li.strolch.model.policy.PolicyDef;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.policy.StrolchPolicy;
@@ -14,6 +15,9 @@ import li.strolch.policy.StrolchPolicy;
*/
public class ActivityArchivalPolicy extends StrolchPolicy {
+ public static PolicyDef DEFAULT_ACTIVITY_ARCHIVAL = PolicyDef
+ .valueOf(ActivityArchivalPolicy.class.getSimpleName(), "key:DefaultActivityArchival");
+
public ActivityArchivalPolicy(StrolchTransaction tx) {
super(tx);
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/policy/ConfirmationPolicy.java b/li.strolch.service/src/main/java/li/strolch/execution/policy/ConfirmationPolicy.java
index c290ddb5b..e8e4173a8 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/policy/ConfirmationPolicy.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/policy/ConfirmationPolicy.java
@@ -1,6 +1,7 @@
package li.strolch.execution.policy;
import li.strolch.model.activity.Action;
+import li.strolch.model.policy.PolicyDef;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.policy.StrolchPolicy;
@@ -12,6 +13,9 @@ import li.strolch.policy.StrolchPolicy;
*/
public class ConfirmationPolicy extends StrolchPolicy {
+ public static PolicyDef DEFAULT_CONFIRMATION = PolicyDef
+ .valueOf(ConfirmationPolicy.class.getSimpleName(), "key:DefaultConfirmation");
+
public ConfirmationPolicy(StrolchTransaction tx) {
super(tx);
}
@@ -20,11 +24,11 @@ public class ConfirmationPolicy extends StrolchPolicy {
// do nothing
}
- public void toPlanning(Action action) {
+ public void toPlanned(Action action) {
// do nothing
}
- public void toPlanned(Action action) {
+ public void toExecutable(Action action) {
// do nothing
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/policy/DurationExecution.java b/li.strolch.service/src/main/java/li/strolch/execution/policy/DurationExecution.java
index 5910bf0e7..c48848b84 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/policy/DurationExecution.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/policy/DurationExecution.java
@@ -16,6 +16,8 @@ import li.strolch.runtime.StrolchConstants.PolicyConstants;
*/
public class DurationExecution extends SimpleExecution {
+ protected Locator actionLoc;
+
public DurationExecution(StrolchTransaction tx) {
super(tx);
}
@@ -27,10 +29,15 @@ public class DurationExecution extends SimpleExecution {
.findParameter(PolicyConstants.BAG_OBJECTIVES, PolicyConstants.PARAM_DURATION, true);
String realmName = tx().getRealmName();
- Locator locator = action.getLocator();
- logger.info("Executing action " + action.getLocator() + " has a duration of " + durationP.getValueAsString());
- getDelayedExecutionTimer().execute(realmName, getContainer(), locator, durationP.toMillis());
+ this.actionLoc = action.getLocator();
+ logger.info("Executing action " + actionLoc + " has a duration of " + durationP.getValueAsString());
+ getDelayedExecutionTimer().execute(realmName, getContainer(), this.actionLoc, durationP.toMillis());
super.toExecution(action);
}
+
+ @Override
+ protected void handleStopped() {
+ getDelayedExecutionTimer().cancel(this.actionLoc);
+ }
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/policy/ExecutionPolicy.java b/li.strolch.service/src/main/java/li/strolch/execution/policy/ExecutionPolicy.java
index 0c3efc71f..294666182 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/policy/ExecutionPolicy.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/policy/ExecutionPolicy.java
@@ -3,8 +3,10 @@ package li.strolch.execution.policy;
import li.strolch.agent.api.ComponentContainer;
import li.strolch.agent.api.StrolchRealm;
import li.strolch.exception.StrolchException;
+import li.strolch.execution.Controller;
import li.strolch.execution.DelayedExecutionTimer;
import li.strolch.execution.ExecutionHandler;
+import li.strolch.model.Locator;
import li.strolch.model.State;
import li.strolch.model.activity.Action;
import li.strolch.model.activity.Activity;
@@ -33,6 +35,12 @@ import li.strolch.runtime.privilege.PrivilegedRunnableWithResult;
*/
public abstract class ExecutionPolicy extends StrolchPolicy {
+ private Controller controller;
+ private boolean stopped;
+
+ protected String actionType;
+ protected Locator actionLoc;
+
/**
* The TX for this execution policy. The TX needs to be updated when this execution policy has a longer life time
* than the actual TX
@@ -44,6 +52,19 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
this.tx = tx;
}
+ public void setController(StrolchTransaction tx, Controller controller) {
+ this.tx = tx;
+ this.controller = controller;
+ }
+
+ public Controller getController() {
+ return this.controller;
+ }
+
+ public boolean isStopped() {
+ return this.stopped;
+ }
+
/**
* Returns the TX which is defined on this class, not the one defined on {@link StrolchPolicy}
*/
@@ -76,6 +97,18 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
return true;
}
+ /**
+ * Performs any initialization of this {@link ExecutionPolicy} for the given action, this method stores the {@link
+ * Locator} of the action and its type
+ *
+ * @param action
+ * the action for which to initialize
+ */
+ public void initialize(Action action) {
+ this.actionType = action.getType();
+ this.actionLoc = action.getLocator();
+ }
+
/**
* Starts the execution of the given {@link Action}, i.e. sets the state to {@link State#EXECUTION}
*
@@ -119,6 +152,21 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
*/
public abstract void toWarning(Action action);
+ /**
+ * Stops any active components in this {@link ExecutionPolicy}. This is used to notify the {@link ExecutionPolicy}
+ * that any scheduled actions should be stopped, that listening and observing registrations can be taken back, etc.
+ */
+ public void stop() {
+ this.stopped = true;
+ try {
+ handleStopped();
+ } catch (Exception e) {
+ logger.error("Stopping failed for " + this.actionLoc, e);
+ }
+ }
+
+ protected abstract void handleStopped();
+
protected void setActionState(Action action, State state) {
action.setState(state);
@@ -142,15 +190,6 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
return getComponent(ExecutionHandler.class).getDelayedExecutionTimer();
}
- /**
- * Returns the execution handler instance
- *
- * @return the {@link ExecutionHandler} instance
- */
- protected ExecutionHandler getExecutionHandler() {
- return getComponent(ExecutionHandler.class);
- }
-
/**
* Opens a {@link StrolchTransaction} where the realm retrieved using {@link ComponentContainer#getRealm(Certificate)}.
* This transaction should be used in a try-with-resource clause so it is properly closed.
@@ -206,9 +245,4 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
throws PrivilegeException, Exception {
return getContainer().getPrivilegeHandler().runWithResult(StrolchConstants.SYSTEM_USER_AGENT, runnable);
}
-
- @Override
- public void undo() {
- // do nothing
- }
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/policy/NoPlanning.java b/li.strolch.service/src/main/java/li/strolch/execution/policy/NoPlanning.java
index 10ff52249..4e9741456 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/policy/NoPlanning.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/policy/NoPlanning.java
@@ -9,7 +9,7 @@ import li.strolch.utils.dbc.DBC;
public class NoPlanning extends PlanningPolicy {
- public static PolicyDef NO_PLANNING = PolicyDef
+ public static PolicyDef DEFAULT_PLANNING = PolicyDef
.valueOf(PlanningPolicy.class.getSimpleName(), "key:DefaultPlanning");
public NoPlanning(StrolchTransaction tx) {
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/policy/ReservationExecution.java b/li.strolch.service/src/main/java/li/strolch/execution/policy/ReservationExecution.java
index a7da4e592..87cab7089 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/policy/ReservationExecution.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/policy/ReservationExecution.java
@@ -53,8 +53,9 @@ public class ReservationExecution extends DurationExecution {
}
protected boolean isReserved(Action action) {
+
// get resource
- Resource resource = getResource(action);
+ Resource resource = tx().getResourceFor(action, true);
if (!resource.hasParameter(BAG_PARAMETERS, PARAM_RESERVED))
throw new StrolchModelException(
@@ -67,55 +68,55 @@ public class ReservationExecution extends DurationExecution {
@Override
public void toExecution(Action action) {
+ switch (action.getType()) {
- // only do if reserve or release
- boolean isReserve = action.getType().equals(TYPE_RESERVE);
- boolean isRelease = action.getType().equals(TYPE_RELEASE);
- if (!isReserve && !isRelease) {
- // otherwise delegate to super class
+ case TYPE_RESERVE:
+ case TYPE_RELEASE:
+
+ boolean isReserve = action.getType().equals(TYPE_RESERVE);
+ setReservation(action, isReserve);
+
+ String realmName = tx().getRealmName();
+ Locator locator = action.getLocator();
+ getDelayedExecutionTimer().execute(realmName, getContainer(), locator, 0L);
+
+ setActionState(action, State.EXECUTION);
+ break;
+
+ default:
super.toExecution(action);
-
- return;
}
-
- setReservation(action);
-
- String realmName = tx().getRealmName();
- Locator locator = action.getLocator();
- getDelayedExecutionTimer().execute(realmName, getContainer(), locator, 0L);
-
- setActionState(action, State.EXECUTION);
}
@Override
public void toExecuted(Action action) {
- // only do if reserve or release
- boolean isReserve = action.getType().equals(TYPE_RESERVE);
- boolean isRelease = action.getType().equals(TYPE_RELEASE);
- if (!isReserve && !isRelease) {
- // otherwise delegate to super class
+ switch (action.getType()) {
+
+ case TYPE_RESERVE:
+ case TYPE_RELEASE:
+
+ boolean isReserve = action.getType().equals(TYPE_RESERVE);
+ setReservation(action, isReserve);
+
+ FloatValue value = new FloatValue(isReserve ? 1.0D : 0.0D);
+ action.addChange(new ValueChange<>(System.currentTimeMillis(), value, ""));
+
+ setActionState(action, State.EXECUTED);
+ break;
+
+ default:
super.toExecuted(action);
-
- return;
}
-
- setReservation(action);
- setActionState(action, State.EXECUTED);
-
- FloatValue value = new FloatValue(isReserve ? 1.0D : 0.0D);
- action.addChange(new ValueChange<>(System.currentTimeMillis(), value, ""));
}
- public void setReservation(Action action) {
+ private void setReservation(Action action, boolean isReserve) {
- Resource resource = getResource(action);
-
- boolean reserved = action.getType().equals(TYPE_RESERVE);
+ Resource resource = tx().getResourceFor(action, true);
// release the resource
BooleanParameter reservedP = resource.getParameter(BAG_PARAMETERS, PARAM_RESERVED);
- reservedP.setValue(reserved);
+ reservedP.setValue(isReserve);
// save changes
tx().update(resource);
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/policy/SimpleExecution.java b/li.strolch.service/src/main/java/li/strolch/execution/policy/SimpleExecution.java
index 097e46a00..01cc6b5e9 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/policy/SimpleExecution.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/policy/SimpleExecution.java
@@ -36,6 +36,8 @@ public class SimpleExecution extends ExecutionPolicy {
@Override
public void toExecuted(Action action) {
+ stop();
+
setActionState(action, State.EXECUTED);
FloatValue value = new FloatValue(0.0D);
@@ -44,7 +46,8 @@ public class SimpleExecution extends ExecutionPolicy {
@Override
public void toStopped(Action action) {
- getDelayedExecutionTimer().cancel(action.getLocator());
+ stop();
+
setActionState(action, State.STOPPED);
FloatValue value = new FloatValue(0.0D);
@@ -53,7 +56,8 @@ public class SimpleExecution extends ExecutionPolicy {
@Override
public void toError(Action action) {
- getDelayedExecutionTimer().cancel(action.getLocator());
+ stop();
+
setActionState(action, State.ERROR);
FloatValue value = new FloatValue(0.0D);
@@ -68,18 +72,20 @@ public class SimpleExecution extends ExecutionPolicy {
}
protected void toError(LogMessage message) {
+ stop();
logger.error("Action " + message.getLocator() + " failed because of: " + message.formatMessage());
addMessage(message);
- getExecutionHandler().toError(message.getRealm(), message.getLocator());
+ getController().asyncToError(message.getLocator());
}
protected void toWarning(LogMessage message) {
+ stop();
addMessage(message);
- getExecutionHandler().toWarning(message.getRealm(), message.getLocator());
+ getController().asyncToWarning(message.getLocator());
}
@Override
- public void undo() {
- logger.error("Can not undo execution policy " + getClass());
+ protected void handleStopped() {
+ getDelayedExecutionTimer().cancel(this.actionLoc);
}
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/policy/ToErrorReservationExecution.java b/li.strolch.service/src/main/java/li/strolch/execution/policy/ToErrorReservationExecution.java
index 73fe29ad7..d903ae2e3 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/policy/ToErrorReservationExecution.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/policy/ToErrorReservationExecution.java
@@ -27,8 +27,6 @@ public class ToErrorReservationExecution extends ReservationExecution {
@Override
public boolean isExecutable(Action action) {
- tx().lock(getResource(action));
-
if (action.getType().equals(TYPE_RESERVE)) {
return true;
}
@@ -39,14 +37,12 @@ public class ToErrorReservationExecution extends ReservationExecution {
@Override
public void toExecution(Action action) {
- tx().lock(getResource(action));
-
if (action.getType().equals(TYPE_RESERVE) && isReserved(action)) {
setActionState(action, State.EXECUTION);
toError(new LogMessage(tx().getRealmName(), tx().getCertificate().getUsername(), action.getLocator(),
LogSeverity.Error, ResourceBundle.getBundle("strolch-service"),
"execution.policy.reservation.alreadyReserved")
- .value("resourceLoc", getResource(action).getLocator().toString()));
+ .value("resourceLoc", action.getResourceLocator().toString()));
} else {
super.toExecution(action);
}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/service/SetActionToPlanningService.java b/li.strolch.service/src/main/java/li/strolch/execution/service/ExecuteActionService.java
similarity index 55%
rename from li.strolch.service/src/main/java/li/strolch/execution/service/SetActionToPlanningService.java
rename to li.strolch.service/src/main/java/li/strolch/execution/service/ExecuteActionService.java
index edac06606..bdbd5e1e2 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/service/SetActionToPlanningService.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/service/ExecuteActionService.java
@@ -1,14 +1,16 @@
package li.strolch.execution.service;
-import li.strolch.execution.command.SetActionToPlanningCommand;
+import li.strolch.execution.ExecutionHandler;
+import li.strolch.model.State;
import li.strolch.model.activity.Action;
+import li.strolch.model.activity.Activity;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.service.LocatorArgument;
import li.strolch.service.api.AbstractService;
import li.strolch.service.api.ServiceResult;
import li.strolch.service.api.ServiceResultState;
-public class SetActionToPlanningService extends AbstractService {
+public class ExecuteActionService extends AbstractService {
@Override
protected ServiceResult getResultInstance() {
@@ -23,17 +25,27 @@ public class SetActionToPlanningService extends AbstractService {
-
- @Override
- protected ServiceResult getResultInstance() {
- return new ServiceResult(ServiceResultState.FAILED);
- }
-
- @Override
- public StringMapArgument getArgumentInstance() {
- return new StringMapArgument();
- }
-
- @Override
- protected ServiceResult internalDoService(StringMapArgument arg) throws Exception {
-
- State state = State.parse(arg.map.get("state"));
- Locator locator = Locator.valueOf(arg.map.get("locator"));
-
- String realm;
- try (StrolchTransaction tx = openArgOrUserTx(arg)) {
- realm = tx.getRealmName();
-
- Action action = tx.findElement(locator);
-
- switch (state) {
- case CREATED: {
-
- SetActionToCreatedCommand command = new SetActionToCreatedCommand(tx);
- command.setAction(action);
- tx.addCommand(command);
-
- break;
- }
-
- case PLANNING: {
-
- SetActionToPlanningCommand command = new SetActionToPlanningCommand(tx);
- command.setAction(action);
- tx.addCommand(command);
-
- break;
- }
-
- case PLANNED: {
-
- SetActionToPlannedCommand command = new SetActionToPlannedCommand(tx);
- command.setAction(action);
- tx.addCommand(command);
-
- break;
- }
-
- case EXECUTION: {
-
- tx.lock(locator);
-
- IActivityElement element = tx.findElement(locator);
- if (element.getState().canNotSetToExecution()) {
- String msg = "Current state is {0} and can not be changed to {1} for action {2}";
- msg = MessageFormat.format(msg, element.getState(), State.EXECUTION, element.getLocator());
- throw new StrolchException(msg);
- }
-
- ExecutionHandler executionHandler = getContainer().getComponent(ExecutionHandler.class);
- executionHandler.toExecution(tx.getRealmName(), locator);
-
- break;
- }
-
- case WARNING: {
-
- SetActionToWarningCommand command = new SetActionToWarningCommand(tx);
- command.setAction(action);
- tx.addCommand(command);
-
- break;
- }
-
- case ERROR: {
-
- SetActionToErrorCommand command = new SetActionToErrorCommand(tx);
- command.setAction(action);
- tx.addCommand(command);
-
- break;
- }
-
- case STOPPED: {
-
- SetActionToStoppedCommand command = new SetActionToStoppedCommand(tx);
- command.setAction(action);
- tx.addCommand(command);
-
- break;
- }
-
- case EXECUTED: {
-
- SetActionToExecutedCommand command = new SetActionToExecutedCommand(tx);
- command.setAction(action);
- tx.addCommand(command);
-
- break;
- }
-
- case CLOSED: {
-
- SetActionToClosedCommand command = new SetActionToClosedCommand(tx);
- command.setAction(action);
- tx.addCommand(command);
-
- break;
- }
-
- default:
- throw new UnsupportedOperationException("Unhandled state " + state);
- }
-
- tx.commitOnClose();
- }
-
- ExecutionHandler executionHandler = getContainer().getComponent(ExecutionHandler.class);
- executionHandler.triggerExecution(realm);
-
- return ServiceResult.success();
- }
-}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/service/SetActionToClosedService.java b/li.strolch.service/src/main/java/li/strolch/execution/service/SetActionToClosedService.java
index eea5f995f..df21fd7b9 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/service/SetActionToClosedService.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/service/SetActionToClosedService.java
@@ -25,7 +25,9 @@ public class SetActionToClosedService extends AbstractService {
-
- @Override
- protected ServiceResult getResultInstance() {
- return new ServiceResult(ServiceResultState.FAILED);
- }
-
- @Override
- public LocatorArgument getArgumentInstance() {
- return new LocatorArgument();
- }
-
- @Override
- protected ServiceResult internalDoService(LocatorArgument arg) throws Exception {
-
- String realm = isEmpty(arg.realm) ? StrolchConstants.DEFAULT_REALM : arg.realm;
-
- Activity activity;
- try (StrolchTransaction tx = openTx(realm)) {
- tx.lock(arg.locator);
-
- IActivityElement element = tx.findElement(arg.locator);
- if (element.getState().canNotSetToExecution()) {
- String msg = "Current state is {0} and can not be changed to {1} for action {2}";
- msg = MessageFormat.format(msg, element.getState(), State.EXECUTION, element.getLocator());
- throw new StrolchException(msg);
- }
-
- if (element.isAction() && element.getState() == State.STOPPED) {
- ((Action) element).setState(State.EXECUTABLE);
- }
-
- activity = element.getRootElement();
- }
-
- ExecutionHandler executionHandler = getContainer().getComponent(ExecutionHandler.class);
- executionHandler.addForExecution(realm, activity);
-
- return ServiceResult.success();
- }
-}
diff --git a/li.strolch.service/src/main/java/li/strolch/execution/service/StartActivityExecutionService.java b/li.strolch.service/src/main/java/li/strolch/execution/service/StartActivityExecutionService.java
index 4187c7401..f5007d9c7 100644
--- a/li.strolch.service/src/main/java/li/strolch/execution/service/StartActivityExecutionService.java
+++ b/li.strolch.service/src/main/java/li/strolch/execution/service/StartActivityExecutionService.java
@@ -43,7 +43,7 @@ public class StartActivityExecutionService extends AbstractService getList(T t) {
synchronized (this.mutex) {
- return new SynchronizedList<>(this.m.getList(t), this.mutex);
+ List list = this.m.getList(t);
+ if (list == null)
+ return null;
+ return new SynchronizedList<>(list, this.mutex);
}
}
@@ -194,7 +197,10 @@ public class SynchronizedCollections {
@Override
public Map getMap(T t) {
synchronized (this.mutex) {
- return new SynchronizedMap<>(this.m.getMap(t), this.mutex);
+ Map map = this.m.getMap(t);
+ if (map == null)
+ return null;
+ return new SynchronizedMap<>(map, this.mutex);
}
}
@@ -358,7 +364,10 @@ public class SynchronizedCollections {
@Override
public Set getSet(T t) {
synchronized (this.mutex) {
- return new SynchronizedSet<>(this.m.getSet(t), this.mutex);
+ Set set = this.m.getSet(t);
+ if (set == null)
+ return null;
+ return new SynchronizedSet<>(set, this.mutex);
}
}
diff --git a/li.strolch.utils/src/main/java/li/strolch/utils/objectfilter/ObjectFilter.java b/li.strolch.utils/src/main/java/li/strolch/utils/objectfilter/ObjectFilter.java
index 689dcf1f0..93d6b3b63 100644
--- a/li.strolch.utils/src/main/java/li/strolch/utils/objectfilter/ObjectFilter.java
+++ b/li.strolch.utils/src/main/java/li/strolch/utils/objectfilter/ObjectFilter.java
@@ -463,6 +463,19 @@ public class ObjectFilter {
return this.cache.containsElement(key, objectKey);
}
+ /**
+ * Allows clearing the object cache for an element
+ *
+ * @param key
+ * the key under which it was registered
+ * @param objectKey
+ * the objectKey
+ */
+ public void removeObjectCache(String key, Object objectKey) {
+ this.keySet.remove(key);
+ this.cache.removeElement(key, objectKey);
+ }
+
/**
* Get all objects that were registered under the given key and that have as a resulting final action an addition.
*
diff --git a/pom.xml b/pom.xml
index f5eb7836d..ee0267ede 100644
--- a/pom.xml
+++ b/pom.xml
@@ -97,7 +97,6 @@
4.122.1
- 2.28.21.11.2
@@ -328,12 +327,6 @@
${hamcrest.version}test
-
- org.mockito
- mockito-core
- ${mockito.version}
- test
-