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 396f8f50e..227e1abad 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 @@ -15,15 +15,11 @@ */ package li.strolch.model; -import java.util.Iterator; -import java.util.Map.Entry; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import java.util.Set; +import java.util.stream.Collectors; import li.strolch.exception.StrolchException; import li.strolch.model.activity.Activity; -import li.strolch.model.activity.IActivityElement; import li.strolch.utils.dbc.DBC; /** @@ -34,15 +30,14 @@ public enum State { CREATED("Created"), //$NON-NLS-1$ PLANNING("Planning"), //$NON-NLS-1$ PLANNED("Planned"), //$NON-NLS-1$ + STARTING("Starting"), //$NON-NLS-1$ EXECUTION("Execution"), //$NON-NLS-1$ - STOPPED("Stopped"), //$NON-NLS-1$ WARNING("Warning"), //$NON-NLS-1$ ERROR("Error"), //$NON-NLS-1$ + STOPPED("Stopped"), //$NON-NLS-1$ EXECUTED("Executed"), //$NON-NLS-1$ CLOSED("Closed"); //$NON-NLS-1$ - private static final Logger logger = LoggerFactory.getLogger(State.class); - private String state; private State(String state) { @@ -75,6 +70,13 @@ public enum State { return this == EXECUTION || this == STOPPED || this == WARNING || this == ERROR; } + /** + * @return true if the state is {@link #ERROR} or {@link #STOPPED} + */ + public boolean inErrorPhase() { + return this == State.ERROR || this == State.STOPPED; + } + /** * @return true if the state is one of {@link #STOPPED}, {@link #WARNING} or {@link #ERROR} */ @@ -86,7 +88,7 @@ public enum State { * @return true if the state is {@link #CLOSED} */ public boolean inClosedPhase() { - return this == CLOSED; + return this == EXECUTED || this == CLOSED; } /** @@ -117,6 +119,20 @@ public enum State { return this == State.EXECUTION; } + /** + * @return true if the state is {@link #WARNING} + */ + public boolean isInWarning() { + return this == State.WARNING; + } + + /** + * @return true if the state is {@link #ERROR} + */ + public boolean isInError() { + return this == State.ERROR; + } + /** * @return true if the state is {@link #EXECUTED} */ @@ -132,31 +148,31 @@ public enum State { } /** - * @return true if {@link #inExecutionPhase()} but not executed and not already in warning + * @return true if {@link #EXECUTION} */ public boolean canSetToWarning() { - return inExecutionPhase(); + return this == EXECUTION; } /** - * @return true if {@link #inExecutionPhase()} but not executed and not already stopped + * @return true if {@link #ERROR} */ public boolean canSetToStopped() { - return inExecutionPhase(); + return this == State.ERROR; } /** - * @return true if {@link #inExecutionPhase()} but not executed and not already in error + * @return true if {@link #STARTING} or {@link #EXECUTION} or {@link #WARNING} */ public boolean canSetToError() { - return inExecutionPhase(); + return this == State.STARTING || this == State.EXECUTION || this == State.WARNING; } /** - * @return true if {@link #inExecutionPhase()} but not executed + * @return true if {@link #EXECUTION} or {@link #WARNING} or {@link #STOPPED} */ public boolean canSetToExecuted() { - return inExecutionPhase(); + return this == State.EXECUTION || this == State.WARNING || this == State.STOPPED; } public static State parse(String s) { @@ -169,86 +185,49 @@ public enum State { throw new StrolchException("No State for " + s); } - public static State max(State state1, State state2) { - return state1.ordinal() >= state2.ordinal() ? state1 : state2; - } - - public static State min(State state1, State state2) { - return state1.ordinal() <= state2.ordinal() ? state1 : state2; - } - public static State getState(Activity activity) { - Iterator> elementIterator = activity.elementIterator(); + Set states = activity.elementStream().map(e -> e.getValue().getState()).collect(Collectors.toSet()); - IActivityElement first = elementIterator.next().getValue(); - State state = first.getState(); + // if only one state + if (states.size() == 1) + return states.iterator().next(); - while (elementIterator.hasNext()) { - IActivityElement child = elementIterator.next().getValue(); - State childState = child.getState(); + // error + if (states.contains(State.ERROR)) + return State.ERROR; - // error trumps all - if (childState == State.ERROR) { - state = State.ERROR; - break; - } + // stopped + if (states.contains(State.STOPPED)) + return State.STOPPED; - // then in execution warning - if (childState.inExecutionWarningPhase()) { - if (state.inExecutionWarningPhase()) - state = State.max(state, childState); - else - state = childState; - } + // warning + if (states.contains(State.WARNING)) + return State.WARNING; - // then execution - else if (childState.inExecutionPhase() || childState == State.EXECUTED) { - if (!state.inExecutionWarningPhase()) { - if (state.inExecutionPhase() || state == State.EXECUTED) - state = State.min(state, childState); - else - state = State.EXECUTION; - } - } + // execution + if (states.contains(State.EXECUTION) || states.contains(State.STARTING)) + return State.EXECUTION; + if (states.contains(State.EXECUTED) && (states.contains(State.CREATED) || states.contains(State.PLANNING) + || states.contains(State.PLANNED))) + return State.EXECUTION; - // then planning - else if (childState.inPlanningPhase()) { - if (state.inExecutionPhase() || state == State.EXECUTED) { - if (!state.inExecutionWarningPhase()) - state = State.EXECUTION; - } else { - if (state.inPlanningPhase()) - state = State.min(state, childState); - else if ((state.inClosedPhase() || state.inCreatedPhase()) && childState.inPlanningPhase()) - state = State.PLANNING; - } - } + // executed + if (states.contains(State.EXECUTED) && (states.contains(State.CLOSED))) + return State.EXECUTED; - // then created - else if (childState.inCreatedPhase()) { - if (state.inExecutionPhase() || state == State.EXECUTED) { - if (!state.inExecutionWarningPhase()) - state = State.EXECUTION; - } else { - if (state.inPlanningPhase()) { - state = State.PLANNING; - } - } - } + // planning + if (states.contains(State.PLANNING)) + return State.PLANNING; + if (states.contains(State.PLANNED) && (states.contains(State.CREATED) || states.contains(State.PLANNING))) + return State.PLANNING; - // then closed - else if (childState.inClosedPhase()) { - state = State.min(state, childState); - } + // planned + if (states.contains(State.PLANNED) && (states.contains(State.CLOSED))) + return State.PLANNED; - // should never occur - else { - logger.warn("Else case for getState() child: " + child.getLocator() + " childState: " + childState - + " state: " + state); - } - } - - return 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 f03b38f76..4d83c9e59 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 @@ -24,6 +24,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Optional; +import java.util.stream.Stream; import li.strolch.exception.StrolchException; import li.strolch.exception.StrolchModelException; @@ -324,6 +325,15 @@ public class Activity extends AbstractStrolchRootElement return this.elements.entrySet().iterator(); } + /** + * @return the stream for entries, which include the id as key and the {@link IActivityElement} as value + */ + public Stream> elementStream() { + if (this.elements == null) + return Collections. emptyMap().entrySet().stream(); + return this.elements.entrySet().stream(); + } + @Override public Long getStart() { Long start = Long.MAX_VALUE; diff --git a/li.strolch.model/src/test/java/li/strolch/model/activity/StateTest.java b/li.strolch.model/src/test/java/li/strolch/model/activity/StateTest.java index 367d153fa..2546474d9 100644 --- a/li.strolch.model/src/test/java/li/strolch/model/activity/StateTest.java +++ b/li.strolch.model/src/test/java/li/strolch/model/activity/StateTest.java @@ -312,8 +312,8 @@ public class StateTest { this.subAction.setState(State.STOPPED); this.subSubAction1.setState(State.WARNING); - assertEquals(State.WARNING, this.activity.getState()); - assertEquals(State.WARNING, this.subActivity.getState()); + assertEquals(State.STOPPED, this.activity.getState()); + assertEquals(State.STOPPED, this.subActivity.getState()); assertEquals(State.WARNING, this.subSubActivity.getState()); this.action.setState(State.STOPPED); @@ -397,8 +397,8 @@ public class StateTest { this.subSubAction1.setState(State.PLANNED); this.subSubAction2.setState(State.PLANNED); - assertEquals(State.PLANNING, this.activity.getState()); - assertEquals(State.PLANNING, this.subActivity.getState()); + assertEquals(State.PLANNED, this.activity.getState()); + assertEquals(State.PLANNED, this.subActivity.getState()); assertEquals(State.PLANNED, this.subSubActivity.getState()); } } 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 909caff72..e53cc9e05 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 @@ -117,15 +117,23 @@ public abstract class ExecutionPolicy extends StrolchPolicy { * @param action * the action to set to warning state */ - public void toWarning(Action action) { + public abstract void toWarning(Action action); - action.setState(State.WARNING); + protected void setActionState(Action action, State state) { + + action.setState(state); UpdateActivityCommand command = new UpdateActivityCommand(getContainer(), tx()); command.setActivity(action.getRootElement()); command.doCommand(); - logger.warn("Action " + action.getLocator() + " is now in WARNING!"); + String msg = "Action " + action.getLocator() + " is now in state " + state; + if (state == State.ERROR) + logger.error(msg); + else if (state == State.STOPPED) + logger.warn(msg); + else + logger.info(msg); } /** @@ -177,5 +185,4 @@ public abstract class ExecutionPolicy extends StrolchPolicy { protected void runAsAgent(PrivilegedRunnable runnable) throws PrivilegeException { getContainer().getPrivilegeHandler().runAs(StrolchConstants.SYSTEM_USER_AGENT, runnable); } - } 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 852f8cc07..aec0d79e0 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 @@ -1,7 +1,6 @@ package li.strolch.execution.policy; import li.strolch.agent.api.ComponentContainer; -import li.strolch.command.UpdateActivityCommand; import li.strolch.model.State; import li.strolch.model.activity.Action; import li.strolch.persistence.api.StrolchTransaction; @@ -19,11 +18,20 @@ public class SimpleExecution extends ExecutionPolicy { super(container, tx); } + protected void toStarting(Action action) { + setActionState(action, State.STARTING); + } + @Override public void toExecution(Action action) { setActionState(action, State.EXECUTION); } + @Override + public void toWarning(Action action) { + setActionState(action, State.WARNING); + } + @Override public void toExecuted(Action action) { setActionState(action, State.EXECUTED); @@ -41,23 +49,6 @@ public class SimpleExecution extends ExecutionPolicy { setActionState(action, State.ERROR); } - protected void setActionState(Action action, State state) { - - action.setState(state); - - UpdateActivityCommand command = new UpdateActivityCommand(getContainer(), tx()); - command.setActivity(action.getRootElement()); - command.doCommand(); - - String msg = "Action " + action.getLocator() + " is now in state " + state; - if (state == State.ERROR) - logger.error(msg); - else if (state == State.STOPPED) - logger.warn(msg); - else - logger.info(msg); - } - @Override public void undo() { logger.error("Can not undo execution policy " + getClass());