Merge branch 'feature/planning' into develop
This commit is contained in:
commit
c312f4b5b0
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
@ -416,13 +420,14 @@ public abstract class AbstractTransaction implements StrolchTransaction {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T extends StrolchElement> T findElement(Locator locator) throws StrolchException, ClassCastException {
|
||||
public <T extends StrolchElement> T findElement(Locator locator) throws StrolchModelException, ClassCastException {
|
||||
return findElement(locator, false);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T extends StrolchElement> T findElement(Locator locator, boolean allowNull) {
|
||||
public <T extends StrolchElement> T findElement(Locator locator, boolean allowNull)
|
||||
throws StrolchModelException, ClassCastException {
|
||||
|
||||
// Resource/<type>/<id>
|
||||
// Resource/<type>/<id>/Bag/<id>
|
||||
|
@ -435,7 +440,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<String> elements = locator.getPathElements();
|
||||
|
@ -454,14 +459,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 +483,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 +496,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 +504,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 +525,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 +538,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
|
||||
|
@ -1044,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)
|
||||
|
|
|
@ -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:
|
||||
* <ul>
|
||||
* <li>{@link Command#validate()}</li>
|
||||
* <li>{@link Command#doCommand()}</li>
|
||||
* </ul>
|
||||
*
|
||||
* and if an exception occurs:
|
||||
* <ul>
|
||||
* <li>{@link Command#undo()}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @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)}
|
||||
|
@ -534,11 +552,11 @@ public interface StrolchTransaction extends AutoCloseable {
|
|||
* Used to find a {@link StrolchElement} by a {@link Locator}, throwing exception if the element is not found
|
||||
* </p>
|
||||
*
|
||||
* @throws StrolchException
|
||||
* @throws StrolchModelException
|
||||
* if the element could not be found
|
||||
* @see #findElement(Locator, boolean)
|
||||
*/
|
||||
<T extends StrolchElement> T findElement(Locator locator) throws StrolchException, ClassCastException;
|
||||
<T extends StrolchElement> T findElement(Locator locator) throws StrolchModelException, ClassCastException;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
|
@ -565,14 +583,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 extends StrolchElement> T findElement(Locator locator, boolean allowNull)
|
||||
throws StrolchException, ClassCastException;
|
||||
throws StrolchModelException, ClassCastException;
|
||||
|
||||
/**
|
||||
* <p>Finds a parameter with the given @bagKey and @paramKey on the given @element, but if it does not exists
|
||||
|
@ -1361,6 +1379,14 @@ public interface StrolchTransaction extends AutoCloseable {
|
|||
List<Order> 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
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -304,11 +304,12 @@ public abstract class Command implements Restrictable {
|
|||
|
||||
/**
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
*/
|
||||
public abstract void undo();
|
||||
public void undo() {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
* Copyright 2015 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
*
|
||||
* 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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
* Copyright 2015 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
*
|
||||
* 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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
* Copyright 2015 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
*
|
||||
* 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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,24 @@ 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 #STOPPED}
|
||||
*/
|
||||
public boolean canSetToExecution() {
|
||||
return this == CREATED || this == PLANNING || this == PLANNED || this == EXECUTION || this == State.STOPPED;
|
||||
public boolean canSetToExecutable() {
|
||||
return this == PLANNED || this == EXECUTABLE || this == State.STOPPED;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if {@link #PLANNED} or {@link #EXECUTABLE} or {@link #EXECUTION}
|
||||
*/
|
||||
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 +264,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 +290,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(", ")));
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
@ -381,6 +382,29 @@ public class Activity extends AbstractStrolchRootElement
|
|||
}
|
||||
}
|
||||
|
||||
public <T extends IActivityElement> 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);
|
||||
if (element == null)
|
||||
throw new StrolchElementNotFoundException(locator + " does not exist!");
|
||||
}
|
||||
|
||||
@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
|
||||
*/
|
||||
|
@ -449,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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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.setActivityLoc(activity.getLocator());
|
||||
tx.addCommand(command);
|
||||
}
|
||||
});
|
||||
|
||||
tx.commitOnClose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +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.ResourceBundle;
|
||||
|
||||
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.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<Locator, ExecutionPolicy> inExecution;
|
||||
|
||||
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 = Collections.synchronizedMap(new HashMap<>());
|
||||
}
|
||||
|
||||
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 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(this.realm, cert, getClass(), false);
|
||||
}
|
||||
|
||||
protected void runAsAgent(PrivilegedRunnable runnable) throws PrivilegeException, Exception {
|
||||
this.executionHandler.runAsAgent(runnable);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
|
@ -1,15 +1,16 @@
|
|||
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;
|
||||
|
||||
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.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;
|
||||
|
@ -17,16 +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.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.dbc.DBC;
|
||||
import li.strolch.utils.collections.MapOfMaps;
|
||||
|
||||
/**
|
||||
* The event based execution handler waits for events in that the {@link ExecutionPolicy} implementations must call the
|
||||
|
@ -36,11 +33,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<String, ExecutionHandlerState> statesByRealm;
|
||||
private MapOfSets<String, Locator> registeredActivities;
|
||||
private MapOfMaps<String, Locator, Controller> controllers;
|
||||
|
||||
private DelayedExecutionTimer delayedExecutionTimer;
|
||||
|
||||
|
@ -48,11 +44,29 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
|
|||
super(container, componentName);
|
||||
}
|
||||
|
||||
@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
|
||||
public Set<Locator> getActiveActivitiesLocator(String realm) {
|
||||
if (this.controllers == null)
|
||||
return emptySet();
|
||||
Map<Locator, Controller> 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);
|
||||
}
|
||||
|
||||
|
@ -86,66 +100,46 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Set<Locator> 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) {
|
||||
|
||||
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!");
|
||||
|
||||
Locator rootElemLoc = activity.getLocator();
|
||||
synchronized (this.registeredActivities) {
|
||||
this.registeredActivities.addElement(realm, rootElemLoc);
|
||||
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);
|
||||
}
|
||||
|
||||
notifyObserverAdd(realm, activity);
|
||||
toExecution(realm, rootElemLoc);
|
||||
toExecution(controller);
|
||||
}
|
||||
|
||||
@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);
|
||||
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));
|
||||
}
|
||||
|
||||
getExecutor().submit(() -> notifyObserverAdd(realm, activityLoc));
|
||||
toExecution(realm, activityLoc);
|
||||
}
|
||||
|
||||
@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(controller));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearAllCurrentExecutions(String realm) {
|
||||
Set<Locator> removed = this.registeredActivities.removeSet(realm);
|
||||
Map<Locator, Controller> 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 +174,8 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
|
|||
tx.update(activity);
|
||||
|
||||
// register for execution
|
||||
this.registeredActivities.addElement(realmName, activity.getLocator());
|
||||
Controller controller = new Controller(realmName, this, activity);
|
||||
this.controllers.addElement(realmName, activity.getLocator(), controller);
|
||||
});
|
||||
|
||||
// commit changes to state
|
||||
|
@ -200,12 +195,12 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
|
|||
return;
|
||||
}
|
||||
|
||||
synchronized (this.registeredActivities) {
|
||||
Set<Locator> locators = this.registeredActivities.getSet(realm);
|
||||
if (locators != null) {
|
||||
for (Locator locator : locators) {
|
||||
synchronized (this.controllers) {
|
||||
Map<Locator, Controller> controllers = this.controllers.getMap(realm);
|
||||
if (controllers != null) {
|
||||
for (Controller controller : controllers.values()) {
|
||||
// execute async
|
||||
toExecution(realm, locator);
|
||||
toExecution(controller);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -282,24 +277,26 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toExecution(String realm, Locator locator) {
|
||||
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 " + locator + " 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, locator, ctx));
|
||||
controller.execute();
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to set " + locator + " to execution due to " + e.getMessage(), 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, locator, 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));
|
||||
}
|
||||
|
@ -307,17 +304,15 @@ 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);
|
||||
});
|
||||
|
||||
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);
|
||||
|
||||
|
@ -335,9 +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);
|
||||
|
||||
|
@ -355,9 +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);
|
||||
|
||||
|
@ -375,9 +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);
|
||||
|
||||
|
@ -392,42 +393,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));
|
||||
}
|
||||
|
@ -435,255 +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, 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) {
|
||||
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, Activity rootElement) {
|
||||
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, Activity rootElement) {
|
||||
if (!getContainer().getRealm(tx.getRealmName()).isUpdateObservers())
|
||||
private void notifyObserverRemove(String realmName, Map<Locator, Controller> 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, 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.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, Set<Locator> activityLocs) {
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
|
@ -11,8 +12,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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
|
@ -21,7 +25,7 @@ import li.strolch.privilege.model.PrivilegeContext;
|
|||
*
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
|
@ -41,16 +45,41 @@ public abstract class ExecutionHandler extends StrolchComponent {
|
|||
|
||||
public static final String PARAM_STATE = "state";
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given {@link Locator} of an {@link Activity} for execution, and submits it for execution
|
||||
* immediately in an asynchronous manner
|
||||
* Returns the controller for the given realm and activity, null if it does not exist
|
||||
*
|
||||
* @param realm
|
||||
* the realm where the {@link Activity} resides
|
||||
* @param activityLoc
|
||||
* the {@link Locator} of the {@link Activity}
|
||||
* 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 void addForExecution(String realm, Locator activityLoc);
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -126,10 +163,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
|
||||
|
@ -148,24 +185,14 @@ public abstract class ExecutionHandler extends StrolchComponent {
|
|||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
* </p>
|
||||
*
|
||||
* @return the {@link DelayedExecutionTimer}
|
||||
*/
|
||||
public abstract DelayedExecutionTimer getDelayedExecutionTimer();
|
||||
|
||||
/**
|
||||
* Starts the execution of the given {@link Activity} with the given {@link Locator}
|
||||
*
|
||||
* @param realm
|
||||
* the realm where the {@link Activity} resides
|
||||
* @param activityLoc
|
||||
* the {@link Locator} of the {@link Activity}
|
||||
*/
|
||||
public abstract void toExecution(String realm, Locator activityLoc);
|
||||
|
||||
/**
|
||||
* Completes the execution of the given {@link Action} with the given {@link Locator}
|
||||
*
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
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.service.api.Command;
|
||||
import li.strolch.utils.dbc.DBC;
|
||||
|
||||
public class ArchiveActivityCommand extends Command {
|
||||
|
||||
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() {
|
||||
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 = activity.getPolicyDef(ActivityArchivalPolicy.class, DEFAULT_ACTIVITY_ARCHIVAL);
|
||||
ActivityArchivalPolicy archivalPolicy = tx().getPolicy(policyDef);
|
||||
archivalPolicy.archive(activity);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -1,42 +1,186 @@
|
|||
package li.strolch.execution.command;
|
||||
|
||||
import li.strolch.agent.api.ComponentContainer;
|
||||
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<Void> {
|
||||
|
||||
private Activity activity;
|
||||
private Controller controller;
|
||||
private boolean needsRetriggerOfExecution;
|
||||
|
||||
public ExecuteActivityCommand(ComponentContainer container, StrolchTransaction tx) {
|
||||
super(container, tx);
|
||||
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);
|
||||
tx().lock(this.activity.getRootElement());
|
||||
DBC.PRE.assertNotNull("controller can not be null!", this.controller);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doCommand() {
|
||||
Activity rootElement = this.activity.getRootElement();
|
||||
tx().lock(rootElement);
|
||||
|
||||
State currentState = rootElement.getState();
|
||||
this.activity.accept(this);
|
||||
|
||||
updateOrderState(tx(), rootElement, currentState, rootElement.getState());
|
||||
Activity activity = this.controller.getActivity();
|
||||
State currentState = activity.getState();
|
||||
activity.accept(this);
|
||||
updateOrderState(tx(), activity, currentState, activity.getState());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo() {
|
||||
// can't undo execution
|
||||
public Void visitAction(Action action) {
|
||||
execute(action);
|
||||
return null;
|
||||
}
|
||||
|
||||
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<Entry<String, IActivityElement>> 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<Entry<String, IActivityElement>> 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
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;
|
||||
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(ComponentContainer container, StrolchTransaction tx) {
|
||||
super(container, 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());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo() {
|
||||
// can't undo execution
|
||||
}
|
||||
}
|
|
@ -1,209 +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.agent.api.ComponentContainer;
|
||||
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<Void> {
|
||||
|
||||
public ExecutionCommand(ComponentContainer container, StrolchTransaction tx) {
|
||||
super(container, 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<Entry<String, IActivityElement>> 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<Entry<String, IActivityElement>> 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;
|
||||
}
|
||||
}
|
|
@ -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 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,22 +23,16 @@ import li.strolch.model.activity.Activity;
|
|||
import li.strolch.model.activity.IActivityElement;
|
||||
import li.strolch.model.visitor.IActivityElementVisitor;
|
||||
import li.strolch.persistence.api.StrolchTransaction;
|
||||
import li.strolch.service.api.Command;
|
||||
|
||||
/**
|
||||
* @author Martin Smock <martin.smock@bluewin.ch>
|
||||
*/
|
||||
public abstract class PlanningCommand extends Command implements IActivityElementVisitor<Void> {
|
||||
public abstract class PlanningCommand extends BasePlanningAndExecutionCommand implements IActivityElementVisitor<Void> {
|
||||
|
||||
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)
|
||||
|
|
|
@ -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;
|
||||
|
@ -10,12 +9,12 @@ 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;
|
||||
|
||||
public SetActionToClosedCommand(ComponentContainer container, StrolchTransaction tx) {
|
||||
super(container, tx);
|
||||
public SetActionToClosedCommand(StrolchTransaction tx) {
|
||||
super(tx);
|
||||
}
|
||||
|
||||
public void setAction(Action action) {
|
||||
|
@ -26,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());
|
||||
|
@ -38,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);
|
||||
|
@ -55,9 +48,4 @@ public class SetActionToClosedCommand extends ExecutionCommand {
|
|||
|
||||
updateOrderState(tx(), rootElement, currentState, rootElement.getState());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo() {
|
||||
// can not undo
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -10,12 +9,12 @@ 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;
|
||||
|
||||
public SetActionToCreatedCommand(ComponentContainer container, StrolchTransaction tx) {
|
||||
super(container, tx);
|
||||
public SetActionToCreatedCommand(StrolchTransaction tx) {
|
||||
super(tx);
|
||||
}
|
||||
|
||||
public void setAction(Action action) {
|
||||
|
@ -26,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());
|
||||
|
@ -38,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);
|
||||
|
@ -55,9 +48,4 @@ public class SetActionToCreatedCommand extends ExecutionCommand {
|
|||
|
||||
updateOrderState(tx(), rootElement, currentState, rootElement.getState());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo() {
|
||||
// can not undo
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,32 +2,20 @@ 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;
|
||||
import li.strolch.model.activity.Activity;
|
||||
import li.strolch.persistence.api.StrolchTransaction;
|
||||
import li.strolch.utils.dbc.DBC;
|
||||
|
||||
public class SetActionToErrorCommand extends ExecutionCommand {
|
||||
public class SetActionToErrorCommand extends ActionExecutionCommand {
|
||||
|
||||
private Action action;
|
||||
|
||||
public SetActionToErrorCommand(ComponentContainer container, StrolchTransaction tx) {
|
||||
super(container, tx);
|
||||
}
|
||||
|
||||
public void setAction(Action action) {
|
||||
this.action = action;
|
||||
public SetActionToErrorCommand(StrolchTransaction tx) {
|
||||
super(tx);
|
||||
}
|
||||
|
||||
@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}";
|
||||
|
@ -38,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);
|
||||
|
@ -54,9 +39,4 @@ public class SetActionToErrorCommand extends ExecutionCommand {
|
|||
|
||||
updateOrderState(tx(), rootElement, currentState, rootElement.getState());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo() {
|
||||
// can not undo
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -2,32 +2,20 @@ 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;
|
||||
import li.strolch.model.activity.Activity;
|
||||
import li.strolch.persistence.api.StrolchTransaction;
|
||||
import li.strolch.utils.dbc.DBC;
|
||||
|
||||
public class SetActionToExecutedCommand extends ExecutionCommand {
|
||||
public class SetActionToExecutedCommand extends ActionExecutionCommand {
|
||||
|
||||
private Action action;
|
||||
|
||||
public SetActionToExecutedCommand(ComponentContainer container, StrolchTransaction tx) {
|
||||
super(container, tx);
|
||||
}
|
||||
|
||||
public void setAction(Action action) {
|
||||
this.action = action;
|
||||
public SetActionToExecutedCommand(StrolchTransaction tx) {
|
||||
super(tx);
|
||||
}
|
||||
|
||||
@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}";
|
||||
|
@ -38,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);
|
||||
|
@ -54,9 +39,4 @@ public class SetActionToExecutedCommand extends ExecutionCommand {
|
|||
|
||||
updateOrderState(tx(), rootElement, currentState, rootElement.getState());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo() {
|
||||
// can not undo
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -10,12 +9,12 @@ 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;
|
||||
|
||||
public SetActionToPlannedCommand(ComponentContainer container, StrolchTransaction tx) {
|
||||
super(container, tx);
|
||||
public SetActionToPlannedCommand(StrolchTransaction tx) {
|
||||
super(tx);
|
||||
}
|
||||
|
||||
public void setAction(Action action) {
|
||||
|
@ -26,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());
|
||||
|
@ -38,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);
|
||||
|
@ -55,9 +48,4 @@ public class SetActionToPlannedCommand extends ExecutionCommand {
|
|||
|
||||
updateOrderState(tx(), rootElement, currentState, rootElement.getState());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo() {
|
||||
// can not undo
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
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;
|
||||
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(ComponentContainer container, StrolchTransaction tx) {
|
||||
super(container, 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());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo() {
|
||||
// can not undo
|
||||
}
|
||||
}
|
|
@ -2,32 +2,20 @@ 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;
|
||||
import li.strolch.model.activity.Activity;
|
||||
import li.strolch.persistence.api.StrolchTransaction;
|
||||
import li.strolch.utils.dbc.DBC;
|
||||
|
||||
public class SetActionToStoppedCommand extends ExecutionCommand {
|
||||
public class SetActionToStoppedCommand extends ActionExecutionCommand {
|
||||
|
||||
private Action action;
|
||||
|
||||
public SetActionToStoppedCommand(ComponentContainer container, StrolchTransaction tx) {
|
||||
super(container, tx);
|
||||
}
|
||||
|
||||
public void setAction(Action action) {
|
||||
this.action = action;
|
||||
public SetActionToStoppedCommand(StrolchTransaction tx) {
|
||||
super(tx);
|
||||
}
|
||||
|
||||
@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}";
|
||||
|
@ -38,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);
|
||||
|
@ -54,9 +39,4 @@ public class SetActionToStoppedCommand extends ExecutionCommand {
|
|||
|
||||
updateOrderState(tx(), rootElement, currentState, rootElement.getState());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo() {
|
||||
// can not undo
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,32 +2,20 @@ 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;
|
||||
import li.strolch.model.activity.Activity;
|
||||
import li.strolch.persistence.api.StrolchTransaction;
|
||||
import li.strolch.utils.dbc.DBC;
|
||||
|
||||
public class SetActionToWarningCommand extends ExecutionCommand {
|
||||
public class SetActionToWarningCommand extends ActionExecutionCommand {
|
||||
|
||||
private Action action;
|
||||
|
||||
public SetActionToWarningCommand(ComponentContainer container, StrolchTransaction tx) {
|
||||
super(container, tx);
|
||||
}
|
||||
|
||||
public void setAction(Action action) {
|
||||
this.action = action;
|
||||
public SetActionToWarningCommand(StrolchTransaction tx) {
|
||||
super(tx);
|
||||
}
|
||||
|
||||
@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}";
|
||||
|
@ -38,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);
|
||||
|
@ -54,9 +39,4 @@ public class SetActionToWarningCommand extends ExecutionCommand {
|
|||
|
||||
updateOrderState(tx(), rootElement, currentState, rootElement.getState());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo() {
|
||||
// can not undo
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -52,8 +52,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(
|
||||
|
@ -66,55 +67,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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,8 +29,6 @@ public class ToErrorReservationExecution extends ReservationExecution {
|
|||
@Override
|
||||
public boolean isExecutable(Action action) {
|
||||
|
||||
tx().lock(getResource(action));
|
||||
|
||||
if (action.getType().equals(TYPE_RESERVE)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -41,14 +39,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);
|
||||
}
|
||||
|
|
|
@ -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<LocatorArgument, ServiceResult> {
|
||||
public class ExecuteActionService extends AbstractService<LocatorArgument, ServiceResult> {
|
||||
|
||||
@Override
|
||||
protected ServiceResult getResultInstance() {
|
||||
|
@ -23,17 +25,27 @@ public class SetActionToPlanningService extends AbstractService<LocatorArgument,
|
|||
@Override
|
||||
protected ServiceResult internalDoService(LocatorArgument arg) throws Exception {
|
||||
|
||||
String realm;
|
||||
Activity activity;
|
||||
try (StrolchTransaction tx = openArgOrUserTx(arg)) {
|
||||
realm = tx.getRealmName();
|
||||
|
||||
tx.lock(arg.locator.trim(3));
|
||||
Action action = tx.findElement(arg.locator);
|
||||
|
||||
SetActionToPlanningCommand command = new SetActionToPlanningCommand(getContainer(), tx);
|
||||
command.setAction(action);
|
||||
tx.addCommand(command);
|
||||
// this is so we can re-execute stopped actions
|
||||
if (action.getState() == State.STOPPED) {
|
||||
action.setState(State.EXECUTABLE);
|
||||
|
||||
tx.commitOnClose();
|
||||
tx.update(action.getRootElement());
|
||||
tx.commitOnClose();
|
||||
}
|
||||
|
||||
activity = action.getRootElement();
|
||||
}
|
||||
|
||||
getComponent(ExecutionHandler.class).toExecution(realm, activity);
|
||||
|
||||
return ServiceResult.success();
|
||||
}
|
||||
}
|
|
@ -1,144 +0,0 @@
|
|||
package li.strolch.execution.service;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import li.strolch.exception.StrolchException;
|
||||
import li.strolch.execution.ExecutionHandler;
|
||||
import li.strolch.execution.command.*;
|
||||
import li.strolch.model.Locator;
|
||||
import li.strolch.model.State;
|
||||
import li.strolch.model.activity.Action;
|
||||
import li.strolch.model.activity.IActivityElement;
|
||||
import li.strolch.persistence.api.StrolchTransaction;
|
||||
import li.strolch.service.StringMapArgument;
|
||||
import li.strolch.service.api.AbstractService;
|
||||
import li.strolch.service.api.ServiceResult;
|
||||
import li.strolch.service.api.ServiceResultState;
|
||||
|
||||
public class SetActionStateService extends AbstractService<StringMapArgument, ServiceResult> {
|
||||
|
||||
@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(getContainer(), tx);
|
||||
command.setAction(action);
|
||||
tx.addCommand(command);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PLANNING: {
|
||||
|
||||
SetActionToPlanningCommand command = new SetActionToPlanningCommand(getContainer(), tx);
|
||||
command.setAction(action);
|
||||
tx.addCommand(command);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PLANNED: {
|
||||
|
||||
SetActionToPlannedCommand command = new SetActionToPlannedCommand(getContainer(), tx);
|
||||
command.setAction(action);
|
||||
tx.addCommand(command);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case EXECUTION: {
|
||||
|
||||
tx.lock(locator);
|
||||
|
||||
IActivityElement element = tx.findElement(locator);
|
||||
if (!element.getState().canSetToExecution()) {
|
||||
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(getContainer(), tx);
|
||||
command.setAction(action);
|
||||
tx.addCommand(command);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ERROR: {
|
||||
|
||||
SetActionToErrorCommand command = new SetActionToErrorCommand(getContainer(), tx);
|
||||
command.setAction(action);
|
||||
tx.addCommand(command);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case STOPPED: {
|
||||
|
||||
SetActionToStoppedCommand command = new SetActionToStoppedCommand(getContainer(), tx);
|
||||
command.setAction(action);
|
||||
tx.addCommand(command);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case EXECUTED: {
|
||||
|
||||
SetActionToExecutedCommand command = new SetActionToExecutedCommand(getContainer(), tx);
|
||||
command.setAction(action);
|
||||
tx.addCommand(command);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CLOSED: {
|
||||
|
||||
SetActionToClosedCommand command = new SetActionToClosedCommand(getContainer(), 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();
|
||||
}
|
||||
}
|
|
@ -25,9 +25,11 @@ public class SetActionToClosedService extends AbstractService<LocatorArgument, S
|
|||
|
||||
try (StrolchTransaction tx = openArgOrUserTx(arg)) {
|
||||
|
||||
tx.lock(arg.locator.trim(3));
|
||||
Action action = tx.findElement(arg.locator);
|
||||
tx.lock(action.getResourceLocator());
|
||||
|
||||
SetActionToClosedCommand command = new SetActionToClosedCommand(getContainer(), tx);
|
||||
SetActionToClosedCommand command = new SetActionToClosedCommand(tx);
|
||||
command.setAction(action);
|
||||
tx.addCommand(command);
|
||||
|
||||
|
|
|
@ -25,9 +25,12 @@ public class SetActionToCreatedService extends AbstractService<LocatorArgument,
|
|||
|
||||
try (StrolchTransaction tx = openArgOrUserTx(arg)) {
|
||||
|
||||
tx.lock(arg.locator.trim(3));
|
||||
Action action = tx.findElement(arg.locator);
|
||||
if (action.hasResourceDefined())
|
||||
tx.lock(action.getResourceLocator());
|
||||
|
||||
SetActionToCreatedCommand command = new SetActionToCreatedCommand(getContainer(), tx);
|
||||
SetActionToCreatedCommand command = new SetActionToCreatedCommand(tx);
|
||||
command.setAction(action);
|
||||
tx.addCommand(command);
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package li.strolch.execution.service;
|
||||
|
||||
import li.strolch.execution.Controller;
|
||||
import li.strolch.execution.ExecutionHandler;
|
||||
import li.strolch.execution.command.SetActionToErrorCommand;
|
||||
import li.strolch.model.activity.Action;
|
||||
import li.strolch.persistence.api.StrolchTransaction;
|
||||
|
@ -25,11 +27,20 @@ public class SetActionToErrorService extends AbstractService<LocatorArgument, Se
|
|||
|
||||
try (StrolchTransaction tx = openArgOrUserTx(arg)) {
|
||||
|
||||
tx.lock(arg.locator.trim(3));
|
||||
Action action = tx.findElement(arg.locator);
|
||||
tx.lock(action.getResourceLocator());
|
||||
|
||||
SetActionToErrorCommand command = new SetActionToErrorCommand(getContainer(), tx);
|
||||
command.setAction(action);
|
||||
tx.addCommand(command);
|
||||
ExecutionHandler executionHandler = getComponent(ExecutionHandler.class);
|
||||
Controller controller = executionHandler.getController(tx.getRealmName(), action.getRootElement());
|
||||
if (controller != null) {
|
||||
controller.toError(action.getLocator());
|
||||
} else {
|
||||
|
||||
SetActionToErrorCommand command = new SetActionToErrorCommand(tx);
|
||||
command.setAction(action);
|
||||
tx.addCommand(command);
|
||||
}
|
||||
|
||||
tx.commitOnClose();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package li.strolch.execution.service;
|
||||
|
||||
import li.strolch.execution.Controller;
|
||||
import li.strolch.execution.ExecutionHandler;
|
||||
import li.strolch.execution.command.SetActionToExecutedCommand;
|
||||
import li.strolch.model.activity.Action;
|
||||
import li.strolch.persistence.api.StrolchTransaction;
|
||||
|
@ -25,11 +27,19 @@ public class SetActionToExecutedService extends AbstractService<LocatorArgument,
|
|||
|
||||
try (StrolchTransaction tx = openArgOrUserTx(arg)) {
|
||||
|
||||
tx.lock(arg.locator.trim(3));
|
||||
Action action = tx.findElement(arg.locator);
|
||||
tx.lock(action.getResourceLocator());
|
||||
|
||||
SetActionToExecutedCommand command = new SetActionToExecutedCommand(getContainer(), tx);
|
||||
command.setAction(action);
|
||||
tx.addCommand(command);
|
||||
ExecutionHandler executionHandler = getComponent(ExecutionHandler.class);
|
||||
Controller controller = executionHandler.getController(tx.getRealmName(), action.getRootElement());
|
||||
if (controller != null) {
|
||||
controller.toExecuted(action.getLocator());
|
||||
} else {
|
||||
SetActionToExecutedCommand command = new SetActionToExecutedCommand(tx);
|
||||
command.setAction(action);
|
||||
tx.addCommand(command);
|
||||
}
|
||||
|
||||
tx.commitOnClose();
|
||||
}
|
||||
|
|
|
@ -25,9 +25,12 @@ public class SetActionToPlannedService extends AbstractService<LocatorArgument,
|
|||
|
||||
try (StrolchTransaction tx = openArgOrUserTx(arg)) {
|
||||
|
||||
tx.lock(arg.locator.trim(3));
|
||||
Action action = tx.findElement(arg.locator);
|
||||
if (!action.hasResourceDefined())
|
||||
return ServiceResult.error("Resource not defined for " + action.getLocator());
|
||||
|
||||
SetActionToPlannedCommand command = new SetActionToPlannedCommand(getContainer(), tx);
|
||||
SetActionToPlannedCommand command = new SetActionToPlannedCommand(tx);
|
||||
command.setAction(action);
|
||||
tx.addCommand(command);
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package li.strolch.execution.service;
|
||||
|
||||
import li.strolch.execution.Controller;
|
||||
import li.strolch.execution.ExecutionHandler;
|
||||
import li.strolch.execution.command.SetActionToStoppedCommand;
|
||||
import li.strolch.model.activity.Action;
|
||||
import li.strolch.persistence.api.StrolchTransaction;
|
||||
|
@ -25,11 +27,19 @@ public class SetActionToStoppedService extends AbstractService<LocatorArgument,
|
|||
|
||||
try (StrolchTransaction tx = openArgOrUserTx(arg)) {
|
||||
|
||||
tx.lock(arg.locator.trim(3));
|
||||
Action action = tx.findElement(arg.locator);
|
||||
tx.lock(action.getResourceLocator());
|
||||
|
||||
SetActionToStoppedCommand command = new SetActionToStoppedCommand(getContainer(), tx);
|
||||
command.setAction(action);
|
||||
tx.addCommand(command);
|
||||
ExecutionHandler executionHandler = getComponent(ExecutionHandler.class);
|
||||
Controller controller = executionHandler.getController(tx.getRealmName(), action.getRootElement());
|
||||
if (controller != null) {
|
||||
controller.toStopped(action.getLocator());
|
||||
} else {
|
||||
SetActionToStoppedCommand command = new SetActionToStoppedCommand(tx);
|
||||
command.setAction(action);
|
||||
tx.addCommand(command);
|
||||
}
|
||||
|
||||
tx.commitOnClose();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package li.strolch.execution.service;
|
||||
|
||||
import li.strolch.execution.Controller;
|
||||
import li.strolch.execution.ExecutionHandler;
|
||||
import li.strolch.execution.command.SetActionToWarningCommand;
|
||||
import li.strolch.model.activity.Action;
|
||||
import li.strolch.persistence.api.StrolchTransaction;
|
||||
|
@ -25,11 +27,19 @@ public class SetActionToWarningService extends AbstractService<LocatorArgument,
|
|||
|
||||
try (StrolchTransaction tx = openArgOrUserTx(arg)) {
|
||||
|
||||
tx.lock(arg.locator.trim(3));
|
||||
Action action = tx.findElement(arg.locator);
|
||||
tx.lock(action.getResourceLocator());
|
||||
|
||||
SetActionToWarningCommand command = new SetActionToWarningCommand(getContainer(), tx);
|
||||
command.setAction(action);
|
||||
tx.addCommand(command);
|
||||
ExecutionHandler executionHandler = getComponent(ExecutionHandler.class);
|
||||
Controller controller = executionHandler.getController(tx.getRealmName(), action.getRootElement());
|
||||
if (controller != null) {
|
||||
controller.toWarning(action.getLocator());
|
||||
} else {
|
||||
SetActionToWarningCommand command = new SetActionToWarningCommand(tx);
|
||||
command.setAction(action);
|
||||
tx.addCommand(command);
|
||||
}
|
||||
|
||||
tx.commitOnClose();
|
||||
}
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
package li.strolch.execution.service;
|
||||
|
||||
import static li.strolch.utils.helper.StringHelper.isEmpty;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import li.strolch.exception.StrolchException;
|
||||
import li.strolch.execution.ExecutionHandler;
|
||||
import li.strolch.model.State;
|
||||
import li.strolch.model.activity.IActivityElement;
|
||||
import li.strolch.persistence.api.StrolchTransaction;
|
||||
import li.strolch.runtime.StrolchConstants;
|
||||
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 SetToExecutionService extends AbstractService<LocatorArgument, ServiceResult> {
|
||||
|
||||
@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;
|
||||
|
||||
try (StrolchTransaction tx = openTx(realm)) {
|
||||
tx.lock(arg.locator);
|
||||
|
||||
IActivityElement element = tx.findElement(arg.locator);
|
||||
if (!element.getState().canSetToExecution()) {
|
||||
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(realm, arg.locator);
|
||||
}
|
||||
|
||||
return ServiceResult.success();
|
||||
}
|
||||
}
|
|
@ -4,6 +4,8 @@ import static li.strolch.service.I18nService.i18nService;
|
|||
|
||||
import li.strolch.execution.ExecutionHandler;
|
||||
import li.strolch.execution.ExecutionHandlerState;
|
||||
import li.strolch.model.activity.Activity;
|
||||
import li.strolch.persistence.api.StrolchTransaction;
|
||||
import li.strolch.runtime.StrolchConstants;
|
||||
import li.strolch.service.LocatorArgument;
|
||||
import li.strolch.service.StrolchRootElementResult;
|
||||
|
@ -36,7 +38,12 @@ public class StartActivityExecutionService extends AbstractService<LocatorArgume
|
|||
"ExecutionHandler is not running, can not start new jobs!")
|
||||
.i18n(i18nService, "execution.handler.invalidState", "state", executionHandlerState);
|
||||
|
||||
executionHandler.addForExecution(realm, arg.locator);
|
||||
Activity activity;
|
||||
try (StrolchTransaction tx = openTx(realm, true)) {
|
||||
activity = tx.getActivityBy(arg.locator.get(1), arg.locator.get(2), true);
|
||||
}
|
||||
|
||||
executionHandler.toExecution(realm, activity);
|
||||
|
||||
return ServiceResult.success();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
execution.handler.invalidState=ExecutionHandler has state {state}, can not start new jobs!
|
||||
execution.handler.failed.execution=Failed to set to execution due to {reason}
|
||||
execution.handler.failed.executed=Failed to set to execution due to {reason}
|
||||
execution.handler.failed.executed=Failed to set to executed due to {reason}
|
||||
execution.handler.failed.stopped=Failed to set to execution due to {reason}
|
||||
execution.handler.failed.error=Failed to set to execution due to {reason}
|
||||
execution.handler.failed.warning=Failed to set to execution due to {reason}
|
||||
|
|
|
@ -23,9 +23,13 @@ import li.strolch.testbase.runtime.RuntimeMock;
|
|||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ReservationExecutionTest extends RuntimeMock {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ReservationExecutionTest.class);
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
mockRuntime(new File("target/" + ReservationExecutionTest.class.getName()),
|
||||
|
@ -83,6 +87,7 @@ public class ReservationExecutionTest extends RuntimeMock {
|
|||
// verify that the machine is not reserved
|
||||
Resource machine = tx.getResourceBy("Machine", "machine1");
|
||||
BooleanParameter reservedP = machine.getParameter(BAG_PARAMETERS, PARAM_RESERVED);
|
||||
logger.info("Checking machine is not reserved initially");
|
||||
assertFalse(reservedP.getValue());
|
||||
}
|
||||
|
||||
|
@ -105,6 +110,7 @@ public class ReservationExecutionTest extends RuntimeMock {
|
|||
// verify that the machine is reserved
|
||||
Resource machine = tx.getResourceBy("Machine", "machine1");
|
||||
BooleanParameter reservedP = machine.getParameter(BAG_PARAMETERS, PARAM_RESERVED);
|
||||
logger.info("Checking machine is reserved, after reserve action is executed.");
|
||||
assertTrue(reservedP.getValue());
|
||||
}
|
||||
|
||||
|
@ -120,6 +126,7 @@ public class ReservationExecutionTest extends RuntimeMock {
|
|||
// verify that the machine is not reserved anymore
|
||||
Resource machine = tx.getResourceBy("Machine", "machine1");
|
||||
BooleanParameter reservedP = machine.getParameter(BAG_PARAMETERS, PARAM_RESERVED);
|
||||
logger.info("Checking machine is released, after release action is executed.");
|
||||
assertFalse(reservedP.getValue());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,10 @@ public class SynchronizedCollections {
|
|||
@Override
|
||||
public List<U> getList(T t) {
|
||||
synchronized (this.mutex) {
|
||||
return new SynchronizedList<>(this.m.getList(t), this.mutex);
|
||||
List<U> 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<U, V> getMap(T t) {
|
||||
synchronized (this.mutex) {
|
||||
return new SynchronizedMap<>(this.m.getMap(t), this.mutex);
|
||||
Map<U, V> 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<U> getSet(T t) {
|
||||
synchronized (this.mutex) {
|
||||
return new SynchronizedSet<>(this.m.getSet(t), this.mutex);
|
||||
Set<U> set = this.m.getSet(t);
|
||||
if (set == null)
|
||||
return null;
|
||||
return new SynchronizedSet<>(set, this.mutex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<li><a href="index.html">Overview</a></li>
|
||||
<li class="active"><a href="api.html">API</a></li>
|
||||
<li><a href="documentation.html">Documentation</a></li>
|
||||
<li><a href="plc.html">PLC</a></li>
|
||||
<li><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="downloads.html">Downloads</a></li>
|
||||
<li><a href="development.html">Development</a></li>
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="api.html">API</a></li>
|
||||
<li><a href="documentation.html">Documentation</a></li>
|
||||
<li><a href="plc.html">PLC</a></li>
|
||||
<li><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="downloads.html">Downloads</a></li>
|
||||
<li><a href="development.html">Development</a></li>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="api.html">API</a></li>
|
||||
<li><a href="documentation.html">Documentation</a></li>
|
||||
<li><a href="plc.html">PLC</a></li>
|
||||
<li><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="downloads.html">Downloads</a></li>
|
||||
<li class="active"><a href="development.html">Development</a></li>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="api.html">API</a></li>
|
||||
<li class="active"><a href="documentation.html">Documentation</a></li>
|
||||
<li><a href="plc.html">PLC</a></li>
|
||||
<li><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="downloads.html">Downloads</a></li>
|
||||
<li><a href="development.html">Development</a></li>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="api.html">API</a></li>
|
||||
<li class="active"><a href="documentation.html">Documentation</a></li>
|
||||
<li><a href="plc.html">PLC</a></li>
|
||||
<li><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="downloads.html">Downloads</a></li>
|
||||
<li><a href="development.html">Development</a></li>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="api.html">API</a></li>
|
||||
<li class="active"><a href="documentation.html">Documentation</a></li>
|
||||
<li><a href="plc.html">PLC</a></li>
|
||||
<li><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="downloads.html">Downloads</a></li>
|
||||
<li><a href="development.html">Development</a></li>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="api.html">API</a></li>
|
||||
<li class="active"><a href="documentation.html">Documentation</a></li>
|
||||
<li><a href="plc.html">PLC</a></li>
|
||||
<li><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="downloads.html">Downloads</a></li>
|
||||
<li><a href="development.html">Development</a></li>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="api.html">API</a></li>
|
||||
<li class="active"><a href="documentation.html">Documentation</a></li>
|
||||
<li><a href="plc.html">PLC</a></li>
|
||||
<li><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="downloads.html">Downloads</a></li>
|
||||
<li><a href="development.html">Development</a></li>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="api.html">API</a></li>
|
||||
<li class="active"><a href="documentation.html">Documentation</a></li>
|
||||
<li><a href="plc.html">PLC</a></li>
|
||||
<li><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="downloads.html">Downloads</a></li>
|
||||
<li><a href="development.html">Development</a></li>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="api.html">API</a></li>
|
||||
<li class="active"><a href="documentation.html">Documentation</a></li>
|
||||
<li><a href="plc.html">PLC</a></li>
|
||||
<li><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="downloads.html">Downloads</a></li>
|
||||
<li><a href="development.html">Development</a></li>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="api.html">API</a></li>
|
||||
<li class="active"><a href="documentation.html">Documentation</a></li>
|
||||
<li><a href="plc.html">PLC</a></li>
|
||||
<li><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="downloads.html">Downloads</a></li>
|
||||
<li><a href="development.html">Development</a></li>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="api.html">API</a></li>
|
||||
<li class="active"><a href="documentation.html">Documentation</a></li>
|
||||
<li><a href="plc.html">PLC</a></li>
|
||||
<li><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="downloads.html">Downloads</a></li>
|
||||
<li><a href="development.html">Development</a></li>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="api.html">API</a></li>
|
||||
<li class="active"><a href="documentation.html">Documentation</a></li>
|
||||
<li><a href="plc.html">PLC</a></li>
|
||||
<li><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="downloads.html">Downloads</a></li>
|
||||
<li><a href="development.html">Development</a></li>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="api.html">API</a></li>
|
||||
<li class="active"><a href="documentation.html">Documentation</a></li>
|
||||
<li><a href="plc.html">PLC</a></li>
|
||||
<li><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="downloads.html">Downloads</a></li>
|
||||
<li><a href="development.html">Development</a></li>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="api.html">API</a></li>
|
||||
<li class="active"><a href="documentation.html">Documentation</a></li>
|
||||
<li><a href="plc.html">PLC</a></li>
|
||||
<li><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="downloads.html">Downloads</a></li>
|
||||
<li><a href="development.html">Development</a></li>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="api.html">API</a></li>
|
||||
<li class="active"><a href="documentation.html">Documentation</a></li>
|
||||
<li><a href="plc.html">PLC</a></li>
|
||||
<li><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="downloads.html">Downloads</a></li>
|
||||
<li><a href="development.html">Development</a></li>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="api.html">API</a></li>
|
||||
<li class="active"><a href="documentation.html">Documentation</a></li>
|
||||
<li><a href="plc.html">PLC</a></li>
|
||||
<li><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="downloads.html">Downloads</a></li>
|
||||
<li><a href="development.html">Development</a></li>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="api.html">API</a></li>
|
||||
<li class="active"><a href="documentation.html">Documentation</a></li>
|
||||
<li><a href="plc.html">PLC</a></li>
|
||||
<li><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="downloads.html">Downloads</a></li>
|
||||
<li><a href="development.html">Development</a></li>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="api.html">API</a></li>
|
||||
<li class="active"><a href="documentation.html">Documentation</a></li>
|
||||
<li><a href="plc.html">PLC</a></li>
|
||||
<li><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="downloads.html">Downloads</a></li>
|
||||
<li><a href="development.html">Development</a></li>
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="api.html">API</a></li>
|
||||
<li><a href="documentation.html">Documentation</a></li>
|
||||
<li><a href="plc.html">PLC</a></li>
|
||||
<li><a href="tutorial.html">Tutorial</a></li>
|
||||
<li class="active"><a href="downloads.html">Downloads</a></li>
|
||||
<li><a href="development.html">Development</a></li>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<li class="active"><a href="index.html">Overview</a></li>
|
||||
<li><a href="api.html">API</a></li>
|
||||
<li><a href="documentation.html">Documentation</a></li>
|
||||
<li><a href="plc.html">PLC</a></li>
|
||||
<li><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="downloads.html">Downloads</a></li>
|
||||
<li><a href="development.html">Development</a></li>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<li class="active"><a href="index.html">Overview</a></li>
|
||||
<li><a href="api.html">API</a></li>
|
||||
<li><a href="documentation.html">Documentation</a></li>
|
||||
<li><a href="plc.html">PLC</a></li>
|
||||
<li><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="downloads.html">Downloads</a></li>
|
||||
<li><a href="development.html">Development</a></li>
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="google-site-verification" content="CPhbjooaiTdROm7Vs4E7kuHZvBfkeLUtonGgcVUbTL8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<link rel="shortcut icon" href="ico/favicon.ico">
|
||||
|
||||
<title>Strolch: PLC</title>
|
||||
|
||||
<!-- Bootstrap core CSS -->
|
||||
<link href="css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
<!-- Custom styles for this template -->
|
||||
<link href="css/custom.css" rel="stylesheet">
|
||||
|
||||
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries --><!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
||||
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script><![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="index.html">Strolch</a>
|
||||
</div>
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="api.html">API</a></li>
|
||||
<li><a href="documentation.html">Documentation</a></li>
|
||||
<li class="active"><a href="plc.html">PLC</a></li>
|
||||
<li><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="downloads.html">Downloads</a></li>
|
||||
<li><a href="development.html">Development</a></li>
|
||||
<li><a href="blog.html">Blog</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<!--/.nav-collapse -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
|
||||
<div class="page-header">
|
||||
<h1 class="page-title">Strolch as a PLC</h1>
|
||||
|
||||
<p class="lead page-description">This page how Strolch can act as software based PLC with soft realtime.</p>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
|
||||
<!-- content here -->
|
||||
|
||||
<h2>Overview</h2>
|
||||
|
||||
<p>Using Strolch as a PLC has certain advantages and disadvantages. The following is a list of advantages:</p>
|
||||
<ul>
|
||||
<li>Same programming model and language for server and PLC</li>
|
||||
<li>PLC has the same privilege handling as in Strolch</li>
|
||||
<li>Simulating down to the PLC level is easily possible to quickly test the server logic</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<!-- /.content -->
|
||||
|
||||
<div id="footer">
|
||||
<div class="container">
|
||||
<p class="text-muted">© Strolch / <a href="mailto:eitch@eitchnet.ch">Robert von Burg</a> / Hosting by
|
||||
<a href="http://www.eitchnet.ch">eitchnet.ch</a></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- /.container -->
|
||||
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
|
||||
<!-- Include all compiled plugins (below), or include individual xsd as needed -->
|
||||
<script src="js/bootstrap.min.js"></script>
|
||||
|
||||
<!-- Piwik -->
|
||||
<script type="text/javascript">
|
||||
var _paq = _paq || [];
|
||||
_paq.push(['trackPageView']);
|
||||
_paq.push(['enableLinkTracking']);
|
||||
(function () {
|
||||
var u = (("https:" == document.location.protocol) ? "https" : "http") + "://piwik.eitchnet.ch/";
|
||||
_paq.push(['setTrackerUrl', u + 'piwik.php']);
|
||||
_paq.push(['setSiteId', 2]);
|
||||
var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0];
|
||||
g.type = 'text/javascript';
|
||||
g.defer = true;
|
||||
g.async = true;
|
||||
g.src = u + 'piwik.js';
|
||||
s.parentNode.insertBefore(g, s);
|
||||
})();
|
||||
</script>
|
||||
<noscript><p><img src="http://piwik.eitchnet.ch/piwik.php?idsite=2" style="border:0;" alt="" /></p></noscript>
|
||||
<!-- End Piwik Code -->
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -32,6 +32,7 @@
|
|||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="api.html">API</a></li>
|
||||
<li><a href="documentation.html">Documentation</a></li>
|
||||
<li><a href="plc.html">PLC</a></li>
|
||||
<li class="active"><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="downloads.html">Downloads</a></li>
|
||||
<li><a href="development.html">Development</a></li>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="api.html">API</a></li>
|
||||
<li><a href="documentation.html">Documentation</a></li>
|
||||
<li><a href="plc.html">PLC</a></li>
|
||||
<li class="active"><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="downloads.html">Downloads</a></li>
|
||||
<li><a href="development.html">Development</a></li>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="api.html">API</a></li>
|
||||
<li><a href="documentation.html">Documentation</a></li>
|
||||
<li><a href="plc.html">PLC</a></li>
|
||||
<li class="active"><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="downloads.html">Downloads</a></li>
|
||||
<li><a href="development.html">Development</a></li>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="api.html">API</a></li>
|
||||
<li><a href="documentation.html">Documentation</a></li>
|
||||
<li><a href="plc.html">PLC</a></li>
|
||||
<li class="active"><a href="tutorial.html">Tutorial</a></li>
|
||||
<li><a href="downloads.html">Downloads</a></li>
|
||||
<li><a href="development.html">Development</a></li>
|
||||
|
|
7
pom.xml
7
pom.xml
|
@ -97,7 +97,6 @@
|
|||
<!-- test time dependencies -->
|
||||
<junit.version>4.12</junit.version>
|
||||
<hamcrest.version>2.1</hamcrest.version>
|
||||
<mockito.version>2.28.2</mockito.version>
|
||||
|
||||
<!-- maven plug-in dependencies -->
|
||||
<maven-scm-plugin.version>1.11.2</maven-scm-plugin.version>
|
||||
|
@ -328,12 +327,6 @@
|
|||
<version>${hamcrest.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>${mockito.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
|
Loading…
Reference in New Issue