From d86e23b58f42ef97e0c826ae09093032463400a8 Mon Sep 17 00:00:00 2001 From: Robert von Burg Date: Fri, 23 Sep 2016 13:29:02 +0200 Subject: [PATCH] [Fix] Fixed locator finding for Activity and Action --- .../persistence/api/AbstractTransaction.java | 31 +++- .../java/li/strolch/policy/StrolchPolicy.java | 31 ++++ .../src/test/java/li/strolch/RuntimeMock.java | 7 +- .../query/inmemory/FindByLocatorTest.java | 152 +++++++++++++----- .../transienttest/data/Activities.xml | 26 +++ .../transienttest/data/StrolchModel.xml | 1 + .../li/strolch/model/activity/Activity.java | 15 +- .../li/strolch/model/policy/PolicyDef.java | 3 + .../command/planning/AbstractPlanCommand.java | 38 ++--- 9 files changed, 235 insertions(+), 69 deletions(-) create mode 100644 li.strolch.agent/src/test/resources/transienttest/data/Activities.xml diff --git a/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java b/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java index fb8ffeb76..98c25270e 100644 --- a/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java +++ b/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java @@ -19,6 +19,7 @@ import java.text.MessageFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Set; @@ -50,6 +51,7 @@ import li.strolch.model.StrolchElement; import li.strolch.model.StrolchRootElement; import li.strolch.model.Tags; import li.strolch.model.activity.Activity; +import li.strolch.model.activity.IActivityElement; import li.strolch.model.audit.AccessType; import li.strolch.model.audit.Audit; import li.strolch.model.audit.AuditQuery; @@ -368,8 +370,8 @@ public abstract class AbstractTransaction implements StrolchTransaction { return (T) groupedParameterizedElement; // state or bag - String stateOrBag = elements.get(3); - if (stateOrBag.equals(Tags.BAG)) { + String stateOrBagOrActivity = elements.get(3); + if (stateOrBagOrActivity.equals(Tags.BAG)) { String parameterBagId = elements.get(4); ParameterBag bag = groupedParameterizedElement.getParameterBag(parameterBagId); @@ -386,7 +388,7 @@ public abstract class AbstractTransaction implements StrolchTransaction { Parameter parameter = bag.getParameter(parameterId); return (T) parameter; - } else if (stateOrBag.equals(Tags.STATE)) { + } else if (stateOrBagOrActivity.equals(Tags.STATE)) { if (elements.size() != 5) { String msg = "Missing state Id on locator {0}"; //$NON-NLS-1$ @@ -398,10 +400,29 @@ public abstract class AbstractTransaction implements StrolchTransaction { StrolchTimedState> timedState = resource.getTimedState(stateId); return (T) timedState; + + } else if (groupedParameterizedElement instanceof Activity) { + + Activity activity = (Activity) groupedParameterizedElement; + + Iterator iter = elements.subList(3, elements.size()).iterator(); + IActivityElement element = activity; + while (iter.hasNext()) { + String next = iter.next(); + + 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)); + } + + element = ((Activity) element).getElement(next); + } + + return (T) element; } - String msg = "Invalid locator {0} on with part {1}"; //$NON-NLS-1$ - throw new StrolchException(MessageFormat.format(msg, locator, stateOrBag)); + String msg = "Invalid locator {0} with part {1}"; //$NON-NLS-1$ + throw new StrolchException(MessageFormat.format(msg, locator, stateOrBagOrActivity)); } @Override diff --git a/li.strolch.agent/src/main/java/li/strolch/policy/StrolchPolicy.java b/li.strolch.agent/src/main/java/li/strolch/policy/StrolchPolicy.java index 0f0b0ac05..914fcd639 100644 --- a/li.strolch.agent/src/main/java/li/strolch/policy/StrolchPolicy.java +++ b/li.strolch.agent/src/main/java/li/strolch/policy/StrolchPolicy.java @@ -15,13 +15,19 @@ */ package li.strolch.policy; +import static li.strolch.utils.helper.StringHelper.DASH; + 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.activity.Action; import li.strolch.persistence.api.StrolchTransaction; import li.strolch.service.api.Command; +import li.strolch.utils.helper.StringHelper; /** * Interface for all Strolch policies, which are instantiated by the {@link PolicyHandler} @@ -79,6 +85,31 @@ 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()); + + Resource resource = this.tx.getResourceBy(resourceType, resourceId, true); + return resource; + } + /** * @see Command#undo() */ diff --git a/li.strolch.agent/src/test/java/li/strolch/RuntimeMock.java b/li.strolch.agent/src/test/java/li/strolch/RuntimeMock.java index ca122ac65..c9a629080 100644 --- a/li.strolch.agent/src/test/java/li/strolch/RuntimeMock.java +++ b/li.strolch.agent/src/test/java/li/strolch/RuntimeMock.java @@ -160,6 +160,10 @@ public class RuntimeMock implements AutoCloseable { return this; } + public void run(StrolchRunnable runnable) { + runnable.run(getAgent()); + } + @Override public void close() throws RuntimeException { destroyRuntime(); @@ -180,8 +184,7 @@ public class RuntimeMock implements AutoCloseable { try (RuntimeMock runtimeMock = new RuntimeMock(targetPath, srcPath)) { runtimeMock.mockRuntime(); runtimeMock.startContainer(); - - runnable.run(runtimeMock.getAgent()); + runtimeMock.run(runnable); } } diff --git a/li.strolch.agent/src/test/java/li/strolch/runtime/query/inmemory/FindByLocatorTest.java b/li.strolch.agent/src/test/java/li/strolch/runtime/query/inmemory/FindByLocatorTest.java index 45bc66957..4d07cd98d 100644 --- a/li.strolch.agent/src/test/java/li/strolch/runtime/query/inmemory/FindByLocatorTest.java +++ b/li.strolch.agent/src/test/java/li/strolch/runtime/query/inmemory/FindByLocatorTest.java @@ -15,18 +15,20 @@ */ package li.strolch.runtime.query.inmemory; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import org.junit.BeforeClass; import org.junit.Test; import li.strolch.RuntimeMock; import li.strolch.agent.ComponentContainerTest; -import li.strolch.agent.api.ComponentContainer; -import li.strolch.agent.api.StrolchAgent; import li.strolch.model.Locator; import li.strolch.model.Order; import li.strolch.model.ParameterBag; import li.strolch.model.Resource; +import li.strolch.model.activity.Action; +import li.strolch.model.activity.Activity; import li.strolch.model.parameter.FloatParameter; import li.strolch.model.parameter.StringParameter; import li.strolch.model.timedstate.IntegerTimedState; @@ -42,53 +44,125 @@ public class FindByLocatorTest { private static final String PATH_FIND_BY_LOCATOR_RUNTIME = "target/FindByLocatorTest/"; - @Test - public void shouldFindByLocator() { - RuntimeMock.runInStrolch(PATH_FIND_BY_LOCATOR_RUNTIME, ComponentContainerTest.PATH_TRANSIENT_CONTAINER, - agent -> doLocatorTest(agent)); + private static RuntimeMock runtimeMock; + private static Certificate certificate; + + @BeforeClass + public static void beforeClass() { + runtimeMock = new RuntimeMock(PATH_FIND_BY_LOCATOR_RUNTIME, ComponentContainerTest.PATH_TRANSIENT_CONTAINER); + runtimeMock.mockRuntime(); + runtimeMock.startContainer(); + certificate = runtimeMock.getPrivilegeHandler().authenticate("test", "test".getBytes()); + } - private void doLocatorTest(StrolchAgent agent) { - ComponentContainer container = agent.getContainer(); + @Test + public void shouldFindByResource() { + runtimeMock.run(agent -> { + try (StrolchTransaction tx = agent.getContainer().getRealm(StrolchConstants.DEFAULT_REALM) + .openTx(certificate, "test")) { - Certificate certificate = container.getPrivilegeHandler().authenticate("test", "test".getBytes()); + // Resource + Locator locResource = Locator.valueOf("Resource/TestType/MyTestResource"); + Resource resource = tx.findElement(locResource); + assertNotNull("Should have found a FloatParameter with the locator " + locResource, resource); - try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, "test")) { + // Bag on Resource + Locator locResBag = Locator.valueOf("Resource/TestType/MyTestResource/Bag/@bag01"); + ParameterBag resBag = tx.findElement(locResBag); + assertNotNull("Should have found a ParameterBag with the locator " + locResBag, resBag); - // Resource - Locator locResource = Locator.valueOf("Resource/TestType/MyTestResource"); - Resource resource = tx.findElement(locResource); - assertNotNull("Should have found a FloatParameter with the locator " + locResource, resource); + // Parameter on Resource + Locator locResStringParam = Locator.valueOf("Resource/TestType/MyTestResource/Bag/@bag01/@param5"); + StringParameter resStringParam = tx.findElement(locResStringParam); + assertNotNull("Should have found a StringParameter with the locator " + locResStringParam, + resStringParam); - // Order - Locator locOrder = Locator.valueOf("Order/TestType/MyTestOrder"); - Order order = tx.findElement(locOrder); - assertNotNull("Should have found an Order with the locator " + locOrder, order); + // TimedState on Resource + Locator locResIntegerState = Locator.valueOf("Resource/TestType/MyTestResource/State/@integerState"); + IntegerTimedState integerS = tx.findElement(locResIntegerState); + assertNotNull("Should have found a IntegerTimedState with the locator " + locResIntegerState, integerS); - // Bag on Resource - Locator locResBag = Locator.valueOf("Resource/TestType/MyTestResource/Bag/@bag01"); - ParameterBag resBag = tx.findElement(locResBag); - assertNotNull("Should have found a ParameterBag with the locator " + locResBag, resBag); + } + }); + } - // Bag on Order - Locator locOrdBag = Locator.valueOf("Order/TestType/MyTestOrder/Bag/@bag01"); - ParameterBag ordBag = tx.findElement(locOrdBag); - assertNotNull("Should have found a ParameterBag with the locator " + ordBag, locOrdBag); + @Test + public void shouldFindByOrder() { + runtimeMock.run(agent -> { + try (StrolchTransaction tx = agent.getContainer().getRealm(StrolchConstants.DEFAULT_REALM) + .openTx(certificate, "test")) { - // Parameter on Resource - Locator locResStringParam = Locator.valueOf("Resource/TestType/MyTestResource/Bag/@bag01/@param5"); - StringParameter resStringParam = tx.findElement(locResStringParam); - assertNotNull("Should have found a StringParameter with the locator " + locResStringParam, resStringParam); + // Order + Locator locOrder = Locator.valueOf("Order/TestType/MyTestOrder"); + Order order = tx.findElement(locOrder); + assertNotNull("Should have found an Order with the locator " + locOrder, order); - // Parameter on Order - Locator locOrderFloatParam = Locator.valueOf("Order/TestType/MyTestOrder/Bag/@bag01/@param2"); - FloatParameter orderFloatP = tx.findElement(locOrderFloatParam); - assertNotNull("Should have found a FloatParameter with the locator " + locOrderFloatParam, orderFloatP); + // Bag on Order + Locator locOrdBag = Locator.valueOf("Order/TestType/MyTestOrder/Bag/@bag01"); + ParameterBag ordBag = tx.findElement(locOrdBag); + assertNotNull("Should have found a ParameterBag with the locator " + ordBag, locOrdBag); - // TimedState on Resource - Locator locResIntegerState = Locator.valueOf("Resource/TestType/MyTestResource/State/@integerState"); - IntegerTimedState integerS = tx.findElement(locResIntegerState); - assertNotNull("Should have found a IntegerTimedState with the locator " + locResIntegerState, integerS); - } + // Parameter on Order + Locator locOrderFloatParam = Locator.valueOf("Order/TestType/MyTestOrder/Bag/@bag01/@param2"); + FloatParameter orderFloatP = tx.findElement(locOrderFloatParam); + assertNotNull("Should have found a FloatParameter with the locator " + locOrderFloatParam, orderFloatP); + + } + }); + } + + @Test + public void shouldFindByActivity() { + runtimeMock.run(agent -> { + try (StrolchTransaction tx = agent.getContainer().getRealm(StrolchConstants.DEFAULT_REALM) + .openTx(certificate, "test")) { + + // Activity + Locator locActivity = Locator.valueOf("Activity/ActivityType/activity_1"); + Activity activity = tx.findElement(locActivity); + assertNotNull("Should have found Activity with id activity_1", activity); + assertEquals("activity_1", activity.getId()); + assertEquals(locActivity.toString(), activity.getLocator().toString()); + + // sub activity + Locator locAction = Locator.valueOf("Activity/ActivityType/activity_1/child_activity"); + activity = tx.findElement(locAction); + assertNotNull("Should have found sub Activity with id child_activity", activity); + assertEquals("child_activity", activity.getId()); + assertEquals(locAction.toString(), activity.getLocator().toString()); + + } + }); + } + + @Test + public void shouldFindByAction() { + runtimeMock.run(agent -> { + try (StrolchTransaction tx = agent.getContainer().getRealm(StrolchConstants.DEFAULT_REALM) + .openTx(certificate, "test")) { + + // sub action + Locator locAction = Locator.valueOf("Activity/ActivityType/activity_1/action_1"); + Action action = tx.findElement(locAction); + assertNotNull("Should have found Action with id action_1 on Activity activity_1", action); + assertEquals("action_1", action.getId()); + assertEquals(locAction.toString(), action.getLocator().toString()); + + // sub sub action + locAction = Locator.valueOf("Activity/ActivityType/activity_1/child_activity/action_2"); + action = tx.findElement(locAction); + assertNotNull("Should have found sub Activity with id child_activity", action); + assertEquals("action_2", action.getId()); + assertEquals(locAction.toString(), action.getLocator().toString()); + + // sub sub action + locAction = Locator.valueOf("Activity/ActivityType/activity_1/child_activity/action_3"); + action = tx.findElement(locAction); + assertNotNull("Should have found sub Activity with id child_activity", action); + assertEquals("action_3", action.getId()); + assertEquals(locAction.toString(), action.getLocator().toString()); + } + }); } } diff --git a/li.strolch.agent/src/test/resources/transienttest/data/Activities.xml b/li.strolch.agent/src/test/resources/transienttest/data/Activities.xml new file mode 100644 index 000000000..9ae9da51b --- /dev/null +++ b/li.strolch.agent/src/test/resources/transienttest/data/Activities.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/li.strolch.agent/src/test/resources/transienttest/data/StrolchModel.xml b/li.strolch.agent/src/test/resources/transienttest/data/StrolchModel.xml index 9fd6b2020..96af9e88d 100644 --- a/li.strolch.agent/src/test/resources/transienttest/data/StrolchModel.xml +++ b/li.strolch.agent/src/test/resources/transienttest/data/StrolchModel.xml @@ -26,5 +26,6 @@ + \ No newline at end of file diff --git a/li.strolch.model/src/main/java/li/strolch/model/activity/Activity.java b/li.strolch.model/src/main/java/li/strolch/model/activity/Activity.java index bac68c3ec..2b94f4b1b 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/activity/Activity.java +++ b/li.strolch.model/src/main/java/li/strolch/model/activity/Activity.java @@ -65,9 +65,12 @@ public class Activity extends GroupedParameterizedElement /** * Default constructor * - * @param id the id - * @param name the name - * @param type the type + * @param id + * the id + * @param name + * the name + * @param type + * the type */ public Activity(String id, String name, String type, TimeOrdering timeOrdering) { super(id, name, type); @@ -261,7 +264,11 @@ public class Activity extends GroupedParameterizedElement @Override protected void fillLocator(LocatorBuilder locatorBuilder) { - locatorBuilder.append(Tags.ACTIVITY).append(getType()).append(getId()); + if (this.parent != null) + this.parent.fillLocator(locatorBuilder); + else + locatorBuilder.append(Tags.ACTIVITY).append(getType()); + locatorBuilder.append(getId()); } @Override diff --git a/li.strolch.model/src/main/java/li/strolch/model/policy/PolicyDef.java b/li.strolch.model/src/main/java/li/strolch/model/policy/PolicyDef.java index 3163696f6..7f8e36e81 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/policy/PolicyDef.java +++ b/li.strolch.model/src/main/java/li/strolch/model/policy/PolicyDef.java @@ -16,6 +16,7 @@ package li.strolch.model.policy; import li.strolch.exception.StrolchPolicyException; +import li.strolch.utils.helper.StringHelper; /** *

@@ -116,6 +117,8 @@ public abstract class PolicyDef { if (xmlValue.startsWith(JavaPolicyDef.XML_PREFIX)) { String value = xmlValue.substring(JavaPolicyDef.XML_PREFIX.length()); + if (StringHelper.isEmpty(value)) + throw new StrolchPolicyException("Invalid policy configuration. Policy value is empty for " + type); try { Class.forName(value); diff --git a/li.strolch.service/src/main/java/li/strolch/command/planning/AbstractPlanCommand.java b/li.strolch.service/src/main/java/li/strolch/command/planning/AbstractPlanCommand.java index 4295af127..d6396c32d 100644 --- a/li.strolch.service/src/main/java/li/strolch/command/planning/AbstractPlanCommand.java +++ b/li.strolch.service/src/main/java/li/strolch/command/planning/AbstractPlanCommand.java @@ -43,7 +43,7 @@ public abstract class AbstractPlanCommand extends Command { * @param container * @param tx */ - public AbstractPlanCommand(final ComponentContainer container, final StrolchTransaction tx) { + public AbstractPlanCommand(ComponentContainer container, StrolchTransaction tx) { super(container, tx); } @@ -54,11 +54,11 @@ public abstract class AbstractPlanCommand extends Command { * @param action */ @SuppressWarnings({ "unchecked", "rawtypes" }) - protected void plan(final Action action) { + protected void plan(Action action) { - final Locator locator = Locator.newBuilder(Tags.RESOURCE, action.getResourceType(), action.getResourceId()) + Locator locator = Locator.newBuilder(Tags.RESOURCE, action.getResourceType(), action.getResourceId()) .build(); - final Resource resource = tx().findElement(locator); + Resource resource = tx().findElement(locator); if (resource == null) throw new StrolchException("Resource with " + locator + " referenced by " + action.getLocator() @@ -66,9 +66,9 @@ public abstract class AbstractPlanCommand extends Command { tx().lock(resource); - final List>> changes = action.getChanges(); - for (final IValueChange change : changes) { - final StrolchTimedState timedState = resource.getTimedState(change.getStateId()); + List>> changes = action.getChanges(); + for (IValueChange change : changes) { + StrolchTimedState timedState = resource.getTimedState(change.getStateId()); timedState.applyChange(change); } @@ -79,14 +79,14 @@ public abstract class AbstractPlanCommand extends Command { * plan an {@link Activity} by navigating to the {#link Action} and delegating the planning depending on the * {@link IActivityElement} class. */ - protected void plan(final Activity activity) { + protected void plan(Activity activity) { // TODO Martin: Use a visitor pattern so we don't start with instanceof again... - final Iterator> elementIterator = activity.elementIterator(); + Iterator> elementIterator = activity.elementIterator(); while (elementIterator.hasNext()) { - final IActivityElement activityElement = elementIterator.next().getValue(); + IActivityElement activityElement = elementIterator.next().getValue(); if (activityElement instanceof Activity) plan((Activity) activityElement); else if (activityElement instanceof Action) @@ -95,27 +95,27 @@ public abstract class AbstractPlanCommand extends Command { } @SuppressWarnings({ "unchecked", "rawtypes" }) - protected void unplan(final Action action) { + protected void unplan(Action action) { - final Locator locator = Locator.newBuilder(Tags.RESOURCE, action.getResourceType(), action.getResourceId()) + Locator locator = Locator.newBuilder(Tags.RESOURCE, action.getResourceType(), action.getResourceId()) .build(); - final Resource resource = tx().findElement(locator); + Resource resource = tx().findElement(locator); - final List>> changes = action.getChanges(); - for (final IValueChange change : changes) { - final StrolchTimedState timedState = resource.getTimedState(change.getStateId()); + List>> changes = action.getChanges(); + for (IValueChange change : changes) { + StrolchTimedState timedState = resource.getTimedState(change.getStateId()); timedState.applyChange(change.getInverse()); } action.setState(State.CREATED); } - protected void unplan(final Activity activity) { + protected void unplan(Activity activity) { - final Iterator> elementIterator = activity.elementIterator(); + Iterator> elementIterator = activity.elementIterator(); while (elementIterator.hasNext()) { - final IActivityElement activityElement = elementIterator.next().getValue(); + IActivityElement activityElement = elementIterator.next().getValue(); if (activityElement instanceof Activity) unplan((Activity) activityElement);