diff --git a/ch.eitchnet.utils b/ch.eitchnet.utils index f5cf3e3ad..4b9e16602 160000 --- a/ch.eitchnet.utils +++ b/ch.eitchnet.utils @@ -1 +1 @@ -Subproject commit f5cf3e3ad0a4865ec75ffb4e58b03557b4d1db2e +Subproject commit 4b9e166025c85df5c427ed1e15bc3a1d98ff9252 diff --git a/li.strolch.agent/src/main/java/li/strolch/policy/DefaultPolicyHandler.java b/li.strolch.agent/src/main/java/li/strolch/policy/DefaultPolicyHandler.java new file mode 100644 index 000000000..04513e96e --- /dev/null +++ b/li.strolch.agent/src/main/java/li/strolch/policy/DefaultPolicyHandler.java @@ -0,0 +1,164 @@ +/* + * Copyright 2015 Robert von Burg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package li.strolch.policy; + +import java.io.File; +import java.text.MessageFormat; +import java.util.Map; + +import ch.eitchnet.utils.collections.MapOfMaps; +import ch.eitchnet.utils.helper.XmlHelper; +import li.strolch.agent.api.ComponentContainer; +import li.strolch.agent.api.StrolchComponent; +import li.strolch.exception.StrolchPolicyException; +import li.strolch.policy.StrolchPolicyFileParser.PolicyModel; +import li.strolch.policy.StrolchPolicyFileParser.PolicyType; +import li.strolch.runtime.configuration.ComponentConfiguration; + +/** + *

+ * This is the default Strolch {@link PolicyHandler} which implements {@link PolicyDefVisitor}. This + * {@link PolicyHandler} parses a policy configuration file to handle the look-up of {@link KeyPolicyDef} + *

+ * + * This {@link StrolchComponent} uses two configuration properties: + * + * + * @author Robert von Burg + */ +public class DefaultPolicyHandler extends StrolchComponent implements PolicyHandler, PolicyDefVisitor { + + private static final String PROP_POLICY_CONFIG = "policyConfig"; + private static final String PROP_READ_POLICY_FILE = "readPolicyFile"; + private static final String DEF_STROLCH_POLICIES_XML = "StrolchPolicies.xml"; + + private MapOfMaps> classByTypeMap; + + public DefaultPolicyHandler(ComponentContainer container, String componentName) { + super(container, componentName); + } + + @Override + public void initialize(ComponentConfiguration configuration) throws Exception { + + if (configuration.getBoolean(PROP_READ_POLICY_FILE, Boolean.FALSE)) { + File policyFile = configuration.getConfigFile(PROP_POLICY_CONFIG, DEF_STROLCH_POLICIES_XML, + configuration.getRuntimeConfiguration()); + parsePolicyFile(policyFile); + } + + super.initialize(configuration); + } + + @Override + public T getPolicy(PolicyDef policyDef) { + return policyDef.accept(this); + } + + @Override + public T visit(JavaPolicyDef policyDef) { + try { + + String value = policyDef.getValue(); + + @SuppressWarnings("unchecked") + Class clazz = (Class) Class.forName(value); + return clazz.newInstance(); + + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { + throw new StrolchPolicyException( + MessageFormat.format("Failed to instantiate policy {0} due to {1}", policyDef, e.getMessage()), e); + } + } + + @SuppressWarnings("unchecked") + @Override + public T visit(KeyPolicyDef policyDef) { + + try { + Class clazz = this.classByTypeMap.getElement(policyDef.getType(), policyDef.getValue()); + if (clazz == null) + throw new StrolchPolicyException(MessageFormat.format("No policy is configured for {0}", policyDef)); + + return (T) clazz.newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + throw new StrolchPolicyException( + MessageFormat.format("Failed to instantiate policy {0} due to {1}", policyDef, e.getMessage()), e); + } + } + + private void parsePolicyFile(File policyFile) { + + // first we parse the file + StrolchPolicyFileParser xmlHandler = new StrolchPolicyFileParser(); + XmlHelper.parseDocument(policyFile, xmlHandler); + PolicyModel policyModel = xmlHandler.getPolicyModel(); + + // then we iterate the parsed model, validating that we can: + // - access the API class + // - instantiate the class + // - assign the class to the API + Map policyTypes = policyModel.getPolicyTypes(); + this.classByTypeMap = new MapOfMaps<>(); + for (PolicyType policyType : policyTypes.values()) { + + String type = policyType.getType(); + String api = policyType.getApi(); + + try { + + // get the API class + Class apiClass = Class.forName(api); + + // now iterate all configured policies for this API + Map policyByKeyMap = policyType.getPolicyByKeyMap(); + for (String key : policyByKeyMap.keySet()) { + String className = policyByKeyMap.get(key); + + try { + + // get the class + Class implClass = Class.forName(className); + if (!apiClass.isAssignableFrom(implClass)) { + throw new StrolchPolicyException( + "Invalid " + StrolchPolicyFileParser.POLICY + " configuration for Type=" + type + + " Key=" + key + " as " + className + " is not assignable from " + api); + } + + // test that we can instantiate the instance + implClass.newInstance(); + + // store the implementation class + this.classByTypeMap.addElement(type, key, implClass); + + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { + throw new StrolchPolicyException("Invalid " + StrolchPolicyFileParser.POLICY + + " configuration for Type=" + type + " Key=" + key + " due to " + e.getMessage(), e); + } + } + } catch (ClassNotFoundException e) { + throw new StrolchPolicyException("Invalid " + StrolchPolicyFileParser.POLICY_TYPE + + " configuration for Type=" + type + " due to " + e.getMessage(), e); + } + } + } +} diff --git a/li.strolch.agent/src/main/java/li/strolch/policy/PolicyHandler.java b/li.strolch.agent/src/main/java/li/strolch/policy/PolicyHandler.java new file mode 100644 index 000000000..39d5ad444 --- /dev/null +++ b/li.strolch.agent/src/main/java/li/strolch/policy/PolicyHandler.java @@ -0,0 +1,51 @@ +/* + * Copyright 2015 Robert von Burg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package li.strolch.policy; + +/** + *

+ * The {@link PolicyHandler} is Strolch's mechanism of dependency injection + *

+ * + *

+ * Objects which require delegation can use a {@link PolicyConfiguration} element and then retrieve a Policy instance + * from this {@link PolicyHandler}. + *

+ * + *

+ * {@link PolicyConfiguration} have a mapping of a policy type, i.e. an interface for a specific delegation. This + * interface has concrete implementations which are then returned by the {@link PolicyHandler} depending on the current + * configuration + *

+ * + *

+ * The resolving of a policy instance is handled by a {@link PolicyDefVisitor} + *

+ * + * @author Robert von Burg + */ +public interface PolicyHandler { + + /** + * Instantiates the actual policy by resolving the {@link PolicyDef} using a {@link PolicyDefVisitor} + * + * @param policyDef + * the {@link PolicyDef} referencing a concrete policy + * + * @return the instantiated instance of the referenced policy + */ + public T getPolicy(PolicyDef policyDef); +} diff --git a/li.strolch.agent/src/main/java/li/strolch/policy/StrolchPolicyFileParser.java b/li.strolch.agent/src/main/java/li/strolch/policy/StrolchPolicyFileParser.java new file mode 100644 index 000000000..d354cec86 --- /dev/null +++ b/li.strolch.agent/src/main/java/li/strolch/policy/StrolchPolicyFileParser.java @@ -0,0 +1,130 @@ +/* + * Copyright 2015 Robert von Burg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package li.strolch.policy; + +import java.util.HashMap; +import java.util.Map; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import ch.eitchnet.utils.dbc.DBC; + +/** + * @author Robert von Burg + */ +public class StrolchPolicyFileParser extends DefaultHandler { + + public static final String POLICY = "Policy"; + public static final String POLICY_TYPE = "PolicyType"; + + public static final String TYPE = "Type"; + public static final String API = "Api"; + + public static final String KEY = "Key"; + public static final String CLASS = "Class"; + + private PolicyModel policyModel; + private PolicyType policyType; + + public StrolchPolicyFileParser() { + this.policyModel = new PolicyModel(); + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + switch (qName) { + case POLICY_TYPE: + + String type = attributes.getValue(TYPE); + String api = attributes.getValue(API); + + DBC.PRE.assertNotEmpty(TYPE + " not defined on a " + POLICY_TYPE, type); + DBC.PRE.assertNotEmpty(API + " not defined on a " + POLICY_TYPE, api); + + this.policyType = new PolicyType(type, api); + this.policyModel.getPolicyTypes().put(type, policyType); + + break; + case POLICY: + + String key = attributes.getValue(KEY); + String clazz = attributes.getValue(CLASS); + + DBC.PRE.assertNotEmpty(KEY + " not defined on a " + POLICY_TYPE, key); + DBC.PRE.assertNotEmpty(CLASS + " not defined on a " + POLICY_TYPE, clazz); + + this.policyType.getPolicyByKeyMap().put(key, clazz); + + break; + default: + break; + } + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + switch (qName) { + case POLICY_TYPE: + this.policyType = null; + break; + default: + break; + } + } + + public PolicyModel getPolicyModel() { + return this.policyModel; + } + + public class PolicyModel { + private Map policyTypes; + + public PolicyModel() { + this.policyTypes = new HashMap<>(); + } + + public Map getPolicyTypes() { + return this.policyTypes; + } + } + + public class PolicyType { + private String type; + private String api; + private Map policyByKeyMap; + + public PolicyType(String type, String api) { + super(); + this.type = type; + this.api = api; + this.policyByKeyMap = new HashMap<>(); + } + + public String getApi() { + return this.api; + } + + public String getType() { + return this.type; + } + + public Map getPolicyByKeyMap() { + return this.policyByKeyMap; + } + } +} diff --git a/li.strolch.agent/src/test/java/li/strolch/RuntimeMock.java b/li.strolch.agent/src/test/java/li/strolch/RuntimeMock.java new file mode 100644 index 000000000..fa53a58c6 --- /dev/null +++ b/li.strolch.agent/src/test/java/li/strolch/RuntimeMock.java @@ -0,0 +1,199 @@ +/* + * Copyright 2015 Robert von Burg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package li.strolch; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import java.io.File; +import java.text.MessageFormat; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ch.eitchnet.utils.helper.FileHelper; +import ch.eitchnet.utils.helper.StringHelper; +import li.strolch.agent.api.ComponentContainer; +import li.strolch.agent.api.StrolchAgent; +import li.strolch.agent.api.StrolchRealm; +import li.strolch.runtime.configuration.RuntimeConfiguration; +import li.strolch.runtime.privilege.PrivilegeHandler; +import li.strolch.service.api.ServiceHandler; +import li.strolch.service.api.ServiceResult; +import li.strolch.service.api.ServiceResultState; + +/** + * Basically you should use the RuntimeMock class in the testbase project, but to mitigate circular dependencies, in + * tests of the agent project we use this implementation + * + * @author Robert von Burg + */ +public class RuntimeMock implements AutoCloseable { + + private static final Logger logger = LoggerFactory.getLogger(RuntimeMock.class); + private static final String TARGET = "target"; //$NON-NLS-1$ + + private ComponentContainer container; + private StrolchAgent agent; + private File targetPathF; + private File srcPathF; + + public RuntimeMock(String targetPath, String srcPath) { + this(new File(targetPath), new File(srcPath)); + } + + public RuntimeMock(File targetPathF, File srcPathF) { + this.targetPathF = targetPathF; + this.srcPathF = srcPathF; + } + + public ComponentContainer getContainer() { + return this.container; + } + + public StrolchAgent getAgent() { + return this.agent; + } + + public PrivilegeHandler getPrivilegeHandler() { + return this.container.getPrivilegeHandler(); + } + + public ServiceHandler getServiceHandler() { + return this.container.getComponent(ServiceHandler.class); + } + + public StrolchRealm getRealm(String realm) { + return this.container.getRealm(realm); + } + + public RuntimeMock mockRuntime() { + + if (!this.targetPathF.getParentFile().getName().equals(TARGET)) { + String msg = "Mocking path must be in a maven target: {0}"; //$NON-NLS-1$ + msg = MessageFormat.format(msg, this.targetPathF.getAbsolutePath()); + throw new RuntimeException(msg); + } + + File configSrc = new File(this.srcPathF, RuntimeConfiguration.PATH_CONFIG); + + if (!configSrc.isDirectory() || !configSrc.canRead()) { + String msg = "Could not find config source in: {0}"; //$NON-NLS-1$ + msg = MessageFormat.format(msg, configSrc.getAbsolutePath()); + throw new RuntimeException(msg); + } + + if (this.targetPathF.exists()) { + logger.info("Deleting all files in " + this.targetPathF.getAbsolutePath()); //$NON-NLS-1$ + if (!FileHelper.deleteFile(this.targetPathF, true)) { + String msg = "Failed to delete {0}"; //$NON-NLS-1$ + msg = MessageFormat.format(msg, this.targetPathF.getAbsolutePath()); + throw new RuntimeException(msg); + } + } + + if (!this.targetPathF.mkdirs()) { + String msg = "Failed to create {0}"; //$NON-NLS-1$ + msg = MessageFormat.format(msg, this.targetPathF.getAbsolutePath()); + throw new RuntimeException(msg); + } + + logger.info(MessageFormat.format("Mocking runtime from {0} to {1}", this.srcPathF.getAbsolutePath(), //$NON-NLS-1$ + this.targetPathF.getAbsolutePath())); + + if (!FileHelper.copy(this.srcPathF.listFiles(), this.targetPathF, false)) { + String msg = "Failed to copy source files from {0} to {1}"; //$NON-NLS-1$ + msg = MessageFormat.format(msg, this.srcPathF.getAbsolutePath(), this.targetPathF.getAbsolutePath()); + throw new RuntimeException(msg); + } + + return this; + } + + public RuntimeMock startContainer() { + return startContainer("dev"); + } + + public RuntimeMock startContainer(String environment) { + + try { + StrolchAgent agent = new StrolchAgent(); + agent.setup(environment, this.targetPathF); + agent.initialize(); + agent.start(); + + this.agent = agent; + this.container = agent.getContainer(); + + } catch (Exception e) { + logger.error("Failed to start mocked container due to: " + e.getMessage(), e); //$NON-NLS-1$ + destroyRuntime(); + throw e; + } + + return this; + } + + public RuntimeMock destroyRuntime() { + + if (this.agent == null) + return this; + + try { + this.agent.stop(); + } catch (Exception e) { + logger.info("Failed to stop container: " + e.getMessage()); //$NON-NLS-1$ + } + + try { + this.agent.destroy(); + } catch (Exception e) { + logger.info("Failed to destroy container: " + e.getMessage()); //$NON-NLS-1$ + } + + return this; + } + + @Override + public void close() throws RuntimeException { + this.destroyRuntime(); + } + + public static void assertServiceResult(ServiceResultState expectedState, Class expectedResultType, + ServiceResult result) { + assertEquals("Expected service result of type " + expectedResultType + " but was " + result.getClass(), + expectedResultType, result.getClass()); + + if (!expectedState.equals(result.getState())) { + fail("Expected service result state " + expectedState + " but was " + result.getState() + ": Reason: " + + StringHelper.formatException(result.getThrowable())); + } + } + + public static void runInStrolch(String targetPath, String srcPath, StrolchRunnable runnable) { + try (RuntimeMock runtimeMock = new RuntimeMock(targetPath, srcPath)) { + runtimeMock.mockRuntime(); + runtimeMock.startContainer(); + + runnable.run(runtimeMock.getAgent()); + } + } + + public interface StrolchRunnable { + + public void run(StrolchAgent agent); + } +} diff --git a/li.strolch.agent/src/test/java/li/strolch/agent/ComponentContainerTest.java b/li.strolch.agent/src/test/java/li/strolch/agent/ComponentContainerTest.java index 44e507d33..a29ed8641 100644 --- a/li.strolch.agent/src/test/java/li/strolch/agent/ComponentContainerTest.java +++ b/li.strolch.agent/src/test/java/li/strolch/agent/ComponentContainerTest.java @@ -19,9 +19,12 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; -import java.io.File; -import java.text.MessageFormat; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import ch.eitchnet.privilege.model.Certificate; +import li.strolch.RuntimeMock; import li.strolch.agent.api.ComponentContainer; import li.strolch.agent.api.OrderMap; import li.strolch.agent.api.ResourceMap; @@ -33,19 +36,11 @@ import li.strolch.persistence.api.OrderDao; import li.strolch.persistence.api.ResourceDao; import li.strolch.persistence.api.StrolchTransaction; import li.strolch.runtime.StrolchConstants; -import li.strolch.runtime.configuration.RuntimeConfiguration; import li.strolch.runtime.configuration.model.ResourceGeneratorHandlerTest; import li.strolch.runtime.configuration.model.ServiceHandlerTest; import li.strolch.runtime.configuration.model.ServiceResultTest; import li.strolch.runtime.privilege.PrivilegeHandler; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import ch.eitchnet.privilege.model.Certificate; -import ch.eitchnet.utils.helper.FileHelper; - @SuppressWarnings("nls") public class ComponentContainerTest { @@ -62,17 +57,13 @@ public class ComponentContainerTest { public static final String PATH_CACHED_RUNTIME = "target/cachedtest/"; public static final String PATH_EMPTY_RUNTIME = "target/emptytest/"; - public static final Logger logger = LoggerFactory.getLogger(ComponentContainerTest.class); - - private static final String TARGET = "target"; //$NON-NLS-1$ + protected static final Logger logger = LoggerFactory.getLogger(ComponentContainerTest.class); @Test public void shouldStartEmptyContainer() { try { - StrolchAgent agent = startContainer(PATH_EMPTY_RUNTIME, PATH_EMPTY_CONTAINER); - testContainer(agent); - destroyContainer(agent); + RuntimeMock.runInStrolch(PATH_EMPTY_RUNTIME, PATH_EMPTY_CONTAINER, agent -> testContainer(agent)); } catch (Exception e) { logger.error(e.getMessage(), e); throw e; @@ -83,9 +74,7 @@ public class ComponentContainerTest { public void shouldStartTransientContainer() { try { - StrolchAgent agent = startContainer(PATH_TRANSIENT_RUNTIME, PATH_TRANSIENT_CONTAINER); - testContainer(agent); - destroyContainer(agent); + RuntimeMock.runInStrolch(PATH_TRANSIENT_RUNTIME, PATH_TRANSIENT_CONTAINER, agent -> testContainer(agent)); } catch (Exception e) { logger.error(e.getMessage(), e); throw e; @@ -96,10 +85,10 @@ public class ComponentContainerTest { public void shouldStartTransactionalContainer() { try { - StrolchAgent agent = startContainer(PATH_TRANSACTIONAL_RUNTIME, PATH_TRANSACTIONAL_CONTAINER); - testPersistenceContainer(agent); - testElementMaps(agent); - destroyContainer(agent); + RuntimeMock.runInStrolch(PATH_TRANSACTIONAL_RUNTIME, PATH_TRANSACTIONAL_CONTAINER, agent -> { + testPersistenceContainer(agent); + testElementMaps(agent); + }); } catch (Exception e) { logger.error(e.getMessage(), e); throw e; @@ -110,10 +99,10 @@ public class ComponentContainerTest { public void shouldStartCachedContainer() { try { - StrolchAgent agent = startContainer(PATH_CACHED_RUNTIME, PATH_CACHED_CONTAINER); - testPersistenceContainer(agent); - testElementMaps(agent); - destroyContainer(agent); + RuntimeMock.runInStrolch(PATH_CACHED_RUNTIME, PATH_CACHED_CONTAINER, agent -> { + testPersistenceContainer(agent); + testElementMaps(agent); + }); } catch (Exception e) { logger.error(e.getMessage(), e); throw e; @@ -124,9 +113,7 @@ public class ComponentContainerTest { public void shouldStartRealmTestContainer() { try { - StrolchAgent agent = startContainer(PATH_REALM_RUNTIME, PATH_REALM_CONTAINER); - testContainer(agent); - destroyContainer(agent); + RuntimeMock.runInStrolch(PATH_REALM_RUNTIME, PATH_REALM_CONTAINER, agent -> testContainer(agent)); } catch (Exception e) { logger.error(e.getMessage(), e); throw e; @@ -137,10 +124,10 @@ public class ComponentContainerTest { public void shouldTestRealms() { try { - StrolchAgent agent = startContainer(PATH_REALM_RUNTIME, PATH_REALM_CONTAINER); - testContainer(agent); - testRealms(agent); - destroyContainer(agent); + RuntimeMock.runInStrolch(PATH_REALM_RUNTIME, PATH_REALM_CONTAINER, agent -> { + testContainer(agent); + testRealms(agent); + }); } catch (Exception e) { logger.error(e.getMessage(), e); throw e; @@ -151,15 +138,12 @@ public class ComponentContainerTest { public void shouldTestMinimal() { try { - StrolchAgent agent = startContainer(PATH_REALM_RUNTIME, PATH_MINIMAL_CONTAINER); - - ComponentContainer container = agent.getContainer(); - - ServiceHandlerTest serviceHandler = container.getComponent(ServiceHandlerTest.class); - ServiceResultTest result = serviceHandler.doService(); - assertEquals(1, result.getResult()); - - destroyContainer(agent); + RuntimeMock.runInStrolch(PATH_REALM_RUNTIME, PATH_MINIMAL_CONTAINER, agent -> { + ComponentContainer container = agent.getContainer(); + ServiceHandlerTest serviceHandler = container.getComponent(ServiceHandlerTest.class); + ServiceResultTest result = serviceHandler.doService(); + assertEquals(1, result.getResult()); + }); } catch (Exception e) { logger.error(e.getMessage(), e); throw e; @@ -291,78 +275,4 @@ public class ComponentContainerTest { tx.commitOnClose(); } } - - public static StrolchAgent startContainer(String rootPath, String configSrc) { - File rootPathF = new File(rootPath); - File configSrcF = new File(configSrc); - mockRuntime(rootPathF, configSrcF); - return startContainer(rootPathF); - } - - public static StrolchAgent startContainer(File rootPathF) { - StrolchAgent agent = new StrolchAgent(); - agent.setup("dev", rootPathF); - agent.initialize(); - agent.start(); - - return agent; - } - - public static void destroyContainer(StrolchAgent agent) { - agent.stop(); - agent.destroy(); - } - - public static void mockRuntime(File rootPathF, File rootSrc) { - - if (!rootPathF.getParentFile().getName().equals(TARGET)) { - String msg = "Mocking path must be in a maven target: {0}"; //$NON-NLS-1$ - msg = MessageFormat.format(msg, rootPathF.getAbsolutePath()); - throw new RuntimeException(msg); - } - - File configSrc = new File(rootSrc, RuntimeConfiguration.PATH_CONFIG); - File dataSrc = new File(rootSrc, RuntimeConfiguration.PATH_DATA); - - if (!configSrc.isDirectory() || !configSrc.canRead()) { - String msg = "Could not find config source in: {0}"; //$NON-NLS-1$ - msg = MessageFormat.format(msg, configSrc.getAbsolutePath()); - throw new RuntimeException(msg); - } - - if (rootPathF.exists()) { - logger.info("Deleting all files in " + rootPathF.getAbsolutePath()); //$NON-NLS-1$ - if (!FileHelper.deleteFile(rootPathF, true)) { - String msg = "Failed to delete {0}"; //$NON-NLS-1$ - msg = MessageFormat.format(msg, rootPathF.getAbsolutePath()); - throw new RuntimeException(msg); - } - } - - if (!rootPathF.mkdirs()) { - String msg = "Failed to create {0}"; //$NON-NLS-1$ - msg = MessageFormat.format(msg, rootPathF.getAbsolutePath()); - throw new RuntimeException(msg); - } - - File configPathF = new File(rootPathF, RuntimeConfiguration.PATH_CONFIG); - configPathF.mkdir(); - - if (!FileHelper.copy(configSrc.listFiles(), configPathF, false)) { - String msg = "Failed to copy source configs from {0} to {1}"; //$NON-NLS-1$ - msg = MessageFormat.format(msg, configSrc.getAbsolutePath(), configPathF.getAbsolutePath()); - throw new RuntimeException(msg); - } - - if (dataSrc.exists()) { - File dataPathF = new File(rootPathF, RuntimeConfiguration.PATH_DATA); - dataPathF.mkdir(); - - if (!FileHelper.copy(dataSrc.listFiles(), dataPathF, false)) { - String msg = "Failed to copy source data from {0} to {1}"; //$NON-NLS-1$ - msg = MessageFormat.format(msg, configSrc.getAbsolutePath(), configPathF.getAbsolutePath()); - throw new RuntimeException(msg); - } - } - } } diff --git a/li.strolch.agent/src/test/java/li/strolch/agent/RealmTest.java b/li.strolch.agent/src/test/java/li/strolch/agent/RealmTest.java index cbc5947f0..cf49d6009 100644 --- a/li.strolch.agent/src/test/java/li/strolch/agent/RealmTest.java +++ b/li.strolch.agent/src/test/java/li/strolch/agent/RealmTest.java @@ -17,9 +17,7 @@ package li.strolch.agent; import static li.strolch.agent.ComponentContainerTest.PATH_REALM_CONTAINER; import static li.strolch.agent.ComponentContainerTest.PATH_REALM_RUNTIME; -import static li.strolch.agent.ComponentContainerTest.destroyContainer; import static li.strolch.agent.ComponentContainerTest.logger; -import static li.strolch.agent.ComponentContainerTest.startContainer; import static li.strolch.agent.ComponentContainerTest.testContainer; import static org.junit.Assert.assertEquals; @@ -27,12 +25,12 @@ import java.util.Arrays; import java.util.HashSet; import java.util.Set; -import li.strolch.agent.api.ComponentContainer; -import li.strolch.agent.api.StrolchAgent; -import li.strolch.agent.impl.DataStoreMode; - import org.junit.Test; +import li.strolch.RuntimeMock; +import li.strolch.agent.api.ComponentContainer; +import li.strolch.agent.impl.DataStoreMode; + /** * @author Robert von Burg */ @@ -43,25 +41,24 @@ public class RealmTest { public void shouldStartRealmTestContainer() { try { - StrolchAgent agent = startContainer(PATH_REALM_RUNTIME, PATH_REALM_CONTAINER); - testContainer(agent); + RuntimeMock.runInStrolch(PATH_REALM_RUNTIME, PATH_REALM_CONTAINER, agent -> { + testContainer(agent); - ComponentContainer container = agent.getContainer(); - Set realmNames = container.getRealmNames(); - assertEquals(6, realmNames.size()); + ComponentContainer container = agent.getContainer(); + Set realmNames = container.getRealmNames(); + assertEquals(6, realmNames.size()); - Set expectedRealmNames = new HashSet<>(Arrays.asList("defaultRealm", "myRealm", "otherRealm", - "cachedRealm", "transactionalRealm", "emptyRealm")); - assertEquals(expectedRealmNames, realmNames); + Set expectedRealmNames = new HashSet<>(Arrays.asList("defaultRealm", "myRealm", "otherRealm", + "cachedRealm", "transactionalRealm", "emptyRealm")); + assertEquals(expectedRealmNames, realmNames); - assertEquals(DataStoreMode.TRANSIENT, container.getRealm("defaultRealm").getMode()); - assertEquals(DataStoreMode.TRANSIENT, container.getRealm("myRealm").getMode()); - assertEquals(DataStoreMode.TRANSIENT, container.getRealm("otherRealm").getMode()); - assertEquals(DataStoreMode.CACHED, container.getRealm("cachedRealm").getMode()); - assertEquals(DataStoreMode.TRANSACTIONAL, container.getRealm("transactionalRealm").getMode()); - assertEquals(DataStoreMode.EMPTY, container.getRealm("emptyRealm").getMode()); - - destroyContainer(agent); + assertEquals(DataStoreMode.TRANSIENT, container.getRealm("defaultRealm").getMode()); + assertEquals(DataStoreMode.TRANSIENT, container.getRealm("myRealm").getMode()); + assertEquals(DataStoreMode.TRANSIENT, container.getRealm("otherRealm").getMode()); + assertEquals(DataStoreMode.CACHED, container.getRealm("cachedRealm").getMode()); + assertEquals(DataStoreMode.TRANSACTIONAL, container.getRealm("transactionalRealm").getMode()); + assertEquals(DataStoreMode.EMPTY, container.getRealm("emptyRealm").getMode()); + }); } catch (Exception e) { logger.error(e.getMessage(), e); throw e; diff --git a/li.strolch.agent/src/test/java/li/strolch/policytest/PolicyHandlerTest.java b/li.strolch.agent/src/test/java/li/strolch/policytest/PolicyHandlerTest.java new file mode 100644 index 000000000..96cec3d19 --- /dev/null +++ b/li.strolch.agent/src/test/java/li/strolch/policytest/PolicyHandlerTest.java @@ -0,0 +1,67 @@ +/* + * Copyright 2015 Robert von Burg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package li.strolch.policytest; + +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; + +import ch.eitchnet.privilege.model.Certificate; +import li.strolch.RuntimeMock; +import li.strolch.agent.ComponentContainerTest; +import li.strolch.agent.api.ComponentContainer; +import li.strolch.model.Resource; +import li.strolch.persistence.api.StrolchTransaction; +import li.strolch.policy.PolicyDef; +import li.strolch.policy.PolicyHandler; +import li.strolch.runtime.StrolchConstants; + +/** + * @author Robert von Burg + */ +public class PolicyHandlerTest { + + public static final String PATH_EMPTY_RUNTIME = "target/PolicyHandlerTest/"; //$NON-NLS-1$ + + @Test + public void shouldInstantiatePolicies() { + + RuntimeMock.runInStrolch(PATH_EMPTY_RUNTIME, ComponentContainerTest.PATH_TRANSIENT_CONTAINER, agent -> { + + PolicyHandler policyHandler = agent.getContainer().getComponent(PolicyHandler.class); + + ComponentContainer container = agent.getContainer(); + Certificate certificate = container.getPrivilegeHandler().authenticate("test", "test".getBytes()); + try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, + "test")) { + + Resource res = tx.getResourceBy("TestType", "MyTestResource"); + + PolicyDef planningPolicyDef = res.getPolicyDefs().getPolicyDef("PlanningPolicy"); + TestPlanningPolicy planningPolicy = policyHandler.getPolicy(planningPolicyDef); + assertNotNull(planningPolicy); + + PolicyDef executionPolicyDef = res.getPolicyDefs().getPolicyDef("ExecutionPolicy"); + TestExecutionPolicy executionPolicy = policyHandler.getPolicy(executionPolicyDef); + assertNotNull(executionPolicy); + + PolicyDef confirmationPolicyDef = res.getPolicyDefs().getPolicyDef("ConfirmationPolicy"); + TestConfirmationPolicy confirmationPolicy = policyHandler.getPolicy(confirmationPolicyDef); + assertNotNull(confirmationPolicy); + } + }); + } +} diff --git a/li.strolch.agent/src/test/java/li/strolch/policytest/TestConfirmationPolicy.java b/li.strolch.agent/src/test/java/li/strolch/policytest/TestConfirmationPolicy.java new file mode 100644 index 000000000..706deb1c5 --- /dev/null +++ b/li.strolch.agent/src/test/java/li/strolch/policytest/TestConfirmationPolicy.java @@ -0,0 +1,26 @@ +/* + * Copyright 2015 Robert von Burg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package li.strolch.policytest; + +import li.strolch.model.activity.Action; + +/** + * @author Robert von Burg + */ +public interface TestConfirmationPolicy { + + public void confirm(Action action); +} diff --git a/li.strolch.agent/src/test/java/li/strolch/policytest/TestExecutionPolicy.java b/li.strolch.agent/src/test/java/li/strolch/policytest/TestExecutionPolicy.java new file mode 100644 index 000000000..98be00c06 --- /dev/null +++ b/li.strolch.agent/src/test/java/li/strolch/policytest/TestExecutionPolicy.java @@ -0,0 +1,26 @@ +/* + * Copyright 2015 Robert von Burg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package li.strolch.policytest; + +import li.strolch.model.activity.Action; + +/** + * @author Robert von Burg + */ +public interface TestExecutionPolicy { + + public void execute(Action action); +} diff --git a/li.strolch.agent/src/test/java/li/strolch/policytest/TestNoConfirmationPolicy.java b/li.strolch.agent/src/test/java/li/strolch/policytest/TestNoConfirmationPolicy.java new file mode 100644 index 000000000..d0c0b0e17 --- /dev/null +++ b/li.strolch.agent/src/test/java/li/strolch/policytest/TestNoConfirmationPolicy.java @@ -0,0 +1,30 @@ +/* + * Copyright 2015 Robert von Burg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package li.strolch.policytest; + +import li.strolch.model.State; +import li.strolch.model.activity.Action; + +/** + * @author Robert von Burg + */ +public class TestNoConfirmationPolicy implements TestConfirmationPolicy { + + @Override + public void confirm(Action action) { + action.setState(State.CLOSED); + } +} diff --git a/li.strolch.agent/src/test/java/li/strolch/policytest/TestPlanningPolicy.java b/li.strolch.agent/src/test/java/li/strolch/policytest/TestPlanningPolicy.java new file mode 100644 index 000000000..a2a8bab17 --- /dev/null +++ b/li.strolch.agent/src/test/java/li/strolch/policytest/TestPlanningPolicy.java @@ -0,0 +1,26 @@ +/* + * Copyright 2015 Robert von Burg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package li.strolch.policytest; + +import li.strolch.model.activity.Action; + +/** + * @author Robert von Burg + */ +public interface TestPlanningPolicy { + + public void plan(Action action); +} diff --git a/li.strolch.agent/src/test/java/li/strolch/policytest/TestSimplePlanningPolicy.java b/li.strolch.agent/src/test/java/li/strolch/policytest/TestSimplePlanningPolicy.java new file mode 100644 index 000000000..624f70c90 --- /dev/null +++ b/li.strolch.agent/src/test/java/li/strolch/policytest/TestSimplePlanningPolicy.java @@ -0,0 +1,30 @@ +/* + * Copyright 2015 Robert von Burg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package li.strolch.policytest; + +import li.strolch.model.State; +import li.strolch.model.activity.Action; + +/** + * @author Robert von Burg + */ +public class TestSimplePlanningPolicy implements TestPlanningPolicy { + + @Override + public void plan(Action action) { + action.setState(State.PLANNED); + } +} diff --git a/li.strolch.agent/src/test/java/li/strolch/policytest/TestSimulatedExecutionPolicy.java b/li.strolch.agent/src/test/java/li/strolch/policytest/TestSimulatedExecutionPolicy.java new file mode 100644 index 000000000..d8e3577cf --- /dev/null +++ b/li.strolch.agent/src/test/java/li/strolch/policytest/TestSimulatedExecutionPolicy.java @@ -0,0 +1,30 @@ +/* + * Copyright 2015 Robert von Burg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package li.strolch.policytest; + +import li.strolch.model.State; +import li.strolch.model.activity.Action; + +/** + * @author Robert von Burg + */ +public class TestSimulatedExecutionPolicy implements TestExecutionPolicy { + + @Override + public void execute(Action action) { + action.setState(State.EXECUTION); + } +} diff --git a/li.strolch.agent/src/test/java/li/strolch/runtime/query/enums/EnumHandlerTest.java b/li.strolch.agent/src/test/java/li/strolch/runtime/query/enums/EnumHandlerTest.java index 9c17c1860..22aa63d94 100644 --- a/li.strolch.agent/src/test/java/li/strolch/runtime/query/enums/EnumHandlerTest.java +++ b/li.strolch.agent/src/test/java/li/strolch/runtime/query/enums/EnumHandlerTest.java @@ -21,13 +21,12 @@ import java.util.Collections; import java.util.List; import java.util.Locale; -import li.strolch.agent.ComponentContainerTest; -import li.strolch.agent.api.ComponentContainer; -import li.strolch.agent.api.StrolchAgent; - import org.junit.Test; import ch.eitchnet.privilege.model.Certificate; +import li.strolch.RuntimeMock; +import li.strolch.agent.ComponentContainerTest; +import li.strolch.agent.api.ComponentContainer; /** * @author Robert von Burg @@ -40,35 +39,36 @@ public class EnumHandlerTest { @Test public void shouldFindByLocator() { - StrolchAgent agent = ComponentContainerTest.startContainer(ENUM_HANDLER_TEST_RUNTIME, - ComponentContainerTest.PATH_TRANSIENT_CONTAINER); - ComponentContainer container = agent.getContainer(); + RuntimeMock.runInStrolch(ENUM_HANDLER_TEST_RUNTIME, ComponentContainerTest.PATH_TRANSIENT_CONTAINER, agent -> { - Certificate certificate = container.getPrivilegeHandler().authenticate("test", "test".getBytes()); + ComponentContainer container = agent.getContainer(); - EnumHandler enumHandler = container.getComponent(EnumHandler.class); - StrolchEnum sexEnum = enumHandler.getEnum(certificate, "sex", Locale.ENGLISH); - assertEquals("sex", sexEnum.getName()); - assertEquals("en", sexEnum.getLocale()); - assertEquals(3, sexEnum.getValues().size()); - List values = sexEnum.getEnumValues(); - Collections.sort(values); - assertEquals("both", values.get(0)); + Certificate certificate = container.getPrivilegeHandler().authenticate("test", "test".getBytes()); - StrolchEnum salutationsEnum = enumHandler.getEnum(certificate, "salutations", Locale.UK); - assertEquals("salutations", salutationsEnum.getName()); - assertEquals("en_GB", salutationsEnum.getLocale()); - assertEquals(3, salutationsEnum.getValues().size()); - values = salutationsEnum.getEnumValues(); - Collections.sort(values); - assertEquals("Mr", values.get(0)); + EnumHandler enumHandler = container.getComponent(EnumHandler.class); + StrolchEnum sexEnum = enumHandler.getEnum(certificate, "sex", Locale.ENGLISH); + assertEquals("sex", sexEnum.getName()); + assertEquals("en", sexEnum.getLocale()); + assertEquals(3, sexEnum.getValues().size()); + List values = sexEnum.getEnumValues(); + Collections.sort(values); + assertEquals("both", values.get(0)); - StrolchEnum religionsEnum = enumHandler.getEnum(certificate, "religions", Locale.CANADA); - assertEquals("religions", religionsEnum.getName()); - assertEquals("en_CA", religionsEnum.getLocale()); - assertEquals(9, religionsEnum.getValues().size()); - values = religionsEnum.getEnumValues(); - Collections.sort(values); - assertEquals("Atheist", values.get(0)); + StrolchEnum salutationsEnum = enumHandler.getEnum(certificate, "salutations", Locale.UK); + assertEquals("salutations", salutationsEnum.getName()); + assertEquals("en_GB", salutationsEnum.getLocale()); + assertEquals(3, salutationsEnum.getValues().size()); + values = salutationsEnum.getEnumValues(); + Collections.sort(values); + assertEquals("Mr", values.get(0)); + + StrolchEnum religionsEnum = enumHandler.getEnum(certificate, "religions", Locale.CANADA); + assertEquals("religions", religionsEnum.getName()); + assertEquals("en_CA", religionsEnum.getLocale()); + assertEquals(9, religionsEnum.getValues().size()); + values = religionsEnum.getEnumValues(); + Collections.sort(values); + assertEquals("Atheist", values.get(0)); + }); } } 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 da637ad3b..88888ea64 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 @@ -16,6 +16,11 @@ package li.strolch.runtime.query.inmemory; import static org.junit.Assert.assertNotNull; + +import org.junit.Test; + +import ch.eitchnet.privilege.model.Certificate; +import li.strolch.RuntimeMock; import li.strolch.agent.ComponentContainerTest; import li.strolch.agent.api.ComponentContainer; import li.strolch.agent.api.StrolchAgent; @@ -29,10 +34,6 @@ import li.strolch.model.timedstate.IntegerTimedState; import li.strolch.persistence.api.StrolchTransaction; import li.strolch.runtime.StrolchConstants; -import org.junit.Test; - -import ch.eitchnet.privilege.model.Certificate; - /** * @author Robert von Burg */ @@ -43,9 +44,11 @@ public class FindByLocatorTest { @Test public void shouldFindByLocator() { + RuntimeMock.runInStrolch(PATH_FIND_BY_LOCATOR_RUNTIME, ComponentContainerTest.PATH_TRANSIENT_CONTAINER, + agent -> doLocatorTest(agent)); + } - StrolchAgent agent = ComponentContainerTest.startContainer(PATH_FIND_BY_LOCATOR_RUNTIME, - ComponentContainerTest.PATH_TRANSIENT_CONTAINER); + private void doLocatorTest(StrolchAgent agent) { ComponentContainer container = agent.getContainer(); Certificate certificate = container.getPrivilegeHandler().authenticate("test", "test".getBytes()); diff --git a/li.strolch.agent/src/test/java/li/strolch/runtime/query/inmemory/QueryTest.java b/li.strolch.agent/src/test/java/li/strolch/runtime/query/inmemory/QueryTest.java index 737edb549..8a9c7f4f5 100644 --- a/li.strolch.agent/src/test/java/li/strolch/runtime/query/inmemory/QueryTest.java +++ b/li.strolch.agent/src/test/java/li/strolch/runtime/query/inmemory/QueryTest.java @@ -24,9 +24,13 @@ import static org.junit.Assert.assertEquals; import java.util.ArrayList; import java.util.List; +import org.junit.Test; + +import ch.eitchnet.privilege.model.Certificate; +import ch.eitchnet.utils.StringMatchMode; +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.Order; import li.strolch.model.Resource; import li.strolch.model.parameter.IntegerParameter; @@ -38,11 +42,6 @@ import li.strolch.model.query.Selection; import li.strolch.persistence.api.StrolchTransaction; import li.strolch.runtime.StrolchConstants; -import org.junit.Test; - -import ch.eitchnet.privilege.model.Certificate; -import ch.eitchnet.utils.StringMatchMode; - /** * @author Robert von Burg * @@ -59,222 +58,234 @@ public class QueryTest { @Test public void shouldQueryResourceWithParamValue() { - StrolchAgent agent = ComponentContainerTest.startContainer(PATH_EMPTY_RUNTIME, - ComponentContainerTest.PATH_EMPTY_CONTAINER); - ComponentContainer container = agent.getContainer(); + RuntimeMock.runInStrolch(PATH_EMPTY_RUNTIME, ComponentContainerTest.PATH_EMPTY_CONTAINER, agent -> { + ComponentContainer container = agent.getContainer(); - Certificate certificate = login(container); + Certificate certificate = login(container); - Resource res1 = createResource("@1", "Test Resource", "MyType"); - IntegerParameter iP = new IntegerParameter("nbOfBooks", "Number of Books", 33); - res1.addParameter(BAG_ID, iP); - try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, "test")) { - tx.getResourceMap().add(tx, res1); - tx.commitOnClose(); - } + Resource res1 = createResource("@1", "Test Resource", "MyType"); + IntegerParameter iP = new IntegerParameter("nbOfBooks", "Number of Books", 33); + res1.addParameter(BAG_ID, iP); + try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, + "test")) { + tx.getResourceMap().add(tx, res1); + tx.commitOnClose(); + } - ResourceQuery query = ResourceQuery.query("MyType"); - List elementAndSelections = new ArrayList<>(); - elementAndSelections.add(new IdSelection("@1")); - elementAndSelections.add(ParameterSelection.integerSelection(BAG_ID, "nbOfBooks", 33)); - query.and().with(elementAndSelections); + ResourceQuery query = ResourceQuery.query("MyType"); + List elementAndSelections = new ArrayList<>(); + elementAndSelections.add(new IdSelection("@1")); + elementAndSelections.add(ParameterSelection.integerSelection(BAG_ID, "nbOfBooks", 33)); + query.and().with(elementAndSelections); - InMemoryResourceQueryVisitor resourceQuery = new InMemoryResourceQueryVisitor(); - InMemoryQuery inMemoryQuery = resourceQuery.visit(query); - List result; - try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, "test")) { - result = inMemoryQuery.doQuery(tx.getPersistenceHandler().getResourceDao(tx)); - } - assertEquals(1, result.size()); - assertEquals("@1", result.get(0).getId()); + InMemoryResourceQueryVisitor resourceQuery = new InMemoryResourceQueryVisitor(); + InMemoryQuery inMemoryQuery = resourceQuery.visit(query); + List result; + try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, + "test")) { + result = inMemoryQuery.doQuery(tx.getPersistenceHandler().getResourceDao(tx)); + } + assertEquals(1, result.size()); + assertEquals("@1", result.get(0).getId()); + }); } @Test public void shouldQueryOrderWithParamValue() { - StrolchAgent agent = ComponentContainerTest.startContainer(PATH_EMPTY_RUNTIME, - ComponentContainerTest.PATH_EMPTY_CONTAINER); - ComponentContainer container = agent.getContainer(); + RuntimeMock.runInStrolch(PATH_EMPTY_RUNTIME, ComponentContainerTest.PATH_EMPTY_CONTAINER, agent -> { + ComponentContainer container = agent.getContainer(); - Certificate certificate = login(container); + Certificate certificate = login(container); - Order o1 = createOrder("@1", "Test Order", "MyType"); - IntegerParameter iP = new IntegerParameter("nbOfBooks", "Number of Books", 33); - o1.addParameter(BAG_ID, iP); - try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, "test")) { - tx.getOrderMap().add(tx, o1); - tx.commitOnClose(); - } + Order o1 = createOrder("@1", "Test Order", "MyType"); + IntegerParameter iP = new IntegerParameter("nbOfBooks", "Number of Books", 33); + o1.addParameter(BAG_ID, iP); + try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, + "test")) { + tx.getOrderMap().add(tx, o1); + tx.commitOnClose(); + } - OrderQuery query = OrderQuery.query("MyType"); - List elementAndSelections = new ArrayList<>(); - elementAndSelections.add(new IdSelection("@1")); - elementAndSelections.add(ParameterSelection.integerSelection(BAG_ID, "nbOfBooks", 33)); - query.and().with(elementAndSelections); + OrderQuery query = OrderQuery.query("MyType"); + List elementAndSelections = new ArrayList<>(); + elementAndSelections.add(new IdSelection("@1")); + elementAndSelections.add(ParameterSelection.integerSelection(BAG_ID, "nbOfBooks", 33)); + query.and().with(elementAndSelections); - InMemoryOrderQueryVisitor orderQuery = new InMemoryOrderQueryVisitor(); - InMemoryQuery inMemoryQuery = orderQuery.visit(query); - List result; - try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, "test")) { - result = inMemoryQuery.doQuery(tx.getPersistenceHandler().getOrderDao(tx)); - } - assertEquals(1, result.size()); - assertEquals("@1", result.get(0).getId()); + InMemoryOrderQueryVisitor orderQuery = new InMemoryOrderQueryVisitor(); + InMemoryQuery inMemoryQuery = orderQuery.visit(query); + List result; + try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, + "test")) { + result = inMemoryQuery.doQuery(tx.getPersistenceHandler().getOrderDao(tx)); + } + assertEquals(1, result.size()); + assertEquals("@1", result.get(0).getId()); + }); } @Test public void shouldQueryContainsString() { - StrolchAgent agent = ComponentContainerTest.startContainer(PATH_EMPTY_RUNTIME, - ComponentContainerTest.PATH_EMPTY_CONTAINER); - ComponentContainer container = agent.getContainer(); + RuntimeMock.runInStrolch(PATH_EMPTY_RUNTIME, ComponentContainerTest.PATH_EMPTY_CONTAINER, agent -> { + ComponentContainer container = agent.getContainer(); - Certificate certificate = login(container); + Certificate certificate = login(container); - Resource res1 = createResource("@1", "Test Resource", "MyType"); - try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, "test")) { - tx.getResourceMap().add(tx, res1); - tx.commitOnClose(); - } + Resource res1 = createResource("@1", "Test Resource", "MyType"); + try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, + "test")) { + tx.getResourceMap().add(tx, res1); + tx.commitOnClose(); + } - ResourceQuery query = ResourceQuery.query("MyType"); - query.and().with( - ParameterSelection.stringSelection(BAG_ID, PARAM_STRING_ID, "olch", - StringMatchMode.CONTAINS_CASE_SENSITIVE)); - List result; - try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, "test")) { - result = tx.doQuery(query); - } - assertEquals(1, result.size()); - assertEquals("@1", result.get(0).getId()); + ResourceQuery query = ResourceQuery.query("MyType"); + query.and().with(ParameterSelection.stringSelection(BAG_ID, PARAM_STRING_ID, "olch", + StringMatchMode.CONTAINS_CASE_SENSITIVE)); + List result; + try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, + "test")) { + result = tx.doQuery(query); + } + assertEquals(1, result.size()); + assertEquals("@1", result.get(0).getId()); + }); } @Test public void shouldNotQueryContainsString() { - StrolchAgent agent = ComponentContainerTest.startContainer(PATH_EMPTY_RUNTIME, - ComponentContainerTest.PATH_EMPTY_CONTAINER); - ComponentContainer container = agent.getContainer(); + RuntimeMock.runInStrolch(PATH_EMPTY_RUNTIME, ComponentContainerTest.PATH_EMPTY_CONTAINER, agent -> { + ComponentContainer container = agent.getContainer(); - Certificate certificate = login(container); + Certificate certificate = login(container); - Resource res1 = createResource("@1", "Test Resource", "MyType"); - try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, "test")) { - tx.getResourceMap().add(tx, res1); - tx.commitOnClose(); - } + Resource res1 = createResource("@1", "Test Resource", "MyType"); + try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, + "test")) { + tx.getResourceMap().add(tx, res1); + tx.commitOnClose(); + } - ResourceQuery query = ResourceQuery.query("MyType"); - query.and().with( - ParameterSelection.stringSelection(BAG_ID, PARAM_STRING_ID, "str", - StringMatchMode.CONTAINS_CASE_SENSITIVE)); - List result; - try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, "test")) { - result = tx.doQuery(query); - } - assertEquals(0, result.size()); + ResourceQuery query = ResourceQuery.query("MyType"); + query.and().with(ParameterSelection.stringSelection(BAG_ID, PARAM_STRING_ID, "str", + StringMatchMode.CONTAINS_CASE_SENSITIVE)); + List result; + try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, + "test")) { + result = tx.doQuery(query); + } + assertEquals(0, result.size()); + }); } @Test public void shouldQueryCaseInsensitiveString() { - StrolchAgent agent = ComponentContainerTest.startContainer(PATH_EMPTY_RUNTIME, - ComponentContainerTest.PATH_EMPTY_CONTAINER); - ComponentContainer container = agent.getContainer(); + RuntimeMock.runInStrolch(PATH_EMPTY_RUNTIME, ComponentContainerTest.PATH_EMPTY_CONTAINER, agent -> { + ComponentContainer container = agent.getContainer(); - Certificate certificate = login(container); + Certificate certificate = login(container); - Resource res1 = createResource("@1", "Test Resource", "MyType"); - try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, "test")) { - tx.getResourceMap().add(tx, res1); - tx.commitOnClose(); - } + Resource res1 = createResource("@1", "Test Resource", "MyType"); + try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, + "test")) { + tx.getResourceMap().add(tx, res1); + tx.commitOnClose(); + } - ResourceQuery query = ResourceQuery.query("MyType"); - query.and().with( - ParameterSelection.stringSelection(BAG_ID, PARAM_STRING_ID, "strolch", - StringMatchMode.EQUALS_CASE_INSENSITIVE)); - List result; - try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, "test")) { - result = tx.doQuery(query); - } - assertEquals(1, result.size()); - assertEquals("@1", result.get(0).getId()); + ResourceQuery query = ResourceQuery.query("MyType"); + query.and().with(ParameterSelection.stringSelection(BAG_ID, PARAM_STRING_ID, "strolch", + StringMatchMode.EQUALS_CASE_INSENSITIVE)); + List result; + try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, + "test")) { + result = tx.doQuery(query); + } + assertEquals(1, result.size()); + assertEquals("@1", result.get(0).getId()); + }); } @Test public void shouldNotQueryCaseInsensitiveString() { - StrolchAgent agent = ComponentContainerTest.startContainer(PATH_EMPTY_RUNTIME, - ComponentContainerTest.PATH_EMPTY_CONTAINER); - ComponentContainer container = agent.getContainer(); + RuntimeMock.runInStrolch(PATH_EMPTY_RUNTIME, ComponentContainerTest.PATH_EMPTY_CONTAINER, agent -> { + ComponentContainer container = agent.getContainer(); - Certificate certificate = login(container); + Certificate certificate = login(container); - Resource res1 = createResource("@1", "Test Resource", "MyType"); - try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, "test")) { - tx.getResourceMap().add(tx, res1); - tx.commitOnClose(); - } + Resource res1 = createResource("@1", "Test Resource", "MyType"); + try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, + "test")) { + tx.getResourceMap().add(tx, res1); + tx.commitOnClose(); + } - ResourceQuery query = ResourceQuery.query("MyType"); - query.and().with( - ParameterSelection.stringSelection(BAG_ID, PARAM_STRING_ID, "strolch", - StringMatchMode.EQUALS_CASE_SENSITIVE)); - List result; - try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, "test")) { - result = tx.doQuery(query); - } - assertEquals(0, result.size()); + ResourceQuery query = ResourceQuery.query("MyType"); + query.and().with(ParameterSelection.stringSelection(BAG_ID, PARAM_STRING_ID, "strolch", + StringMatchMode.EQUALS_CASE_SENSITIVE)); + List result; + try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, + "test")) { + result = tx.doQuery(query); + } + assertEquals(0, result.size()); + }); } @Test public void shouldQueryNot() { - StrolchAgent agent = ComponentContainerTest.startContainer(PATH_EMPTY_RUNTIME, - ComponentContainerTest.PATH_EMPTY_CONTAINER); - ComponentContainer container = agent.getContainer(); + RuntimeMock.runInStrolch(PATH_EMPTY_RUNTIME, ComponentContainerTest.PATH_EMPTY_CONTAINER, agent -> { + ComponentContainer container = agent.getContainer(); - Certificate certificate = login(container); + Certificate certificate = login(container); - Resource res1 = createResource("@1", "Test Resource", "MyType"); - Resource res2 = createResource("@2", "Test Resource", "MyType"); - try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, "test")) { - tx.getResourceMap().add(tx, res1); - tx.getResourceMap().add(tx, res2); - tx.commitOnClose(); - } - - { - ResourceQuery query = ResourceQuery.query("MyType"); - query.not(new IdSelection("@1")); - List result; - try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, "test")) { - result = tx.doQuery(query); + Resource res1 = createResource("@1", "Test Resource", "MyType"); + Resource res2 = createResource("@2", "Test Resource", "MyType"); + try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, + "test")) { + tx.getResourceMap().add(tx, res1); + tx.getResourceMap().add(tx, res2); + tx.commitOnClose(); } - assertEquals(1, result.size()); - assertEquals("@2", result.get(0).getId()); - } - { - ResourceQuery query = ResourceQuery.query("MyType"); - query.not(new IdSelection("@2")); - List result; - try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, "test")) { - result = tx.doQuery(query); + { + ResourceQuery query = ResourceQuery.query("MyType"); + query.not(new IdSelection("@1")); + List result; + try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, + "test")) { + result = tx.doQuery(query); + } + assertEquals(1, result.size()); + assertEquals("@2", result.get(0).getId()); } - assertEquals(1, result.size()); - assertEquals("@1", result.get(0).getId()); - } - { - ResourceQuery query = ResourceQuery.query("MyType"); - query.not(new IdSelection("@1", "@2")); - List result; - try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, "test")) { - result = tx.doQuery(query); + { + ResourceQuery query = ResourceQuery.query("MyType"); + query.not(new IdSelection("@2")); + List result; + try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, + "test")) { + result = tx.doQuery(query); + } + assertEquals(1, result.size()); + assertEquals("@1", result.get(0).getId()); } - assertEquals(0, result.size()); - } + + { + ResourceQuery query = ResourceQuery.query("MyType"); + query.not(new IdSelection("@1", "@2")); + List result; + try (StrolchTransaction tx = container.getRealm(StrolchConstants.DEFAULT_REALM).openTx(certificate, + "test")) { + result = tx.doQuery(query); + } + assertEquals(0, result.size()); + } + }); } } diff --git a/li.strolch.agent/src/test/resources/transienttest/config/StrolchConfiguration.xml b/li.strolch.agent/src/test/resources/transienttest/config/StrolchConfiguration.xml index 04f5bee01..b49a7cf85 100644 --- a/li.strolch.agent/src/test/resources/transienttest/config/StrolchConfiguration.xml +++ b/li.strolch.agent/src/test/resources/transienttest/config/StrolchConfiguration.xml @@ -61,5 +61,14 @@ Resource/Enumeration/religions + + PolicyHandler + li.strolch.policy.PolicyHandler + li.strolch.policy.DefaultPolicyHandler + + true + StrolchPolicies.xml + + \ No newline at end of file diff --git a/li.strolch.agent/src/test/resources/transienttest/config/StrolchPolicies.xml b/li.strolch.agent/src/test/resources/transienttest/config/StrolchPolicies.xml new file mode 100644 index 000000000..e4a55e6ae --- /dev/null +++ b/li.strolch.agent/src/test/resources/transienttest/config/StrolchPolicies.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/li.strolch.agent/src/test/resources/transienttest/data/Resources.xml b/li.strolch.agent/src/test/resources/transienttest/data/Resources.xml index 6a550eb7e..42f477139 100644 --- a/li.strolch.agent/src/test/resources/transienttest/data/Resources.xml +++ b/li.strolch.agent/src/test/resources/transienttest/data/Resources.xml @@ -36,5 +36,10 @@ + + + + + diff --git a/li.strolch.model/src/main/java/li/strolch/exception/StrolchPolicyException.java b/li.strolch.model/src/main/java/li/strolch/exception/StrolchPolicyException.java new file mode 100644 index 000000000..9c520fe54 --- /dev/null +++ b/li.strolch.model/src/main/java/li/strolch/exception/StrolchPolicyException.java @@ -0,0 +1,40 @@ +/* + * Copyright 2015 Robert von Burg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package li.strolch.exception; + +/** + * @author Robert von Burg + * + */ +public class StrolchPolicyException extends StrolchException { + + private static final long serialVersionUID = 1L; + + /** + * @param message + * @param cause + */ + public StrolchPolicyException(String message, Throwable cause) { + super(message, cause); + } + + /** + * @param message + */ + public StrolchPolicyException(String message) { + super(message); + } +} diff --git a/li.strolch.model/src/main/java/li/strolch/model/ModelGenerator.java b/li.strolch.model/src/main/java/li/strolch/model/ModelGenerator.java index fa1a7f4be..be84415d4 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/ModelGenerator.java +++ b/li.strolch.model/src/main/java/li/strolch/model/ModelGenerator.java @@ -23,6 +23,8 @@ import java.util.List; import java.util.Random; import java.util.Set; +import ch.eitchnet.utils.helper.StringHelper; +import ch.eitchnet.utils.iso8601.ISO8601FormatFactory; import li.strolch.model.activity.Action; import li.strolch.model.activity.Activity; import li.strolch.model.audit.AccessType; @@ -50,8 +52,9 @@ import li.strolch.model.timevalue.impl.FloatValue; import li.strolch.model.timevalue.impl.IntegerValue; import li.strolch.model.timevalue.impl.StringSetValue; import li.strolch.model.timevalue.impl.ValueChange; -import ch.eitchnet.utils.helper.StringHelper; -import ch.eitchnet.utils.iso8601.ISO8601FormatFactory; +import li.strolch.policy.JavaPolicyDef; +import li.strolch.policy.PolicyDef; +import li.strolch.policy.PolicyDefs; /** * Class which can be used to generate objects which implement {@link StrolchElement}. These generated classes can then @@ -159,6 +162,8 @@ public class ModelGenerator { resource.addParameterBag(bag); addTimedStates(resource); + resource.setPolicyDefs(createPolicyDefs()); + return resource; } @@ -298,9 +303,23 @@ public class ModelGenerator { ParameterBag bag = createParameterBag(BAG_ID, BAG_NAME, BAG_TYPE); order.addParameterBag(bag); + order.setPolicyDefs(createPolicyDefs()); + return order; } + /** + * Creates a simple {@link PolicyDefs} object with a "ObjectPolicy" with value "java:java.lang.Object" + * + * @return the created {@link PolicyDefs} + */ + public static PolicyDefs createPolicyDefs() { + PolicyDefs policyDefs = new PolicyDefs(); + PolicyDef policyDef = new JavaPolicyDef("ObjectPolicy", "java.lang.Object"); + policyDefs.addOrUpdate(policyDef); + return policyDefs; + } + /** * Creates a list of {@link Order Orders} with the given values and adds a {@link ParameterBag} by calling * {@link #createParameterBag(String, String, String)} @@ -352,6 +371,8 @@ public class ModelGenerator { action = createAction("act_" + id, "Action " + name, "Use"); subSubActivity.addElement(action); + rootActivity.setPolicyDefs(createPolicyDefs()); + return rootActivity; } diff --git a/li.strolch.model/src/main/java/li/strolch/model/Order.java b/li.strolch.model/src/main/java/li/strolch/model/Order.java index 843aea62c..a37dc53f6 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/Order.java +++ b/li.strolch.model/src/main/java/li/strolch/model/Order.java @@ -17,9 +17,11 @@ package li.strolch.model; import java.util.Date; +import ch.eitchnet.utils.iso8601.ISO8601FormatFactory; +import li.strolch.exception.StrolchPolicyException; import li.strolch.model.Locator.LocatorBuilder; import li.strolch.model.visitor.StrolchRootElementVisitor; -import ch.eitchnet.utils.iso8601.ISO8601FormatFactory; +import li.strolch.policy.PolicyDefs; /** * The Order is an object used in the EDF to transfer data from one range to another. Orders are not to be thought of as @@ -37,6 +39,7 @@ public class Order extends GroupedParameterizedElement implements StrolchRootEle private Date date; private State state; + private PolicyDefs policyDefs; /** * Empty constructor - for marshalling only! @@ -75,36 +78,37 @@ public class Order extends GroupedParameterizedElement implements StrolchRootEle setDate(date); } - /** - * @return the date - */ public Date getDate() { return this.date; } - /** - * @param date - * the date to set - */ public void setDate(Date date) { this.date = date; } - /** - * @return the state - */ public State getState() { return this.state; } - /** - * @param state - * the state to set - */ public void setState(State state) { this.state = state; } + public PolicyDefs getPolicyDefs() { + if (this.policyDefs == null) + throw new StrolchPolicyException(getLocator() + " has no Policies defined!"); + return this.policyDefs; + } + + public boolean hasPolicyDefs() { + return this.policyDefs != null; + } + + public void setPolicyDefs(PolicyDefs policyDefs) { + this.policyDefs = policyDefs; + this.policyDefs.setParent(this); + } + @Override public Order getClone() { Order clone = new Order(); @@ -114,6 +118,9 @@ public class Order extends GroupedParameterizedElement implements StrolchRootEle clone.setDate(this.date); clone.setState(this.state); + if (this.policyDefs != null) + clone.setPolicyDefs(this.policyDefs.getClone()); + return clone; } diff --git a/li.strolch.model/src/main/java/li/strolch/model/Resource.java b/li.strolch.model/src/main/java/li/strolch/model/Resource.java index 674721b17..797bd2df4 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/Resource.java +++ b/li.strolch.model/src/main/java/li/strolch/model/Resource.java @@ -23,10 +23,12 @@ import java.util.List; import java.util.Map; import java.util.Set; +import li.strolch.exception.StrolchPolicyException; import li.strolch.model.Locator.LocatorBuilder; import li.strolch.model.timedstate.StrolchTimedState; import li.strolch.model.timevalue.IValue; import li.strolch.model.visitor.StrolchRootElementVisitor; +import li.strolch.policy.PolicyDefs; /** * @author Robert von Burg @@ -36,6 +38,7 @@ public class Resource extends GroupedParameterizedElement implements StrolchRoot private static final long serialVersionUID = 0L; private Map>> timedStateMap; + private PolicyDefs policyDefs; /** * Empty constructor - for marshalling only! @@ -103,6 +106,21 @@ public class Resource extends GroupedParameterizedElement implements StrolchRoot return this.timedStateMap != null && this.timedStateMap.containsKey(id); } + public PolicyDefs getPolicyDefs() { + if (this.policyDefs == null) + throw new StrolchPolicyException(getLocator() + " has no Policies defined!"); + return this.policyDefs; + } + + public boolean hasPolicyDefs() { + return this.policyDefs != null; + } + + public void setPolicyDefs(PolicyDefs policyDefs) { + this.policyDefs = policyDefs; + this.policyDefs.setParent(this); + } + @Override public Resource getClone() { Resource clone = new Resource(); @@ -114,6 +132,9 @@ public class Resource extends GroupedParameterizedElement implements StrolchRoot } } + if (this.policyDefs != null) + clone.setPolicyDefs(this.policyDefs.getClone()); + return clone; } @@ -165,7 +186,7 @@ public class Resource extends GroupedParameterizedElement implements StrolchRoot return builder.toString(); } - + @Override public int compareTo(Resource o) { return getId().compareTo(o.getId()); diff --git a/li.strolch.model/src/main/java/li/strolch/model/Tags.java b/li.strolch.model/src/main/java/li/strolch/model/Tags.java index d14fd3408..0f25acc73 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/Tags.java +++ b/li.strolch.model/src/main/java/li/strolch/model/Tags.java @@ -41,6 +41,8 @@ public class Tags { public static final String FILE = "file"; public static final String BAG = "Bag"; public static final String AUDIT = "Audit"; + public static final String POLICIES = "Policies"; + public static final String POLICY = "Policy"; public static final String ACTIVITY = "Activity"; public static final String ACTION = "Action"; 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 cd031a8a6..cb191f080 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 @@ -21,7 +21,9 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; +import ch.eitchnet.utils.dbc.DBC; import li.strolch.exception.StrolchException; +import li.strolch.exception.StrolchPolicyException; import li.strolch.model.GroupedParameterizedElement; import li.strolch.model.Locator; import li.strolch.model.Locator.LocatorBuilder; @@ -30,7 +32,7 @@ import li.strolch.model.StrolchElement; import li.strolch.model.StrolchRootElement; import li.strolch.model.Tags; import li.strolch.model.visitor.StrolchRootElementVisitor; -import ch.eitchnet.utils.dbc.DBC; +import li.strolch.policy.PolicyDefs; /** * Parameterized object grouping a collection of {@link Activity} and {@link Action} objects defining the process to be @@ -38,14 +40,14 @@ import ch.eitchnet.utils.dbc.DBC; * * @author Martin Smock */ -public class Activity extends GroupedParameterizedElement implements IActivityElement, StrolchRootElement, - Comparable { +public class Activity extends GroupedParameterizedElement + implements IActivityElement, StrolchRootElement, Comparable { private static final long serialVersionUID = 1L; protected Activity parent; - protected Map elements; + private PolicyDefs policyDefs; /** * Empty constructor - for marshalling only! @@ -105,8 +107,8 @@ public class Activity extends GroupedParameterizedElement implements IActivityEl if (id == null) throw new StrolchException("Cannot add IActivityElement without id."); else if (elements.containsKey(id)) - throw new StrolchException("Activiy " + getLocator() + " already contains an activity element with id = " - + id); + throw new StrolchException( + "Activiy " + getLocator() + " already contains an activity element with id = " + id); else { activityElement.setParent(this); return elements.put(activityElement.getId(), activityElement); @@ -145,6 +147,7 @@ public class Activity extends GroupedParameterizedElement implements IActivityEl return elements.entrySet().iterator(); } + @Override public Long getStart() { Long start = Long.MAX_VALUE; if (this.elements == null) @@ -157,6 +160,7 @@ public class Activity extends GroupedParameterizedElement implements IActivityEl return start; } + @Override public Long getEnd() { Long end = 0L; if (this.elements == null) @@ -169,6 +173,7 @@ public class Activity extends GroupedParameterizedElement implements IActivityEl return end; } + @Override public State getState() { State state = State.PLANNED; if (this.elements == null) @@ -184,6 +189,21 @@ public class Activity extends GroupedParameterizedElement implements IActivityEl return state; } + public PolicyDefs getPolicyDefs() { + if (this.policyDefs == null) + throw new StrolchPolicyException(getLocator() + " has no Policies defined!"); + return this.policyDefs; + } + + public boolean hasPolicyDefs() { + return this.policyDefs != null; + } + + public void setPolicyDefs(PolicyDefs policyDefs) { + this.policyDefs = policyDefs; + this.policyDefs.setParent(this); + } + @Override public Locator getLocator() { LocatorBuilder lb = new LocatorBuilder(); @@ -222,6 +242,10 @@ public class Activity extends GroupedParameterizedElement implements IActivityEl for (IActivityElement element : this.elements.values()) { clone.addElement(element.getClone()); } + + if (this.policyDefs != null) + clone.setPolicyDefs(this.policyDefs.getClone()); + return clone; } diff --git a/li.strolch.model/src/main/java/li/strolch/model/visitor/StrolchElementDeepEqualsVisitor.java b/li.strolch.model/src/main/java/li/strolch/model/visitor/StrolchElementDeepEqualsVisitor.java index 8b138c297..fb151990d 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/visitor/StrolchElementDeepEqualsVisitor.java +++ b/li.strolch.model/src/main/java/li/strolch/model/visitor/StrolchElementDeepEqualsVisitor.java @@ -21,6 +21,7 @@ import java.util.List; import java.util.Map.Entry; import java.util.Set; +import ch.eitchnet.utils.dbc.DBC; import li.strolch.model.GroupedParameterizedElement; import li.strolch.model.Locator; import li.strolch.model.Order; @@ -33,7 +34,8 @@ import li.strolch.model.activity.IActivityElement; import li.strolch.model.parameter.Parameter; import li.strolch.model.timedstate.StrolchTimedState; import li.strolch.model.timevalue.ITimeVariable; -import ch.eitchnet.utils.dbc.DBC; +import li.strolch.policy.PolicyDef; +import li.strolch.policy.PolicyDefs; /** * @author Robert von Burg @@ -78,12 +80,49 @@ public class StrolchElementDeepEqualsVisitor { } deepEquals((GroupedParameterizedElement) srcOrder, (GroupedParameterizedElement) dstOrder); + + if (srcOrder.hasPolicyDefs() && dstOrder.hasPolicyDefs()) + deepEquals(srcOrder.getPolicyDefs(), dstOrder.getPolicyDefs()); + else if (srcOrder.hasPolicyDefs() != dstOrder.hasPolicyDefs()) + this.mismatchedLocators.add(srcOrder.getLocator()); + } + + private void deepEquals(PolicyDefs srcPolicyDefs, PolicyDefs dstPolicyDefs) { + + Set srcTypes = srcPolicyDefs.getPolicyTypes(); + for (String srcType : srcTypes) { + PolicyDef srcPolicyDef = srcPolicyDefs.getPolicyDef(srcType); + + if (!dstPolicyDefs.hasPolicyDef(srcType)) { + this.mismatchedLocators.add(dstPolicyDefs.getParent().getLocator()); + continue; + } + + PolicyDef dstPolicyDef = dstPolicyDefs.getPolicyDef(srcType); + + if (srcPolicyDef.getClass() != dstPolicyDef.getClass()) + this.mismatchedLocators.add(dstPolicyDefs.getParent().getLocator()); + if (!srcPolicyDef.getValue().equals(dstPolicyDef.getValue())) + this.mismatchedLocators.add(dstPolicyDefs.getParent().getLocator()); + } + + Set dstTypes = dstPolicyDefs.getPolicyTypes(); + for (String dstType : dstTypes) { + if (!srcPolicyDefs.hasPolicyDef(dstType)) { + this.mismatchedLocators.add(srcPolicyDefs.getParent().getLocator()); + } + } } protected void deepEquals(Resource srcRes, Resource dstRes) { deepEquals((StrolchElement) srcRes, (StrolchElement) dstRes); deepEquals((GroupedParameterizedElement) srcRes, (GroupedParameterizedElement) dstRes); + if (srcRes.hasPolicyDefs() && dstRes.hasPolicyDefs()) + deepEquals(srcRes.getPolicyDefs(), dstRes.getPolicyDefs()); + else if (srcRes.hasPolicyDefs() != dstRes.hasPolicyDefs()) + this.mismatchedLocators.add(srcRes.getLocator()); + Set srcTimedStateKeySet = srcRes.getTimedStateKeySet(); for (String timedStateKey : srcTimedStateKeySet) { StrolchTimedState srcTimedState = srcRes.getTimedState(timedStateKey); @@ -110,6 +149,11 @@ public class StrolchElementDeepEqualsVisitor { deepEquals((StrolchElement) srcActivity, (StrolchElement) dstActivity); deepEquals((GroupedParameterizedElement) srcActivity, (GroupedParameterizedElement) dstActivity); + if (srcActivity.hasPolicyDefs() && dstActivity.hasPolicyDefs()) + deepEquals(srcActivity.getPolicyDefs(), dstActivity.getPolicyDefs()); + else if (srcActivity.hasPolicyDefs() != dstActivity.hasPolicyDefs()) + this.mismatchedLocators.add(srcActivity.getLocator()); + Iterator> iter = srcActivity.elementIterator(); while (iter.hasNext()) { IActivityElement srcActivityElement = iter.next().getValue(); diff --git a/li.strolch.model/src/main/java/li/strolch/model/xml/StrolchElementFromDomVisitor.java b/li.strolch.model/src/main/java/li/strolch/model/xml/StrolchElementFromDomVisitor.java index 68053d3ac..6abb44609 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/xml/StrolchElementFromDomVisitor.java +++ b/li.strolch.model/src/main/java/li/strolch/model/xml/StrolchElementFromDomVisitor.java @@ -18,6 +18,13 @@ package li.strolch.model.xml; import java.text.MessageFormat; import java.util.Date; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import ch.eitchnet.utils.dbc.DBC; +import ch.eitchnet.utils.helper.StringHelper; +import ch.eitchnet.utils.iso8601.ISO8601FormatFactory; import li.strolch.exception.StrolchException; import li.strolch.model.AbstractStrolchElement; import li.strolch.model.GroupedParameterizedElement; @@ -34,14 +41,8 @@ import li.strolch.model.parameter.Parameter; import li.strolch.model.timedstate.StrolchTimedState; import li.strolch.model.timevalue.IValue; import li.strolch.model.timevalue.impl.ValueChange; - -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import ch.eitchnet.utils.dbc.DBC; -import ch.eitchnet.utils.helper.StringHelper; -import ch.eitchnet.utils.iso8601.ISO8601FormatFactory; +import li.strolch.policy.PolicyDef; +import li.strolch.policy.PolicyDefs; /** * @author Robert von Burg @@ -51,6 +52,10 @@ public class StrolchElementFromDomVisitor { public void fillElement(Element element, Order order) { fillElement(element, (GroupedParameterizedElement) order); + PolicyDefs defs = parsePolicies(element); + if (defs.hasPolicyDefs()) + order.setPolicyDefs(defs); + String date = element.getAttribute(Tags.DATE); String state = element.getAttribute(Tags.STATE); @@ -70,6 +75,10 @@ public class StrolchElementFromDomVisitor { public void fillElement(Element resourceElement, Resource resource) { fillElement(resourceElement, (GroupedParameterizedElement) resource); + PolicyDefs defs = parsePolicies(resourceElement); + if (defs.hasPolicyDefs()) + resource.setPolicyDefs(defs); + NodeList childNodes = resourceElement.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { Node item = childNodes.item(i); @@ -239,6 +248,10 @@ public class StrolchElementFromDomVisitor { protected void fillElement(Element activityElement, Activity activity) { fillElement(activityElement, (GroupedParameterizedElement) activity); + PolicyDefs defs = parsePolicies(activityElement); + if (defs.hasPolicyDefs()) + activity.setPolicyDefs(defs); + NodeList childNodes = activityElement.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { Node item = childNodes.item(i); @@ -259,8 +272,8 @@ public class StrolchElementFromDomVisitor { activity.addElement(childAction); break; case Tags.PARAMETER_BAG: + case Tags.POLICIES: break; - default: throw new IllegalArgumentException("Unexpected element tag " + childElem.getNodeName()); } @@ -302,4 +315,38 @@ public class StrolchElementFromDomVisitor { action.addChange(valueChange); } } + + private PolicyDefs parsePolicies(Element element) { + + PolicyDefs policyDefs = new PolicyDefs(); + + NodeList childNodes = element.getChildNodes(); + for (int i = 0; i < childNodes.getLength(); i++) { + Node resourceChildItem = childNodes.item(i); + if (!(resourceChildItem instanceof Element)) + continue; + + Element policiesElem = (Element) resourceChildItem; + if (!policiesElem.getNodeName().equals(Tags.POLICIES)) + continue; + + NodeList policyChildNodes = policiesElem.getChildNodes(); + for (int j = 0; j < policyChildNodes.getLength(); j++) { + Node policiesChildItem = policyChildNodes.item(j); + if (!(policiesChildItem instanceof Element)) + continue; + + Element policyElem = (Element) policiesChildItem; + if (!policyElem.getNodeName().equals(Tags.POLICY)) + continue; + + String type = policyElem.getAttribute(Tags.TYPE); + String value = policyElem.getAttribute(Tags.VALUE); + + policyDefs.addOrUpdate(PolicyDef.valueOf(type, value)); + } + } + + return policyDefs; + } } diff --git a/li.strolch.model/src/main/java/li/strolch/model/xml/StrolchElementToDomVisitor.java b/li.strolch.model/src/main/java/li/strolch/model/xml/StrolchElementToDomVisitor.java index ada305048..a4ecc3027 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/xml/StrolchElementToDomVisitor.java +++ b/li.strolch.model/src/main/java/li/strolch/model/xml/StrolchElementToDomVisitor.java @@ -19,6 +19,10 @@ import java.util.Iterator; import java.util.Map.Entry; import java.util.SortedSet; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import ch.eitchnet.utils.iso8601.ISO8601FormatFactory; import li.strolch.model.AbstractStrolchElement; import li.strolch.model.GroupedParameterizedElement; import li.strolch.model.Order; @@ -35,11 +39,8 @@ import li.strolch.model.timedstate.StrolchTimedState; import li.strolch.model.timevalue.ITimeValue; import li.strolch.model.timevalue.IValue; import li.strolch.model.timevalue.IValueChange; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import ch.eitchnet.utils.iso8601.ISO8601FormatFactory; +import li.strolch.policy.PolicyDef; +import li.strolch.policy.PolicyDefs; /** * @author Robert von Burg @@ -55,11 +56,14 @@ public class StrolchElementToDomVisitor { protected Element toDom(Order order) { Element asDom = document.createElement(Tags.ORDER); - fillElement(asDom, order); - asDom.setAttribute(Tags.DATE, ISO8601FormatFactory.getInstance().formatDate(order.getDate())); asDom.setAttribute(Tags.STATE, order.getState().name()); + fillElement(asDom, order); + + if (order.hasPolicyDefs()) + fillElement(asDom, order.getPolicyDefs()); + return asDom; } @@ -76,13 +80,38 @@ public class StrolchElementToDomVisitor { } } + if (resource.hasPolicyDefs()) + fillElement(asDom, resource.getPolicyDefs()); + return asDom; } + private void fillElement(Element asDom, PolicyDefs policyDefs) { + if (policyDefs == null || !policyDefs.hasPolicyDefs()) + return; + + Element policiesElem = this.document.createElement(Tags.POLICIES); + + for (String type : policyDefs.getPolicyTypes()) { + PolicyDef policyDef = policyDefs.getPolicyDef(type); + + Element policyElem = this.document.createElement(Tags.POLICY); + policyElem.setAttribute(Tags.TYPE, policyDef.getType()); + policyElem.setAttribute(Tags.VALUE, policyDef.getValueForXml()); + + policiesElem.appendChild(policyElem); + } + + asDom.appendChild(policiesElem); + } + protected Element toDom(Activity activity) { Element element = document.createElement(Tags.ACTIVITY); fillElement(element, activity); + if (activity.hasPolicyDefs()) + fillElement(element, activity.getPolicyDefs()); + if (activity.hasElements()) { Iterator> iter = activity.elementIterator(); while (iter.hasNext()) { @@ -165,7 +194,7 @@ public class StrolchElementToDomVisitor { protected Element toDom(ParameterBag bag) { Element bagElement = document.createElement(Tags.PARAMETER_BAG); - fillElement(bagElement, (ParameterizedElement) bag); + fillElement(bagElement, bag); return bagElement; } diff --git a/li.strolch.model/src/main/java/li/strolch/model/xml/StrolchElementToSaxVisitor.java b/li.strolch.model/src/main/java/li/strolch/model/xml/StrolchElementToSaxVisitor.java index e06f581a1..e45ebc0b0 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/xml/StrolchElementToSaxVisitor.java +++ b/li.strolch.model/src/main/java/li/strolch/model/xml/StrolchElementToSaxVisitor.java @@ -23,6 +23,12 @@ import java.util.Map.Entry; import java.util.Set; import java.util.SortedSet; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +import ch.eitchnet.utils.iso8601.ISO8601FormatFactory; import li.strolch.model.GroupedParameterizedElement; import li.strolch.model.Order; import li.strolch.model.ParameterBag; @@ -37,13 +43,8 @@ import li.strolch.model.timedstate.StrolchTimedState; import li.strolch.model.timevalue.ITimeValue; import li.strolch.model.timevalue.IValue; import li.strolch.model.timevalue.IValueChange; - -import org.xml.sax.Attributes; -import org.xml.sax.ContentHandler; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.AttributesImpl; - -import ch.eitchnet.utils.iso8601.ISO8601FormatFactory; +import li.strolch.policy.PolicyDef; +import li.strolch.policy.PolicyDefs; /** * @author Robert von Burg @@ -146,6 +147,9 @@ public abstract class StrolchElementToSaxVisitor { this.contentHandler.endElement(null, null, Tags.TIMED_STATE); } + if (resource.hasPolicyDefs()) + toSax(resource.getPolicyDefs()); + this.contentHandler.endElement(null, null, Tags.RESOURCE); } @@ -162,6 +166,9 @@ public abstract class StrolchElementToSaxVisitor { toSax((GroupedParameterizedElement) order); + if (order.hasPolicyDefs()) + toSax(order.getPolicyDefs()); + this.contentHandler.endElement(null, null, Tags.ORDER); } @@ -169,6 +176,9 @@ public abstract class StrolchElementToSaxVisitor { this.contentHandler.startElement(null, null, Tags.ACTIVITY, attributesFor(activity)); toSax((GroupedParameterizedElement) activity); + if (activity.hasPolicyDefs()) + toSax(activity.getPolicyDefs()); + Iterator> iter = activity.elementIterator(); while (iter.hasNext()) { IActivityElement activityElement = iter.next().getValue(); @@ -185,6 +195,26 @@ public abstract class StrolchElementToSaxVisitor { this.contentHandler.endElement(null, null, Tags.ACTIVITY); } + private void toSax(PolicyDefs policyDefs) throws SAXException { + if (!policyDefs.hasPolicyDefs()) + return; + + this.contentHandler.startElement(null, null, Tags.POLICIES, null); + for (String type : policyDefs.getPolicyTypes()) { + PolicyDef policyDef = policyDefs.getPolicyDef(type); + this.contentHandler.startElement(null, null, Tags.POLICY, attributesFor(policyDef)); + this.contentHandler.endElement(null, null, Tags.POLICY); + } + this.contentHandler.endElement(null, null, Tags.POLICIES); + } + + protected AttributesImpl attributesFor(PolicyDef policyDef) { + AttributesImpl attributes = new AttributesImpl(); + attributes.addAttribute(null, null, Tags.TYPE, Tags.CDATA, policyDef.getType()); + attributes.addAttribute(null, null, Tags.VALUE, Tags.CDATA, policyDef.getValueForXml()); + return attributes; + } + protected AttributesImpl attributesFor(Action action) { AttributesImpl attributes = attributesFor((StrolchElement) action); attributes.addAttribute(null, null, Tags.RESOURCE_ID, Tags.CDATA, action.getResourceId()); diff --git a/li.strolch.model/src/main/java/li/strolch/model/xml/XmlModelSaxReader.java b/li.strolch.model/src/main/java/li/strolch/model/xml/XmlModelSaxReader.java index 9b7788794..6d627fe82 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/xml/XmlModelSaxReader.java +++ b/li.strolch.model/src/main/java/li/strolch/model/xml/XmlModelSaxReader.java @@ -20,7 +20,16 @@ import java.util.ArrayDeque; import java.util.Date; import java.util.Deque; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import ch.eitchnet.utils.helper.StringHelper; +import ch.eitchnet.utils.iso8601.ISO8601FormatFactory; import li.strolch.exception.StrolchException; +import li.strolch.exception.StrolchPolicyException; import li.strolch.model.GroupedParameterizedElement; import li.strolch.model.ModelStatistics; import li.strolch.model.Order; @@ -35,15 +44,8 @@ import li.strolch.model.parameter.Parameter; import li.strolch.model.timedstate.StrolchTimedState; import li.strolch.model.timevalue.IValue; import li.strolch.model.timevalue.impl.ValueChange; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; - -import ch.eitchnet.utils.helper.StringHelper; -import ch.eitchnet.utils.iso8601.ISO8601FormatFactory; +import li.strolch.policy.PolicyDef; +import li.strolch.policy.PolicyDefs; /** * @author Robert von Burg @@ -60,6 +62,7 @@ public class XmlModelSaxReader extends DefaultHandler { private ParameterBag pBag; private StrolchTimedState> state; private StrolchValueType stateType; + private PolicyDefs policies; public XmlModelSaxReader(StrolchElementListener listener) { this.listener = listener; @@ -174,8 +177,8 @@ public class XmlModelSaxReader extends DefaultHandler { String paramIndexS = attributes.getValue(Tags.INDEX); try { int index = StringHelper.isEmpty(paramIndexS) ? 0 : Integer.valueOf(paramIndexS); - boolean paramHidden = StringHelper.isEmpty(paramHiddenS) ? false : StringHelper - .parseBoolean(paramHiddenS); + boolean paramHidden = StringHelper.isEmpty(paramHiddenS) ? false + : StringHelper.parseBoolean(paramHiddenS); String paramUom = attributes.getValue(Tags.UOM); String paramInterpretation = attributes.getValue(Tags.INTERPRETATION); @@ -224,6 +227,22 @@ public class XmlModelSaxReader extends DefaultHandler { break; + case Tags.POLICIES: + + this.policies = new PolicyDefs(); + + break; + + case Tags.POLICY: + + String policyType = attributes.getValue(Tags.TYPE); + String policyValue = attributes.getValue(Tags.VALUE); + + PolicyDef policyDef = PolicyDef.valueOf(policyType, policyValue); + this.policies.addOrUpdate(policyDef); + + break; + default: throw new IllegalArgumentException(MessageFormat.format("The element ''{0}'' is unhandled!", qName)); //$NON-NLS-1$ } @@ -281,6 +300,22 @@ public class XmlModelSaxReader extends DefaultHandler { break; + case Tags.POLICIES: + + if (this.parameterizedElement instanceof Resource) { + ((Resource) this.parameterizedElement).setPolicyDefs(this.policies); + } else if (this.parameterizedElement instanceof Order) { + ((Order) this.parameterizedElement).setPolicyDefs(this.policies); + } else if (this.parameterizedElement instanceof Activity) { + ((Activity) this.parameterizedElement).setPolicyDefs(this.policies); + } else { + throw new StrolchPolicyException( + "Policies are currently not allowed on " + this.parameterizedElement.getClass()); + } + + this.policies = null; + + case Tags.POLICY: case Tags.PARAMETER: case Tags.INCLUDE_FILE: case Tags.VALUE: diff --git a/li.strolch.model/src/main/java/li/strolch/policy/JavaPolicyDef.java b/li.strolch.model/src/main/java/li/strolch/policy/JavaPolicyDef.java new file mode 100644 index 000000000..77b40db0a --- /dev/null +++ b/li.strolch.model/src/main/java/li/strolch/policy/JavaPolicyDef.java @@ -0,0 +1,45 @@ +/* + * Copyright 2015 Robert von Burg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package li.strolch.policy; + +/** + * Simple {@link PolicyDef} where the value references a concrete class which can simply be instantiated + * + * @author Robert von Burg + */ +public class JavaPolicyDef extends PolicyDef { + + public static final String XML_PREFIX = "java:"; + + public JavaPolicyDef(String type, String value) { + super(type, value); + } + + @Override + public T accept(PolicyDefVisitor visitor) { + return visitor.visit(this); + } + + @Override + public String getValueForXml() { + return XML_PREFIX + this.value; + } + + @Override + public JavaPolicyDef getClone() { + return new JavaPolicyDef(this.type, this.value); + } +} \ No newline at end of file diff --git a/li.strolch.model/src/main/java/li/strolch/policy/KeyPolicyDef.java b/li.strolch.model/src/main/java/li/strolch/policy/KeyPolicyDef.java new file mode 100644 index 000000000..1d43926d4 --- /dev/null +++ b/li.strolch.model/src/main/java/li/strolch/policy/KeyPolicyDef.java @@ -0,0 +1,47 @@ +/* + * Copyright 2015 Robert von Burg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package li.strolch.policy; + +/** + * This {@link PolicyDef} adds a further indirection in the resolving of a policy. In this {@link PolicyDef} the value + * is a key used to look up the concrete implementation. Where the look-up is performed depends on the + * {@link PolicyDefVisitor} + * + * @author Robert von Burg + */ +public class KeyPolicyDef extends PolicyDef { + + public static final String XML_PREFIX = "key:"; + + public KeyPolicyDef(String type, String value) { + super(type, value); + } + + @Override + public T accept(PolicyDefVisitor visitor) { + return visitor.visit(this); + } + + @Override + public String getValueForXml() { + return XML_PREFIX + this.value; + } + + @Override + public KeyPolicyDef getClone() { + return new KeyPolicyDef(this.type, this.value); + } +} \ No newline at end of file diff --git a/li.strolch.model/src/main/java/li/strolch/policy/PolicyDef.java b/li.strolch.model/src/main/java/li/strolch/policy/PolicyDef.java new file mode 100644 index 000000000..605952bef --- /dev/null +++ b/li.strolch.model/src/main/java/li/strolch/policy/PolicyDef.java @@ -0,0 +1,137 @@ +/* + * Copyright 2015 Robert von Burg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package li.strolch.policy; + +import li.strolch.exception.StrolchPolicyException; + +/** + *

+ * A Policy definition defines a reference to delegation + *

+ * + *

+ * The {@link #getType()} defines the policy interface which the value references a concrete implementation + *

+ * + *

+ * To actually resolve a policy, use a {@link PolicyDefVisitor} which handles difference resolving strategies + *

+ * + * @author Robert von Burg + */ +public abstract class PolicyDef { + protected String type; + protected String value; + + /** + * Create a new policy definition + * + * @param type + * @param value + */ + public PolicyDef(String type, String value) { + super(); + this.type = type; + this.value = value; + } + + /** + * Returns the type of policy being referenced, i.e. the interface + * + * @return the type of policy being referenced, i.e. the interface + */ + public String getType() { + return this.type; + } + + /** + * Returns which policy instance is being referenced + * + * @return which policy instance is being referenced + */ + public String getValue() { + return this.value; + } + + /** + * Resolves an instance to the policy. The {@link PolicyDefVisitor} handles the resolving of an actual policy + * implementation instantiating the found class and returning a new instance + * + * @param visitor + * @return + */ + public abstract T accept(PolicyDefVisitor visitor); + + /** + * Returns the value formatted for XML marshalling, so that the {@link #valueOf(String, String)} can then again + * parse the value and instantiate a concrete {@link PolicyDef} instance + * + * @return the value formatted for XML marshalling + */ + public abstract String getValueForXml(); + + /** + * Return a clone of this {@link PolicyDef} instance + * + * @return a clone of this {@link PolicyDef} instance + */ + public abstract PolicyDef getClone(); + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("PolicyDef [type="); + sb.append(this.type); + sb.append(", value="); + sb.append(this.value); + sb.append("]"); + return sb.toString(); + } + + /** + * Returns a {@link PolicyDef} instance which handles the given type of XML Value + * + * @param type + * the type + * @param xmlValue + * the XML formatted value with the prefix denoting the {@link PolicyDef} type + * + * @return a {@link PolicyDef} instance which handles the given type of XML Value + */ + public static PolicyDef valueOf(String type, String xmlValue) { + + if (xmlValue.startsWith(JavaPolicyDef.XML_PREFIX)) { + + String value = xmlValue.substring(JavaPolicyDef.XML_PREFIX.length()); + + try { + Class.forName(value); + } catch (ClassNotFoundException e) { + throw new StrolchPolicyException("Invalid policy configuration. Policy does not exist: " + value); + } + + return new JavaPolicyDef(type, value); + + } else if (xmlValue.startsWith(KeyPolicyDef.XML_PREFIX)) { + + String value = xmlValue.substring(KeyPolicyDef.XML_PREFIX.length()); + return new KeyPolicyDef(type, value); + + } else { + throw new StrolchPolicyException("Unhandled PolicyDef from xml value " + xmlValue); + } + } +} \ No newline at end of file diff --git a/li.strolch.model/src/main/java/li/strolch/policy/PolicyDefVisitor.java b/li.strolch.model/src/main/java/li/strolch/policy/PolicyDefVisitor.java new file mode 100644 index 000000000..4f351257e --- /dev/null +++ b/li.strolch.model/src/main/java/li/strolch/policy/PolicyDefVisitor.java @@ -0,0 +1,47 @@ +/* + * Copyright 2015 Robert von Burg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package li.strolch.policy; + +/** + * This is the visitor interface to resolve a policy from a {@link PolicyDef} + * + * @author Robert von Burg + */ +public interface PolicyDefVisitor { + + /** + * Resolves a policy instance by returning an instance of a Java class by instantiating it by the + * {@link PolicyDef#getValue()} defined on the {@link JavaPolicyDef} + * + * @param javaPolicyDef + * the {@link PolicyDef} referencing a Java Class + * + * @return an instance of the policy referenced by the {@link PolicyDef#getValue()} + */ + public T visit(JavaPolicyDef javaPolicyDef); + + /** + * This method resolves a Policy by further indirection. I.e. the {@link PolicyDef#getValue()} is a key to the + * actual implementation. Use this if many elements use the same policy and it is required to change the + * implementation easily + * + * @param keyPolicyDef + * the {@link PolicyDef} using a key to reference a policy + * + * @return an instance of the policy resolved by the key {@link PolicyDef#getValue()} + */ + public T visit(KeyPolicyDef keyPolicyDef); +} \ No newline at end of file diff --git a/li.strolch.model/src/main/java/li/strolch/policy/PolicyDefs.java b/li.strolch.model/src/main/java/li/strolch/policy/PolicyDefs.java new file mode 100644 index 000000000..2f4cd074e --- /dev/null +++ b/li.strolch.model/src/main/java/li/strolch/policy/PolicyDefs.java @@ -0,0 +1,101 @@ +/* + * Copyright 2015 Robert von Burg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package li.strolch.policy; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import ch.eitchnet.utils.dbc.DBC; +import li.strolch.exception.StrolchPolicyException; +import li.strolch.model.StrolchRootElement; + +/** + * The {@link PolicyDefs} contains the policy configuration of any {@link StrolchRootElement} which requires policies + * + * @author Robert von Burg + */ +public class PolicyDefs { + + private StrolchRootElement parent; + + private Map policyDefMap; + + public PolicyDefs() { + this.policyDefMap = new HashMap<>(0); + } + + public void setParent(StrolchRootElement parent) { + this.parent = parent; + } + + public StrolchRootElement getParent() { + return this.parent; + } + + public Set getPolicyTypes() { + return this.policyDefMap.keySet(); + } + + public PolicyDef getPolicyDef(String type) { + if (!this.policyDefMap.containsKey(type)) { + throw new StrolchPolicyException( + "The PolicyDef does not exist with type " + type + " on " + this.parent.getLocator()); + } + return this.policyDefMap.get(type); + } + + public boolean hasPolicyDef(String type) { + return this.policyDefMap.containsKey(type); + } + + public boolean hasPolicyDefs() { + return !this.policyDefMap.isEmpty(); + } + + public void addOrUpdate(PolicyDef policyDef) { + DBC.PRE.assertNotNull("policyDef", policyDef); + this.policyDefMap.put(policyDef.getType(), policyDef); + } + + public void remove(String type) { + this.policyDefMap.remove(type); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("PolicyDefs [parent="); + sb.append(this.parent == null ? "null" : this.parent.getLocator()); + sb.append(", policyDefMap="); + sb.append(this.policyDefMap); + sb.append("]"); + return sb.toString(); + } + + /** + * Returns a clone of this {@link PolicyDefs} + * + * @return a clone of this {@link PolicyDefs} + */ + public PolicyDefs getClone() { + PolicyDefs clone = new PolicyDefs(); + for (PolicyDef policyDef : this.policyDefMap.values()) { + clone.addOrUpdate(policyDef.getClone()); + } + return clone; + } +} diff --git a/li.strolch.model/src/test/java/li/strolch/model/XmlToDomTest.java b/li.strolch.model/src/test/java/li/strolch/model/XmlToDomTest.java index 9f6a652d8..56505d3eb 100644 --- a/li.strolch.model/src/test/java/li/strolch/model/XmlToDomTest.java +++ b/li.strolch.model/src/test/java/li/strolch/model/XmlToDomTest.java @@ -16,6 +16,10 @@ package li.strolch.model; import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.w3c.dom.Document; + import li.strolch.model.activity.Activity; import li.strolch.model.visitor.ActivityDeepEqualsVisitor; import li.strolch.model.visitor.OrderDeepEqualsVisitor; @@ -27,9 +31,6 @@ import li.strolch.model.xml.OrderToDomVisitor; import li.strolch.model.xml.ResourceFromDomVisitor; import li.strolch.model.xml.ResourceToDomVisitor; -import org.junit.Test; -import org.w3c.dom.Document; - /** * @author Robert von Burg */ @@ -65,7 +66,8 @@ public class XmlToDomTest extends ModelTest { ResourceDeepEqualsVisitor visitor = new ResourceDeepEqualsVisitor(resource); visitor.visit(parsedResource); - assertTrue("To DOM and back should equal same Resource:\n" + visitor.getMismatchedLocators(), visitor.isEqual()); + assertTrue("To DOM and back should equal same Resource:\n" + visitor.getMismatchedLocators(), + visitor.isEqual()); } @Test @@ -79,9 +81,9 @@ public class XmlToDomTest extends ModelTest { Activity parsedActivity = new ActivityFromDomVisitor().visit(document); - ActivityDeepEqualsVisitor visitor = new ActivityDeepEqualsVisitor(parsedActivity); + ActivityDeepEqualsVisitor visitor = new ActivityDeepEqualsVisitor(activity); visitor.visit(parsedActivity); - assertTrue("To DOM and back should equal same Activity:\n" + visitor.getMismatchedLocators(), visitor.isEqual()); + assertTrue("To DOM and back should equal same Activity:\n" + visitor.getMismatchedLocators(), + visitor.isEqual()); } - } diff --git a/li.strolch.model/src/test/resources/data/resources/Templates.xml b/li.strolch.model/src/test/resources/data/resources/Templates.xml index f122f0346..bac3dbea6 100644 --- a/li.strolch.model/src/test/resources/data/resources/Templates.xml +++ b/li.strolch.model/src/test/resources/data/resources/Templates.xml @@ -10,5 +10,10 @@ + + + + + diff --git a/li.strolch.testbase/src/main/java/li/strolch/testbase/runtime/RuntimeMock.java b/li.strolch.testbase/src/main/java/li/strolch/testbase/runtime/RuntimeMock.java index 757aa84f3..1dfe229e7 100644 --- a/li.strolch.testbase/src/main/java/li/strolch/testbase/runtime/RuntimeMock.java +++ b/li.strolch.testbase/src/main/java/li/strolch/testbase/runtime/RuntimeMock.java @@ -43,8 +43,8 @@ public final class RuntimeMock { private ComponentContainer container; private StrolchAgent agent; - private File rootPath; - private File rootSrc; + private File targetPathF; + private File srcPathF; public ComponentContainer getContainer() { return this.container; @@ -66,18 +66,18 @@ public final class RuntimeMock { return this.container.getRealm(realm); } - public void mockRuntime(File rootPath, File rootSrc) { + public void mockRuntime(File targetPathF, File srcPathF) { - this.rootPath = rootPath; - this.rootSrc = rootSrc; + this.targetPathF = targetPathF; + this.srcPathF = srcPathF; - if (!this.rootPath.getParentFile().getName().equals(TARGET)) { + if (!this.targetPathF.getParentFile().getName().equals(TARGET)) { String msg = "Mocking path must be in a maven target: {0}"; //$NON-NLS-1$ - msg = MessageFormat.format(msg, this.rootPath.getAbsolutePath()); + msg = MessageFormat.format(msg, this.targetPathF.getAbsolutePath()); throw new RuntimeException(msg); } - File configSrc = new File(this.rootSrc, RuntimeConfiguration.PATH_CONFIG); + File configSrc = new File(this.srcPathF, RuntimeConfiguration.PATH_CONFIG); if (!configSrc.isDirectory() || !configSrc.canRead()) { String msg = "Could not find config source in: {0}"; //$NON-NLS-1$ @@ -85,27 +85,27 @@ public final class RuntimeMock { throw new RuntimeException(msg); } - if (this.rootPath.exists()) { - logger.info("Deleting all files in " + this.rootPath.getAbsolutePath()); //$NON-NLS-1$ - if (!FileHelper.deleteFile(this.rootPath, true)) { + if (this.targetPathF.exists()) { + logger.info("Deleting all files in " + this.targetPathF.getAbsolutePath()); //$NON-NLS-1$ + if (!FileHelper.deleteFile(this.targetPathF, true)) { String msg = "Failed to delete {0}"; //$NON-NLS-1$ - msg = MessageFormat.format(msg, this.rootPath.getAbsolutePath()); + msg = MessageFormat.format(msg, this.targetPathF.getAbsolutePath()); throw new RuntimeException(msg); } } - if (!this.rootPath.mkdirs()) { + if (!this.targetPathF.mkdirs()) { String msg = "Failed to create {0}"; //$NON-NLS-1$ - msg = MessageFormat.format(msg, this.rootPath.getAbsolutePath()); + msg = MessageFormat.format(msg, this.targetPathF.getAbsolutePath()); throw new RuntimeException(msg); } - logger.info(MessageFormat.format("Mocking runtime from {0} to {1}", this.rootSrc.getAbsolutePath(), //$NON-NLS-1$ - this.rootPath.getAbsolutePath())); + logger.info(MessageFormat.format("Mocking runtime from {0} to {1}", this.srcPathF.getAbsolutePath(), //$NON-NLS-1$ + this.targetPathF.getAbsolutePath())); - if (!FileHelper.copy(this.rootSrc.listFiles(), this.rootPath, false)) { + if (!FileHelper.copy(this.srcPathF.listFiles(), this.targetPathF, false)) { String msg = "Failed to copy source files from {0} to {1}"; //$NON-NLS-1$ - msg = MessageFormat.format(msg, this.rootSrc.getAbsolutePath(), this.rootPath.getAbsolutePath()); + msg = MessageFormat.format(msg, this.srcPathF.getAbsolutePath(), this.targetPathF.getAbsolutePath()); throw new RuntimeException(msg); } } @@ -118,7 +118,7 @@ public final class RuntimeMock { try { StrolchAgent agent = new StrolchAgent(); - agent.setup(environment, this.rootPath); + agent.setup(environment, this.targetPathF); agent.initialize(); agent.start();