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

  • API
  • Documentation
  • +
  • PLC
  • Tutorial
  • Downloads
  • Development
  • diff --git a/li.strolch.website/www.strolch.li/blog.html b/li.strolch.website/www.strolch.li/blog.html index e3e81ceb6..71567debe 100644 --- a/li.strolch.website/www.strolch.li/blog.html +++ b/li.strolch.website/www.strolch.li/blog.html @@ -33,6 +33,7 @@
  • Overview
  • API
  • Documentation
  • +
  • PLC
  • Tutorial
  • Downloads
  • Development
  • diff --git a/li.strolch.website/www.strolch.li/development.html b/li.strolch.website/www.strolch.li/development.html index 67acc3c38..130823289 100644 --- a/li.strolch.website/www.strolch.li/development.html +++ b/li.strolch.website/www.strolch.li/development.html @@ -32,6 +32,7 @@
  • Overview
  • API
  • Documentation
  • +
  • PLC
  • Tutorial
  • Downloads
  • Development
  • diff --git a/li.strolch.website/www.strolch.li/documentation-architecture.html b/li.strolch.website/www.strolch.li/documentation-architecture.html index a5418a734..bcd4ff32d 100644 --- a/li.strolch.website/www.strolch.li/documentation-architecture.html +++ b/li.strolch.website/www.strolch.li/documentation-architecture.html @@ -32,6 +32,7 @@
  • Overview
  • API
  • Documentation
  • +
  • PLC
  • Tutorial
  • Downloads
  • Development
  • diff --git a/li.strolch.website/www.strolch.li/documentation-components.html b/li.strolch.website/www.strolch.li/documentation-components.html index 70412dbf2..2281ec1cb 100644 --- a/li.strolch.website/www.strolch.li/documentation-components.html +++ b/li.strolch.website/www.strolch.li/documentation-components.html @@ -32,6 +32,7 @@
  • Overview
  • API
  • Documentation
  • +
  • PLC
  • Tutorial
  • Downloads
  • Development
  • diff --git a/li.strolch.website/www.strolch.li/documentation-do-and-dont.html b/li.strolch.website/www.strolch.li/documentation-do-and-dont.html index 88f5641dc..2d54e1744 100644 --- a/li.strolch.website/www.strolch.li/documentation-do-and-dont.html +++ b/li.strolch.website/www.strolch.li/documentation-do-and-dont.html @@ -32,6 +32,7 @@
  • Overview
  • API
  • Documentation
  • +
  • PLC
  • Tutorial
  • Downloads
  • Development
  • diff --git a/li.strolch.website/www.strolch.li/documentation-model.html b/li.strolch.website/www.strolch.li/documentation-model.html index 8c7469d41..db4c9b881 100644 --- a/li.strolch.website/www.strolch.li/documentation-model.html +++ b/li.strolch.website/www.strolch.li/documentation-model.html @@ -32,6 +32,7 @@
  • Overview
  • API
  • Documentation
  • +
  • PLC
  • Tutorial
  • Downloads
  • Development
  • diff --git a/li.strolch.website/www.strolch.li/documentation-observers.html b/li.strolch.website/www.strolch.li/documentation-observers.html index c86bdd742..21d4d95bd 100644 --- a/li.strolch.website/www.strolch.li/documentation-observers.html +++ b/li.strolch.website/www.strolch.li/documentation-observers.html @@ -32,6 +32,7 @@
  • Overview
  • API
  • Documentation
  • +
  • PLC
  • Tutorial
  • Downloads
  • Development
  • diff --git a/li.strolch.website/www.strolch.li/documentation-policies.html b/li.strolch.website/www.strolch.li/documentation-policies.html index 0e56388b5..d17f43389 100644 --- a/li.strolch.website/www.strolch.li/documentation-policies.html +++ b/li.strolch.website/www.strolch.li/documentation-policies.html @@ -32,6 +32,7 @@
  • Overview
  • API
  • Documentation
  • +
  • PLC
  • Tutorial
  • Downloads
  • Development
  • diff --git a/li.strolch.website/www.strolch.li/documentation-privileges.html b/li.strolch.website/www.strolch.li/documentation-privileges.html index 15b255204..514e50b0d 100644 --- a/li.strolch.website/www.strolch.li/documentation-privileges.html +++ b/li.strolch.website/www.strolch.li/documentation-privileges.html @@ -32,6 +32,7 @@
  • Overview
  • API
  • Documentation
  • +
  • PLC
  • Tutorial
  • Downloads
  • Development
  • diff --git a/li.strolch.website/www.strolch.li/documentation-queries.html b/li.strolch.website/www.strolch.li/documentation-queries.html index ac160274d..7f5b5b3fb 100644 --- a/li.strolch.website/www.strolch.li/documentation-queries.html +++ b/li.strolch.website/www.strolch.li/documentation-queries.html @@ -32,6 +32,7 @@
  • Overview
  • API
  • Documentation
  • +
  • PLC
  • Tutorial
  • Downloads
  • Development
  • diff --git a/li.strolch.website/www.strolch.li/documentation-realms.html b/li.strolch.website/www.strolch.li/documentation-realms.html index 829127491..94264e9d8 100644 --- a/li.strolch.website/www.strolch.li/documentation-realms.html +++ b/li.strolch.website/www.strolch.li/documentation-realms.html @@ -32,6 +32,7 @@
  • Overview
  • API
  • Documentation
  • +
  • PLC
  • Tutorial
  • Downloads
  • Development
  • diff --git a/li.strolch.website/www.strolch.li/documentation-reports.html b/li.strolch.website/www.strolch.li/documentation-reports.html index d57ca556d..a6ac5606a 100644 --- a/li.strolch.website/www.strolch.li/documentation-reports.html +++ b/li.strolch.website/www.strolch.li/documentation-reports.html @@ -32,6 +32,7 @@
  • Overview
  • API
  • Documentation
  • +
  • PLC
  • Tutorial
  • Downloads
  • Development
  • diff --git a/li.strolch.website/www.strolch.li/documentation-runtime.html b/li.strolch.website/www.strolch.li/documentation-runtime.html index 23a5df6ea..6cd59334a 100644 --- a/li.strolch.website/www.strolch.li/documentation-runtime.html +++ b/li.strolch.website/www.strolch.li/documentation-runtime.html @@ -32,6 +32,7 @@
  • Overview
  • API
  • Documentation
  • +
  • PLC
  • Tutorial
  • Downloads
  • Development
  • diff --git a/li.strolch.website/www.strolch.li/documentation-searches.html b/li.strolch.website/www.strolch.li/documentation-searches.html index d2cdae18d..c0f81b3da 100644 --- a/li.strolch.website/www.strolch.li/documentation-searches.html +++ b/li.strolch.website/www.strolch.li/documentation-searches.html @@ -32,6 +32,7 @@
  • Overview
  • API
  • Documentation
  • +
  • PLC
  • Tutorial
  • Downloads
  • Development
  • diff --git a/li.strolch.website/www.strolch.li/documentation-services-and-commands.html b/li.strolch.website/www.strolch.li/documentation-services-and-commands.html index b4b29ccc2..1a2fc9927 100644 --- a/li.strolch.website/www.strolch.li/documentation-services-and-commands.html +++ b/li.strolch.website/www.strolch.li/documentation-services-and-commands.html @@ -32,6 +32,7 @@
  • Overview
  • API
  • Documentation
  • +
  • PLC
  • Tutorial
  • Downloads
  • Development
  • diff --git a/li.strolch.website/www.strolch.li/documentation-transactions.html b/li.strolch.website/www.strolch.li/documentation-transactions.html index ae6428dd3..0839f305a 100644 --- a/li.strolch.website/www.strolch.li/documentation-transactions.html +++ b/li.strolch.website/www.strolch.li/documentation-transactions.html @@ -32,6 +32,7 @@
  • Overview
  • API
  • Documentation
  • +
  • PLC
  • Tutorial
  • Downloads
  • Development
  • diff --git a/li.strolch.website/www.strolch.li/documentation-versioning.html b/li.strolch.website/www.strolch.li/documentation-versioning.html index fc35246c8..01d33f344 100644 --- a/li.strolch.website/www.strolch.li/documentation-versioning.html +++ b/li.strolch.website/www.strolch.li/documentation-versioning.html @@ -32,6 +32,7 @@
  • Overview
  • API
  • Documentation
  • +
  • PLC
  • Tutorial
  • Downloads
  • Development
  • diff --git a/li.strolch.website/www.strolch.li/documentation.html b/li.strolch.website/www.strolch.li/documentation.html index 1a0ab897a..cbdc7ea93 100644 --- a/li.strolch.website/www.strolch.li/documentation.html +++ b/li.strolch.website/www.strolch.li/documentation.html @@ -32,6 +32,7 @@
  • Overview
  • API
  • Documentation
  • +
  • PLC
  • Tutorial
  • Downloads
  • Development
  • diff --git a/li.strolch.website/www.strolch.li/downloads.html b/li.strolch.website/www.strolch.li/downloads.html index 0fff25e7d..95d0916a1 100644 --- a/li.strolch.website/www.strolch.li/downloads.html +++ b/li.strolch.website/www.strolch.li/downloads.html @@ -33,6 +33,7 @@
  • Overview
  • API
  • Documentation
  • +
  • PLC
  • Tutorial
  • Downloads
  • Development
  • diff --git a/li.strolch.website/www.strolch.li/history.html b/li.strolch.website/www.strolch.li/history.html index e6278d2fe..25c134b5d 100644 --- a/li.strolch.website/www.strolch.li/history.html +++ b/li.strolch.website/www.strolch.li/history.html @@ -32,6 +32,7 @@
  • Overview
  • API
  • Documentation
  • +
  • PLC
  • Tutorial
  • Downloads
  • Development
  • diff --git a/li.strolch.website/www.strolch.li/index.html b/li.strolch.website/www.strolch.li/index.html index c4154930e..b27326690 100644 --- a/li.strolch.website/www.strolch.li/index.html +++ b/li.strolch.website/www.strolch.li/index.html @@ -32,6 +32,7 @@
  • Overview
  • API
  • Documentation
  • +
  • PLC
  • Tutorial
  • Downloads
  • Development
  • diff --git a/li.strolch.website/www.strolch.li/plc.html b/li.strolch.website/www.strolch.li/plc.html new file mode 100644 index 000000000..b99cfa2e6 --- /dev/null +++ b/li.strolch.website/www.strolch.li/plc.html @@ -0,0 +1,109 @@ + + + + + + + + + + + + Strolch: PLC + + + + + + + + + + + + +
    + + + +
    + + + +

    Overview

    + +

    Using Strolch as a PLC has certain advantages and disadvantages. The following is a list of advantages:

    +
      +
    • Same programming model and language for server and PLC
    • +
    • PLC has the same privilege handling as in Strolch
    • +
    • Simulating down to the PLC level is easily possible to quickly test the server logic
    • +
    + + + + +
    + + + + +
    + + + + + + + + + + + + + + diff --git a/li.strolch.website/www.strolch.li/tutorial-configuration.html b/li.strolch.website/www.strolch.li/tutorial-configuration.html index bd1bb7da0..583de548c 100644 --- a/li.strolch.website/www.strolch.li/tutorial-configuration.html +++ b/li.strolch.website/www.strolch.li/tutorial-configuration.html @@ -32,6 +32,7 @@
  • Overview
  • API
  • Documentation
  • +
  • PLC
  • Tutorial
  • Downloads
  • Development
  • diff --git a/li.strolch.website/www.strolch.li/tutorial-crud-book.html b/li.strolch.website/www.strolch.li/tutorial-crud-book.html index 63b9f58cf..ad2ca837f 100644 --- a/li.strolch.website/www.strolch.li/tutorial-crud-book.html +++ b/li.strolch.website/www.strolch.li/tutorial-crud-book.html @@ -32,6 +32,7 @@
  • Overview
  • API
  • Documentation
  • +
  • PLC
  • Tutorial
  • Downloads
  • Development
  • diff --git a/li.strolch.website/www.strolch.li/tutorial-model.html b/li.strolch.website/www.strolch.li/tutorial-model.html index b00074929..db63661c4 100644 --- a/li.strolch.website/www.strolch.li/tutorial-model.html +++ b/li.strolch.website/www.strolch.li/tutorial-model.html @@ -32,6 +32,7 @@
  • Overview
  • API
  • Documentation
  • +
  • PLC
  • Tutorial
  • Downloads
  • Development
  • diff --git a/li.strolch.website/www.strolch.li/tutorial.html b/li.strolch.website/www.strolch.li/tutorial.html index 03703b94f..62e2cf184 100644 --- a/li.strolch.website/www.strolch.li/tutorial.html +++ b/li.strolch.website/www.strolch.li/tutorial.html @@ -32,6 +32,7 @@
  • Overview
  • API
  • Documentation
  • +
  • PLC
  • Tutorial
  • Downloads
  • Development
  • From dadc2a8cb892efb25a79e5a1d315c434589e82a9 Mon Sep 17 00:00:00 2001 From: Robert von Burg Date: Tue, 18 Feb 2020 18:11:22 +0100 Subject: [PATCH 2/2] [Major] Rewrote execution with controllers --- .../persistence/api/AbstractTransaction.java | 12 + .../persistence/api/StrolchTransaction.java | 26 ++ .../java/li/strolch/policy/StrolchPolicy.java | 35 +- .../li/strolch/runtime/StrolchConstants.java | 3 + .../policytest/TestNoConfirmationPolicy.java | 11 +- .../policytest/TestSimplePlanningPolicy.java | 11 +- .../TestSimulatedExecutionPolicy.java | 11 +- .../src/main/java/li/strolch/model/Order.java | 14 + .../li/strolch/model/PolicyContainer.java | 36 +- .../main/java/li/strolch/model/Resource.java | 14 + .../src/main/java/li/strolch/model/State.java | 7 + .../li/strolch/model/activity/Action.java | 26 ++ .../li/strolch/model/activity/Activity.java | 17 + .../li/strolch/model/policy/PolicyDefs.java | 7 + .../rest/endpoint/ControlResource.java | 82 ++++- .../ArchiveExecutedActivitiesJob.java | 2 +- .../java/li/strolch/execution/Controller.java | 311 +++++++++++++++-- .../execution/EventBasedExecutionHandler.java | 314 +++++------------- .../strolch/execution/ExecutionHandler.java | 61 +++- .../SimpleDurationExecutionTimer.java | 23 +- .../command/ActionExecutionCommand.java | 35 ++ .../command/ArchiveActivityCommand.java | 18 +- .../command/AssignActionCommand.java | 12 +- .../BasePlanningAndExecutionCommand.java | 63 ++++ .../command/ExecuteActivityCommand.java | 171 +++++++++- .../command/ExecuteStoppedActionCommand.java | 49 --- .../execution/command/ExecutionCommand.java | 208 ------------ .../execution/command/PlanActionCommand.java | 13 +- .../command/PlanActivityCommand.java | 12 +- .../execution/command/PlanningCommand.java | 35 +- .../command/SetActionToClosedCommand.java | 10 +- .../command/SetActionToCreatedCommand.java | 10 +- .../command/SetActionToErrorCommand.java | 20 +- .../command/SetActionToExecutableCommand.java | 43 +++ .../command/SetActionToExecutedCommand.java | 20 +- .../command/SetActionToPlannedCommand.java | 10 +- .../command/SetActionToPlanningCommand.java | 57 ---- .../command/SetActionToStoppedCommand.java | 20 +- .../command/SetActionToWarningCommand.java | 20 +- .../execution/command/ShiftActionCommand.java | 16 +- .../command/UnplanActionCommand.java | 12 +- .../command/UnplanActivityCommand.java | 12 +- .../policy/ActivityArchivalPolicy.java | 4 + .../execution/policy/ConfirmationPolicy.java | 8 +- .../execution/policy/DurationExecution.java | 13 +- .../execution/policy/ExecutionPolicy.java | 62 +++- .../strolch/execution/policy/NoPlanning.java | 2 +- .../policy/ReservationExecution.java | 69 ++-- .../execution/policy/SimpleExecution.java | 18 +- .../policy/ToErrorReservationExecution.java | 6 +- ...Service.java => ExecuteActionService.java} | 24 +- .../service/SetActionStateService.java | 144 -------- .../service/SetActionToClosedService.java | 2 + .../service/SetActionToCreatedService.java | 3 + .../service/SetActionToErrorService.java | 17 +- .../service/SetActionToExecutedService.java | 16 +- .../service/SetActionToPlannedService.java | 3 + .../service/SetActionToStoppedService.java | 16 +- .../service/SetActionToWarningService.java | 16 +- .../service/SetToExecutionService.java | 60 ---- .../StartActivityExecutionService.java | 2 +- .../main/resources/strolch-service.properties | 2 +- .../execution/ReservationExecutionTest.java | 7 + .../collections/SynchronizedCollections.java | 15 +- .../utils/objectfilter/ObjectFilter.java | 13 + pom.xml | 7 - 66 files changed, 1251 insertions(+), 1167 deletions(-) create mode 100644 li.strolch.service/src/main/java/li/strolch/execution/command/ActionExecutionCommand.java create mode 100644 li.strolch.service/src/main/java/li/strolch/execution/command/BasePlanningAndExecutionCommand.java delete mode 100644 li.strolch.service/src/main/java/li/strolch/execution/command/ExecuteStoppedActionCommand.java delete mode 100644 li.strolch.service/src/main/java/li/strolch/execution/command/ExecutionCommand.java create mode 100644 li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToExecutableCommand.java delete mode 100644 li.strolch.service/src/main/java/li/strolch/execution/command/SetActionToPlanningCommand.java rename li.strolch.service/src/main/java/li/strolch/execution/service/{SetActionToPlanningService.java => ExecuteActionService.java} (55%) delete mode 100644 li.strolch.service/src/main/java/li/strolch/execution/service/SetActionStateService.java delete mode 100644 li.strolch.service/src/main/java/li/strolch/execution/service/SetToExecutionService.java 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 2ccb64bbd..2ddc28125 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 @@ -319,6 +319,10 @@ public abstract class AbstractTransaction implements StrolchTransaction { @Override public void addCommand(Command command) { + add(command); + } + + public void add(Command command) { assertNotReadOnly(); this.commands.add(command); } @@ -1047,6 +1051,14 @@ public abstract class AbstractTransaction implements StrolchTransaction { return getActivitiesBy(refsP, assertExists); } + @Override + public void removeFromCache(Locator locator) { + if (this.resourceCache != null) + this.resourceCache.removeElement(locator.get(1), locator.get(2)); + if (this.objectFilter != null) + this.objectFilter.removeObjectCache(locator.get(0), locator); + } + @Override public Resource getCachedResource(String type, String id) { if (this.resourceCache == null) 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 23d49cf74..ab98cc726 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 @@ -445,6 +445,24 @@ public interface StrolchTransaction extends AutoCloseable { */ void addCommand(Command command); + /** + * Adds the given {@link Command} to the transaction. Using this method guarantees that a {@link Command} is + * executed properly: + *
      + *
    • {@link Command#validate()}
    • + *
    • {@link Command#doCommand()}
    • + *
    + * + * and if an exception occurs: + *
      + *
    • {@link Command#undo()}
    • + *
    + * + * @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.12 2.1 - 2.28.2 1.11.2 @@ -328,12 +327,6 @@ ${hamcrest.version} test - - org.mockito - mockito-core - ${mockito.version} - test -