diff --git a/ch.eitchnet.utils b/ch.eitchnet.utils index 1689ff69a..2e58db83f 160000 --- a/ch.eitchnet.utils +++ b/ch.eitchnet.utils @@ -1 +1 @@ -Subproject commit 1689ff69a93f7fcf491400e36b941c905d368018 +Subproject commit 2e58db83fd35fea958431d7a2e9edae14ff6a20b diff --git a/ch.eitchnet.xmlpers b/ch.eitchnet.xmlpers index f72ff76b4..6659b90b8 160000 --- a/ch.eitchnet.xmlpers +++ b/ch.eitchnet.xmlpers @@ -1 +1 @@ -Subproject commit f72ff76b406f2675cf194174aa35872d0c969ab6 +Subproject commit 6659b90b83aa253e79e9a705c42e9c0e3b3fd63c diff --git a/li.strolch.agent/src/main/java/li/strolch/agent/api/ActivityMap.java b/li.strolch.agent/src/main/java/li/strolch/agent/api/ActivityMap.java new file mode 100644 index 000000000..9fe310a1f --- /dev/null +++ b/li.strolch.agent/src/main/java/li/strolch/agent/api/ActivityMap.java @@ -0,0 +1,31 @@ +/* + * 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.agent.api; + +import java.util.List; + +import li.strolch.model.ActivityVisitor; +import li.strolch.model.activity.Activity; +import li.strolch.model.query.ActivityQuery; +import li.strolch.persistence.api.StrolchTransaction; + +/** + * @author Robert von Burg + */ +public interface ActivityMap extends ElementMap { + + public List doQuery(StrolchTransaction tx, ActivityQuery query, ActivityVisitor activityVisitor); +} diff --git a/li.strolch.agent/src/main/java/li/strolch/agent/impl/AuditingActivityMap.java b/li.strolch.agent/src/main/java/li/strolch/agent/impl/AuditingActivityMap.java new file mode 100644 index 000000000..56bdd9c6e --- /dev/null +++ b/li.strolch.agent/src/main/java/li/strolch/agent/impl/AuditingActivityMap.java @@ -0,0 +1,57 @@ +/* + * 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.agent.impl; + +import java.util.List; + +import li.strolch.agent.api.ActivityMap; +import li.strolch.agent.api.AuditTrail; +import li.strolch.agent.api.ElementMap; +import li.strolch.model.ActivityVisitor; +import li.strolch.model.activity.Activity; +import li.strolch.model.query.ActivityQuery; +import li.strolch.persistence.api.StrolchTransaction; + +/** + * This is the {@link AuditTrail} for {@link Activity Activities} + * + * @author Robert von Burg + * + * @see AuditingElementMapFacade + */ +public class AuditingActivityMap extends AuditingElementMapFacade implements ActivityMap { + + /** + * @param elementMap + */ + public AuditingActivityMap(ElementMap elementMap, boolean observeAccessReads) { + super(elementMap, observeAccessReads); + } + + @Override + protected ActivityMap getElementMap() { + return (ActivityMap) super.getElementMap(); + } + + @Override + public List doQuery(StrolchTransaction tx, ActivityQuery query, ActivityVisitor activityVisitor) { + List result = getElementMap().doQuery(tx, query, activity -> { + this.read.add(activity); + return activityVisitor.visit(activity); + }); + return result; + } +} diff --git a/li.strolch.agent/src/main/java/li/strolch/agent/impl/CachedActivityMap.java b/li.strolch.agent/src/main/java/li/strolch/agent/impl/CachedActivityMap.java new file mode 100644 index 000000000..5bf7dc7a9 --- /dev/null +++ b/li.strolch.agent/src/main/java/li/strolch/agent/impl/CachedActivityMap.java @@ -0,0 +1,59 @@ +/* + * 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.agent.impl; + +import static li.strolch.model.StrolchModelConstants.INTERPRETATION_ACTIVITY_REF; + +import java.util.List; + +import li.strolch.agent.api.ActivityMap; +import li.strolch.model.ActivityVisitor; +import li.strolch.model.activity.Activity; +import li.strolch.model.parameter.Parameter; +import li.strolch.model.query.ActivityQuery; +import li.strolch.persistence.api.ActivityDao; +import li.strolch.persistence.api.StrolchTransaction; +import li.strolch.persistence.inmemory.InMemoryActivityDao; + +public class CachedActivityMap extends CachedElementMap implements ActivityMap { + + private ActivityDao cachedDao; + + public CachedActivityMap() { + super(); + this.cachedDao = new InMemoryActivityDao(); + } + + @Override + protected void assertIsRefParam(Parameter refP) { + ElementMapHelpers.assertIsRefParam(INTERPRETATION_ACTIVITY_REF, refP); + } + + @Override + protected ActivityDao getDbDao(StrolchTransaction tx) { + return tx.getPersistenceHandler().getActivityDao(tx); + } + + @Override + public ActivityDao getCachedDao() { + return this.cachedDao; + } + + @Override + public List doQuery(StrolchTransaction tx, ActivityQuery query, ActivityVisitor activityVisitor) { + return getCachedDao().doQuery(query, activityVisitor); + } +} diff --git a/li.strolch.agent/src/main/java/li/strolch/agent/impl/CachedOrderMap.java b/li.strolch.agent/src/main/java/li/strolch/agent/impl/CachedOrderMap.java index cde783d74..76ee49584 100644 --- a/li.strolch.agent/src/main/java/li/strolch/agent/impl/CachedOrderMap.java +++ b/li.strolch.agent/src/main/java/li/strolch/agent/impl/CachedOrderMap.java @@ -16,13 +16,10 @@ package li.strolch.agent.impl; import static li.strolch.model.StrolchModelConstants.INTERPRETATION_ORDER_REF; -import static li.strolch.model.StrolchModelConstants.UOM_NONE; -import java.text.MessageFormat; import java.util.List; import li.strolch.agent.api.OrderMap; -import li.strolch.exception.StrolchException; import li.strolch.model.Order; import li.strolch.model.OrderVisitor; import li.strolch.model.parameter.Parameter; @@ -42,18 +39,7 @@ public class CachedOrderMap extends CachedElementMap implements OrderMap @Override protected void assertIsRefParam(Parameter refP) { - - String interpretation = refP.getInterpretation(); - if (!interpretation.equals(INTERPRETATION_ORDER_REF)) { - String msg = "{0} is not an Order reference as its interpretation is not {1} it is {2}"; //$NON-NLS-1$ - throw new StrolchException(MessageFormat.format(msg, refP.getLocator(), INTERPRETATION_ORDER_REF, - interpretation)); - } - - if (refP.getUom().equals(UOM_NONE)) { - String msg = "{0} is not an Order reference as its UOM is not set to a type!"; //$NON-NLS-1$ - throw new StrolchException(MessageFormat.format(msg, refP.getLocator())); - } + ElementMapHelpers.assertIsRefParam(INTERPRETATION_ORDER_REF, refP); } @Override diff --git a/li.strolch.agent/src/main/java/li/strolch/agent/impl/CachedRealm.java b/li.strolch.agent/src/main/java/li/strolch/agent/impl/CachedRealm.java index 6291b6718..b3384bbf8 100644 --- a/li.strolch.agent/src/main/java/li/strolch/agent/impl/CachedRealm.java +++ b/li.strolch.agent/src/main/java/li/strolch/agent/impl/CachedRealm.java @@ -19,12 +19,15 @@ import java.text.MessageFormat; import java.util.List; import java.util.Set; +import li.strolch.agent.api.ActivityMap; import li.strolch.agent.api.AuditTrail; import li.strolch.agent.api.ComponentContainer; import li.strolch.agent.api.OrderMap; import li.strolch.agent.api.ResourceMap; import li.strolch.model.Order; import li.strolch.model.Resource; +import li.strolch.model.activity.Activity; +import li.strolch.persistence.api.ActivityDao; import li.strolch.persistence.api.OrderDao; import li.strolch.persistence.api.PersistenceHandler; import li.strolch.persistence.api.ResourceDao; @@ -43,6 +46,7 @@ public class CachedRealm extends InternalStrolchRealm { private PersistenceHandler persistenceHandler; private CachedResourceMap resourceMap; private CachedOrderMap orderMap; + private CachedActivityMap activityMap; private AuditTrail auditTrail; public CachedRealm(String realm) { @@ -76,6 +80,11 @@ public class CachedRealm extends InternalStrolchRealm { return this.orderMap; } + @Override + public ActivityMap getActivityMap() { + return this.activityMap; + } + @Override public AuditTrail getAuditTrail() { return this.auditTrail; @@ -88,6 +97,7 @@ public class CachedRealm extends InternalStrolchRealm { this.persistenceHandler = container.getComponent(PersistenceHandler.class); this.resourceMap = new CachedResourceMap(); this.orderMap = new CachedOrderMap(); + this.activityMap = new CachedActivityMap(); if (isAuditTrailEnabled()) { this.auditTrail = new CachedAuditTrail(); @@ -104,6 +114,7 @@ public class CachedRealm extends InternalStrolchRealm { long start = System.nanoTime(); int nrOfOrders = 0; int nrOfResources = 0; + int nrOfActivities = 0; try (StrolchTransaction tx = openTx(privilegeContext.getCertificate(), DefaultRealmHandler.AGENT_BOOT)) { ResourceDao resourceDao = tx.getPersistenceHandler().getResourceDao(tx); @@ -133,11 +144,26 @@ public class CachedRealm extends InternalStrolchRealm { tx.commitOnClose(); } + try (StrolchTransaction tx = openTx(privilegeContext.getCertificate(), DefaultRealmHandler.AGENT_BOOT)) { + ActivityDao activityDao = tx.getPersistenceHandler().getActivityDao(tx); + Set activityTypes = activityDao.queryTypes(); + for (String type : activityTypes) { + List activities = activityDao.queryAll(type); + for (Activity activity : activities) { + this.activityMap.insert(activity); + nrOfActivities++; + } + } + + tx.commitOnClose(); + } + long duration = System.nanoTime() - start; String durationS = StringHelper.formatNanoDuration(duration); logger.info(MessageFormat.format("Loading Model from Database for realm {0} took {1}.", getRealm(), durationS)); //$NON-NLS-1$ logger.info(MessageFormat.format("Loaded {0} Orders", nrOfOrders)); //$NON-NLS-1$ logger.info(MessageFormat.format("Loaded {0} Resources", nrOfResources)); //$NON-NLS-1$ + logger.info(MessageFormat.format("Loaded {0} Activities", nrOfActivities)); //$NON-NLS-1$ } @Override diff --git a/li.strolch.agent/src/main/java/li/strolch/agent/impl/CachedResourceMap.java b/li.strolch.agent/src/main/java/li/strolch/agent/impl/CachedResourceMap.java index c719d0c31..f67a9eaa2 100644 --- a/li.strolch.agent/src/main/java/li/strolch/agent/impl/CachedResourceMap.java +++ b/li.strolch.agent/src/main/java/li/strolch/agent/impl/CachedResourceMap.java @@ -16,13 +16,10 @@ package li.strolch.agent.impl; import static li.strolch.model.StrolchModelConstants.INTERPRETATION_RESOURCE_REF; -import static li.strolch.model.StrolchModelConstants.UOM_NONE; -import java.text.MessageFormat; import java.util.List; import li.strolch.agent.api.ResourceMap; -import li.strolch.exception.StrolchException; import li.strolch.model.Resource; import li.strolch.model.ResourceVisitor; import li.strolch.model.parameter.Parameter; @@ -42,20 +39,7 @@ public class CachedResourceMap extends CachedElementMap implements Res @Override protected void assertIsRefParam(Parameter refP) { - - String interpretation = refP.getInterpretation(); - if (!interpretation.equals(INTERPRETATION_RESOURCE_REF)) { - String msg = MessageFormat.format( - "{0} is not an Resource reference as its interpretation is not {1} it is {2}", //$NON-NLS-1$ - refP.getLocator(), INTERPRETATION_RESOURCE_REF, interpretation); - throw new StrolchException(msg); - } - - if (refP.getUom().equals(UOM_NONE)) { - String msg = MessageFormat.format("{0} is not an Resource reference as its UOM is not set to a type!", //$NON-NLS-1$ - refP.getLocator()); - throw new StrolchException(msg); - } + ElementMapHelpers.assertIsRefParam(INTERPRETATION_RESOURCE_REF, refP); } @Override diff --git a/li.strolch.agent/src/main/java/li/strolch/agent/impl/ElementMapHelpers.java b/li.strolch.agent/src/main/java/li/strolch/agent/impl/ElementMapHelpers.java new file mode 100644 index 000000000..42d8204b0 --- /dev/null +++ b/li.strolch.agent/src/main/java/li/strolch/agent/impl/ElementMapHelpers.java @@ -0,0 +1,44 @@ +/* + * 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.agent.impl; + +import static li.strolch.model.StrolchModelConstants.UOM_NONE; + +import java.text.MessageFormat; + +import li.strolch.exception.StrolchException; +import li.strolch.model.parameter.Parameter; + +/** + * @author Robert von Burg + */ +class ElementMapHelpers { + + public static void assertIsRefParam(String expectedInterpretation, Parameter refP) { + + String interpretation = refP.getInterpretation(); + if (!interpretation.equals(expectedInterpretation)) { + String msg = "{0} is not an expected element reference as its interpretation is {1} instead of {2}"; //$NON-NLS-1$ + throw new StrolchException(MessageFormat.format(msg, refP.getLocator(), expectedInterpretation, + interpretation)); + } + + if (refP.getUom().equals(UOM_NONE)) { + String msg = "{0} is not an expected element reference as its UOM is not set to a type it is set to {1}!"; //$NON-NLS-1$ + throw new StrolchException(MessageFormat.format(msg, refP.getLocator(), UOM_NONE)); + } + } +} diff --git a/li.strolch.agent/src/main/java/li/strolch/agent/impl/EmptyRealm.java b/li.strolch.agent/src/main/java/li/strolch/agent/impl/EmptyRealm.java index 33d2e0bbd..9801b2368 100644 --- a/li.strolch.agent/src/main/java/li/strolch/agent/impl/EmptyRealm.java +++ b/li.strolch.agent/src/main/java/li/strolch/agent/impl/EmptyRealm.java @@ -17,6 +17,7 @@ package li.strolch.agent.impl; import java.text.MessageFormat; +import li.strolch.agent.api.ActivityMap; import li.strolch.agent.api.AuditTrail; import li.strolch.agent.api.ComponentContainer; import li.strolch.agent.api.OrderMap; @@ -37,6 +38,7 @@ public class EmptyRealm extends InternalStrolchRealm { private ResourceMap resourceMap; private OrderMap orderMap; + private ActivityMap activityMap; private AuditTrail auditTrail; private PersistenceHandler persistenceHandler; @@ -71,6 +73,11 @@ public class EmptyRealm extends InternalStrolchRealm { return this.orderMap; } + @Override + public ActivityMap getActivityMap() { + return this.activityMap; + } + @Override public AuditTrail getAuditTrail() { return this.auditTrail; diff --git a/li.strolch.agent/src/main/java/li/strolch/agent/impl/InMemoryElementListener.java b/li.strolch.agent/src/main/java/li/strolch/agent/impl/InMemoryElementListener.java index d3c92ee74..8a818f23d 100644 --- a/li.strolch.agent/src/main/java/li/strolch/agent/impl/InMemoryElementListener.java +++ b/li.strolch.agent/src/main/java/li/strolch/agent/impl/InMemoryElementListener.java @@ -18,10 +18,12 @@ package li.strolch.agent.impl; import java.util.Collections; import java.util.Set; +import li.strolch.agent.api.ActivityMap; import li.strolch.agent.api.OrderMap; import li.strolch.agent.api.ResourceMap; import li.strolch.model.Order; import li.strolch.model.Resource; +import li.strolch.model.activity.Activity; import li.strolch.model.xml.StrolchElementListener; import li.strolch.persistence.api.StrolchTransaction; @@ -32,26 +34,34 @@ public class InMemoryElementListener implements StrolchElementListener { private boolean addOrders; private boolean addResources; + private boolean addActivities; private boolean updateOrders; private boolean updateResources; + private boolean updateActivities; private Set orderTypes; private Set resourceTypes; + private Set activityTypes; private StrolchTransaction tx; private ResourceMap resourceMap; private OrderMap orderMap; + private ActivityMap activityMap; public InMemoryElementListener(StrolchTransaction tx) { this.tx = tx; this.resourceMap = tx.getResourceMap(); this.orderMap = tx.getOrderMap(); + this.activityMap = tx.getActivityMap(); this.addResources = true; this.addOrders = true; + this.addActivities = true; this.updateResources = true; this.updateOrders = true; + this.updateActivities = true; this.orderTypes = Collections.emptySet(); this.resourceTypes = Collections.emptySet(); + this.activityTypes = Collections.emptySet(); } /** @@ -70,6 +80,14 @@ public class InMemoryElementListener implements StrolchElementListener { this.addOrders = addOrders; } + /** + * @param addActivities + * the addActivities to set + */ + public void setAddActivities(boolean addActivities) { + this.addActivities = addActivities; + } + /** * @param updateResources * the updateResources to set @@ -86,6 +104,14 @@ public class InMemoryElementListener implements StrolchElementListener { this.updateOrders = updateOrders; } + /** + * @param updateActivities + * the updateActivities to set + */ + public void setUpdateActivities(boolean updateActivities) { + this.updateActivities = updateActivities; + } + /** * @param orderTypes * the orderTypes to set @@ -102,6 +128,14 @@ public class InMemoryElementListener implements StrolchElementListener { this.resourceTypes = resourceTypes; } + /** + * @param activityTypes + * the activityTypes to set + */ + public void setActivityTypes(Set activityTypes) { + this.activityTypes = activityTypes; + } + @Override public void notifyResource(Resource resource) { if (!this.resourceTypes.isEmpty() && !this.resourceTypes.contains(resource.getType())) @@ -129,4 +163,18 @@ public class InMemoryElementListener implements StrolchElementListener { this.orderMap.add(this.tx, order); } } + + @Override + public void notifyActivity(Activity activity) { + if (!this.activityTypes.isEmpty() && !this.activityTypes.contains(activity.getType())) + return; + + if (this.activityMap.hasElement(this.tx, activity.getType(), activity.getId())) { + if (this.updateActivities) { + this.activityMap.update(this.tx, activity); + } + } else if (this.addActivities) { + this.activityMap.add(this.tx, activity); + } + } } diff --git a/li.strolch.agent/src/main/java/li/strolch/agent/impl/InternalStrolchRealm.java b/li.strolch.agent/src/main/java/li/strolch/agent/impl/InternalStrolchRealm.java index 1fc60dfb6..bba2e338a 100644 --- a/li.strolch.agent/src/main/java/li/strolch/agent/impl/InternalStrolchRealm.java +++ b/li.strolch.agent/src/main/java/li/strolch/agent/impl/InternalStrolchRealm.java @@ -18,6 +18,7 @@ package li.strolch.agent.impl; import java.text.MessageFormat; import java.util.concurrent.TimeUnit; +import li.strolch.agent.api.ActivityMap; import li.strolch.agent.api.AuditTrail; import li.strolch.agent.api.ComponentContainer; import li.strolch.agent.api.LockHandler; @@ -132,6 +133,8 @@ public abstract class InternalStrolchRealm implements StrolchRealm { public abstract OrderMap getOrderMap(); + public abstract ActivityMap getActivityMap(); + public abstract AuditTrail getAuditTrail(); } diff --git a/li.strolch.agent/src/main/java/li/strolch/agent/impl/StoreToDaoElementListener.java b/li.strolch.agent/src/main/java/li/strolch/agent/impl/StoreToDaoElementListener.java index a151f8b43..b48cbc000 100644 --- a/li.strolch.agent/src/main/java/li/strolch/agent/impl/StoreToDaoElementListener.java +++ b/li.strolch.agent/src/main/java/li/strolch/agent/impl/StoreToDaoElementListener.java @@ -17,7 +17,9 @@ package li.strolch.agent.impl; import li.strolch.model.Order; import li.strolch.model.Resource; +import li.strolch.model.activity.Activity; import li.strolch.model.xml.StrolchElementListener; +import li.strolch.persistence.api.ActivityDao; import li.strolch.persistence.api.OrderDao; import li.strolch.persistence.api.ResourceDao; import li.strolch.persistence.api.StrolchTransaction; @@ -27,11 +29,13 @@ public class StoreToDaoElementListener implements StrolchElementListener { private StrolchTransaction tx; private ResourceDao resourceDao; private OrderDao orderDao; + private ActivityDao activityDao; public StoreToDaoElementListener(StrolchTransaction tx) { this.tx = tx; this.resourceDao = tx.getPersistenceHandler().getResourceDao(this.tx); this.orderDao = tx.getPersistenceHandler().getOrderDao(this.tx); + this.activityDao = tx.getPersistenceHandler().getActivityDao(this.tx); } @Override @@ -43,4 +47,9 @@ public class StoreToDaoElementListener implements StrolchElementListener { public void notifyOrder(Order order) { this.orderDao.save(order); } + + @Override + public void notifyActivity(Activity activity) { + this.activityDao.save(activity); + } } \ No newline at end of file diff --git a/li.strolch.agent/src/main/java/li/strolch/agent/impl/TransactionalActivityMap.java b/li.strolch.agent/src/main/java/li/strolch/agent/impl/TransactionalActivityMap.java new file mode 100644 index 000000000..3b06a72ec --- /dev/null +++ b/li.strolch.agent/src/main/java/li/strolch/agent/impl/TransactionalActivityMap.java @@ -0,0 +1,46 @@ +/* + * 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.agent.impl; + +import static li.strolch.model.StrolchModelConstants.INTERPRETATION_ACTIVITY_REF; + +import java.util.List; + +import li.strolch.agent.api.ActivityMap; +import li.strolch.model.ActivityVisitor; +import li.strolch.model.activity.Activity; +import li.strolch.model.parameter.Parameter; +import li.strolch.model.query.ActivityQuery; +import li.strolch.persistence.api.ActivityDao; +import li.strolch.persistence.api.StrolchTransaction; + +public class TransactionalActivityMap extends TransactionalElementMap implements ActivityMap { + + @Override + protected void assertIsRefParam(Parameter refP) { + ElementMapHelpers.assertIsRefParam(INTERPRETATION_ACTIVITY_REF, refP); + } + + @Override + protected ActivityDao getDao(StrolchTransaction tx) { + return tx.getPersistenceHandler().getActivityDao(tx); + } + + @Override + public List doQuery(StrolchTransaction tx, ActivityQuery query, ActivityVisitor activityVisitor) { + return getDao(tx).doQuery(query, activityVisitor); + } +} diff --git a/li.strolch.agent/src/main/java/li/strolch/agent/impl/TransactionalOrderMap.java b/li.strolch.agent/src/main/java/li/strolch/agent/impl/TransactionalOrderMap.java index 76ddb40fd..ccb2bcc36 100644 --- a/li.strolch.agent/src/main/java/li/strolch/agent/impl/TransactionalOrderMap.java +++ b/li.strolch.agent/src/main/java/li/strolch/agent/impl/TransactionalOrderMap.java @@ -16,13 +16,10 @@ package li.strolch.agent.impl; import static li.strolch.model.StrolchModelConstants.INTERPRETATION_ORDER_REF; -import static li.strolch.model.StrolchModelConstants.UOM_NONE; -import java.text.MessageFormat; import java.util.List; import li.strolch.agent.api.OrderMap; -import li.strolch.exception.StrolchException; import li.strolch.model.Order; import li.strolch.model.OrderVisitor; import li.strolch.model.parameter.Parameter; @@ -34,18 +31,7 @@ public class TransactionalOrderMap extends TransactionalElementMap implem @Override protected void assertIsRefParam(Parameter refP) { - - String interpretation = refP.getInterpretation(); - if (!interpretation.equals(INTERPRETATION_ORDER_REF)) { - String msg = "{0} is not an Order reference as its interpretation is not {1} it is {2}"; //$NON-NLS-1$ - throw new StrolchException(MessageFormat.format(msg, refP.getLocator(), INTERPRETATION_ORDER_REF, - interpretation)); - } - - if (refP.getUom().equals(UOM_NONE)) { - String msg = "{0} is not an Order reference as its UOM is not set to a type!"; //$NON-NLS-1$ - throw new StrolchException(MessageFormat.format(msg, refP.getLocator())); - } + ElementMapHelpers.assertIsRefParam(INTERPRETATION_ORDER_REF, refP); } @Override diff --git a/li.strolch.agent/src/main/java/li/strolch/agent/impl/TransactionalRealm.java b/li.strolch.agent/src/main/java/li/strolch/agent/impl/TransactionalRealm.java index 56a1b8a4e..bd7cfd173 100644 --- a/li.strolch.agent/src/main/java/li/strolch/agent/impl/TransactionalRealm.java +++ b/li.strolch.agent/src/main/java/li/strolch/agent/impl/TransactionalRealm.java @@ -17,6 +17,7 @@ package li.strolch.agent.impl; import java.text.MessageFormat; +import li.strolch.agent.api.ActivityMap; import li.strolch.agent.api.AuditTrail; import li.strolch.agent.api.ComponentContainer; import li.strolch.agent.api.OrderMap; @@ -36,6 +37,7 @@ public class TransactionalRealm extends InternalStrolchRealm { private ResourceMap resourceMap; private OrderMap orderMap; + private ActivityMap activityMap; private AuditTrail auditTrail; private PersistenceHandler persistenceHandler; @@ -70,6 +72,11 @@ public class TransactionalRealm extends InternalStrolchRealm { return this.orderMap; } + @Override + public ActivityMap getActivityMap() { + return this.activityMap; + } + @Override public AuditTrail getAuditTrail() { return this.auditTrail; @@ -80,6 +87,7 @@ public class TransactionalRealm extends InternalStrolchRealm { super.initialize(container, configuration); this.resourceMap = new TransactionalResourceMap(); this.orderMap = new TransactionalOrderMap(); + this.activityMap = new TransactionalActivityMap(); if (isAuditTrailEnabled()) { this.auditTrail = new TransactionalAuditTrail(); @@ -98,6 +106,7 @@ public class TransactionalRealm extends InternalStrolchRealm { long start = System.nanoTime(); int nrOfOrders = 0; int nrOfResources = 0; + int nrOfActivities = 0; try (StrolchTransaction tx = openTx(privilegeContext.getCertificate(), DefaultRealmHandler.AGENT_BOOT)) { nrOfOrders = this.orderMap.getAllKeys(tx).size(); @@ -107,12 +116,17 @@ public class TransactionalRealm extends InternalStrolchRealm { nrOfResources = this.resourceMap.getAllKeys(tx).size(); } + try (StrolchTransaction tx = openTx(privilegeContext.getCertificate(), DefaultRealmHandler.AGENT_BOOT)) { + nrOfActivities = this.activityMap.getAllKeys(tx).size(); + } + long duration = System.nanoTime() - start; String durationS = StringHelper.formatNanoDuration(duration); logger.info(MessageFormat.format( "Initialized Transactional Maps for realm {0} took {1}.", getRealm(), durationS)); //$NON-NLS-1$ logger.info(MessageFormat.format("There are {0} Orders", nrOfOrders)); //$NON-NLS-1$ logger.info(MessageFormat.format("There are {0} Resources", nrOfResources)); //$NON-NLS-1$ + logger.info(MessageFormat.format("There are {0} Activities", nrOfActivities)); //$NON-NLS-1$ } @Override diff --git a/li.strolch.agent/src/main/java/li/strolch/agent/impl/TransactionalResourceMap.java b/li.strolch.agent/src/main/java/li/strolch/agent/impl/TransactionalResourceMap.java index 6b93b56a6..6f6eeebfa 100644 --- a/li.strolch.agent/src/main/java/li/strolch/agent/impl/TransactionalResourceMap.java +++ b/li.strolch.agent/src/main/java/li/strolch/agent/impl/TransactionalResourceMap.java @@ -16,13 +16,10 @@ package li.strolch.agent.impl; import static li.strolch.model.StrolchModelConstants.INTERPRETATION_RESOURCE_REF; -import static li.strolch.model.StrolchModelConstants.UOM_NONE; -import java.text.MessageFormat; import java.util.List; import li.strolch.agent.api.ResourceMap; -import li.strolch.exception.StrolchException; import li.strolch.model.Resource; import li.strolch.model.ResourceVisitor; import li.strolch.model.parameter.Parameter; @@ -34,18 +31,7 @@ public class TransactionalResourceMap extends TransactionalElementMap @Override protected void assertIsRefParam(Parameter refP) { - - String interpretation = refP.getInterpretation(); - if (!interpretation.equals(INTERPRETATION_RESOURCE_REF)) { - String msg = "{0} is not an Resource reference as its interpretation is not {1} it is {2}"; //$NON-NLS-1$ - throw new StrolchException(MessageFormat.format(msg, refP.getLocator(), INTERPRETATION_RESOURCE_REF, - interpretation)); - } - - if (refP.getUom().equals(UOM_NONE)) { - String msg = "{0} is not an Resource reference as its UOM is not set to a type!"; //$NON-NLS-1$ - throw new StrolchException(MessageFormat.format(msg, refP.getLocator())); - } + ElementMapHelpers.assertIsRefParam(INTERPRETATION_RESOURCE_REF, refP); } @Override diff --git a/li.strolch.agent/src/main/java/li/strolch/agent/impl/TransientRealm.java b/li.strolch.agent/src/main/java/li/strolch/agent/impl/TransientRealm.java index e470c2769..755aa30b6 100644 --- a/li.strolch.agent/src/main/java/li/strolch/agent/impl/TransientRealm.java +++ b/li.strolch.agent/src/main/java/li/strolch/agent/impl/TransientRealm.java @@ -18,6 +18,7 @@ package li.strolch.agent.impl; import java.io.File; import java.text.MessageFormat; +import li.strolch.agent.api.ActivityMap; import li.strolch.agent.api.AuditTrail; import li.strolch.agent.api.ComponentContainer; import li.strolch.agent.api.OrderMap; @@ -42,6 +43,7 @@ public class TransientRealm extends InternalStrolchRealm { private ResourceMap resourceMap; private OrderMap orderMap; + private ActivityMap activityMap; private AuditTrail auditTrail; private PersistenceHandler persistenceHandler; @@ -78,6 +80,11 @@ public class TransientRealm extends InternalStrolchRealm { return this.orderMap; } + @Override + public ActivityMap getActivityMap() { + return this.activityMap; + } + @Override public AuditTrail getAuditTrail() { return this.auditTrail; @@ -99,6 +106,7 @@ public class TransientRealm extends InternalStrolchRealm { this.persistenceHandler = new InMemoryPersistence(container.getPrivilegeHandler()); this.resourceMap = new TransactionalResourceMap(); this.orderMap = new TransactionalOrderMap(); + this.activityMap = new TransactionalActivityMap(); if (isAuditTrailEnabled()) { this.auditTrail = new TransactionalAuditTrail(); @@ -126,6 +134,7 @@ public class TransientRealm extends InternalStrolchRealm { "Loading XML Model file {0} for realm {1} took {2}.", this.modelFile.getName(), getRealm(), durationS)); //$NON-NLS-1$ logger.info(MessageFormat.format("Loaded {0} Orders", statistics.nrOfOrders)); //$NON-NLS-1$ logger.info(MessageFormat.format("Loaded {0} Resources", statistics.nrOfResources)); //$NON-NLS-1$ + logger.info(MessageFormat.format("Loaded {0} Activities", statistics.nrOfActivities)); //$NON-NLS-1$ } @Override diff --git a/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java b/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java index 3cb1a9cd1..a5dced69a 100644 --- a/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java +++ b/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java @@ -23,6 +23,7 @@ import java.util.List; import java.util.ListIterator; import java.util.Set; +import li.strolch.agent.api.ActivityMap; import li.strolch.agent.api.AuditTrail; import li.strolch.agent.api.ObserverHandler; import li.strolch.agent.api.OrderMap; @@ -30,12 +31,14 @@ import li.strolch.agent.api.ResourceMap; import li.strolch.agent.api.StrolchAgent; import li.strolch.agent.api.StrolchLockException; import li.strolch.agent.api.StrolchRealm; +import li.strolch.agent.impl.AuditingActivityMap; import li.strolch.agent.impl.AuditingAuditMapFacade; import li.strolch.agent.impl.AuditingOrderMap; import li.strolch.agent.impl.AuditingResourceMap; import li.strolch.agent.impl.InternalStrolchRealm; import li.strolch.exception.StrolchAccessDeniedException; import li.strolch.exception.StrolchException; +import li.strolch.model.ActivityVisitor; import li.strolch.model.GroupedParameterizedElement; import li.strolch.model.Locator; import li.strolch.model.Order; @@ -46,6 +49,7 @@ import li.strolch.model.ResourceVisitor; import li.strolch.model.StrolchElement; import li.strolch.model.StrolchRootElement; import li.strolch.model.Tags; +import li.strolch.model.activity.Activity; import li.strolch.model.audit.AccessType; import li.strolch.model.audit.Audit; import li.strolch.model.audit.AuditQuery; @@ -54,12 +58,14 @@ import li.strolch.model.audit.NoStrategyAuditVisitor; import li.strolch.model.parameter.Parameter; import li.strolch.model.parameter.StringListParameter; import li.strolch.model.parameter.StringParameter; +import li.strolch.model.query.ActivityQuery; import li.strolch.model.query.OrderQuery; import li.strolch.model.query.ResourceQuery; import li.strolch.model.query.StrolchQuery; import li.strolch.model.timedstate.StrolchTimedState; import li.strolch.model.timevalue.IValue; import li.strolch.model.visitor.ElementTypeVisitor; +import li.strolch.model.visitor.NoStrategyActivityVisitor; import li.strolch.model.visitor.NoStrategyOrderVisitor; import li.strolch.model.visitor.NoStrategyResourceVisitor; import li.strolch.runtime.StrolchConstants; @@ -95,6 +101,7 @@ public abstract class AbstractTransaction implements StrolchTransaction { private AuditingOrderMap orderMap; private AuditingResourceMap resourceMap; + private AuditingActivityMap activityMap; private AuditingAuditMapFacade auditTrail; private String action; @@ -257,6 +264,15 @@ public abstract class AbstractTransaction implements StrolchTransaction { return this.orderMap; } + @Override + public ActivityMap getActivityMap() { + if (this.activityMap == null) { + this.activityMap = new AuditingActivityMap(this.realm.getActivityMap(), + this.realm.isAuditTrailEnabledForRead()); + } + return this.activityMap; + } + @Override public AuditTrail getAuditTrail() { if (this.auditTrail == null) { @@ -298,6 +314,18 @@ public abstract class AbstractTransaction implements StrolchTransaction { assertQueryAllowed(query); return getResourceMap().doQuery(this, query, resourceVisitor); } + + @Override + public List doQuery(ActivityQuery query) { + assertQueryAllowed(query); + return getActivityMap().doQuery(this, query, new NoStrategyActivityVisitor()); + } + + @Override + public List doQuery(ActivityQuery query, ActivityVisitor activityVisitor) { + assertQueryAllowed(query); + return getActivityMap().doQuery(this, query, activityVisitor); + } @Override public List doQuery(AuditQuery query) { @@ -486,7 +514,78 @@ public abstract class AbstractTransaction implements StrolchTransaction { DBC.PRE.assertNotNull("refP", refP); return getResourceMap().getBy(this, refP, assertExists); } + + + + + + + + + + + + + @Override + public Activity getActivityBy(String type, String id) { + return getActivityBy(type, id, false); + } + + @Override + public Activity getActivityBy(String type, String id, boolean assertExists) throws StrolchException { + Activity activity = getActivityMap().getBy(this, type, id); + if (assertExists && activity == null) { + String msg = "No Activity exists with the id {0} with type {1}"; + throw new StrolchException(MessageFormat.format(msg, id, type)); + } + return activity; + } + + @Override + public Activity getActivityBy(StringParameter refP) throws StrolchException { + DBC.PRE.assertNotNull("refP", refP); + return getActivityBy(refP, false); + } + + @Override + public Activity getActivityBy(StringParameter refP, boolean assertExists) throws StrolchException { + DBC.PRE.assertNotNull("refP", refP); + return getActivityMap().getBy(this, refP, assertExists); + } + + @Override + public List getActivitiesBy(StringListParameter refP) throws StrolchException { + DBC.PRE.assertNotNull("refP", refP); + return getActivityMap().getBy(this, refP, false); + } + + @Override + public List getActivitiesBy(StringListParameter refP, boolean assertExists) throws StrolchException { + DBC.PRE.assertNotNull("refP", refP); + return getActivityMap().getBy(this, refP, assertExists); + } + + + + + + + + + + + + + + + + + + + + + @Override public void flush() { try { diff --git a/li.strolch.agent/src/main/java/li/strolch/persistence/api/ActivityDao.java b/li.strolch.agent/src/main/java/li/strolch/persistence/api/ActivityDao.java new file mode 100644 index 000000000..79e2ea9ad --- /dev/null +++ b/li.strolch.agent/src/main/java/li/strolch/persistence/api/ActivityDao.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.persistence.api; + +import java.util.List; + +import li.strolch.model.ActivityVisitor; +import li.strolch.model.activity.Activity; +import li.strolch.model.query.ActivityQuery; + +/** + * @author Robert von Burg + */ +public interface ActivityDao extends StrolchDao { + + public List doQuery(ActivityQuery query, ActivityVisitor activityVisitor); +} diff --git a/li.strolch.agent/src/main/java/li/strolch/persistence/api/PersistenceHandler.java b/li.strolch.agent/src/main/java/li/strolch/persistence/api/PersistenceHandler.java index 94d224fd5..eb52f4716 100644 --- a/li.strolch.agent/src/main/java/li/strolch/persistence/api/PersistenceHandler.java +++ b/li.strolch.agent/src/main/java/li/strolch/persistence/api/PersistenceHandler.java @@ -15,12 +15,14 @@ */ package li.strolch.persistence.api; +import li.strolch.agent.api.ActivityMap; import li.strolch.agent.api.AuditTrail; import li.strolch.agent.api.OrderMap; import li.strolch.agent.api.ResourceMap; import li.strolch.agent.api.StrolchRealm; import li.strolch.model.Order; import li.strolch.model.Resource; +import li.strolch.model.activity.Activity; import li.strolch.model.audit.Audit; import ch.eitchnet.privilege.model.Certificate; @@ -68,6 +70,18 @@ public interface PersistenceHandler { */ public ResourceDao getResourceDao(StrolchTransaction tx); + /** + * Returns the {@link ActivityDao} for the given transaction. Use this only if you want to bypass certain + * transaction features. Accessing {@link Activity Activities} should be done through the {@link ActivityMap} + * accessed from the transaction + * + * @param tx + * the transaction for which the {@link ActivityDao} is to be returned + * + * @return the {@link ActivityDao} + */ + public ActivityDao getActivityDao(StrolchTransaction tx); + /** * Returns the {@link AuditDao} for the given transaction. Use this only if you want to bypass certain transaction * features. Accessing {@link Audit Audits} should be done through the {@link AuditTrail} accessed from the diff --git a/li.strolch.agent/src/main/java/li/strolch/persistence/api/StrolchTransaction.java b/li.strolch.agent/src/main/java/li/strolch/persistence/api/StrolchTransaction.java index dace3d9ed..081e50bfc 100644 --- a/li.strolch.agent/src/main/java/li/strolch/persistence/api/StrolchTransaction.java +++ b/li.strolch.agent/src/main/java/li/strolch/persistence/api/StrolchTransaction.java @@ -17,6 +17,7 @@ package li.strolch.persistence.api; import java.util.List; +import li.strolch.agent.api.ActivityMap; import li.strolch.agent.api.AuditTrail; import li.strolch.agent.api.OrderMap; import li.strolch.agent.api.ResourceMap; @@ -25,6 +26,7 @@ import li.strolch.agent.api.StrolchLockException; import li.strolch.agent.api.StrolchRealm; import li.strolch.agent.impl.DataStoreMode; import li.strolch.exception.StrolchException; +import li.strolch.model.ActivityVisitor; import li.strolch.model.Locator; import li.strolch.model.Order; import li.strolch.model.OrderVisitor; @@ -34,6 +36,7 @@ import li.strolch.model.ResourceVisitor; import li.strolch.model.StrolchElement; import li.strolch.model.StrolchRootElement; import li.strolch.model.Tags; +import li.strolch.model.activity.Activity; import li.strolch.model.audit.AccessType; import li.strolch.model.audit.Audit; import li.strolch.model.audit.AuditQuery; @@ -41,6 +44,7 @@ import li.strolch.model.audit.AuditVisitor; import li.strolch.model.parameter.Parameter; import li.strolch.model.parameter.StringListParameter; import li.strolch.model.parameter.StringParameter; +import li.strolch.model.query.ActivityQuery; import li.strolch.model.query.OrderQuery; import li.strolch.model.query.ResourceQuery; import li.strolch.runtime.StrolchConstants; @@ -123,6 +127,13 @@ public interface StrolchTransaction extends AutoCloseable { */ public OrderMap getOrderMap(); + /** + * Returns a reference to the {@link ActivityMap} for the {@link StrolchRealm} for which this transaction was opened + * + * @return the {@link ActivityMap} + */ + public ActivityMap getActivityMap(); + /** * Returns the {@link PersistenceHandler}. If the {@link StrolchRealm} is not running in * {@link DataStoreMode#TRANSIENT} mode, then the {@link PersistenceHandler} will be a {@link StrolchComponent}, @@ -424,6 +435,42 @@ public interface StrolchTransaction extends AutoCloseable { */ public List doQuery(ResourceQuery query, ResourceVisitor resourceVisitor); + /** + *

+ * Performs the given {@link ActivityQuery} returning the resulting list of {@link Activity Activities}. + *

+ * + *

+ * Note: Should the result be mapped to different objects, then use + * {@link #doQuery(ActivityQuery, ActivityVisitor)} + *

+ * + * @param query + * the query to perform + * + * @return the result list, never null + */ + public List doQuery(ActivityQuery query); + + /** + *

+ * Performs the given {@link ActivityQuery} and each returned {@link Activity} is passed through the + * {@link ActivityVisitor} and the return value of the visitor is added to the return list + *

+ * + *

+ * This method is intended for situations where the query result should not be {@link Activity} but some other + * object type. For instance in a restful API, the result might have to be mapped to a POJO, thus using this method + * can perform the mapping step for you + *

+ * + * @param query + * the query to perform + * + * @return the result list of elements as returned by the {@link ActivityVisitor}, never null + */ + public List doQuery(ActivityQuery query, ActivityVisitor activityVisitor); + /** *

* Performs the given {@link AuditQuery} returning the resulting list of {@link Audit Audits}. @@ -670,13 +717,111 @@ public interface StrolchTransaction extends AutoCloseable { * if true, and resource does not exist, then a {@link StrolchException} is thrown * * @return the resources referenced by the parameter, or the empty list if they do not exist. Note: Any - * missing resources are not returned! + * missing resources are not returned unless assertExists is true * * @throws StrolchException * if the {@link StringListParameter} is not a properly configured as a reference parameter */ public List getResourcesBy(StringListParameter refP, boolean assertExists) throws StrolchException; + /** + * Returns the {@link Activity} with the given type and id, or null if it does not exist + * + * @param type + * the type of the {@link Activity} + * @param id + * the id of the {@link Activity} + * + * @return the {@link Activity} with the given type and id, or null if it does not exist + */ + public Activity getActivityBy(String type, String id); + + /** + * Returns the {@link Activity} with the given type and id, or null if it does not exist + * + * @param type + * the type of the {@link Activity} + * @param id + * the id of the {@link Activity} + * @param assertExists + * if true, and activity does not exist, then a {@link StrolchException} is thrown + * + * @return the {@link Activity} with the given type and id, or null if it does not exist + * + * @throws StrolchException + * if the activity does not exist, and assertExists is true + */ + public Activity getActivityBy(String type, String id, boolean assertExists) throws StrolchException; + + /** + * Returns the {@link Activity} which is referenced by the given {@link StringParameter}. A reference + * {@link Parameter} must have its interpretation set to {@link StrolchConstants#INTERPRETATION_ACTIVITY_REF} and + * the UOM must be set to the activity's type and the value is the id of the activity + * + * @param refP + * the {@link StringParameter} which references an {@link Activity} + * + * @return the activity referenced by the parameter, or null if it does not exist + * + * @throws StrolchException + * if the {@link StringParameter} is not a properly configured as a reference parameter + */ + public Activity getActivityBy(StringParameter refP) throws StrolchException; + + /** + * Returns the {@link Activity} which is referenced by the given {@link StringParameter}. A reference + * {@link Parameter} must have its interpretation set to {@link StrolchConstants#INTERPRETATION_ACTIVITY_REF} and + * the UOM must be set to the activity's type and the value is the id of the activity + * + * @param refP + * the {@link StringParameter} which references an {@link Activity} + * @param assertExists + * if true, and activity does not exist, then a {@link StrolchException} is thrown + * + * @return the activity referenced by the parameter, or null if it does not exist + * + * @throws StrolchException + * if the {@link StringParameter} is not a properly configured as a reference parameter, or if the + * activity does not exist, and assertExists is true + */ + public Activity getActivityBy(StringParameter refP, boolean assertExists) throws StrolchException; + + /** + * Returns all {@link Activity Activities} which are referenced by the given {@link StringListParameter}. A + * reference {@link Parameter} must have its interpretation set to + * {@link StrolchConstants#INTERPRETATION_ACTIVITY_REF} and the UOM must be set to the activity's type and the value + * is the id of the activity + * + * @param refP + * the {@link StringListParameter} which references a list of {@link Activity Activities} + * + * @return the activities referenced by the parameter, or the empty list if they do not exist. Note: Any + * missing activities are not returned! + * + * @throws StrolchException + * if the {@link StringListParameter} is not a properly configured as a reference parameter + */ + public List getActivitiesBy(StringListParameter refP) throws StrolchException; + + /** + * Returns all {@link Activity Activities} which are referenced by the given {@link StringListParameter}. A + * reference {@link Parameter} must have its interpretation set to + * {@link StrolchConstants#INTERPRETATION_ACTIVITY_REF} and the UOM must be set to the activity's type and the value + * is the id of the activity + * + * @param refP + * the {@link StringListParameter} which references a list of {@link Activity Activities} + * @param assertExists + * if true, and activity does not exist, then a {@link StrolchException} is thrown + * + * @return the activities referenced by the parameter, or the empty list if they do not exist. Note: Any + * missing activities are not returned unless assertExists is true + * + * @throws StrolchException + * if the {@link StringListParameter} is not a properly configured as a reference parameter + */ + public List getActivitiesBy(StringListParameter refP, boolean assertExists) throws StrolchException; + /** * Returns the {@link Order} with the given type and id, or null if it does not exist * @@ -766,7 +911,7 @@ public interface StrolchTransaction extends AutoCloseable { * if true, and order does not exist, then a {@link StrolchException} is thrown * * @return the orders referenced by the parameter, or the empty list if they do not exist. Note: Any missing - * orders are not returned! + * orders are not returned unless assertExists is true * * @throws StrolchException * if the {@link StringListParameter} is not a properly configured as a reference parameter diff --git a/li.strolch.agent/src/main/java/li/strolch/persistence/inmemory/InMemoryActivityDao.java b/li.strolch.agent/src/main/java/li/strolch/persistence/inmemory/InMemoryActivityDao.java new file mode 100644 index 000000000..665a6b86a --- /dev/null +++ b/li.strolch.agent/src/main/java/li/strolch/persistence/inmemory/InMemoryActivityDao.java @@ -0,0 +1,35 @@ +/* + * 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.persistence.inmemory; + +import java.util.List; + +import li.strolch.model.ActivityVisitor; +import li.strolch.model.activity.Activity; +import li.strolch.model.query.ActivityQuery; +import li.strolch.persistence.api.ActivityDao; +import li.strolch.runtime.query.inmemory.InMemoryActivityQueryVisitor; +import li.strolch.runtime.query.inmemory.InMemoryQuery; + +public class InMemoryActivityDao extends InMemoryDao implements ActivityDao { + + @Override + public List doQuery(ActivityQuery activityQuery, ActivityVisitor activityVisitor) { + InMemoryActivityQueryVisitor visitor = new InMemoryActivityQueryVisitor(); + InMemoryQuery query = visitor.visit(activityQuery, activityVisitor); + return query.doQuery(this); + } +} diff --git a/li.strolch.agent/src/main/java/li/strolch/persistence/inmemory/InMemoryPersistence.java b/li.strolch.agent/src/main/java/li/strolch/persistence/inmemory/InMemoryPersistence.java index 328d7baff..251da8939 100644 --- a/li.strolch.agent/src/main/java/li/strolch/persistence/inmemory/InMemoryPersistence.java +++ b/li.strolch.agent/src/main/java/li/strolch/persistence/inmemory/InMemoryPersistence.java @@ -19,6 +19,7 @@ import java.util.HashMap; import java.util.Map; import li.strolch.agent.api.StrolchRealm; +import li.strolch.persistence.api.ActivityDao; import li.strolch.persistence.api.AuditDao; import li.strolch.persistence.api.OrderDao; import li.strolch.persistence.api.PersistenceHandler; @@ -54,6 +55,12 @@ public class InMemoryPersistence implements PersistenceHandler { return daoCache.getResourceDao(); } + @Override + public ActivityDao getActivityDao(StrolchTransaction tx) { + DaoCache daoCache = getDaoCache(tx); + return daoCache.getActivityDao(); + } + @Override public AuditDao getAuditDao(StrolchTransaction tx) { DaoCache daoCache = getDaoCache(tx); @@ -68,7 +75,8 @@ public class InMemoryPersistence implements PersistenceHandler { private synchronized DaoCache getDaoCache(StrolchTransaction tx) { DaoCache daoCache = this.daoCache.get(tx.getRealmName()); if (daoCache == null) { - daoCache = new DaoCache(new InMemoryOrderDao(), new InMemoryResourceDao(), new InMemoryAuditDao()); + daoCache = new DaoCache(new InMemoryOrderDao(), new InMemoryResourceDao(), new InMemoryActivityDao(), + new InMemoryAuditDao()); this.daoCache.put(tx.getRealmName(), daoCache); } return daoCache; @@ -77,11 +85,13 @@ public class InMemoryPersistence implements PersistenceHandler { private class DaoCache { private OrderDao orderDao; private ResourceDao resourceDao; + private ActivityDao activityDao; private AuditDao auditDao; - public DaoCache(OrderDao orderDao, ResourceDao resourceDao, AuditDao auditDao) { + public DaoCache(OrderDao orderDao, ResourceDao resourceDao, ActivityDao activityDao, AuditDao auditDao) { this.orderDao = orderDao; this.resourceDao = resourceDao; + this.activityDao = activityDao; this.auditDao = auditDao; } @@ -96,5 +106,9 @@ public class InMemoryPersistence implements PersistenceHandler { public AuditDao getAuditDao() { return this.auditDao; } + + public ActivityDao getActivityDao() { + return this.activityDao; + } } } diff --git a/li.strolch.agent/src/main/java/li/strolch/persistence/inmemory/InMemoryPersistenceHandler.java b/li.strolch.agent/src/main/java/li/strolch/persistence/inmemory/InMemoryPersistenceHandler.java index 7b6165d41..b702dfa43 100644 --- a/li.strolch.agent/src/main/java/li/strolch/persistence/inmemory/InMemoryPersistenceHandler.java +++ b/li.strolch.agent/src/main/java/li/strolch/persistence/inmemory/InMemoryPersistenceHandler.java @@ -18,6 +18,7 @@ package li.strolch.persistence.inmemory; import li.strolch.agent.api.ComponentContainer; import li.strolch.agent.api.StrolchComponent; import li.strolch.agent.api.StrolchRealm; +import li.strolch.persistence.api.ActivityDao; import li.strolch.persistence.api.AuditDao; import li.strolch.persistence.api.OrderDao; import li.strolch.persistence.api.PersistenceHandler; @@ -62,6 +63,11 @@ public class InMemoryPersistenceHandler extends StrolchComponent implements Pers return this.persistence.getResourceDao(tx); } + @Override + public ActivityDao getActivityDao(StrolchTransaction tx) { + return this.persistence.getActivityDao(tx); + } + @Override public AuditDao getAuditDao(StrolchTransaction tx) { return this.persistence.getAuditDao(tx); diff --git a/li.strolch.agent/src/main/java/li/strolch/runtime/StrolchConstants.java b/li.strolch.agent/src/main/java/li/strolch/runtime/StrolchConstants.java index d6ad8a2be..514dbd8df 100644 --- a/li.strolch.agent/src/main/java/li/strolch/runtime/StrolchConstants.java +++ b/li.strolch.agent/src/main/java/li/strolch/runtime/StrolchConstants.java @@ -53,6 +53,11 @@ public class StrolchConstants { */ public static final String INTERPRETATION_ORDER_REF = StrolchModelConstants.INTERPRETATION_ORDER_REF; + /** + * @see StrolchModelConstants#INTERPRETATION_ACTIVITY_REF + */ + public static final String INTERPRETATION_ACTIVITY_REF = StrolchModelConstants.INTERPRETATION_ACTIVITY_REF; + public static String makeRealmKey(String realmName, String key) { String realmKey = key; if (!realmName.equals(DEFAULT_REALM)) diff --git a/li.strolch.agent/src/main/java/li/strolch/runtime/query/inmemory/ActivityTypeNavigator.java b/li.strolch.agent/src/main/java/li/strolch/runtime/query/inmemory/ActivityTypeNavigator.java new file mode 100644 index 000000000..6aed9ba5b --- /dev/null +++ b/li.strolch.agent/src/main/java/li/strolch/runtime/query/inmemory/ActivityTypeNavigator.java @@ -0,0 +1,31 @@ +/* + * 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.runtime.query.inmemory; + +import li.strolch.model.activity.Activity; + +/** + * @author Robert von Burg + */ +public class ActivityTypeNavigator extends StrolchTypeNavigator { + + /** + * @param type + */ + public ActivityTypeNavigator(String type) { + super(type); + } +} diff --git a/li.strolch.agent/src/main/java/li/strolch/runtime/query/inmemory/InMemoryActivityQueryVisitor.java b/li.strolch.agent/src/main/java/li/strolch/runtime/query/inmemory/InMemoryActivityQueryVisitor.java new file mode 100644 index 000000000..482ef37a7 --- /dev/null +++ b/li.strolch.agent/src/main/java/li/strolch/runtime/query/inmemory/InMemoryActivityQueryVisitor.java @@ -0,0 +1,65 @@ +/* + * 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.runtime.query.inmemory; + +import java.util.List; + +import li.strolch.model.ActivityVisitor; +import li.strolch.model.activity.Activity; +import li.strolch.model.query.ActivityQuery; +import li.strolch.model.query.ActivityQueryVisitor; +import li.strolch.model.query.StrolchTypeNavigation; +import li.strolch.persistence.api.ActivityDao; +import ch.eitchnet.utils.dbc.DBC; + +/** + * @author Robert von Burg + */ +public class InMemoryActivityQueryVisitor extends InMemoryQueryVisitor implements + ActivityQueryVisitor { + + public InMemoryActivityQueryVisitor() { + super(); + } + + @Override + protected InMemoryQueryVisitor newInstance() { + return new InMemoryActivityQueryVisitor(); + } + + public InMemoryQuery visit(ActivityQuery activityQuery, ActivityVisitor activityVisitor) { + DBC.PRE.assertNotNull("ActivityVisitor may not be null!", activityVisitor); //$NON-NLS-1$ + activityQuery.accept(this); + + Navigator navigator = getNavigator(); + if (navigator == null) { + String msg = "Query is missing a navigation!"; //$NON-NLS-1$ + throw new QueryException(msg); + } + + List> selectors = getSelectors(); + if (selectors.isEmpty()) + return new InMemoryQuery<>(navigator, null, activityVisitor); + + DBC.PRE.assertTrue("Invalid query as it may only contain one selector!", selectors.size() == 1); //$NON-NLS-1$ + return new InMemoryQuery<>(navigator, selectors.get(0), activityVisitor); + } + + @Override + public void visit(StrolchTypeNavigation navigation) { + setNavigator(new ActivityTypeNavigator(navigation.getType())); + } +} 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 1bae4b526..6a550eb7e 100644 --- a/li.strolch.agent/src/test/resources/transienttest/data/Resources.xml +++ b/li.strolch.agent/src/test/resources/transienttest/data/Resources.xml @@ -10,12 +10,12 @@ - + - + @@ -23,7 +23,7 @@ - + @@ -31,7 +31,7 @@ - + diff --git a/li.strolch.model/src/main/java/li/strolch/model/AbstractStrolchElement.java b/li.strolch.model/src/main/java/li/strolch/model/AbstractStrolchElement.java index 44783903d..dc62e2311 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/AbstractStrolchElement.java +++ b/li.strolch.model/src/main/java/li/strolch/model/AbstractStrolchElement.java @@ -19,9 +19,6 @@ import java.text.MessageFormat; import li.strolch.exception.StrolchException; import li.strolch.model.Locator.LocatorBuilder; - -import org.w3c.dom.Element; - import ch.eitchnet.utils.helper.StringHelper; /** @@ -36,10 +33,10 @@ public abstract class AbstractStrolchElement implements StrolchElement { protected String name; /** - * Empty constructor + * Empty constructor - for marshalling only! */ public AbstractStrolchElement() { - // + super(); } /** @@ -114,31 +111,6 @@ public abstract class AbstractStrolchElement implements StrolchElement { clone.setName(getName()); } - protected void fillElement(Element element) { - element.setAttribute(Tags.ID, getId()); - element.setAttribute(Tags.NAME, getName()); - element.setAttribute(Tags.TYPE, getType()); - } - - /** - * Builds the fields of this {@link StrolchElement} from a {@link Element} - * - * @param element - */ - protected void fromDom(Element element) { - String id = element.getAttribute(Tags.ID); - String name = element.getAttribute(Tags.NAME); - - if (id != null && name != null) { - setId(id); - setName(name); - } else { - String msg = "Check the values of the element: {0} either id or name attribute is null!"; //$NON-NLS-1$ - msg = MessageFormat.format(msg, element.getNodeName()); - throw new StrolchException(msg); - } - } - @Override public int hashCode() { final int prime = 31; diff --git a/li.strolch.model/src/main/java/li/strolch/model/ActivityVisitor.java b/li.strolch.model/src/main/java/li/strolch/model/ActivityVisitor.java new file mode 100644 index 000000000..29bc2f3b4 --- /dev/null +++ b/li.strolch.model/src/main/java/li/strolch/model/ActivityVisitor.java @@ -0,0 +1,29 @@ +/* + * 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.model; + +import li.strolch.model.activity.Activity; +import li.strolch.model.visitor.StrolchElementVisitor; + +/** + * @author Robert von Burg + * @param + */ +public interface ActivityVisitor extends StrolchElementVisitor { + + @Override + public U visit(Activity element); +} diff --git a/li.strolch.model/src/main/java/li/strolch/model/GroupedParameterizedElement.java b/li.strolch.model/src/main/java/li/strolch/model/GroupedParameterizedElement.java index cbb073571..d4b13fec6 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/GroupedParameterizedElement.java +++ b/li.strolch.model/src/main/java/li/strolch/model/GroupedParameterizedElement.java @@ -25,10 +25,6 @@ import java.util.Set; import li.strolch.exception.StrolchException; import li.strolch.exception.StrolchModelException; import li.strolch.model.parameter.Parameter; - -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - import ch.eitchnet.utils.helper.StringHelper; /** @@ -42,10 +38,10 @@ public abstract class GroupedParameterizedElement extends AbstractStrolchElement protected String type; /** - * Empty constructor + * Empty constructor - for marshalling only! */ protected GroupedParameterizedElement() { - // + super(); } /** @@ -291,32 +287,6 @@ public abstract class GroupedParameterizedElement extends AbstractStrolchElement return new HashSet(this.parameterBagMap.keySet()); } - @Override - public void fromDom(Element element) { - super.fromDom(element); - - String type = element.getAttribute(Tags.TYPE); - setType(type); - - NodeList bags = element.getElementsByTagName(Tags.PARAMETER_BAG); - for (int i = 0; i < bags.getLength(); i++) { - Element bagElement = (Element) bags.item(i); - ParameterBag bag = new ParameterBag(bagElement); - addParameterBag(bag); - } - } - - @Override - protected void fillElement(Element element) { - super.fillElement(element); - - if (this.parameterBagMap != null) { - for (ParameterBag bag : this.parameterBagMap.values()) { - element.appendChild(bag.toDom(element.getOwnerDocument())); - } - } - } - /** * Fills {@link GroupedParameterizedElement} properties of this clone * 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 a0ee7780b..fa1a7f4be 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 li.strolch.model.activity.Action; +import li.strolch.model.activity.Activity; import li.strolch.model.audit.AccessType; import li.strolch.model.audit.Audit; import li.strolch.model.parameter.BooleanParameter; @@ -135,6 +137,9 @@ public class ModelGenerator { public static final String BAG_NAME = "Test Bag"; public static final String BAG_TYPE = "TestBag"; + public static final String ACTION_RES_TYPE = "ResType"; + public static final String ACTION_RES_ID = "@resId"; + /** * Creates an {@link Resource} with the given values and adds a {@link ParameterBag} by calling * {@link #createParameterBag(String, String, String)} @@ -322,6 +327,59 @@ public class ModelGenerator { return orders; } + public static Activity createActivity(String id, String name, String type) { + + Activity rootActivity = new Activity(id, name, type); + ParameterBag bag = createParameterBag(BAG_ID, BAG_NAME, BAG_TYPE); + rootActivity.addParameterBag(bag); + + Action action = createAction("act_" + rootActivity.getId(), "Action " + rootActivity.getName(), "Use"); + rootActivity.addElement(action); + + Activity subActivity = new Activity("sub_" + id, "sub_" + name, type); + bag = createParameterBag(BAG_ID, BAG_NAME, BAG_TYPE); + subActivity.addParameterBag(bag); + rootActivity.addElement(subActivity); + + action = createAction("act_" + id, "Action " + name, "Use"); + subActivity.addElement(action); + + Activity subSubActivity = new Activity("subSub_" + id, "subSub_" + name, type); + bag = createParameterBag(BAG_ID, BAG_NAME, BAG_TYPE); + subSubActivity.addParameterBag(bag); + subActivity.addElement(subSubActivity); + + action = createAction("act_" + id, "Action " + name, "Use"); + subSubActivity.addElement(action); + + return rootActivity; + } + + public static Action createAction(String id, String name, String type) { + Action action = new Action(id, name, type); + action.setResourceId(ACTION_RES_ID); + action.setResourceType(ACTION_RES_TYPE); + ParameterBag bag = createParameterBag(BAG_ID, BAG_NAME, BAG_TYPE); + action.addParameterBag(bag); + + action.addChange(new ValueChange<>(0L, new IntegerValue(0), STATE_INTEGER_ID)); + action.addChange(new ValueChange<>(10L, new IntegerValue(10), STATE_INTEGER_ID)); + action.addChange(new ValueChange<>(20L, new IntegerValue(20), STATE_INTEGER_ID)); + action.addChange(new ValueChange<>(30L, new IntegerValue(30), STATE_INTEGER_ID)); + action.addChange(new ValueChange<>(40L, new IntegerValue(20), STATE_INTEGER_ID)); + action.addChange(new ValueChange<>(50L, new IntegerValue(10), STATE_INTEGER_ID)); + action.addChange(new ValueChange<>(60L, new IntegerValue(0), STATE_INTEGER_ID)); + + return action; + } + + public static Action createAction(String id, String name, String type, String resourceId, String resourceType) { + Action action = createAction(id, name, type); + action.setResourceId(resourceId); + action.setResourceType(resourceType); + return action; + } + /** * Creates a {@link ParameterBag} with the given values and calls {@link #addAllParameters(ParameterBag)} to add * {@link Parameter}s @@ -336,7 +394,6 @@ public class ModelGenerator { * @return the newly created {@link ParameterBag} */ public static ParameterBag createParameterBag(String id, String name, String type) { - ParameterBag bag = new ParameterBag(id, name, type); addAllParameters(bag); return bag; diff --git a/li.strolch.model/src/main/java/li/strolch/model/ModelStatistics.java b/li.strolch.model/src/main/java/li/strolch/model/ModelStatistics.java index b5cdc70b7..30c21f1fa 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/ModelStatistics.java +++ b/li.strolch.model/src/main/java/li/strolch/model/ModelStatistics.java @@ -49,6 +49,9 @@ public class ModelStatistics { @XmlAttribute(name = "nrOfOrders") public long nrOfOrders; + @XmlAttribute(name = "nrOfActivities") + public long nrOfActivities; + /** * @return the nrOfOrders */ @@ -70,6 +73,24 @@ public class ModelStatistics { return this.nrOfOrders + this.nrOfResources; } + /** + * @return the nrOfActivities + */ + public long getNrOfActivities() { + return this.nrOfActivities; + } + + /** + * Adds the statistics of the other statistics to this statistics instance + * + * @param statistics + */ + public void add(ModelStatistics statistics) { + this.nrOfOrders += statistics.nrOfOrders; + this.nrOfResources += statistics.nrOfResources; + this.nrOfActivities += statistics.nrOfActivities; + } + @Override public String toString() { StringBuilder builder = new StringBuilder(); @@ -81,6 +102,8 @@ public class ModelStatistics { builder.append(this.nrOfResources); builder.append(", nrOfOrders="); builder.append(this.nrOfOrders); + builder.append(", nrOfActivities="); + builder.append(this.nrOfActivities); builder.append("]"); return builder.toString(); } 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 fe08fcb9a..08d553f62 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 @@ -19,11 +19,6 @@ import java.util.Date; import li.strolch.model.Locator.LocatorBuilder; import li.strolch.model.visitor.StrolchRootElementVisitor; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import ch.eitchnet.utils.helper.StringHelper; import ch.eitchnet.utils.iso8601.ISO8601FormatFactory; /** @@ -44,10 +39,10 @@ public class Order extends GroupedParameterizedElement implements StrolchRootEle private State state; /** - * Empty constructor + * Empty constructor - for marshalling only! */ public Order() { - // + super(); } /** @@ -80,30 +75,6 @@ public class Order extends GroupedParameterizedElement implements StrolchRootEle setDate(date); } - /** - * DOM Constructor - * - * @param element - */ - public Order(Element element) { - super.fromDom(element); - - String date = element.getAttribute(Tags.DATE); - String state = element.getAttribute(Tags.STATE); - - if (StringHelper.isEmpty(date)) { - setDate(ISO8601FormatFactory.getInstance().getDateFormat().parse("-")); //$NON-NLS-1$ - } else { - setDate(ISO8601FormatFactory.getInstance().getDateFormat().parse(date)); - } - - if (state == null || state.isEmpty()) { - setState(State.CREATED); - } else { - setState(State.valueOf(state)); - } - } - /** * @return the date */ @@ -134,18 +105,6 @@ public class Order extends GroupedParameterizedElement implements StrolchRootEle this.state = state; } - @Override - public Element toDom(Document doc) { - - Element orderElement = doc.createElement(Tags.ORDER); - fillElement(orderElement); - - orderElement.setAttribute(Tags.DATE, ISO8601FormatFactory.getInstance().formatDate(this.date)); - orderElement.setAttribute(Tags.STATE, this.state.toString()); - - return orderElement; - } - @Override public Order getClone() { Order clone = new Order(); @@ -179,7 +138,7 @@ public class Order extends GroupedParameterizedElement implements StrolchRootEle public Order getRootElement() { return this; } - + @Override public boolean isRootElement() { return true; diff --git a/li.strolch.model/src/main/java/li/strolch/model/ParameterBag.java b/li.strolch.model/src/main/java/li/strolch/model/ParameterBag.java index 3d59f23e4..8bc9541a4 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/ParameterBag.java +++ b/li.strolch.model/src/main/java/li/strolch/model/ParameterBag.java @@ -17,9 +17,6 @@ package li.strolch.model; import li.strolch.model.Locator.LocatorBuilder; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - /** * @author Robert von Burg */ @@ -45,15 +42,6 @@ public class ParameterBag extends ParameterizedElement { super(id, name, type); } - /** - * DOM Constructor - * - * @param bagElement - */ - public ParameterBag(Element bagElement) { - super.fromDom(bagElement); - } - @Override public ParameterBag getClone() { ParameterBag clone = new ParameterBag(); @@ -68,16 +56,6 @@ public class ParameterBag extends ParameterizedElement { lb.append(this.id); } - @Override - public Element toDom(Document doc) { - - Element element = doc.createElement(Tags.PARAMETER_BAG); - - fillElement(element); - - return element; - } - @Override public boolean isRootElement() { return false; diff --git a/li.strolch.model/src/main/java/li/strolch/model/ParameterizedElement.java b/li.strolch.model/src/main/java/li/strolch/model/ParameterizedElement.java index 95242e77d..6810dbbcd 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/ParameterizedElement.java +++ b/li.strolch.model/src/main/java/li/strolch/model/ParameterizedElement.java @@ -26,23 +26,7 @@ import java.util.Set; import li.strolch.exception.StrolchException; import li.strolch.model.Locator.LocatorBuilder; -import li.strolch.model.parameter.BooleanParameter; -import li.strolch.model.parameter.DateParameter; -import li.strolch.model.parameter.DurationParameter; -import li.strolch.model.parameter.FloatListParameter; -import li.strolch.model.parameter.FloatParameter; -import li.strolch.model.parameter.IntegerListParameter; -import li.strolch.model.parameter.IntegerParameter; -import li.strolch.model.parameter.LongListParameter; -import li.strolch.model.parameter.LongParameter; import li.strolch.model.parameter.Parameter; -import li.strolch.model.parameter.StringListParameter; -import li.strolch.model.parameter.StringParameter; - -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -import ch.eitchnet.utils.dbc.DBC; import ch.eitchnet.utils.helper.StringHelper; /** @@ -206,75 +190,6 @@ public abstract class ParameterizedElement extends AbstractStrolchElement { return lb.build(); } - // TODO remove the whole fromDom methods from strolch model - we want to use the visitor pattern only! - - @Override - protected void fromDom(Element element) { - super.fromDom(element); - - String type = element.getAttribute(Tags.TYPE); - setType(type); - - // add all the parameters - NodeList parameterElements = element.getElementsByTagName(Tags.PARAMETER); - for (int i = 0; i < parameterElements.getLength(); i++) { - Element paramElement = (Element) parameterElements.item(i); - String paramtype = paramElement.getAttribute(Tags.TYPE); - - DBC.PRE.assertNotEmpty("Type must be set on Parameter for bag with id " + this.id, paramtype); - - if (paramtype.equals(StringParameter.TYPE)) { - StringParameter param = new StringParameter(paramElement); - addParameter(param); - } else if (paramtype.equals(IntegerParameter.TYPE)) { - IntegerParameter param = new IntegerParameter(paramElement); - addParameter(param); - } else if (paramtype.equals(FloatParameter.TYPE)) { - FloatParameter param = new FloatParameter(paramElement); - addParameter(param); - } else if (paramtype.equals(LongParameter.TYPE)) { - LongParameter param = new LongParameter(paramElement); - addParameter(param); - } else if (paramtype.equals(DateParameter.TYPE)) { - DateParameter param = new DateParameter(paramElement); - addParameter(param); - } else if (paramtype.equals(DurationParameter.TYPE)) { - DurationParameter param = new DurationParameter(paramElement); - addParameter(param); - } else if (paramtype.equals(BooleanParameter.TYPE)) { - BooleanParameter param = new BooleanParameter(paramElement); - addParameter(param); - } else if (paramtype.equals(StringListParameter.TYPE)) { - StringListParameter param = new StringListParameter(paramElement); - addParameter(param); - } else if (paramtype.equals(IntegerListParameter.TYPE)) { - IntegerListParameter param = new IntegerListParameter(paramElement); - addParameter(param); - } else if (paramtype.equals(FloatListParameter.TYPE)) { - FloatListParameter param = new FloatListParameter(paramElement); - addParameter(param); - } else if (paramtype.equals(LongListParameter.TYPE)) { - LongListParameter param = new LongListParameter(paramElement); - addParameter(param); - } else { - String msg = "What kind of parameter is this: {0}"; //$NON-NLS-1$ - msg = MessageFormat.format(msg, paramtype); - throw new StrolchException(msg); - } - } - } - - @Override - protected void fillElement(Element element) { - super.fillElement(element); - - if (this.parameterMap != null) { - for (Parameter parameter : this.parameterMap.values()) { - element.appendChild(parameter.toDom(element.getOwnerDocument())); - } - } - } - @Override protected void fillClone(StrolchElement clone) { super.fillClone(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 d028e72c4..9f8a2454f 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 @@ -15,7 +15,6 @@ */ package li.strolch.model; -import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -24,22 +23,11 @@ import java.util.List; import java.util.Map; import java.util.Set; -import li.strolch.exception.StrolchException; import li.strolch.model.Locator.LocatorBuilder; -import li.strolch.model.timedstate.BooleanTimedState; -import li.strolch.model.timedstate.FloatTimedState; -import li.strolch.model.timedstate.IntegerTimedState; -import li.strolch.model.timedstate.StringSetTimedState; import li.strolch.model.timedstate.StrolchTimedState; import li.strolch.model.timevalue.IValue; import li.strolch.model.visitor.StrolchRootElementVisitor; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -import ch.eitchnet.utils.dbc.DBC; - /** * @author Robert von Burg */ @@ -50,10 +38,10 @@ public class Resource extends GroupedParameterizedElement implements StrolchRoot private Map>> timedStateMap; /** - * Empty constructor + * Empty constructor - for marshalling only! */ public Resource() { - // + super(); } /** @@ -67,41 +55,6 @@ public class Resource extends GroupedParameterizedElement implements StrolchRoot super(id, name, type); } - /** - * DOM Constructor - * - * @param element - */ - public Resource(Element element) { - super.fromDom(element); - - NodeList timedStateElems = element.getElementsByTagName(Tags.TIMED_STATE); - for (int i = 0; i < timedStateElems.getLength(); i++) { - Element timedStateElem = (Element) timedStateElems.item(i); - String typeS = timedStateElem.getAttribute(Tags.TYPE); - - DBC.PRE.assertNotEmpty("Type must be set on TimedState for resource with id " + this.id, typeS); - - if (typeS.equals(FloatTimedState.TYPE)) { - FloatTimedState timedState = new FloatTimedState(timedStateElem); - addTimedState(timedState); - } else if (typeS.equals(IntegerTimedState.TYPE)) { - IntegerTimedState timedState = new IntegerTimedState(timedStateElem); - addTimedState(timedState); - } else if (typeS.equals(BooleanTimedState.TYPE)) { - BooleanTimedState timedState = new BooleanTimedState(timedStateElem); - addTimedState(timedState); - } else if (typeS.equals(StringSetTimedState.TYPE)) { - StringSetTimedState timedState = new StringSetTimedState(timedStateElem); - addTimedState(timedState); - } else { - String msg = "What kind of TimedState is this: {0}"; //$NON-NLS-1$ - msg = MessageFormat.format(msg, typeS); - throw new StrolchException(msg); - } - } - } - @SuppressWarnings("unchecked") public void addTimedState(StrolchTimedState strolchTimedState) { if (this.timedStateMap == null) { @@ -150,26 +103,9 @@ public class Resource extends GroupedParameterizedElement implements StrolchRoot return this.timedStateMap != null && this.timedStateMap.containsKey(id); } - @Override - public Element toDom(Document doc) { - - Element element = doc.createElement(Tags.RESOURCE); - fillElement(element); - - if (this.timedStateMap != null) { - for (StrolchTimedState state : this.timedStateMap.values()) { - Element timedStateElem = state.toDom(element.getOwnerDocument()); - element.appendChild(timedStateElem); - } - } - - return element; - } - @Override public Resource getClone() { Resource clone = new Resource(); - super.fillClone(clone); if (this.timedStateMap != null) { @@ -202,7 +138,7 @@ public class Resource extends GroupedParameterizedElement implements StrolchRoot public Resource getRootElement() { return this; } - + @Override public boolean isRootElement() { return true; diff --git a/li.strolch.model/src/main/java/li/strolch/model/StrolchElement.java b/li.strolch.model/src/main/java/li/strolch/model/StrolchElement.java index 7328bc4a8..1f3ad4734 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/StrolchElement.java +++ b/li.strolch.model/src/main/java/li/strolch/model/StrolchElement.java @@ -17,9 +17,6 @@ package li.strolch.model; import java.io.Serializable; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - /** * @author Robert von Burg */ @@ -76,17 +73,6 @@ public interface StrolchElement extends Serializable, Comparable */ public long getDbid(); - /** - * Returns an {@link Element} object which is an XML representation of this object - * - * @param doc - * the document to which this element is being written. The client must not append to the document, the - * caller will perform this as needed - * - * @return - */ - public Element toDom(Document doc); - /** * Returns the type of this {@link StrolchElement} * diff --git a/li.strolch.model/src/main/java/li/strolch/model/StrolchModelConstants.java b/li.strolch.model/src/main/java/li/strolch/model/StrolchModelConstants.java index 46cafa2e1..531c458cf 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/StrolchModelConstants.java +++ b/li.strolch.model/src/main/java/li/strolch/model/StrolchModelConstants.java @@ -40,6 +40,12 @@ public class StrolchModelConstants { */ public static final String INTERPRETATION_ORDER_REF = "Order-Ref"; //$NON-NLS-1$ + /** + * This interpretation value indicates that the value of the {@link Parameter} should be understood as a reference + * to an {@link Activity} + */ + public static final String INTERPRETATION_ACTIVITY_REF = "Activity-Ref"; //$NON-NLS-1$ + /** * This interpretation value indicates that the {@link Parameter} has no defined interpretation */ diff --git a/li.strolch.model/src/main/java/li/strolch/model/StrolchValueType.java b/li.strolch.model/src/main/java/li/strolch/model/StrolchValueType.java new file mode 100644 index 000000000..a46e18b43 --- /dev/null +++ b/li.strolch.model/src/main/java/li/strolch/model/StrolchValueType.java @@ -0,0 +1,378 @@ +/* + * 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.model; + +import java.text.MessageFormat; + +import li.strolch.model.parameter.BooleanParameter; +import li.strolch.model.parameter.DateParameter; +import li.strolch.model.parameter.DurationParameter; +import li.strolch.model.parameter.FloatListParameter; +import li.strolch.model.parameter.FloatParameter; +import li.strolch.model.parameter.IntegerListParameter; +import li.strolch.model.parameter.IntegerParameter; +import li.strolch.model.parameter.LongListParameter; +import li.strolch.model.parameter.LongParameter; +import li.strolch.model.parameter.Parameter; +import li.strolch.model.parameter.StringListParameter; +import li.strolch.model.parameter.StringParameter; +import li.strolch.model.timedstate.BooleanTimedState; +import li.strolch.model.timedstate.FloatTimedState; +import li.strolch.model.timedstate.IntegerTimedState; +import li.strolch.model.timedstate.StringSetTimedState; +import li.strolch.model.timedstate.StrolchTimedState; +import li.strolch.model.timedstate.TimedState; +import li.strolch.model.timevalue.IValue; +import li.strolch.model.timevalue.IValueChange; +import li.strolch.model.timevalue.impl.BooleanValue; +import li.strolch.model.timevalue.impl.FloatValue; +import li.strolch.model.timevalue.impl.IntegerValue; +import li.strolch.model.timevalue.impl.StringSetValue; + +public enum StrolchValueType { + + /** + * Can be used for:
+ *

    + *
  • {@link Parameter}
  • + *
  • {@link TimedState}
  • + *
  • {@link IValue}
  • + *
  • {@link IValueChange}
  • + *
+ */ + BOOLEAN("Boolean") { + @Override + public Parameter parameterInstance() { + return new BooleanParameter(); + } + + @Override + public StrolchTimedState> timedStateInstance() { + return new BooleanTimedState(); + } + + @Override + public IValue valueInstance(String valueAsString) { + return new BooleanValue(valueAsString); + } + }, + + /** + * Can be used for:
+ *
    + *
  • {@link Parameter}
  • + *
  • {@link TimedState}
  • + *
  • {@link IValue}
  • + *
  • {@link IValueChange}
  • + *
+ */ + INTEGER("Integer") { + @Override + public Parameter parameterInstance() { + return new IntegerParameter(); + } + + @Override + public StrolchTimedState> timedStateInstance() { + return new IntegerTimedState(); + } + + @Override + public IValue valueInstance(String valueAsString) { + return new IntegerValue(valueAsString); + } + }, + + /** + * Can be used for:
+ *
    + *
  • {@link Parameter}
  • + *
  • {@link TimedState}
  • + *
  • {@link IValue}
  • + *
  • {@link IValueChange}
  • + *
+ */ + FLOAT("Float") { + @Override + public Parameter parameterInstance() { + return new FloatParameter(); + } + + @Override + public StrolchTimedState> timedStateInstance() { + return new FloatTimedState(); + } + + @Override + public IValue valueInstance(String valueAsString) { + return new FloatValue(valueAsString); + } + }, + + /** + * Can be used for:
+ *
    + *
  • {@link Parameter}
  • + *
+ */ + LONG("Long") { + @Override + public Parameter parameterInstance() { + return new LongParameter(); + } + + @Override + public StrolchTimedState> timedStateInstance() { + throw new UnsupportedOperationException(MessageFormat.format( + "TimeStates of type {0} are not supported!", getType())); //$NON-NLS-1$ + } + + @Override + public IValue valueInstance(String valueAsString) { + throw new UnsupportedOperationException(MessageFormat.format( + "Parameters of type {0} are not supported!", getType())); //$NON-NLS-1$ + } + }, + + /** + * Can be used for:
+ *
    + *
  • {@link Parameter}
  • + *
+ */ + STRING("String") { + @Override + public Parameter parameterInstance() { + return new StringParameter(); + } + + @Override + public StrolchTimedState> timedStateInstance() { + throw new UnsupportedOperationException(MessageFormat.format( + "TimeStates of type {0} are not supported!", getType())); //$NON-NLS-1$ + } + + @Override + public IValue valueInstance(String valueAsString) { + throw new UnsupportedOperationException(MessageFormat.format( + "Parameters of type {0} are not supported!", getType())); //$NON-NLS-1$ + } + }, + + /** + * Can be used for:
+ *
    + *
  • {@link Parameter}
  • + *
+ */ + DATE("Date") { + @Override + public Parameter parameterInstance() { + return new DateParameter(); + } + + @Override + public StrolchTimedState> timedStateInstance() { + throw new UnsupportedOperationException(MessageFormat.format( + "TimeStates of type {0} are not supported!", getType())); //$NON-NLS-1$ + } + + @Override + public IValue valueInstance(String valueAsString) { + throw new UnsupportedOperationException(MessageFormat.format( + "Parameters of type {0} are not supported!", getType())); //$NON-NLS-1$ + } + }, + + /** + * Can be used for:
+ *
    + *
  • {@link Parameter}
  • + *
+ */ + DURATION("Duration") { + @Override + public Parameter parameterInstance() { + return new DurationParameter(); + } + + @Override + public StrolchTimedState> timedStateInstance() { + throw new UnsupportedOperationException(MessageFormat.format( + "TimeStates of type {0} are not supported!", getType())); //$NON-NLS-1$ + } + + @Override + public IValue valueInstance(String valueAsString) { + throw new UnsupportedOperationException(MessageFormat.format( + "Parameters of type {0} are not supported!", getType())); //$NON-NLS-1$ + } + }, + + /** + * Can be used for:
+ *
    + *
  • {@link Parameter}
  • + *
+ */ + FLOAT_LIST("FloatList") { + @Override + public Parameter parameterInstance() { + return new FloatListParameter(); + } + + @Override + public StrolchTimedState> timedStateInstance() { + throw new UnsupportedOperationException(MessageFormat.format( + "TimeStates of type {0} are not supported!", getType())); //$NON-NLS-1$ + } + + @Override + public IValue valueInstance(String valueAsString) { + throw new UnsupportedOperationException(MessageFormat.format( + "Parameters of type {0} are not supported!", getType())); //$NON-NLS-1$ + } + }, + + /** + * Can be used for:
+ *
    + *
  • {@link Parameter}
  • + *
+ */ + INTEGER_LIST("IntegerList") { + @Override + public Parameter parameterInstance() { + return new IntegerListParameter(); + } + + @Override + public StrolchTimedState> timedStateInstance() { + throw new UnsupportedOperationException(MessageFormat.format( + "TimeStates of type {0} are not supported!", getType())); //$NON-NLS-1$ + } + + @Override + public IValue valueInstance(String valueAsString) { + throw new UnsupportedOperationException(MessageFormat.format( + "Parameters of type {0} are not supported!", getType())); //$NON-NLS-1$ + } + }, + + /** + * Can be used for:
+ *
    + *
  • {@link Parameter}
  • + *
+ */ + LONG_LIST("LongList") { + @Override + public Parameter parameterInstance() { + return new LongListParameter(); + } + + @Override + public StrolchTimedState> timedStateInstance() { + throw new UnsupportedOperationException(MessageFormat.format( + "TimeStates of type {0} are not supported!", getType())); //$NON-NLS-1$ + } + + @Override + public IValue valueInstance(String valueAsString) { + throw new UnsupportedOperationException(MessageFormat.format( + "Parameters of type {0} are not supported!", getType())); //$NON-NLS-1$ + } + }, + + /** + * Can be used for:
+ *
    + *
  • {@link Parameter}
  • + *
+ */ + STRING_LIST("StringList") { + @Override + public Parameter parameterInstance() { + return new StringListParameter(); + } + + @Override + public StrolchTimedState> timedStateInstance() { + throw new UnsupportedOperationException(MessageFormat.format( + "TimeStates of type {0} are not supported!", getType())); //$NON-NLS-1$ + } + + @Override + public IValue valueInstance(String valueAsString) { + throw new UnsupportedOperationException(MessageFormat.format( + "Values of type {0} are not supported!", getType())); //$NON-NLS-1$ + } + }, + + /** + * Can be used for:
+ *
    + *
  • {@link TimedState}
  • + *
  • {@link IValue}
  • + *
  • {@link IValueChange}
  • + *
+ */ + STRING_SET("StringSet") { + @Override + public Parameter parameterInstance() { + throw new UnsupportedOperationException(MessageFormat.format( + "Parameters of type {0} are not supported!", getType())); //$NON-NLS-1$ + } + + @Override + public StrolchTimedState> timedStateInstance() { + return new StringSetTimedState(); + } + + @Override + public IValue valueInstance(String valueAsString) { + return new StringSetValue(valueAsString); + } + }; + + private String type; + + private StrolchValueType(String type) { + this.type = type; + } + + public String getType() { + return this.type; + } + + public static StrolchValueType parse(String value) { + + // TODO this is for backwards compatibility where we still had States of type BooleanState instead of Boolean + String strippedValue = value.replace("State", ""); + + for (StrolchValueType type : StrolchValueType.values()) { + if (type.type.equals(strippedValue)) + return type; + } + throw new IllegalArgumentException("Type " + value + " does not exist!"); + } + + public abstract Parameter parameterInstance(); + + public abstract StrolchTimedState> timedStateInstance(); + + public abstract IValue valueInstance(String valueAsString); +} \ No newline at end of file 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 92974fa20..d14fd3408 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,19 +41,17 @@ 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 ACTIVITY = "Activity"; public static final String ACTION = "Action"; public static final String START = "Start"; public static final String END = "End"; public static final String VALUE_CHANGE = "ValueChange"; - public static final String VALUE_CLASS = "Class"; public static final String RESOURCE_ID = "ResourceId"; public static final String RESOURCE_TYPE = "ResourceType"; public static final String STATE_ID = "StateId"; - - public class Audit { + public static class Audit { public static final String ID = Tags.ID; public static final String USERNAME = "Username"; diff --git a/li.strolch.model/src/main/java/li/strolch/model/activity/Action.java b/li.strolch.model/src/main/java/li/strolch/model/activity/Action.java index 4da30b4a6..b546933c1 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/activity/Action.java +++ b/li.strolch.model/src/main/java/li/strolch/model/activity/Action.java @@ -18,6 +18,8 @@ package li.strolch.model.activity; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; import java.util.List; import li.strolch.model.GroupedParameterizedElement; @@ -25,19 +27,14 @@ import li.strolch.model.Locator; import li.strolch.model.Locator.LocatorBuilder; import li.strolch.model.Resource; import li.strolch.model.State; -import li.strolch.model.StrolchElement; import li.strolch.model.StrolchRootElement; -import li.strolch.model.Tags; +import li.strolch.model.timevalue.IValue; import li.strolch.model.timevalue.IValueChange; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - /** - * An {@link Action} represents a single step within an {@link Activity}, that - * is, one that is not further decomposed within the {@link Activity}. A - * {@link Activity} applies {@link IValueChange} objects at the start and end - * time of the {@link Activity}. + * An {@link Action} represents a single step within an {@link Activity}, that is, one that is not further decomposed + * within the {@link Activity}. A {@link Activity} applies {@link IValueChange} objects at the start and end time of the + * {@link Activity}. * * @author Martin Smock */ @@ -46,20 +43,41 @@ public class Action extends GroupedParameterizedElement implements IActivityElem protected static final long serialVersionUID = 1L; protected Activity parent; - protected String resourceId, resourceType; - protected State state = State.CREATED; + protected String resourceId; + protected String resourceType; + protected State state; - protected final List> changes = new ArrayList<>(); + protected List>> changes; + + /** + * Empty constructor - for marshalling only! + */ + public Action() { + super(); + } public Action(String id, String name, String type) { super(id, name, type); + this.state = State.CREATED; + } + + public Action(String id, String name, String type, String resourceId, String resourceType) { + super(id, name, type); + this.resourceId = resourceId; + this.resourceType = resourceType; + this.state = State.CREATED; + } + + private void initChanges() { + if (this.changes == null) + this.changes = new ArrayList<>(); } /** * @return the id of the {@link Resource} the {@link Action} acts on */ public String getResourceId() { - return resourceId; + return this.resourceId; } /** @@ -73,8 +91,9 @@ public class Action extends GroupedParameterizedElement implements IActivityElem /** * @return the current State of the aAction */ + @Override public State getState() { - return state; + return this.state; } /** @@ -86,8 +105,7 @@ public class Action extends GroupedParameterizedElement implements IActivityElem } /** - * @return the type of the Resource this Action - * acts on + * @return the type of the Resource this Action acts on */ public String getResourceType() { return this.resourceType; @@ -101,32 +119,48 @@ public class Action extends GroupedParameterizedElement implements IActivityElem } /** - * @param add - * IValueChange to be applied to the - * Resource + * Returns true if this {@link Action} contains any {@link IValueChange changes}, false if not * - * @return true (as specified by {@link Collection#add}) + * @return true if this {@link Action} contains any {@link IValueChange changes}, false if not */ - public boolean addChange(IValueChange change) { - return changes.add(change); + public boolean hasChanges() { + return this.changes != null && !this.changes.isEmpty(); } /** - * @return the list of IValueChange attached to the - * Action start + * @param add + * IValueChange to be applied to the Resource + * + * @return true (as specified by {@link Collection#add}) */ - public List> getChanges() { - return changes; + public boolean addChange(IValueChange> change) { + initChanges(); + return this.changes.add(change); + } + + /** + * @return the list of IValueChange attached to the Action start + */ + public List>> getChanges() { + if (this.changes == null) + return Collections.emptyList(); + return this.changes; + } + + public Iterator>> changesIterator() { + if (this.changes == null) + return Collections.>> emptyList().iterator(); + return this.changes.iterator(); } @Override - public StrolchElement getParent() { - return parent; + public Activity getParent() { + return this.parent; } @Override public StrolchRootElement getRootElement() { - return (parent == null) ? null : parent.getRootElement(); + return (this.parent == null) ? null : this.parent.getRootElement(); } @Override @@ -135,15 +169,20 @@ public class Action extends GroupedParameterizedElement implements IActivityElem } @Override - public StrolchElement getClone() { - Action clone = new Action(getId(), getName(), getType()); - clone.setDbid(getDbid()); - clone.setResourceId(resourceId); - clone.setResourceType(resourceType); - clone.setState(state); - for (IValueChange change : getChanges()) { - clone.changes.add(change.getClone()); + public Action getClone() { + Action clone = new Action(); + super.fillClone(clone); + + clone.setResourceId(this.resourceId); + clone.setResourceType(this.resourceType); + clone.setState(this.state); + + if (this.changes != null) { + for (IValueChange> change : getChanges()) { + clone.addChange(change.getClone()); + } } + return clone; } @@ -185,7 +224,9 @@ public class Action extends GroupedParameterizedElement implements IActivityElem @Override public Long getStart() { Long start = Long.MAX_VALUE; - for (IValueChange change : changes) { + if (this.changes == null) + return start; + for (IValueChange change : this.changes) { start = Math.min(start, change.getTime()); } return start; @@ -194,23 +235,11 @@ public class Action extends GroupedParameterizedElement implements IActivityElem @Override public Long getEnd() { Long end = 0L; - for (IValueChange change : changes) { + if (this.changes == null) + return end; + for (IValueChange change : this.changes) { end = Math.max(end, change.getTime()); } return end; } - - @Override - public Element toDom(Document doc) { - Element element = doc.createElement(Tags.ACTION); - fillElement(element); - element.setAttribute(Tags.STATE, this.state.toString()); - element.setAttribute(Tags.RESOURCE_ID, this.resourceId); - element.setAttribute(Tags.RESOURCE_TYPE, this.resourceType); - for (IValueChange change : changes) { - element.appendChild(change.toDom(doc)); - } - return element; - } - } 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 f550814d8..7a494d117 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 @@ -15,6 +15,7 @@ */ package li.strolch.model.activity; +import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; @@ -29,13 +30,11 @@ import li.strolch.model.StrolchElement; import li.strolch.model.StrolchRootElement; import li.strolch.model.Tags; import li.strolch.model.visitor.StrolchRootElementVisitor; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; +import ch.eitchnet.utils.dbc.DBC; /** - * Parameterized object grouping a collection of {@link Activity} and - * {@link Action} objects defining the process to be scheduled + * Parameterized object grouping a collection of {@link Activity} and {@link Action} objects defining the process to be + * scheduled * * @author Martin Smock */ @@ -45,27 +44,68 @@ public class Activity extends GroupedParameterizedElement implements IActivityEl protected Activity parent; + protected Map elements; + + /** + * Empty constructor - for marshalling only! + */ + public Activity() { + super(); + } + public Activity(String id, String name, String type) { super(id, name, type); } - // use a LinkedHashMap since we will iterate elements in the order added and - // lookup elements by ID - protected Map elements = new LinkedHashMap(); + private void initElements() { + if (this.elements == null) { + // use a LinkedHashMap since we will iterate elements in the order added and lookup elements by ID + elements = new LinkedHashMap(); + } + } /** - * add an activity element to the LinkedHashMap of - * IActivityElements + * Returns true if this {@link Activity} contains any children i.e. any of {@link Action} or {@link Activity} + * + * @return true if this {@link Activity} contains any children i.e. any of {@link Action} or {@link Activity} + */ + public boolean hasElements() { + return this.elements != null && !this.elements.isEmpty(); + } + + /** + * Returns true if this {@link Activity} contains a child with the given id. The element instance type is ignored, + * i.e. {@link Action} or {@link Activity} + * + * @param id + * the id of the element to check for + * + * @return true if this {@link Activity} contains a child with the given id. The element instance type is ignored, + * i.e. {@link Action} or {@link Activity} + */ + public boolean hasElement(String id) { + return this.elements != null && this.elements.containsKey(id); + } + + /** + * add an activity element to the LinkedHashMap of IActivityElements * * @param activityElement * @return the element added */ public IActivityElement addElement(IActivityElement activityElement) { + DBC.PRE.assertNotEquals("Can't add element to itself!", this, activityElement); + DBC.PRE.assertNull("Parent can't already be set!", activityElement.getParent()); + + // TODO make sure we can't create a circular dependency + + initElements(); String id = activityElement.getId(); 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); @@ -79,28 +119,35 @@ public class Activity extends GroupedParameterizedElement implements IActivityEl * the id of the IActivityElement * @return IActivityElement */ - public IActivityElement getElement(String id) { - return elements.get(id); + @SuppressWarnings("unchecked") + public T getElement(String id) { + if (this.elements == null) + return null; + return (T) elements.get(id); } /** - * @return get the LinkedHashMap of - * IActivityElements + * @return get the LinkedHashMap of IActivityElements */ public Map getElements() { + if (this.elements == null) + return Collections.emptyMap(); return elements; } /** - * @return the iterator for entries, which include the id as key and the - * {@link IActivityElement} as value + * @return the iterator for entries, which include the id as key and the {@link IActivityElement} as value */ public Iterator> elementIterator() { + if (this.elements == null) + return Collections. emptyMap().entrySet().iterator(); return elements.entrySet().iterator(); } public Long getStart() { Long start = Long.MAX_VALUE; + if (this.elements == null) + return start; Iterator> elementIterator = elementIterator(); while (elementIterator.hasNext()) { IActivityElement action = elementIterator.next().getValue(); @@ -111,6 +158,8 @@ public class Activity extends GroupedParameterizedElement implements IActivityEl public Long getEnd() { Long end = 0L; + if (this.elements == null) + return end; Iterator> elementIterator = elementIterator(); while (elementIterator.hasNext()) { IActivityElement action = elementIterator.next().getValue(); @@ -121,6 +170,8 @@ public class Activity extends GroupedParameterizedElement implements IActivityEl public State getState() { State state = State.PLANNED; + if (this.elements == null) + return state; Iterator> elementIterator = elementIterator(); while (elementIterator.hasNext()) { IActivityElement child = elementIterator.next().getValue(); @@ -144,18 +195,6 @@ public class Activity extends GroupedParameterizedElement implements IActivityEl locatorBuilder.append(Tags.ACTIVITY).append(getType()).append(getId()); } - @Override - public Element toDom(Document doc) { - Element element = doc.createElement(Tags.ACTIVITY); - fillElement(element); - Iterator> elementIterator = elementIterator(); - while (elementIterator.hasNext()) { - IActivityElement activityElement = elementIterator.next().getValue(); - element.appendChild(activityElement.toDom(doc)); - } - return element; - } - @Override public StrolchElement getParent() { return parent; @@ -172,12 +211,15 @@ public class Activity extends GroupedParameterizedElement implements IActivityEl } @Override - public StrolchElement getClone() { - Activity clone = new Activity(id, name, type); - Iterator> elementIterator = elementIterator(); - while (elementIterator.hasNext()) { - Entry next = elementIterator.next(); - clone.elements.put(next.getKey(), (IActivityElement) next.getValue().getClone()); + public Activity getClone() { + Activity clone = new Activity(); + super.fillClone(clone); + + if (this.elements == null) + return clone; + + for (IActivityElement element : this.elements.values()) { + clone.addElement(element.getClone()); } return clone; } @@ -210,5 +252,4 @@ public class Activity extends GroupedParameterizedElement implements IActivityEl public void setParent(Activity activity) { this.parent = activity; } - } diff --git a/li.strolch.model/src/main/java/li/strolch/model/activity/IActivityElement.java b/li.strolch.model/src/main/java/li/strolch/model/activity/IActivityElement.java index 226d52763..0bee8af39 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/activity/IActivityElement.java +++ b/li.strolch.model/src/main/java/li/strolch/model/activity/IActivityElement.java @@ -22,16 +22,16 @@ import li.strolch.model.StrolchElement; * Marker for all child elements of {@link Activity} objects * * @author Martin Smock - * */ public interface IActivityElement extends StrolchElement { - Long getStart(); + public Long getStart(); - Long getEnd(); + public Long getEnd(); - State getState(); - - void setParent(Activity activity); + public State getState(); + public void setParent(Activity activity); + + public IActivityElement getClone(); } diff --git a/li.strolch.model/src/main/java/li/strolch/model/parameter/AbstractParameter.java b/li.strolch.model/src/main/java/li/strolch/model/parameter/AbstractParameter.java index 04110f754..b5e2c2506 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/parameter/AbstractParameter.java +++ b/li.strolch.model/src/main/java/li/strolch/model/parameter/AbstractParameter.java @@ -26,12 +26,7 @@ import li.strolch.model.Locator; import li.strolch.model.Locator.LocatorBuilder; import li.strolch.model.ParameterizedElement; import li.strolch.model.StrolchRootElement; -import li.strolch.model.Tags; import li.strolch.model.visitor.ParameterVisitor; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - import ch.eitchnet.utils.helper.StringHelper; /** @@ -135,74 +130,6 @@ public abstract class AbstractParameter extends AbstractStrolchElement implem return false; } - @Override - public Element toDom(Document doc) { - Element element = doc.createElement(Tags.PARAMETER); - fillElement(element); - - element.setAttribute(Tags.VALUE, getValueAsString()); - - if (!this.interpretation.equals(INTERPRETATION_NONE)) { - element.setAttribute(Tags.INTERPRETATION, this.interpretation); - } - if (!this.uom.equals(UOM_NONE)) { - element.setAttribute(Tags.UOM, this.uom); - } - if (this.hidden) { - element.setAttribute(Tags.HIDDEN, Boolean.toString(this.hidden)); - } - if (this.index != 0) { - element.setAttribute(Tags.INDEX, Integer.toString(this.index)); - } - - return element; - } - - @Override - public void fromDom(Element element) { - - super.fromDom(element); - - String typeS = element.getAttribute(Tags.TYPE); - if (StringHelper.isEmpty(typeS)) { - String msg = "Type must be set on element with id {0}"; //$NON-NLS-1$ - msg = MessageFormat.format(msg, this.id); - throw new StrolchException(msg); - } else if (!typeS.equals(getType())) { - String msg = "{0} must have type {1}, not: {2}"; //$NON-NLS-1$ - msg = MessageFormat.format(msg, getClass().getSimpleName(), getType(), typeS); - throw new StrolchException(msg); - } - - String interpretation = element.getAttribute(Tags.INTERPRETATION); - String hidden = element.getAttribute(Tags.HIDDEN); - String uom = element.getAttribute(Tags.UOM); - String index = element.getAttribute(Tags.INDEX); - - setInterpretation(interpretation); - setUom(uom); - - if (StringHelper.isEmpty(index)) { - this.index = 0; - } else { - this.index = Integer.valueOf(index); - } - - if (StringHelper.isEmpty(hidden)) { - setHidden(false); - } else { - if (hidden.equalsIgnoreCase(Boolean.TRUE.toString())) { - setHidden(true); - } else if (hidden.equalsIgnoreCase(Boolean.FALSE.toString())) { - setHidden(false); - } else { - String msg = "Boolean string must be either {0} or {1}"; //$NON-NLS-1$ - msg = MessageFormat.format(msg, Boolean.TRUE.toString(), Boolean.FALSE.toString()); - throw new StrolchException(msg); - } - } - } - @Override protected void fillLocator(LocatorBuilder lb) { lb.append(this.id); diff --git a/li.strolch.model/src/main/java/li/strolch/model/parameter/BooleanParameter.java b/li.strolch.model/src/main/java/li/strolch/model/parameter/BooleanParameter.java index 56c1aba28..8f1ada4ab 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/parameter/BooleanParameter.java +++ b/li.strolch.model/src/main/java/li/strolch/model/parameter/BooleanParameter.java @@ -15,14 +15,8 @@ */ package li.strolch.model.parameter; -import java.text.MessageFormat; - -import li.strolch.exception.StrolchException; -import li.strolch.model.Tags; +import li.strolch.model.StrolchValueType; import li.strolch.model.visitor.ParameterVisitor; - -import org.w3c.dom.Element; - import ch.eitchnet.utils.helper.StringHelper; /** @@ -30,7 +24,6 @@ import ch.eitchnet.utils.helper.StringHelper; */ public class BooleanParameter extends AbstractParameter { - public static final String TYPE = "Boolean"; //$NON-NLS-1$ private static final long serialVersionUID = 0L; private Boolean value = Boolean.FALSE; @@ -54,23 +47,6 @@ public class BooleanParameter extends AbstractParameter { setValue(value); } - /** - * DOM Constructor - * - * @param element - */ - public BooleanParameter(Element element) { - super.fromDom(element); - - String valueS = element.getAttribute(Tags.VALUE); - if (StringHelper.isEmpty(valueS)) { - String msg = MessageFormat.format("No value defined for {0}", this.id); //$NON-NLS-1$ - throw new StrolchException(msg); - } - - setValue(parseFromString(valueS)); - } - @Override public String getValueAsString() { return this.value.toString(); @@ -87,9 +63,14 @@ public class BooleanParameter extends AbstractParameter { this.value = value; } + @Override + public void setValueFromString(String valueAsString) { + setValue(parseFromString(valueAsString)); + } + @Override public String getType() { - return BooleanParameter.TYPE; + return StrolchValueType.BOOLEAN.getType(); } @Override diff --git a/li.strolch.model/src/main/java/li/strolch/model/parameter/DateParameter.java b/li.strolch.model/src/main/java/li/strolch/model/parameter/DateParameter.java index ffffb8462..461319b6f 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/parameter/DateParameter.java +++ b/li.strolch.model/src/main/java/li/strolch/model/parameter/DateParameter.java @@ -15,16 +15,10 @@ */ package li.strolch.model.parameter; -import java.text.MessageFormat; import java.util.Date; -import li.strolch.exception.StrolchException; -import li.strolch.model.Tags; +import li.strolch.model.StrolchValueType; import li.strolch.model.visitor.ParameterVisitor; - -import org.w3c.dom.Element; - -import ch.eitchnet.utils.helper.StringHelper; import ch.eitchnet.utils.iso8601.ISO8601FormatFactory; /** @@ -32,7 +26,6 @@ import ch.eitchnet.utils.iso8601.ISO8601FormatFactory; */ public class DateParameter extends AbstractParameter { - public static final String TYPE = "Date"; //$NON-NLS-1$ private static final long serialVersionUID = 0L; private Date value; @@ -56,23 +49,6 @@ public class DateParameter extends AbstractParameter { setValue(value); } - /** - * DOM Constructor - * - * @param element - */ - public DateParameter(Element element) { - super.fromDom(element); - - String valueS = element.getAttribute(Tags.VALUE); - if (StringHelper.isEmpty(valueS)) { - String msg = MessageFormat.format("No value defined for {0}", this.id); //$NON-NLS-1$ - throw new StrolchException(msg); - } - - setValue(parseFromString(valueS)); - } - @Override public String getValueAsString() { return ISO8601FormatFactory.getInstance().formatDate(this.value); @@ -89,9 +65,14 @@ public class DateParameter extends AbstractParameter { this.value = value; } + @Override + public void setValueFromString(String valueAsString) { + setValue(parseFromString(valueAsString)); + } + @Override public String getType() { - return DateParameter.TYPE; + return StrolchValueType.DATE.getType(); } @Override diff --git a/li.strolch.model/src/main/java/li/strolch/model/parameter/DurationParameter.java b/li.strolch.model/src/main/java/li/strolch/model/parameter/DurationParameter.java index 626ce8635..2916d7aff 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/parameter/DurationParameter.java +++ b/li.strolch.model/src/main/java/li/strolch/model/parameter/DurationParameter.java @@ -15,15 +15,8 @@ */ package li.strolch.model.parameter; -import java.text.MessageFormat; - -import li.strolch.exception.StrolchException; -import li.strolch.model.Tags; +import li.strolch.model.StrolchValueType; import li.strolch.model.visitor.ParameterVisitor; - -import org.w3c.dom.Element; - -import ch.eitchnet.utils.helper.StringHelper; import ch.eitchnet.utils.iso8601.ISO8601FormatFactory; /** @@ -31,7 +24,6 @@ import ch.eitchnet.utils.iso8601.ISO8601FormatFactory; */ public class DurationParameter extends AbstractParameter { - public static final String TYPE = "Duration"; //$NON-NLS-1$ private static final long serialVersionUID = 0L; private Long value; @@ -55,23 +47,6 @@ public class DurationParameter extends AbstractParameter { setValue(value); } - /** - * DOM Constructor - * - * @param element - */ - public DurationParameter(Element element) { - super.fromDom(element); - - String valueS = element.getAttribute(Tags.VALUE); - if (StringHelper.isEmpty(valueS)) { - String msg = MessageFormat.format("No value defined for {0}", this.id); //$NON-NLS-1$ - throw new StrolchException(msg); - } - - setValue(parseFromString(valueS)); - } - @Override public String getValueAsString() { return ISO8601FormatFactory.getInstance().formatDuration(this.value); @@ -88,9 +63,14 @@ public class DurationParameter extends AbstractParameter { this.value = value; } + @Override + public void setValueFromString(String valueAsString) { + setValue(parseFromString(valueAsString)); + } + @Override public String getType() { - return DurationParameter.TYPE; + return StrolchValueType.DURATION.getType(); } @Override diff --git a/li.strolch.model/src/main/java/li/strolch/model/parameter/FloatListParameter.java b/li.strolch.model/src/main/java/li/strolch/model/parameter/FloatListParameter.java index 83240a518..5bee81921 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/parameter/FloatListParameter.java +++ b/li.strolch.model/src/main/java/li/strolch/model/parameter/FloatListParameter.java @@ -15,18 +15,13 @@ */ package li.strolch.model.parameter; -import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; -import li.strolch.exception.StrolchException; -import li.strolch.model.Tags; +import li.strolch.model.StrolchValueType; import li.strolch.model.visitor.ParameterVisitor; - -import org.w3c.dom.Element; - import ch.eitchnet.utils.helper.StringHelper; /** @@ -34,7 +29,6 @@ import ch.eitchnet.utils.helper.StringHelper; */ public class FloatListParameter extends AbstractParameter> implements ListParameter { - public static final String TYPE = "FloatList"; //$NON-NLS-1$ private static final long serialVersionUID = 1L; protected List value; @@ -59,23 +53,6 @@ public class FloatListParameter extends AbstractParameter> implemen setValue(value); } - /** - * DOM Constructor - * - * @param element - */ - public FloatListParameter(Element element) { - super.fromDom(element); - - String valueS = element.getAttribute(Tags.VALUE); - if (StringHelper.isEmpty(valueS)) { - String msg = MessageFormat.format("No value defined for {0}", this.id); //$NON-NLS-1$ - throw new StrolchException(msg); - } - - setValue(parseFromString(valueS)); - } - @Override public String getValueAsString() { if (this.value.isEmpty()) { @@ -111,6 +88,11 @@ public class FloatListParameter extends AbstractParameter> implemen this.value.addAll(value); } + @Override + public void setValueFromString(String valueAsString) { + setValue(parseFromString(valueAsString)); + } + @Override public void addValue(Double value) { this.value.add(value); @@ -133,7 +115,7 @@ public class FloatListParameter extends AbstractParameter> implemen @Override public String getType() { - return TYPE; + return StrolchValueType.FLOAT_LIST.getType(); } @Override diff --git a/li.strolch.model/src/main/java/li/strolch/model/parameter/FloatParameter.java b/li.strolch.model/src/main/java/li/strolch/model/parameter/FloatParameter.java index 565ce2738..f9c408ea1 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/parameter/FloatParameter.java +++ b/li.strolch.model/src/main/java/li/strolch/model/parameter/FloatParameter.java @@ -15,23 +15,15 @@ */ package li.strolch.model.parameter; -import java.text.MessageFormat; - -import li.strolch.exception.StrolchException; -import li.strolch.model.Tags; +import li.strolch.model.StrolchValueType; import li.strolch.model.visitor.ParameterVisitor; -import org.w3c.dom.Element; - -import ch.eitchnet.utils.helper.StringHelper; - /** * @author Robert von Burg * */ public class FloatParameter extends AbstractParameter { - public static final String TYPE = "Float"; //$NON-NLS-1$ private static final long serialVersionUID = 0L; private Double value = Double.MAX_VALUE; @@ -56,23 +48,6 @@ public class FloatParameter extends AbstractParameter { setValue(value); } - /** - * DOM Constructor - * - * @param element - */ - public FloatParameter(Element element) { - super.fromDom(element); - - String valueS = element.getAttribute(Tags.VALUE); - if (StringHelper.isEmpty(valueS)) { - String msg = MessageFormat.format("No value defined for {0}", this.id); //$NON-NLS-1$ - throw new StrolchException(msg); - } - - setValue(parseFromString(valueS)); - } - @Override public String getValueAsString() { return Double.toString(this.value); @@ -89,9 +64,14 @@ public class FloatParameter extends AbstractParameter { this.value = value; } + @Override + public void setValueFromString(String valueAsString) { + setValue(parseFromString(valueAsString)); + } + @Override public String getType() { - return FloatParameter.TYPE; + return StrolchValueType.FLOAT.getType(); } @Override diff --git a/li.strolch.model/src/main/java/li/strolch/model/parameter/IntegerListParameter.java b/li.strolch.model/src/main/java/li/strolch/model/parameter/IntegerListParameter.java index 7ee9dfb78..47fc8f55b 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/parameter/IntegerListParameter.java +++ b/li.strolch.model/src/main/java/li/strolch/model/parameter/IntegerListParameter.java @@ -15,18 +15,13 @@ */ package li.strolch.model.parameter; -import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; -import li.strolch.exception.StrolchException; -import li.strolch.model.Tags; +import li.strolch.model.StrolchValueType; import li.strolch.model.visitor.ParameterVisitor; - -import org.w3c.dom.Element; - import ch.eitchnet.utils.helper.StringHelper; /** @@ -34,7 +29,6 @@ import ch.eitchnet.utils.helper.StringHelper; */ public class IntegerListParameter extends AbstractParameter> implements ListParameter { - public static final String TYPE = "IntegerList"; //$NON-NLS-1$ private static final long serialVersionUID = 1L; protected List value; @@ -59,23 +53,6 @@ public class IntegerListParameter extends AbstractParameter> imple setValue(value); } - /** - * DOM Constructor - * - * @param element - */ - public IntegerListParameter(Element element) { - super.fromDom(element); - - String valueS = element.getAttribute(Tags.VALUE); - if (StringHelper.isEmpty(valueS)) { - String msg = MessageFormat.format("No value defined for {0}", this.id); //$NON-NLS-1$ - throw new StrolchException(msg); - } - - setValue(parseFromString(valueS)); - } - @Override public String getValueAsString() { if (this.value.isEmpty()) { @@ -111,6 +88,11 @@ public class IntegerListParameter extends AbstractParameter> imple this.value.addAll(value); } + @Override + public void setValueFromString(String valueAsString) { + setValue(parseFromString(valueAsString)); + } + @Override public void addValue(Integer value) { this.value.add(value); @@ -133,7 +115,7 @@ public class IntegerListParameter extends AbstractParameter> imple @Override public String getType() { - return TYPE; + return StrolchValueType.INTEGER_LIST.getType(); } @Override diff --git a/li.strolch.model/src/main/java/li/strolch/model/parameter/IntegerParameter.java b/li.strolch.model/src/main/java/li/strolch/model/parameter/IntegerParameter.java index cf29997d4..333a2aae4 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/parameter/IntegerParameter.java +++ b/li.strolch.model/src/main/java/li/strolch/model/parameter/IntegerParameter.java @@ -15,23 +15,15 @@ */ package li.strolch.model.parameter; -import java.text.MessageFormat; - -import li.strolch.exception.StrolchException; -import li.strolch.model.Tags; +import li.strolch.model.StrolchValueType; import li.strolch.model.visitor.ParameterVisitor; -import org.w3c.dom.Element; - -import ch.eitchnet.utils.helper.StringHelper; - /** * @author Robert von Burg * */ public class IntegerParameter extends AbstractParameter { - public static final String TYPE = "Integer"; //$NON-NLS-1$ private static final long serialVersionUID = 0L; private Integer value = Integer.MAX_VALUE; @@ -55,26 +47,9 @@ public class IntegerParameter extends AbstractParameter { setValue(value); } - /** - * DOM Constructor - * - * @param element - */ - public IntegerParameter(Element element) { - super.fromDom(element); - - String valueS = element.getAttribute(Tags.VALUE); - if (StringHelper.isEmpty(valueS)) { - String msg = MessageFormat.format("No value defined for {0}", this.id); //$NON-NLS-1$ - throw new StrolchException(msg); - } - - setValue(parseFromString(valueS)); - } - @Override public String getType() { - return IntegerParameter.TYPE; + return StrolchValueType.INTEGER.getType(); } @Override @@ -93,6 +68,11 @@ public class IntegerParameter extends AbstractParameter { this.value = value; } + @Override + public void setValueFromString(String valueAsString) { + setValue(parseFromString(valueAsString)); + } + @Override public IntegerParameter getClone() { IntegerParameter clone = new IntegerParameter(); diff --git a/li.strolch.model/src/main/java/li/strolch/model/parameter/LongListParameter.java b/li.strolch.model/src/main/java/li/strolch/model/parameter/LongListParameter.java index 941b7ccf6..a5be57b2c 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/parameter/LongListParameter.java +++ b/li.strolch.model/src/main/java/li/strolch/model/parameter/LongListParameter.java @@ -15,18 +15,13 @@ */ package li.strolch.model.parameter; -import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; -import li.strolch.exception.StrolchException; -import li.strolch.model.Tags; +import li.strolch.model.StrolchValueType; import li.strolch.model.visitor.ParameterVisitor; - -import org.w3c.dom.Element; - import ch.eitchnet.utils.helper.StringHelper; /** @@ -34,7 +29,6 @@ import ch.eitchnet.utils.helper.StringHelper; */ public class LongListParameter extends AbstractParameter> implements ListParameter { - public static final String TYPE = "LongList"; //$NON-NLS-1$ private static final long serialVersionUID = 1L; protected List value; @@ -59,23 +53,6 @@ public class LongListParameter extends AbstractParameter> implements setValue(value); } - /** - * DOM Constructor - * - * @param element - */ - public LongListParameter(Element element) { - super.fromDom(element); - - String valueS = element.getAttribute(Tags.VALUE); - if (StringHelper.isEmpty(valueS)) { - String msg = MessageFormat.format("No value defined for {0}", this.id); //$NON-NLS-1$ - throw new StrolchException(msg); - } - - setValue(parseFromString(valueS)); - } - @Override public String getValueAsString() { if (this.value.isEmpty()) { @@ -111,6 +88,11 @@ public class LongListParameter extends AbstractParameter> implements this.value.addAll(value); } + @Override + public void setValueFromString(String valueAsString) { + setValue(parseFromString(valueAsString)); + } + @Override public void addValue(Long value) { this.value.add(value); @@ -133,7 +115,7 @@ public class LongListParameter extends AbstractParameter> implements @Override public String getType() { - return TYPE; + return StrolchValueType.LONG_LIST.getType(); } @Override diff --git a/li.strolch.model/src/main/java/li/strolch/model/parameter/LongParameter.java b/li.strolch.model/src/main/java/li/strolch/model/parameter/LongParameter.java index 0e47f51a9..443daf743 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/parameter/LongParameter.java +++ b/li.strolch.model/src/main/java/li/strolch/model/parameter/LongParameter.java @@ -15,23 +15,15 @@ */ package li.strolch.model.parameter; -import java.text.MessageFormat; - -import li.strolch.exception.StrolchException; -import li.strolch.model.Tags; +import li.strolch.model.StrolchValueType; import li.strolch.model.visitor.ParameterVisitor; -import org.w3c.dom.Element; - -import ch.eitchnet.utils.helper.StringHelper; - /** * @author Robert von Burg * */ public class LongParameter extends AbstractParameter { - public static final String TYPE = "Long"; //$NON-NLS-1$ private static final long serialVersionUID = 0L; protected Long value; @@ -55,23 +47,6 @@ public class LongParameter extends AbstractParameter { setValue(value); } - /** - * DOM Constructor - * - * @param element - */ - public LongParameter(Element element) { - super.fromDom(element); - - String valueS = element.getAttribute(Tags.VALUE); - if (StringHelper.isEmpty(valueS)) { - String msg = MessageFormat.format("No value defined for {0}", this.id); //$NON-NLS-1$ - throw new StrolchException(msg); - } - - setValue(parseFromString(valueS)); - } - @Override public String getValueAsString() { return this.value.toString(); @@ -88,9 +63,14 @@ public class LongParameter extends AbstractParameter { this.value = value; } + @Override + public void setValueFromString(String valueAsString) { + setValue(parseFromString(valueAsString)); + } + @Override public String getType() { - return LongParameter.TYPE; + return StrolchValueType.LONG.getType(); } @Override diff --git a/li.strolch.model/src/main/java/li/strolch/model/parameter/Parameter.java b/li.strolch.model/src/main/java/li/strolch/model/parameter/Parameter.java index f55b99594..c6ecde5dd 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/parameter/Parameter.java +++ b/li.strolch.model/src/main/java/li/strolch/model/parameter/Parameter.java @@ -26,12 +26,20 @@ import li.strolch.model.visitor.ParameterVisitor; public interface Parameter extends StrolchElement { /** - * the value of the parameter as string + * Returns the value of the parameter as string * - * @return String + * @return the value as string */ public String getValueAsString(); + /** + * Set the value of the parameter from a string + * + * @param valueAsString + * the string from which to set the value + */ + public void setValueFromString(String valueAsString); + /** * the value of the parameter * diff --git a/li.strolch.model/src/main/java/li/strolch/model/parameter/StringListParameter.java b/li.strolch.model/src/main/java/li/strolch/model/parameter/StringListParameter.java index b19c008cb..323506efb 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/parameter/StringListParameter.java +++ b/li.strolch.model/src/main/java/li/strolch/model/parameter/StringListParameter.java @@ -15,18 +15,13 @@ */ package li.strolch.model.parameter; -import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; -import li.strolch.exception.StrolchException; -import li.strolch.model.Tags; +import li.strolch.model.StrolchValueType; import li.strolch.model.visitor.ParameterVisitor; - -import org.w3c.dom.Element; - import ch.eitchnet.utils.helper.StringHelper; /** @@ -34,7 +29,6 @@ import ch.eitchnet.utils.helper.StringHelper; */ public class StringListParameter extends AbstractParameter> implements ListParameter { - public static final String TYPE = "StringList"; //$NON-NLS-1$ private static final long serialVersionUID = 1L; protected List value; @@ -59,23 +53,6 @@ public class StringListParameter extends AbstractParameter> impleme setValue(value); } - /** - * DOM Constructor - * - * @param element - */ - public StringListParameter(Element element) { - super.fromDom(element); - - String valueS = element.getAttribute(Tags.VALUE); - if (StringHelper.isEmpty(valueS)) { - String msg = MessageFormat.format("No value defined for {0}", this.id); //$NON-NLS-1$ - throw new StrolchException(msg); - } - - setValue(parseFromString(valueS)); - } - @Override public String getValueAsString() { if (this.value.isEmpty()) { @@ -111,6 +88,11 @@ public class StringListParameter extends AbstractParameter> impleme this.value.addAll(value); } + @Override + public void setValueFromString(String valueAsString) { + setValue(parseFromString(valueAsString)); + } + @Override public void addValue(String value) { this.value.add(value); @@ -133,7 +115,7 @@ public class StringListParameter extends AbstractParameter> impleme @Override public String getType() { - return TYPE; + return StrolchValueType.STRING_LIST.getType(); } @Override diff --git a/li.strolch.model/src/main/java/li/strolch/model/parameter/StringParameter.java b/li.strolch.model/src/main/java/li/strolch/model/parameter/StringParameter.java index b7c65b897..81c3e7882 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/parameter/StringParameter.java +++ b/li.strolch.model/src/main/java/li/strolch/model/parameter/StringParameter.java @@ -15,16 +15,9 @@ */ package li.strolch.model.parameter; -import java.text.MessageFormat; - -import li.strolch.exception.StrolchException; -import li.strolch.model.Tags; +import li.strolch.model.StrolchValueType; import li.strolch.model.visitor.ParameterVisitor; -import org.w3c.dom.Element; - -import ch.eitchnet.utils.helper.StringHelper; - /** * @author Robert von Burg * @@ -32,7 +25,6 @@ import ch.eitchnet.utils.helper.StringHelper; public class StringParameter extends AbstractParameter { public static final String UNDEFINED_VALUE = "-"; //$NON-NLS-1$ - public static final String TYPE = "String"; //$NON-NLS-1$ private static final long serialVersionUID = 0L; private String value = UNDEFINED_VALUE; @@ -57,26 +49,9 @@ public class StringParameter extends AbstractParameter { setValue(value); } - /** - * DOM Constructor - * - * @param element - */ - public StringParameter(Element element) { - super.fromDom(element); - - String valueS = element.getAttribute(Tags.VALUE); - if (StringHelper.isEmpty(valueS)) { - String msg = MessageFormat.format("No value defined for {0}", this.id); //$NON-NLS-1$ - throw new StrolchException(msg); - } - - setValue(valueS); - } - @Override public String getType() { - return StringParameter.TYPE; + return StrolchValueType.STRING.getType(); } @Override @@ -95,6 +70,11 @@ public class StringParameter extends AbstractParameter { this.value = value; } + @Override + public void setValueFromString(String valueAsString) { + setValue(valueAsString); + } + @Override public StringParameter getClone() { StringParameter clone = new StringParameter(); diff --git a/li.strolch.model/src/main/java/li/strolch/model/query/ActivityQuery.java b/li.strolch.model/src/main/java/li/strolch/model/query/ActivityQuery.java new file mode 100644 index 000000000..8ec8c16dd --- /dev/null +++ b/li.strolch.model/src/main/java/li/strolch/model/query/ActivityQuery.java @@ -0,0 +1,66 @@ +/* + * 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.model.query; + +import li.strolch.model.ActivityVisitor; +import li.strolch.model.activity.Action; +import li.strolch.model.activity.Activity; + +/** + * {@link ActivityQuery} is the user API to query {@link Activity Activities} in Strolch. The {@link Navigation} is used + * to navigate to a type of activity on which any further {@link Selection Selections} will be performed. The + * {@link ActivityVisitor} is used to transform the returned object into a domain specific object (if required). This + * mechanism allows you to query e.g. a specific {@link Action} instead of having to return all the elements and then + * performing this transformation. + * + * @author Robert von Burg + */ +public class ActivityQuery extends StrolchElementQuery { + + /** + * @param navigation + * @param elementVisitor + */ + public ActivityQuery(Navigation navigation) { + super(navigation); + } + + @Override + public ActivityQuery with(Selection selection) { + super.with(selection); + return this; + } + + @Override + public ActivityQuery not(Selection selection) { + super.not(selection); + return this; + } + + @Override + public ActivityQuery withAny() { + super.withAny(); + return this; + } + + public static ActivityQuery query(Navigation navigation) { + return new ActivityQuery(navigation); + } + + public static ActivityQuery query(String type) { + return new ActivityQuery(new StrolchTypeNavigation(type)); + } +} diff --git a/li.strolch.model/src/main/java/li/strolch/model/query/ActivityQueryVisitor.java b/li.strolch.model/src/main/java/li/strolch/model/query/ActivityQueryVisitor.java new file mode 100644 index 000000000..56540f8a4 --- /dev/null +++ b/li.strolch.model/src/main/java/li/strolch/model/query/ActivityQueryVisitor.java @@ -0,0 +1,24 @@ +/* + * 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.model.query; + +/** + * @author Robert von Burg + */ +public interface ActivityQueryVisitor extends StrolchRootElementSelectionVisitor, ParameterSelectionVisitor { + + // marker interface +} diff --git a/li.strolch.model/src/main/java/li/strolch/model/timedstate/AbstractStrolchTimedState.java b/li.strolch.model/src/main/java/li/strolch/model/timedstate/AbstractStrolchTimedState.java index 4dbd1f1eb..ca27e5365 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/timedstate/AbstractStrolchTimedState.java +++ b/li.strolch.model/src/main/java/li/strolch/model/timedstate/AbstractStrolchTimedState.java @@ -17,10 +17,6 @@ package li.strolch.model.timedstate; import static li.strolch.model.StrolchModelConstants.INTERPRETATION_NONE; import static li.strolch.model.StrolchModelConstants.UOM_NONE; - -import java.text.MessageFormat; - -import li.strolch.exception.StrolchException; import li.strolch.model.AbstractStrolchElement; import li.strolch.model.Locator; import li.strolch.model.Locator.LocatorBuilder; @@ -33,10 +29,6 @@ import li.strolch.model.timevalue.ITimeVariable; import li.strolch.model.timevalue.IValue; import li.strolch.model.timevalue.IValueChange; import li.strolch.model.visitor.TimedStateVisitor; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - import ch.eitchnet.utils.helper.StringHelper; /** @@ -160,72 +152,6 @@ public abstract class AbstractStrolchTimedState extends Abstra return false; } - @Override - public Element toDom(Document doc) { - Element element = doc.createElement(Tags.PARAMETER); - fillElement(element); - - if (!this.interpretation.equals(INTERPRETATION_NONE)) { - element.setAttribute(Tags.INTERPRETATION, this.interpretation); - } - if (!this.uom.equals(UOM_NONE)) { - element.setAttribute(Tags.UOM, this.uom); - } - if (this.hidden) { - element.setAttribute(Tags.HIDDEN, Boolean.toString(this.hidden)); - } - if (this.index != 0) { - element.setAttribute(Tags.INDEX, Integer.toString(this.index)); - } - - return element; - } - - @Override - public void fromDom(Element element) { - - super.fromDom(element); - - String typeS = element.getAttribute(Tags.TYPE); - if (StringHelper.isEmpty(typeS)) { - String msg = "Type must be set on element with id {0}"; //$NON-NLS-1$ - msg = MessageFormat.format(msg, this.id); - throw new StrolchException(msg); - } else if (!typeS.equals(getType())) { - String msg = "{0} must have type {1}, not: {2}"; //$NON-NLS-1$ - msg = MessageFormat.format(msg, getClass().getSimpleName(), getType(), typeS); - throw new StrolchException(msg); - } - - String interpretation = element.getAttribute(Tags.INTERPRETATION); - String hidden = element.getAttribute(Tags.HIDDEN); - String uom = element.getAttribute(Tags.UOM); - String index = element.getAttribute(Tags.INDEX); - - setInterpretation(interpretation); - setUom(uom); - - if (StringHelper.isEmpty(index)) { - this.index = 0; - } else { - this.index = Integer.valueOf(index); - } - - if (StringHelper.isEmpty(hidden)) { - setHidden(false); - } else { - if (hidden.equalsIgnoreCase(Boolean.TRUE.toString())) { - setHidden(true); - } else if (hidden.equalsIgnoreCase(Boolean.FALSE.toString())) { - setHidden(false); - } else { - String msg = "Boolean string must be either {0} or {1}"; //$NON-NLS-1$ - msg = MessageFormat.format(msg, Boolean.TRUE.toString(), Boolean.FALSE.toString()); - throw new StrolchException(msg); - } - } - } - @Override protected void fillLocator(LocatorBuilder lb) { lb.append(Tags.STATE); diff --git a/li.strolch.model/src/main/java/li/strolch/model/timedstate/BooleanTimedState.java b/li.strolch.model/src/main/java/li/strolch/model/timedstate/BooleanTimedState.java index 773421ff8..14c5aede4 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/timedstate/BooleanTimedState.java +++ b/li.strolch.model/src/main/java/li/strolch/model/timedstate/BooleanTimedState.java @@ -15,19 +15,9 @@ */ package li.strolch.model.timedstate; -import java.util.Date; -import java.util.SortedSet; - -import li.strolch.model.Tags; -import li.strolch.model.timevalue.ITimeValue; +import li.strolch.model.StrolchValueType; import li.strolch.model.timevalue.impl.BooleanValue; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -import ch.eitchnet.utils.iso8601.ISO8601FormatFactory; - /** * @author Robert von Burg */ @@ -35,8 +25,6 @@ public class BooleanTimedState extends AbstractStrolchTimedState { private static final long serialVersionUID = 1L; - public static final String TYPE = "BooleanState"; - public BooleanTimedState() { super(); } @@ -45,45 +33,14 @@ public class BooleanTimedState extends AbstractStrolchTimedState { super(id, name); } - public BooleanTimedState(Element element) { - super.fromDom(element); - - this.state = new TimedState<>(); - - NodeList timeValueElems = element.getElementsByTagName(Tags.VALUE); - for (int i = 0; i < timeValueElems.getLength(); i++) { - Element timeValueElem = (Element) timeValueElems.item(i); - String timeS = timeValueElem.getAttribute(Tags.TIME); - Date date = ISO8601FormatFactory.getInstance().parseDate(timeS); - long time = date.getTime(); - - Boolean value = Boolean.valueOf(timeValueElem.getAttribute(Tags.VALUE)); - BooleanValue booleanValue = new BooleanValue(value); - this.state.getTimeEvolution().setValueAt(time, booleanValue); - } - } - @Override - public Element toDom(Document doc) { - - Element stateElement = doc.createElement(Tags.TIMED_STATE); - super.fillElement(stateElement); - SortedSet> values = this.state.getTimeEvolution().getValues(); - for (ITimeValue timeValue : values) { - Long time = timeValue.getTime(); - BooleanValue value = timeValue.getValue(); - Element valueElem = doc.createElement(Tags.VALUE); - valueElem.setAttribute(Tags.TIME, ISO8601FormatFactory.getInstance().formatDate(time)); - valueElem.setAttribute(Tags.VALUE, value.getValue().toString()); - stateElement.appendChild(valueElem); - } - - return stateElement; + public void setStateFromStringAt(Long time, String value) { + getTimeEvolution().setValueAt(time, new BooleanValue(value)); } @Override public String getType() { - return TYPE; + return StrolchValueType.BOOLEAN.getType(); } @Override diff --git a/li.strolch.model/src/main/java/li/strolch/model/timedstate/FloatTimedState.java b/li.strolch.model/src/main/java/li/strolch/model/timedstate/FloatTimedState.java index bf1748cb8..a91918b91 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/timedstate/FloatTimedState.java +++ b/li.strolch.model/src/main/java/li/strolch/model/timedstate/FloatTimedState.java @@ -15,19 +15,9 @@ */ package li.strolch.model.timedstate; -import java.util.Date; -import java.util.SortedSet; - -import li.strolch.model.Tags; -import li.strolch.model.timevalue.ITimeValue; +import li.strolch.model.StrolchValueType; import li.strolch.model.timevalue.impl.FloatValue; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -import ch.eitchnet.utils.iso8601.ISO8601FormatFactory; - /** * @author Robert von Burg */ @@ -35,8 +25,6 @@ public class FloatTimedState extends AbstractStrolchTimedState { private static final long serialVersionUID = 1L; - public static final String TYPE = "FloatState"; - public FloatTimedState() { super(); } @@ -45,45 +33,14 @@ public class FloatTimedState extends AbstractStrolchTimedState { super(id, name); } - public FloatTimedState(Element element) { - super.fromDom(element); - - this.state = new TimedState<>(); - - NodeList timeValueElems = element.getElementsByTagName(Tags.VALUE); - for (int i = 0; i < timeValueElems.getLength(); i++) { - Element timeValueElem = (Element) timeValueElems.item(i); - String timeS = timeValueElem.getAttribute(Tags.TIME); - Date date = ISO8601FormatFactory.getInstance().parseDate(timeS); - long time = date.getTime(); - - Double value = Double.valueOf(timeValueElem.getAttribute(Tags.VALUE)); - FloatValue floatValue = new FloatValue(value); - this.state.getTimeEvolution().setValueAt(time, floatValue); - } - } - @Override - public Element toDom(Document doc) { - - Element stateElement = doc.createElement(Tags.TIMED_STATE); - super.fillElement(stateElement); - SortedSet> values = this.state.getTimeEvolution().getValues(); - for (ITimeValue timeValue : values) { - Long time = timeValue.getTime(); - FloatValue value = timeValue.getValue(); - Element valueElem = doc.createElement(Tags.VALUE); - valueElem.setAttribute(Tags.TIME, ISO8601FormatFactory.getInstance().formatDate(time)); - valueElem.setAttribute(Tags.VALUE, value.getValue().toString()); - stateElement.appendChild(valueElem); - } - - return stateElement; + public void setStateFromStringAt(Long time, String value) { + getTimeEvolution().setValueAt(time, new FloatValue(value)); } @Override public String getType() { - return TYPE; + return StrolchValueType.FLOAT.getType(); } @Override diff --git a/li.strolch.model/src/main/java/li/strolch/model/timedstate/IntegerTimedState.java b/li.strolch.model/src/main/java/li/strolch/model/timedstate/IntegerTimedState.java index dd239adad..63c39e46b 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/timedstate/IntegerTimedState.java +++ b/li.strolch.model/src/main/java/li/strolch/model/timedstate/IntegerTimedState.java @@ -15,19 +15,9 @@ */ package li.strolch.model.timedstate; -import java.util.Date; -import java.util.SortedSet; - -import li.strolch.model.Tags; -import li.strolch.model.timevalue.ITimeValue; +import li.strolch.model.StrolchValueType; import li.strolch.model.timevalue.impl.IntegerValue; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -import ch.eitchnet.utils.iso8601.ISO8601FormatFactory; - /** * @author Robert von Burg */ @@ -35,8 +25,6 @@ public class IntegerTimedState extends AbstractStrolchTimedState { private static final long serialVersionUID = 1L; - public static final String TYPE = "IntegerState"; - public IntegerTimedState() { super(); } @@ -45,45 +33,14 @@ public class IntegerTimedState extends AbstractStrolchTimedState { super(id, name); } - public IntegerTimedState(Element element) { - super.fromDom(element); - - this.state = new TimedState<>(); - - NodeList timeValueElems = element.getElementsByTagName(Tags.VALUE); - for (int i = 0; i < timeValueElems.getLength(); i++) { - Element timeValueElem = (Element) timeValueElems.item(i); - String timeS = timeValueElem.getAttribute(Tags.TIME); - Date date = ISO8601FormatFactory.getInstance().parseDate(timeS); - long time = date.getTime(); - - Integer value = Integer.valueOf(timeValueElem.getAttribute(Tags.VALUE)); - IntegerValue integerValue = new IntegerValue(value); - this.state.getTimeEvolution().setValueAt(time, integerValue); - } - } - @Override - public Element toDom(Document doc) { - - Element stateElement = doc.createElement(Tags.TIMED_STATE); - super.fillElement(stateElement); - SortedSet> values = this.state.getTimeEvolution().getValues(); - for (ITimeValue timeValue : values) { - Long time = timeValue.getTime(); - IntegerValue value = timeValue.getValue(); - Element valueElem = doc.createElement(Tags.VALUE); - valueElem.setAttribute(Tags.TIME, ISO8601FormatFactory.getInstance().formatDate(time)); - valueElem.setAttribute(Tags.VALUE, value.getValue().toString()); - stateElement.appendChild(valueElem); - } - - return stateElement; + public void setStateFromStringAt(Long time, String value) { + getTimeEvolution().setValueAt(time, new IntegerValue(value)); } @Override public String getType() { - return TYPE; + return StrolchValueType.INTEGER.getType(); } @Override diff --git a/li.strolch.model/src/main/java/li/strolch/model/timedstate/StringSetTimedState.java b/li.strolch.model/src/main/java/li/strolch/model/timedstate/StringSetTimedState.java index 72d7e6f10..9ebcfc3ca 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/timedstate/StringSetTimedState.java +++ b/li.strolch.model/src/main/java/li/strolch/model/timedstate/StringSetTimedState.java @@ -15,23 +15,9 @@ */ package li.strolch.model.timedstate; -import java.util.Date; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; -import java.util.SortedSet; - -import li.strolch.model.Tags; -import li.strolch.model.timevalue.ITimeValue; -import li.strolch.model.timevalue.impl.AString; +import li.strolch.model.StrolchValueType; import li.strolch.model.timevalue.impl.StringSetValue; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -import ch.eitchnet.utils.iso8601.ISO8601FormatFactory; - /** * @author Robert von Burg */ @@ -39,8 +25,6 @@ public class StringSetTimedState extends AbstractStrolchTimedState(); - - NodeList timeValueElems = element.getElementsByTagName(Tags.VALUE); - for (int i = 0; i < timeValueElems.getLength(); i++) { - Element timeValueElem = (Element) timeValueElems.item(i); - String timeS = timeValueElem.getAttribute(Tags.TIME); - Date date = ISO8601FormatFactory.getInstance().parseDate(timeS); - long time = date.getTime(); - - String valueAsString = timeValueElem.getAttribute(Tags.VALUE); - Set value = new HashSet<>(); - String[] values = valueAsString.split(","); - for (String s : values) { - value.add(new AString(s.trim())); - } - - StringSetValue integerValue = new StringSetValue(value); - this.state.getTimeEvolution().setValueAt(time, integerValue); - } - } - @Override - public Element toDom(Document doc) { - - Element stateElement = doc.createElement(Tags.TIMED_STATE); - super.fillElement(stateElement); - SortedSet> values = this.state.getTimeEvolution().getValues(); - for (ITimeValue timeValue : values) { - Long time = timeValue.getTime(); - StringSetValue stringSetValue = timeValue.getValue(); - - Set value = stringSetValue.getValue(); - StringBuilder sb = new StringBuilder(); - Iterator iter = value.iterator(); - while (iter.hasNext()) { - sb.append(iter.next().getString()); - if (iter.hasNext()) { - sb.append(", "); - } - } - String valueAsString = sb.toString(); - - Element valueElem = doc.createElement(Tags.VALUE); - valueElem.setAttribute(Tags.TIME, ISO8601FormatFactory.getInstance().formatDate(time)); - valueElem.setAttribute(Tags.VALUE, valueAsString); - stateElement.appendChild(valueElem); - } - - return stateElement; + public void setStateFromStringAt(Long time, String value) { + getTimeEvolution().setValueAt(time, new StringSetValue(value)); } @Override public String getType() { - return TYPE; + return StrolchValueType.STRING_SET.getType(); } @Override diff --git a/li.strolch.model/src/main/java/li/strolch/model/timedstate/StrolchTimedState.java b/li.strolch.model/src/main/java/li/strolch/model/timedstate/StrolchTimedState.java index 89ad1548a..76f8281e8 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/timedstate/StrolchTimedState.java +++ b/li.strolch.model/src/main/java/li/strolch/model/timedstate/StrolchTimedState.java @@ -108,6 +108,16 @@ public interface StrolchTimedState extends StrolchElement { public ITimeValue getStateAt(Long time); + /** + * set the value at a point in time to a given time value object from a string value + * + * @param time + * the time to set the {@link IValue} + * @param value + * the string to parse to an {@link IValue} + */ + void setStateFromStringAt(final Long time, final String value); + public ITimeVariable getTimeEvolution(); public void setParent(Resource aThis); diff --git a/li.strolch.model/src/main/java/li/strolch/model/timevalue/IValue.java b/li.strolch.model/src/main/java/li/strolch/model/timevalue/IValue.java index 2c33a262d..53f8d02fe 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/timevalue/IValue.java +++ b/li.strolch.model/src/main/java/li/strolch/model/timevalue/IValue.java @@ -26,6 +26,11 @@ package li.strolch.model.timevalue; */ public interface IValue { + /** + * @return the type of this {@link IValue} + */ + String getType(); + /** * @return the backing value */ diff --git a/li.strolch.model/src/main/java/li/strolch/model/timevalue/IValueChange.java b/li.strolch.model/src/main/java/li/strolch/model/timevalue/IValueChange.java index f9b880239..3dc923ac7 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/timevalue/IValueChange.java +++ b/li.strolch.model/src/main/java/li/strolch/model/timevalue/IValueChange.java @@ -18,12 +18,9 @@ package li.strolch.model.timevalue; import li.strolch.model.timedstate.AbstractStrolchTimedState; import li.strolch.model.timevalue.impl.TimeVariable; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - /** - * Interface for operators to be used to change the values of {@link ITimeValue} - * in a {@link ITimeVariable} or {@link AbstractStrolchTimedState}. + * Interface for operators to be used to change the values of {@link ITimeValue} in a {@link ITimeVariable} or + * {@link AbstractStrolchTimedState}. * * @author Martin Smock */ @@ -31,15 +28,13 @@ import org.w3c.dom.Element; public interface IValueChange { /** - * @return the id of the {@link AbstractStrolchTimedState} the change - * applies to + * @return the id of the {@link AbstractStrolchTimedState} the change applies to */ String getStateId(); /** * @param id - * the id of the {@link AbstractStrolchTimedState} the change - * applies to + * the id of the {@link AbstractStrolchTimedState} the change applies to */ void setStateId(String id); @@ -47,31 +42,23 @@ public interface IValueChange { * @return the time this change has to be applied */ Long getTime(); - - void setTime(Long time); + + void setTime(Long time); /** * @return the value of the change */ T getValue(); - - void setValue(T value); + + void setValue(T value); /** - * @return the inverse neutralizing a change. Very useful to undo changes - * made to a {@link TimeVariable}. + * @return the inverse neutralizing a change. Very useful to undo changes made to a {@link TimeVariable}. */ IValueChange getInverse(); - + /** * @return a copy of this */ - IValueChange getClone(); - - /** - * @param doc - * @return a xml serialisation of this - */ - Element toDom(Document doc); - + IValueChange getClone(); } diff --git a/li.strolch.model/src/main/java/li/strolch/model/timevalue/impl/BooleanValue.java b/li.strolch.model/src/main/java/li/strolch/model/timevalue/impl/BooleanValue.java index 4e00f603c..e66cdc998 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/timevalue/impl/BooleanValue.java +++ b/li.strolch.model/src/main/java/li/strolch/model/timevalue/impl/BooleanValue.java @@ -17,6 +17,7 @@ package li.strolch.model.timevalue.impl; import java.io.Serializable; +import li.strolch.model.StrolchValueType; import li.strolch.model.timevalue.ITimeValue; import li.strolch.model.timevalue.IValue; @@ -45,6 +46,11 @@ public class BooleanValue implements IValue, Serializable { this.value = Boolean.parseBoolean(valueAsString); } + @Override + public String getType() { + return StrolchValueType.BOOLEAN.getType(); + } + @Override public BooleanValue add(Boolean o) { this.value = o; diff --git a/li.strolch.model/src/main/java/li/strolch/model/timevalue/impl/FloatValue.java b/li.strolch.model/src/main/java/li/strolch/model/timevalue/impl/FloatValue.java index deaddc02d..e1c059d4e 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/timevalue/impl/FloatValue.java +++ b/li.strolch.model/src/main/java/li/strolch/model/timevalue/impl/FloatValue.java @@ -17,6 +17,7 @@ package li.strolch.model.timevalue.impl; import java.io.Serializable; +import li.strolch.model.StrolchValueType; import li.strolch.model.timevalue.ITimeValue; import li.strolch.model.timevalue.IValue; @@ -53,6 +54,11 @@ public class FloatValue implements IValue, Serializable { this.value = Double.parseDouble(valueAsString); } + @Override + public String getType() { + return StrolchValueType.FLOAT.getType(); + } + @Override public FloatValue add(Double o) { this.value += o; diff --git a/li.strolch.model/src/main/java/li/strolch/model/timevalue/impl/IntegerValue.java b/li.strolch.model/src/main/java/li/strolch/model/timevalue/impl/IntegerValue.java index c1476273f..2cf6f5b96 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/timevalue/impl/IntegerValue.java +++ b/li.strolch.model/src/main/java/li/strolch/model/timevalue/impl/IntegerValue.java @@ -17,6 +17,7 @@ package li.strolch.model.timevalue.impl; import java.io.Serializable; +import li.strolch.model.StrolchValueType; import li.strolch.model.timevalue.ITimeValue; import li.strolch.model.timevalue.IValue; @@ -45,6 +46,11 @@ public class IntegerValue implements IValue, Serializable { this.value = Integer.parseInt(valueAsString); } + @Override + public String getType() { + return StrolchValueType.INTEGER.getType(); + } + @Override public IntegerValue add(Integer o) { this.value += o; diff --git a/li.strolch.model/src/main/java/li/strolch/model/timevalue/impl/StringSetValue.java b/li.strolch.model/src/main/java/li/strolch/model/timevalue/impl/StringSetValue.java index e17c590c7..002298022 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/timevalue/impl/StringSetValue.java +++ b/li.strolch.model/src/main/java/li/strolch/model/timevalue/impl/StringSetValue.java @@ -22,6 +22,7 @@ import java.util.Iterator; import java.util.Set; import li.strolch.exception.StrolchException; +import li.strolch.model.StrolchValueType; import li.strolch.model.timevalue.ITimeValue; import li.strolch.model.timevalue.IValue; import ch.eitchnet.utils.dbc.DBC; @@ -42,7 +43,7 @@ public class StringSetValue implements IValue>, Serializable { private Set aStrings = new HashSet<>(); - public StringSetValue() { + private StringSetValue() { } public StringSetValue(final Set aStrings) { @@ -50,6 +51,20 @@ public class StringSetValue implements IValue>, Serializable { this.aStrings = aStrings; } + public StringSetValue(String valueAsString) { + Set value = new HashSet<>(); + String[] values = valueAsString.split(","); + for (String s : values) { + value.add(new AString(s.trim())); + } + this.aStrings = value; + } + + @Override + public String getType() { + return StrolchValueType.STRING_SET.getType(); + } + @Override public Set getValue() { return this.aStrings; diff --git a/li.strolch.model/src/main/java/li/strolch/model/timevalue/impl/ValueChange.java b/li.strolch.model/src/main/java/li/strolch/model/timevalue/impl/ValueChange.java index db56b0936..ce8808558 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/timevalue/impl/ValueChange.java +++ b/li.strolch.model/src/main/java/li/strolch/model/timevalue/impl/ValueChange.java @@ -17,15 +17,9 @@ package li.strolch.model.timevalue.impl; import java.io.Serializable; -import li.strolch.model.Tags; 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; - /** * @author Martin Smock */ @@ -67,7 +61,8 @@ public class ValueChange implements IValueChange, Serializa public Long getTime() { return this.time; } - + + @Override public void setTime(Long time) { this.time = time; } @@ -77,7 +72,8 @@ public class ValueChange implements IValueChange, Serializa public T getValue() { return (T) this.value.getCopy(); } - + + @Override public void setValue(T value) { this.value = value; } @@ -134,13 +130,15 @@ public class ValueChange implements IValueChange, Serializa sb.append(this.time); sb.append(", value="); sb.append(this.value); + sb.append(", stateId="); + sb.append(this.stateId); sb.append("]"); return sb.toString(); } @Override public String getStateId() { - return stateId; + return this.stateId; } @Override @@ -151,17 +149,6 @@ public class ValueChange implements IValueChange, Serializa @SuppressWarnings("unchecked") @Override public IValueChange getClone() { - return new ValueChange(time, value); + return new ValueChange(this.time, this.value, this.stateId); } - - @Override - public Element toDom(Document doc) { - Element element = doc.createElement(Tags.VALUE_CHANGE); - element.setAttribute(Tags.STATE_ID, this.stateId); - element.setAttribute(Tags.TIME, ISO8601FormatFactory.getInstance().formatDate(time)); - element.setAttribute(Tags.VALUE, this.value.getValueAsString()); - element.setAttribute(Tags.VALUE_CLASS, this.value.getClass().getName()); - return element; - } - } diff --git a/li.strolch.model/src/main/java/li/strolch/model/visitor/ActivityDeepEqualsVisitor.java b/li.strolch.model/src/main/java/li/strolch/model/visitor/ActivityDeepEqualsVisitor.java new file mode 100644 index 000000000..ce8fd5932 --- /dev/null +++ b/li.strolch.model/src/main/java/li/strolch/model/visitor/ActivityDeepEqualsVisitor.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013 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.model.visitor; + +import java.util.List; + +import li.strolch.model.ActivityVisitor; +import li.strolch.model.Locator; +import li.strolch.model.activity.Activity; + +/** + * @author Robert von Burg + */ +public class ActivityDeepEqualsVisitor extends StrolchElementDeepEqualsVisitor implements + ActivityVisitor> { + + private Activity sourceActivity; + + public ActivityDeepEqualsVisitor(Activity sourceActivity) { + this.sourceActivity = sourceActivity; + } + + @Override + public List visit(Activity dstActivity) { + deepEquals(this.sourceActivity, dstActivity); + return getMismatchedLocators(); + } +} diff --git a/li.strolch.model/src/main/java/li/strolch/model/visitor/NoStrategyActivityVisitor.java b/li.strolch.model/src/main/java/li/strolch/model/visitor/NoStrategyActivityVisitor.java new file mode 100644 index 000000000..702ef986d --- /dev/null +++ b/li.strolch.model/src/main/java/li/strolch/model/visitor/NoStrategyActivityVisitor.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.model.visitor; + +import li.strolch.model.ActivityVisitor; +import li.strolch.model.activity.Activity; + +/** + * @author Robert von Burg + */ +public class NoStrategyActivityVisitor implements ActivityVisitor { + + @Override + public Activity visit(Activity element) { + return element; + } +} 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 2e8b1b038..8b138c297 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 @@ -16,7 +16,9 @@ package li.strolch.model.visitor; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; +import java.util.Map.Entry; import java.util.Set; import li.strolch.model.GroupedParameterizedElement; @@ -25,9 +27,13 @@ import li.strolch.model.Order; import li.strolch.model.ParameterBag; import li.strolch.model.Resource; import li.strolch.model.StrolchElement; +import li.strolch.model.activity.Action; +import li.strolch.model.activity.Activity; +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; /** * @author Robert von Burg @@ -53,6 +59,7 @@ public class StrolchElementDeepEqualsVisitor { } protected void deepEquals(StrolchElement srcElement, StrolchElement dstElement) { + DBC.PRE.assertEquals("Both elements should have the same ID", srcElement.getId(), dstElement.getId()); if (!srcElement.getName().equals(dstElement.getName())) { this.mismatchedLocators.add(dstElement.getLocator()); } @@ -99,6 +106,74 @@ public class StrolchElementDeepEqualsVisitor { } } + protected void deepEquals(Activity srcActivity, Activity dstActivity) { + deepEquals((StrolchElement) srcActivity, (StrolchElement) dstActivity); + deepEquals((GroupedParameterizedElement) srcActivity, (GroupedParameterizedElement) dstActivity); + + Iterator> iter = srcActivity.elementIterator(); + while (iter.hasNext()) { + IActivityElement srcActivityElement = iter.next().getValue(); + + if (!dstActivity.hasElement(srcActivityElement.getId())) { + this.mismatchedLocators.add(srcActivityElement.getLocator()); + continue; + } + + IActivityElement dstActivityElement = dstActivity.getElement(srcActivityElement.getId()); + + if (!srcActivityElement.getClass().equals(dstActivityElement.getClass())) { + this.mismatchedLocators.add(srcActivityElement.getLocator()); + continue; + } + + if (srcActivityElement instanceof Activity) { + deepEquals((Activity) srcActivityElement, (Activity) dstActivityElement); + } else if (srcActivityElement instanceof Action) { + deepEquals((Action) srcActivityElement, (Action) dstActivityElement); + } else { + throw new UnsupportedOperationException("Unhandled instance type " + srcActivityElement.getClass()); + } + } + + iter = dstActivity.elementIterator(); + while (iter.hasNext()) { + IActivityElement activityElement = iter.next().getValue(); + if (!srcActivity.hasElement(activityElement.getId())) { + this.mismatchedLocators.add(activityElement.getLocator()); + } + } + } + + protected void deepEquals(Action srcAction, Action dstAction) { + deepEquals((StrolchElement) srcAction, (StrolchElement) dstAction); + deepEquals((GroupedParameterizedElement) srcAction, (GroupedParameterizedElement) dstAction); + + if (!srcAction.getResourceId().equals(dstAction.getResourceId())) { + this.mismatchedLocators.add(dstAction.getLocator()); + } + if (!srcAction.getResourceType().equals(dstAction.getResourceType())) { + this.mismatchedLocators.add(dstAction.getLocator()); + } + if (!srcAction.getState().equals(dstAction.getState())) { + this.mismatchedLocators.add(dstAction.getLocator()); + } + + if ((srcAction.getParent() == null && srcAction.getParent() != null) + || (srcAction.getParent() != null && srcAction.getParent() == null)) { + this.mismatchedLocators.add(dstAction.getLocator()); + } else if (!srcAction.getParent().getId().equals(dstAction.getParent().getId())) { + this.mismatchedLocators.add(dstAction.getLocator()); + } else if (!srcAction.getParent().getType().equals(dstAction.getParent().getType())) { + this.mismatchedLocators.add(dstAction.getLocator()); + } + + if (srcAction.hasChanges() != dstAction.hasChanges()) { + this.mismatchedLocators.add(dstAction.getLocator()); + } else if (!srcAction.getChanges().equals(dstAction.getChanges())) { + this.mismatchedLocators.add(dstAction.getLocator()); + } + } + protected void deepEquals(GroupedParameterizedElement srcElement, GroupedParameterizedElement dstElement) { Set srcBagKeySet = srcElement.getParameterBagKeySet(); for (String bagKey : srcBagKeySet) { diff --git a/li.strolch.model/src/main/java/li/strolch/model/xml/AbstractToSaxWriterVisitor.java b/li.strolch.model/src/main/java/li/strolch/model/xml/AbstractToSaxWriterVisitor.java index b71671ec8..c7423b850 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/xml/AbstractToSaxWriterVisitor.java +++ b/li.strolch.model/src/main/java/li/strolch/model/xml/AbstractToSaxWriterVisitor.java @@ -20,8 +20,9 @@ import static li.strolch.model.StrolchModelConstants.UOM_NONE; import java.util.ArrayList; import java.util.Collections; -import java.util.Comparator; +import java.util.Iterator; import java.util.List; +import java.util.Map.Entry; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; @@ -36,12 +37,15 @@ import li.strolch.model.ParameterizedElement; import li.strolch.model.Resource; import li.strolch.model.StrolchElement; import li.strolch.model.Tags; +import li.strolch.model.activity.Action; +import li.strolch.model.activity.Activity; +import li.strolch.model.activity.IActivityElement; import li.strolch.model.parameter.Parameter; import li.strolch.model.timedstate.StrolchTimedState; import li.strolch.model.timevalue.ITimeValue; import li.strolch.model.timevalue.ITimeVariable; import li.strolch.model.timevalue.IValue; -import ch.eitchnet.utils.helper.StringHelper; +import li.strolch.model.timevalue.IValueChange; import ch.eitchnet.utils.iso8601.ISO8601FormatFactory; /** @@ -55,16 +59,81 @@ public abstract class AbstractToSaxWriterVisitor { this.writer = writer; } - protected void writeElement(String tag, Order order) throws XMLStreamException { + protected void writeElement(Order order) throws XMLStreamException { boolean empty = !order.hasParameterBags(); - writeElement(tag, empty, order); + + writeStartStrolchElement(Tags.ORDER, empty, order); + this.writer.writeAttribute(Tags.DATE, ISO8601FormatFactory.getInstance().formatDate(order.getDate())); + this.writer.writeAttribute(Tags.STATE, order.getState().name()); + + if (order.hasParameterBags()) { + writeParameterBags(order); + } + if (!empty) this.writer.writeEndElement(); } - protected void writeElement(String tag, Resource resource) throws XMLStreamException { + protected void writeElement(Activity activity) throws XMLStreamException { + boolean empty = !activity.hasParameterBags() && !activity.hasElements(); + + writeStartStrolchElement(Tags.ACTIVITY, empty, activity); + + if (activity.hasParameterBags()) { + writeParameterBags(activity); + } + + if (activity.hasElements()) { + Iterator> iter = activity.elementIterator(); + while (iter.hasNext()) { + IActivityElement element = iter.next().getValue(); + if (element instanceof Activity) + writeElement((Activity) element); + else if (element instanceof Action) + writeElement((Action) element); + else + throw new IllegalArgumentException("Unhandled Element class " + element.getClass()); + } + } + + if (!empty) + this.writer.writeEndElement(); + } + + private void writeElement(Action action) throws XMLStreamException { + boolean empty = !action.hasParameterBags() && !action.hasChanges(); + + writeStartStrolchElement(Tags.ACTION, empty, action); + this.writer.writeAttribute(Tags.STATE, action.getState().name()); + this.writer.writeAttribute(Tags.RESOURCE_ID, action.getResourceId()); + this.writer.writeAttribute(Tags.RESOURCE_TYPE, action.getResourceType()); + + if (action.hasParameterBags()) { + writeParameterBags(action); + } + + if (action.hasChanges()) { + for (IValueChange> change : action.getChanges()) { + this.writer.writeEmptyElement(Tags.VALUE_CHANGE); + this.writer.writeAttribute(Tags.STATE_ID, change.getStateId()); + this.writer.writeAttribute(Tags.TIME, ISO8601FormatFactory.getInstance().formatDate(change.getTime())); + this.writer.writeAttribute(Tags.VALUE, change.getValue().getValueAsString()); + this.writer.writeAttribute(Tags.TYPE, change.getValue().getClass().getName()); + } + } + + if (!empty) + this.writer.writeEndElement(); + } + + protected void writeElement(Resource resource) throws XMLStreamException { boolean empty = !resource.hasParameterBags() && !resource.hasTimedStates(); - writeElement(tag, empty, resource); + + writeStartStrolchElement(Tags.RESOURCE, empty, resource); + + if (resource.hasParameterBags()) { + writeParameterBags(resource); + } if (resource.hasTimedStates()) writeTimedStates(resource); @@ -97,14 +166,6 @@ public abstract class AbstractToSaxWriterVisitor { } } - protected void writeElement(String tag, boolean empty, GroupedParameterizedElement element) - throws XMLStreamException { - writeStartStrolchElement(tag, empty, element); - if (!empty) { - writeParameterBags(element); - } - } - protected void writeStartStrolchElement(String tag, boolean empty, StrolchElement element) throws XMLStreamException { if (empty) { @@ -114,9 +175,7 @@ public abstract class AbstractToSaxWriterVisitor { } this.writer.writeAttribute(Tags.ID, element.getId()); - if (StringHelper.isNotEmpty(element.getName())) { - this.writer.writeAttribute(Tags.NAME, element.getName()); - } + this.writer.writeAttribute(Tags.NAME, element.getName()); this.writer.writeAttribute(Tags.TYPE, element.getType()); } @@ -136,12 +195,7 @@ public abstract class AbstractToSaxWriterVisitor { protected void writeParameters(ParameterizedElement element) throws XMLStreamException { List> parameters = new ArrayList<>(element.getParameters()); - Collections.sort(parameters, new Comparator>() { - @Override - public int compare(Parameter o1, Parameter o2) { - return Integer.valueOf(o1.getIndex()).compareTo(o2.getIndex()); - } - }); + Collections.sort(parameters, (o1, o2) -> Integer.valueOf(o1.getIndex()).compareTo(o2.getIndex())); for (Parameter parameter : parameters) { writeStartStrolchElement(Tags.PARAMETER, true, parameter); diff --git a/li.strolch.model/src/main/java/li/strolch/model/xml/ActivityFromDomVisitor.java b/li.strolch.model/src/main/java/li/strolch/model/xml/ActivityFromDomVisitor.java new file mode 100644 index 000000000..12208e49f --- /dev/null +++ b/li.strolch.model/src/main/java/li/strolch/model/xml/ActivityFromDomVisitor.java @@ -0,0 +1,32 @@ +/* + * 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.model.xml; + +import li.strolch.model.activity.Activity; + +import org.w3c.dom.Document; + +/** + * @author Robert von Burg + */ +public class ActivityFromDomVisitor extends StrolchElementFromDomVisitor { + + public Activity visit(Document doc) { + Activity activity = new Activity(); + fillElement(doc.getDocumentElement(), activity); + return activity; + } +} diff --git a/li.strolch.model/src/main/java/li/strolch/model/xml/ActivityToDomVisitor.java b/li.strolch.model/src/main/java/li/strolch/model/xml/ActivityToDomVisitor.java new file mode 100644 index 000000000..9cbf8c231 --- /dev/null +++ b/li.strolch.model/src/main/java/li/strolch/model/xml/ActivityToDomVisitor.java @@ -0,0 +1,51 @@ +/* + * Copyright 2013 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.model.xml; + +import javax.xml.parsers.DocumentBuilder; + +import li.strolch.model.ActivityVisitor; +import li.strolch.model.activity.Action; +import li.strolch.model.activity.Activity; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import ch.eitchnet.utils.helper.DomUtil; + +/** + * @author Robert von Burg + */ +public class ActivityToDomVisitor extends StrolchElementToDomVisitor implements ActivityVisitor { + + @Override + public Document visit(Activity activity) { + DocumentBuilder documentBuilder = DomUtil.createDocumentBuilder(); + this.document = documentBuilder.getDOMImplementation().createDocument(null, null, null); + + Element asDom = toDom(activity); + document.appendChild(asDom); + return this.document; + } + + public Element toDom(Action action) { + return super.toDom(action); + } + + public Element toDom(Activity activity) { + return super.toDom(activity); + } +} diff --git a/li.strolch.model/src/main/java/li/strolch/model/xml/ActivityToSaxVisitor.java b/li.strolch.model/src/main/java/li/strolch/model/xml/ActivityToSaxVisitor.java new file mode 100644 index 000000000..073735196 --- /dev/null +++ b/li.strolch.model/src/main/java/li/strolch/model/xml/ActivityToSaxVisitor.java @@ -0,0 +1,48 @@ +/* + * 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.model.xml; + +import java.text.MessageFormat; + +import li.strolch.model.ActivityVisitor; +import li.strolch.model.activity.Activity; + +import org.xml.sax.ContentHandler; + +/** + * @author Robert von Burg + */ +public class ActivityToSaxVisitor extends StrolchElementToSaxVisitor implements ActivityVisitor { + + public ActivityToSaxVisitor(ContentHandler contentHandler) { + super(contentHandler); + } + + @Override + public Void visit(Activity activity) { + try { + + toSax(activity); + + } catch (Exception e) { + String msg = "Failed to transform Activity {0} to XML due to {1}"; //$NON-NLS-1$ + msg = MessageFormat.format(msg, activity.getLocator(), e.getMessage()); + throw new RuntimeException(msg, e); + } + + return null; + } +} diff --git a/li.strolch.model/src/main/java/li/strolch/model/xml/ActivityToSaxWriterVisitor.java b/li.strolch.model/src/main/java/li/strolch/model/xml/ActivityToSaxWriterVisitor.java new file mode 100644 index 000000000..cc0a11204 --- /dev/null +++ b/li.strolch.model/src/main/java/li/strolch/model/xml/ActivityToSaxWriterVisitor.java @@ -0,0 +1,49 @@ +/* + * 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.model.xml; + +import java.text.MessageFormat; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; + +import li.strolch.exception.StrolchException; +import li.strolch.model.ActivityVisitor; +import li.strolch.model.activity.Activity; + +/** + * @author Robert von Burg + */ +public class ActivityToSaxWriterVisitor extends AbstractToSaxWriterVisitor implements ActivityVisitor { + + public ActivityToSaxWriterVisitor(XMLStreamWriter writer) { + super(writer); + } + + @Override + public Void visit(Activity activity) { + try { + writeElement(activity); + this.writer.flush(); + } catch (XMLStreamException e) { + String msg = "Failed to write Activity {0} due to {1}"; //$NON-NLS-1$ + msg = MessageFormat.format(msg, activity.getLocator(), e.getMessage()); + throw new StrolchException(msg, e); + } + + return null; + } +} diff --git a/li.strolch.model/src/main/java/li/strolch/model/xml/OrderFromDomVisitor.java b/li.strolch.model/src/main/java/li/strolch/model/xml/OrderFromDomVisitor.java new file mode 100644 index 000000000..c29594a63 --- /dev/null +++ b/li.strolch.model/src/main/java/li/strolch/model/xml/OrderFromDomVisitor.java @@ -0,0 +1,32 @@ +/* + * 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.model.xml; + +import li.strolch.model.Order; + +import org.w3c.dom.Document; + +/** + * @author Robert von Burg + */ +public class OrderFromDomVisitor extends StrolchElementFromDomVisitor { + + public Order visit(Document doc) { + Order order = new Order(); + fillElement(doc.getDocumentElement(), order); + return order; + } +} diff --git a/li.strolch.model/src/main/java/li/strolch/model/xml/OrderToDomVisitor.java b/li.strolch.model/src/main/java/li/strolch/model/xml/OrderToDomVisitor.java index 77c9995aa..07dc7829b 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/xml/OrderToDomVisitor.java +++ b/li.strolch.model/src/main/java/li/strolch/model/xml/OrderToDomVisitor.java @@ -28,25 +28,15 @@ import ch.eitchnet.utils.helper.DomUtil; /** * @author Robert von Burg */ -public class OrderToDomVisitor implements OrderVisitor { - - private Document document; - - /** - * @return the document - */ - public Document getDocument() { - return this.document; - } +public class OrderToDomVisitor extends StrolchElementToDomVisitor implements OrderVisitor { @Override public Document visit(Order order) { DocumentBuilder documentBuilder = DomUtil.createDocumentBuilder(); - Document document = documentBuilder.getDOMImplementation().createDocument(null, null, null); + this.document = documentBuilder.getDOMImplementation().createDocument(null, null, null); - Element orderDom = order.toDom(document); - document.appendChild(orderDom); - this.document = document; + Element asDom = toDom(order); + document.appendChild(asDom); return this.document; } } diff --git a/li.strolch.model/src/main/java/li/strolch/model/xml/OrderToSaxVisitor.java b/li.strolch.model/src/main/java/li/strolch/model/xml/OrderToSaxVisitor.java index 7911c16d8..a139852b0 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/xml/OrderToSaxVisitor.java +++ b/li.strolch.model/src/main/java/li/strolch/model/xml/OrderToSaxVisitor.java @@ -19,7 +19,6 @@ import java.text.MessageFormat; import li.strolch.model.Order; import li.strolch.model.OrderVisitor; -import li.strolch.model.Tags; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; @@ -37,9 +36,7 @@ public class OrderToSaxVisitor extends StrolchElementToSaxVisitor implements Ord public Void visit(Order order) { try { - this.contentHandler.startElement(null, null, Tags.ORDER, attributesFor(order)); toSax(order); - this.contentHandler.endElement(null, null, Tags.ORDER); } catch (SAXException e) { String msg = "Failed to transform Order {0} to XML due to {1}"; //$NON-NLS-1$ diff --git a/li.strolch.model/src/main/java/li/strolch/model/xml/OrderToSaxWriterVisitor.java b/li.strolch.model/src/main/java/li/strolch/model/xml/OrderToSaxWriterVisitor.java index dc3b16d52..ece6c6984 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/xml/OrderToSaxWriterVisitor.java +++ b/li.strolch.model/src/main/java/li/strolch/model/xml/OrderToSaxWriterVisitor.java @@ -23,7 +23,6 @@ import javax.xml.stream.XMLStreamWriter; import li.strolch.exception.StrolchException; import li.strolch.model.Order; import li.strolch.model.OrderVisitor; -import li.strolch.model.Tags; /** * @author Robert von Burg @@ -37,7 +36,7 @@ public class OrderToSaxWriterVisitor extends AbstractToSaxWriterVisitor implemen @Override public Void visit(Order order) { try { - writeElement(Tags.ORDER, order); + writeElement(order); this.writer.flush(); } catch (XMLStreamException e) { String msg = "Failed to write Order {0} due to {1}"; //$NON-NLS-1$ diff --git a/li.strolch.model/src/main/java/li/strolch/model/xml/ResourceFromDomVisitor.java b/li.strolch.model/src/main/java/li/strolch/model/xml/ResourceFromDomVisitor.java new file mode 100644 index 000000000..8900e4056 --- /dev/null +++ b/li.strolch.model/src/main/java/li/strolch/model/xml/ResourceFromDomVisitor.java @@ -0,0 +1,32 @@ +/* + * 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.model.xml; + +import li.strolch.model.Resource; + +import org.w3c.dom.Document; + +/** + * @author Robert von Burg + */ +public class ResourceFromDomVisitor extends StrolchElementFromDomVisitor { + + public Resource visit(Document doc) { + Resource resource = new Resource(); + fillElement(doc.getDocumentElement(), resource); + return resource; + } +} diff --git a/li.strolch.model/src/main/java/li/strolch/model/xml/ResourceToDomVisitor.java b/li.strolch.model/src/main/java/li/strolch/model/xml/ResourceToDomVisitor.java index 2942d547c..e783bcfc1 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/xml/ResourceToDomVisitor.java +++ b/li.strolch.model/src/main/java/li/strolch/model/xml/ResourceToDomVisitor.java @@ -28,25 +28,15 @@ import ch.eitchnet.utils.helper.DomUtil; /** * @author Robert von Burg */ -public class ResourceToDomVisitor implements ResourceVisitor { - - private Document document; - - /** - * @return the document - */ - public Document getDocument() { - return this.document; - } +public class ResourceToDomVisitor extends StrolchElementToDomVisitor implements ResourceVisitor { @Override public Document visit(Resource resource) { DocumentBuilder documentBuilder = DomUtil.createDocumentBuilder(); - Document document = documentBuilder.getDOMImplementation().createDocument(null, null, null); + this.document = documentBuilder.getDOMImplementation().createDocument(null, null, null); - Element resourceDom = resource.toDom(document); - document.appendChild(resourceDom); - this.document = document; + Element asDom = toDom(resource); + document.appendChild(asDom); return this.document; } } diff --git a/li.strolch.model/src/main/java/li/strolch/model/xml/ResourceToSaxVisitor.java b/li.strolch.model/src/main/java/li/strolch/model/xml/ResourceToSaxVisitor.java index 676ce6a68..e4f881f51 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/xml/ResourceToSaxVisitor.java +++ b/li.strolch.model/src/main/java/li/strolch/model/xml/ResourceToSaxVisitor.java @@ -19,7 +19,6 @@ import java.text.MessageFormat; import li.strolch.model.Resource; import li.strolch.model.ResourceVisitor; -import li.strolch.model.Tags; import org.xml.sax.ContentHandler; @@ -36,9 +35,7 @@ public class ResourceToSaxVisitor extends StrolchElementToSaxVisitor implements public Void visit(Resource res) { try { - this.contentHandler.startElement(null, null, Tags.RESOURCE, attributesFor(res)); toSax(res); - this.contentHandler.endElement(null, null, Tags.RESOURCE); } catch (Exception e) { String msg = "Failed to transform Resource {0} to XML due to {1}"; //$NON-NLS-1$ diff --git a/li.strolch.model/src/main/java/li/strolch/model/xml/ResourceToSaxWriterVisitor.java b/li.strolch.model/src/main/java/li/strolch/model/xml/ResourceToSaxWriterVisitor.java index 764984a14..3b64c4b04 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/xml/ResourceToSaxWriterVisitor.java +++ b/li.strolch.model/src/main/java/li/strolch/model/xml/ResourceToSaxWriterVisitor.java @@ -23,7 +23,6 @@ import javax.xml.stream.XMLStreamWriter; import li.strolch.exception.StrolchException; import li.strolch.model.Resource; import li.strolch.model.ResourceVisitor; -import li.strolch.model.Tags; /** * @author Robert von Burg @@ -37,7 +36,7 @@ public class ResourceToSaxWriterVisitor extends AbstractToSaxWriterVisitor imple @Override public Void visit(Resource resource) { try { - writeElement(Tags.RESOURCE, resource); + writeElement(resource); this.writer.flush(); } catch (XMLStreamException e) { String msg = "Failed to write Resource {0} due to {1}"; //$NON-NLS-1$ diff --git a/li.strolch.model/src/main/java/li/strolch/model/xml/SimpleStrolchElementListener.java b/li.strolch.model/src/main/java/li/strolch/model/xml/SimpleStrolchElementListener.java index 2806d5a41..c339f2725 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/xml/SimpleStrolchElementListener.java +++ b/li.strolch.model/src/main/java/li/strolch/model/xml/SimpleStrolchElementListener.java @@ -21,6 +21,7 @@ import java.util.List; import li.strolch.model.Order; import li.strolch.model.Resource; +import li.strolch.model.activity.Activity; /** * @author Robert von Burg @@ -29,6 +30,7 @@ public class SimpleStrolchElementListener implements StrolchElementListener { private List resources; private List orders; + private List activities; @Override public void notifyResource(Resource resource) { @@ -46,6 +48,14 @@ public class SimpleStrolchElementListener implements StrolchElementListener { this.orders.add(order); } + @Override + public void notifyActivity(Activity activity) { + if (this.activities == null) { + this.activities = new ArrayList<>(); + } + this.activities.add(activity); + } + /** * @return the resources */ @@ -63,4 +73,13 @@ public class SimpleStrolchElementListener implements StrolchElementListener { return Collections.emptyList(); return this.orders; } + + /** + * @return the activities + */ + public List getActivities() { + if (this.activities == null) + return Collections.emptyList(); + return this.activities; + } } 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 new file mode 100644 index 000000000..68053d3ac --- /dev/null +++ b/li.strolch.model/src/main/java/li/strolch/model/xml/StrolchElementFromDomVisitor.java @@ -0,0 +1,305 @@ +/* + * 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.model.xml; + +import java.text.MessageFormat; +import java.util.Date; + +import li.strolch.exception.StrolchException; +import li.strolch.model.AbstractStrolchElement; +import li.strolch.model.GroupedParameterizedElement; +import li.strolch.model.Order; +import li.strolch.model.ParameterBag; +import li.strolch.model.ParameterizedElement; +import li.strolch.model.Resource; +import li.strolch.model.State; +import li.strolch.model.StrolchValueType; +import li.strolch.model.Tags; +import li.strolch.model.activity.Action; +import li.strolch.model.activity.Activity; +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; + +/** + * @author Robert von Burg + */ +public class StrolchElementFromDomVisitor { + + public void fillElement(Element element, Order order) { + fillElement(element, (GroupedParameterizedElement) order); + + String date = element.getAttribute(Tags.DATE); + String state = element.getAttribute(Tags.STATE); + + if (StringHelper.isEmpty(date)) { + order.setDate(ISO8601FormatFactory.getInstance().getDateFormat().parse("-")); //$NON-NLS-1$ + } else { + order.setDate(ISO8601FormatFactory.getInstance().getDateFormat().parse(date)); + } + + if (state == null || state.isEmpty()) { + order.setState(State.CREATED); + } else { + order.setState(State.valueOf(state)); + } + } + + public void fillElement(Element resourceElement, Resource resource) { + fillElement(resourceElement, (GroupedParameterizedElement) resource); + + NodeList childNodes = resourceElement.getChildNodes(); + for (int i = 0; i < childNodes.getLength(); i++) { + Node item = childNodes.item(i); + if (!(item instanceof Element)) + continue; + + Element timedStateElem = (Element) item; + if (!timedStateElem.getNodeName().equals(Tags.TIMED_STATE)) + continue; + + String typeS = timedStateElem.getAttribute(Tags.TYPE); + + DBC.PRE.assertNotEmpty("Type must be set on TimedState for resource with id " + resource.getId(), typeS); + StrolchValueType valueType = StrolchValueType.parse(typeS); + StrolchTimedState> timedState = valueType.timedStateInstance(); + + fillElement(timedStateElem, (AbstractStrolchElement) timedState); + + String interpretation = timedStateElem.getAttribute(Tags.INTERPRETATION); + String hidden = timedStateElem.getAttribute(Tags.HIDDEN); + String uom = timedStateElem.getAttribute(Tags.UOM); + String index = timedStateElem.getAttribute(Tags.INDEX); + + timedState.setInterpretation(interpretation); + timedState.setUom(uom); + + if (StringHelper.isEmpty(index)) { + timedState.setIndex(0); + } else { + timedState.setIndex(Integer.valueOf(index)); + } + + if (StringHelper.isEmpty(hidden)) { + timedState.setHidden(false); + } else { + if (hidden.equalsIgnoreCase(Boolean.TRUE.toString())) { + timedState.setHidden(true); + } else if (hidden.equalsIgnoreCase(Boolean.FALSE.toString())) { + timedState.setHidden(false); + } else { + String msg = "Boolean string must be either {0} or {1}"; //$NON-NLS-1$ + msg = MessageFormat.format(msg, Boolean.TRUE.toString(), Boolean.FALSE.toString()); + throw new StrolchException(msg); + } + } + + NodeList timeValueElems = timedStateElem.getChildNodes(); + for (int j = 0; j < timeValueElems.getLength(); j++) { + Node timeValueItem = timeValueElems.item(j); + if (!(timeValueItem instanceof Element)) + continue; + + Element timeValueElem = (Element) timeValueItem; + if (!timeValueElem.getNodeName().equals(Tags.VALUE)) + continue; + + String timeS = timeValueElem.getAttribute(Tags.TIME); + Date date = ISO8601FormatFactory.getInstance().parseDate(timeS); + long time = date.getTime(); + + String valueS = timeValueElem.getAttribute(Tags.VALUE); + timedState.setStateFromStringAt(time, valueS); + } + + resource.addTimedState(timedState); + } + } + + protected void fillElement(Element element, AbstractStrolchElement strolchElement) { + String id = element.getAttribute(Tags.ID); + String name = element.getAttribute(Tags.NAME); + + if (id != null && name != null) { + strolchElement.setId(id); + strolchElement.setName(name); + } else { + String msg = "Check the values of the element: {0} either id or name attribute is null!"; //$NON-NLS-1$ + msg = MessageFormat.format(msg, element.getNodeName()); + throw new StrolchException(msg); + } + } + + protected void fillElement(Element element, GroupedParameterizedElement groupedParameterizedElement) { + fillElement(element, (AbstractStrolchElement) groupedParameterizedElement); + + String type = element.getAttribute(Tags.TYPE); + groupedParameterizedElement.setType(type); + + NodeList bags = element.getChildNodes(); + for (int i = 0; i < bags.getLength(); i++) { + Node item = bags.item(i); + if (!(item instanceof Element)) + continue; + + Element bagElement = (Element) item; + if (!bagElement.getNodeName().equals(Tags.PARAMETER_BAG)) + continue; + + ParameterBag bag = new ParameterBag(); + fillElement(bagElement, bag); + groupedParameterizedElement.addParameterBag(bag); + } + } + + protected void fillElement(Element element, ParameterizedElement parameterizedElement) { + fillElement(element, (AbstractStrolchElement) parameterizedElement); + + String type = element.getAttribute(Tags.TYPE); + parameterizedElement.setType(type); + + // add all the parameters + NodeList parameterElements = element.getChildNodes(); + for (int i = 0; i < parameterElements.getLength(); i++) { + Node item = parameterElements.item(i); + if (!(item instanceof Element)) + continue; + + Element paramElement = (Element) item; + if (!paramElement.getNodeName().equals(Tags.PARAMETER)) + continue; + + String paramtype = paramElement.getAttribute(Tags.TYPE); + + StrolchValueType paramValueType = StrolchValueType.parse(paramtype); + Parameter parameter = paramValueType.parameterInstance(); + fillElement(paramElement, parameter); + parameterizedElement.addParameter(parameter); + } + } + + protected void fillElement(Element element, Parameter param) { + + fillElement(element, (AbstractStrolchElement) param); + + String value = element.getAttribute(Tags.VALUE); + param.setValueFromString(value); + + String interpretation = element.getAttribute(Tags.INTERPRETATION); + String hidden = element.getAttribute(Tags.HIDDEN); + String uom = element.getAttribute(Tags.UOM); + String index = element.getAttribute(Tags.INDEX); + + param.setInterpretation(interpretation); + param.setUom(uom); + + if (StringHelper.isEmpty(index)) { + param.setIndex(0); + } else { + param.setIndex(Integer.valueOf(index)); + } + + if (StringHelper.isEmpty(hidden)) { + param.setHidden(false); + } else { + if (hidden.equalsIgnoreCase(Boolean.TRUE.toString())) { + param.setHidden(true); + } else if (hidden.equalsIgnoreCase(Boolean.FALSE.toString())) { + param.setHidden(false); + } else { + String msg = "Boolean string must be either {0} or {1}"; //$NON-NLS-1$ + msg = MessageFormat.format(msg, Boolean.TRUE.toString(), Boolean.FALSE.toString()); + throw new StrolchException(msg); + } + } + } + + protected void fillElement(Element activityElement, Activity activity) { + fillElement(activityElement, (GroupedParameterizedElement) activity); + + NodeList childNodes = activityElement.getChildNodes(); + for (int i = 0; i < childNodes.getLength(); i++) { + Node item = childNodes.item(i); + if (!(item instanceof Element)) + continue; + + Element childElem = (Element) item; + + switch (childElem.getNodeName()) { + case Tags.ACTIVITY: + Activity childActivity = new Activity(); + fillElement(childElem, childActivity); + activity.addElement(childActivity); + break; + case Tags.ACTION: + Action childAction = new Action(); + fillElement(childElem, childAction); + activity.addElement(childAction); + break; + case Tags.PARAMETER_BAG: + break; + + default: + throw new IllegalArgumentException("Unexpected element tag " + childElem.getNodeName()); + } + } + } + + protected void fillElement(Element element, Action action) { + fillElement(element, (GroupedParameterizedElement) action); + + String resourceId = element.getAttribute(Tags.RESOURCE_ID); + String resourceType = element.getAttribute(Tags.RESOURCE_TYPE); + String stateS = element.getAttribute(Tags.STATE); + + action.setResourceId(resourceId); + action.setResourceType(resourceType); + action.setState(State.valueOf(stateS)); + + NodeList valueChangeNodes = element.getChildNodes(); + for (int i = 0; i < valueChangeNodes.getLength(); i++) { + Node item = valueChangeNodes.item(i); + if (!(item instanceof Element)) + continue; + + Element valueChangeElem = (Element) item; + if (!valueChangeElem.getNodeName().equals(Tags.VALUE_CHANGE)) + continue; + + String stateId = valueChangeElem.getAttribute(Tags.STATE_ID); + String timeS = valueChangeElem.getAttribute(Tags.TIME); + String valueS = valueChangeElem.getAttribute(Tags.VALUE); + String typeS = valueChangeElem.getAttribute(Tags.TYPE); + + StrolchValueType type = StrolchValueType.parse(typeS); + IValue value = type.valueInstance(valueS); + + long time = ISO8601FormatFactory.getInstance().getDateFormat().parse(timeS).getTime(); + ValueChange> valueChange = new ValueChange>(time, value, stateId); + + action.addChange(valueChange); + } + } +} diff --git a/li.strolch.model/src/main/java/li/strolch/model/xml/StrolchElementListener.java b/li.strolch.model/src/main/java/li/strolch/model/xml/StrolchElementListener.java index 58f1d419c..617694624 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/xml/StrolchElementListener.java +++ b/li.strolch.model/src/main/java/li/strolch/model/xml/StrolchElementListener.java @@ -17,6 +17,7 @@ package li.strolch.model.xml; import li.strolch.model.Order; import li.strolch.model.Resource; +import li.strolch.model.activity.Activity; /** * @author Robert von Burg @@ -27,4 +28,6 @@ public interface StrolchElementListener { public void notifyResource(Resource resource); public void notifyOrder(Order order); + + public void notifyActivity(Activity activity); } 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 new file mode 100644 index 000000000..ada305048 --- /dev/null +++ b/li.strolch.model/src/main/java/li/strolch/model/xml/StrolchElementToDomVisitor.java @@ -0,0 +1,224 @@ +/* + * 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.model.xml; + +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.SortedSet; + +import li.strolch.model.AbstractStrolchElement; +import li.strolch.model.GroupedParameterizedElement; +import li.strolch.model.Order; +import li.strolch.model.ParameterBag; +import li.strolch.model.ParameterizedElement; +import li.strolch.model.Resource; +import li.strolch.model.StrolchModelConstants; +import li.strolch.model.Tags; +import li.strolch.model.activity.Action; +import li.strolch.model.activity.Activity; +import li.strolch.model.activity.IActivityElement; +import li.strolch.model.parameter.Parameter; +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; + +/** + * @author Robert von Burg + */ +public class StrolchElementToDomVisitor { + + protected Document document; + + public Document getDocument() { + return this.document; + } + + 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()); + + return asDom; + } + + protected Element toDom(Resource resource) { + + Element asDom = document.createElement(Tags.RESOURCE); + fillElement(asDom, resource); + + if (resource.hasTimedStates()) { + for (String stateKey : resource.getTimedStateKeySet()) { + StrolchTimedState> timedState = resource.getTimedState(stateKey); + Element stateElement = toDom(timedState); + asDom.appendChild(stateElement); + } + } + + return asDom; + } + + protected Element toDom(Activity activity) { + Element element = document.createElement(Tags.ACTIVITY); + fillElement(element, activity); + + if (activity.hasElements()) { + Iterator> iter = activity.elementIterator(); + while (iter.hasNext()) { + IActivityElement activityElement = iter.next().getValue(); + if (activityElement instanceof Activity) { + element.appendChild(toDom((Activity) activityElement)); + } else if (activityElement instanceof Action) { + element.appendChild(toDom((Action) activityElement)); + } else { + throw new IllegalArgumentException("Unhandled element " + activityElement.getClass()); + } + } + } + + return element; + } + + protected Element toDom(Action action) { + Element element = document.createElement(Tags.ACTION); + fillElement(element, action); + + element.setAttribute(Tags.RESOURCE_ID, action.getResourceId()); + element.setAttribute(Tags.RESOURCE_TYPE, action.getResourceType()); + element.setAttribute(Tags.STATE, action.getState().name()); + + if (action.hasChanges()) { + Iterator>> iter = action.changesIterator(); + while (iter.hasNext()) { + IValueChange> value = iter.next(); + Element valueChangeElement = toDom(value); + element.appendChild(valueChangeElement); + } + } + + return element; + } + + protected Element toDom(IValueChange> value) { + Element element = document.createElement(Tags.VALUE_CHANGE); + element.setAttribute(Tags.STATE_ID, value.getStateId()); + element.setAttribute(Tags.TIME, ISO8601FormatFactory.getInstance().formatDate(value.getTime())); + element.setAttribute(Tags.VALUE, value.getValue().getValueAsString()); + element.setAttribute(Tags.TYPE, value.getValue().getType()); + return element; + } + + protected Element toDom(StrolchTimedState> timedState) { + + Element element = document.createElement(Tags.TIMED_STATE); + fillElement(element, (AbstractStrolchElement) timedState); + + if (!timedState.getInterpretation().equals(StrolchModelConstants.INTERPRETATION_NONE)) { + element.setAttribute(Tags.INTERPRETATION, timedState.getInterpretation()); + } + if (!timedState.getUom().equals(StrolchModelConstants.UOM_NONE)) { + element.setAttribute(Tags.UOM, timedState.getUom()); + } + if (timedState.isHidden()) { + element.setAttribute(Tags.HIDDEN, Boolean.toString(timedState.isHidden())); + } + if (timedState.getIndex() != 0) { + element.setAttribute(Tags.INDEX, Integer.toString(timedState.getIndex())); + } + + SortedSet>> values = timedState.getTimeEvolution().getValues(); + for (ITimeValue> iTimeValue : values) { + + Long time = iTimeValue.getTime(); + String valueS = iTimeValue.getValue().getValueAsString(); + + Element valueElement = document.createElement(Tags.VALUE); + valueElement.setAttribute(Tags.TIME, ISO8601FormatFactory.getInstance().formatDate(time)); + valueElement.setAttribute(Tags.VALUE, valueS); + + element.appendChild(valueElement); + } + + return element; + } + + protected Element toDom(ParameterBag bag) { + Element bagElement = document.createElement(Tags.PARAMETER_BAG); + fillElement(bagElement, (ParameterizedElement) bag); + return bagElement; + } + + protected Element toDom(Parameter param) { + Element element = document.createElement(Tags.PARAMETER); + fillElement(element, (AbstractStrolchElement) param); + + element.setAttribute(Tags.VALUE, param.getValueAsString()); + + if (!param.getInterpretation().equals(StrolchModelConstants.INTERPRETATION_NONE)) { + element.setAttribute(Tags.INTERPRETATION, param.getInterpretation()); + } + if (!param.getUom().equals(StrolchModelConstants.UOM_NONE)) { + element.setAttribute(Tags.UOM, param.getUom()); + } + if (param.isHidden()) { + element.setAttribute(Tags.HIDDEN, Boolean.toString(param.isHidden())); + } + if (param.getIndex() != 0) { + element.setAttribute(Tags.INDEX, Integer.toString(param.getIndex())); + } + + return element; + } + + protected void fillElement(Element element, AbstractStrolchElement strolchElement) { + element.setAttribute(Tags.ID, strolchElement.getId()); + element.setAttribute(Tags.NAME, strolchElement.getName()); + element.setAttribute(Tags.TYPE, strolchElement.getType()); + } + + protected void fillElement(Element element, GroupedParameterizedElement groupedParameterizedElement) { + fillElement(element, (AbstractStrolchElement) groupedParameterizedElement); + + if (groupedParameterizedElement.hasParameterBags()) { + for (String bagKey : groupedParameterizedElement.getParameterBagKeySet()) { + ParameterBag bag = groupedParameterizedElement.getParameterBag(bagKey); + Element bagElement = toDom(bag); + element.appendChild(bagElement); + } + } + } + + protected void fillElement(Element element, ParameterizedElement parameterizedElement) { + fillElement(element, (AbstractStrolchElement) parameterizedElement); + + if (parameterizedElement.hasParameters()) { + for (String paramKey : parameterizedElement.getParameterKeySet()) { + Parameter parameter = parameterizedElement.getParameter(paramKey); + Element paramElement = toDom(parameter); + element.appendChild(paramElement); + } + } + } + +} 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 78c468c26..e06f581a1 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 @@ -18,6 +18,8 @@ package li.strolch.model.xml; import static li.strolch.model.StrolchModelConstants.INTERPRETATION_NONE; import static li.strolch.model.StrolchModelConstants.UOM_NONE; +import java.util.Iterator; +import java.util.Map.Entry; import java.util.Set; import java.util.SortedSet; @@ -27,10 +29,14 @@ import li.strolch.model.ParameterBag; import li.strolch.model.Resource; import li.strolch.model.StrolchElement; import li.strolch.model.Tags; +import li.strolch.model.activity.Action; +import li.strolch.model.activity.Activity; +import li.strolch.model.activity.IActivityElement; import li.strolch.model.parameter.Parameter; 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; @@ -58,14 +64,6 @@ public abstract class StrolchElementToSaxVisitor { return attributes; } - protected AttributesImpl attributesFor(Order order) { - AttributesImpl attributes = attributesFor((StrolchElement) order); - attributes.addAttribute(null, null, Tags.STATE, Tags.CDATA, order.getState().name()); - attributes.addAttribute(null, null, Tags.DATE, Tags.CDATA, - ISO8601FormatFactory.getInstance().formatDate(order.getDate())); - return attributes; - } - protected AttributesImpl attributesFor(Parameter parameter) { AttributesImpl attributes = attributesFor((StrolchElement) parameter); attributes.addAttribute(null, null, Tags.VALUE, Tags.CDATA, parameter.getValueAsString()); @@ -131,6 +129,8 @@ public abstract class StrolchElementToSaxVisitor { } protected void toSax(Resource resource) throws SAXException { + this.contentHandler.startElement(null, null, Tags.RESOURCE, attributesFor(resource)); + toSax((GroupedParameterizedElement) resource); Set stateKeySet = resource.getTimedStateKeySet(); @@ -145,5 +145,75 @@ public abstract class StrolchElementToSaxVisitor { } this.contentHandler.endElement(null, null, Tags.TIMED_STATE); } + + this.contentHandler.endElement(null, null, Tags.RESOURCE); + } + + protected AttributesImpl attributesFor(Order order) { + AttributesImpl attributes = attributesFor((StrolchElement) order); + attributes.addAttribute(null, null, Tags.STATE, Tags.CDATA, order.getState().name()); + attributes.addAttribute(null, null, Tags.DATE, Tags.CDATA, + ISO8601FormatFactory.getInstance().formatDate(order.getDate())); + return attributes; + } + + protected void toSax(Order order) throws SAXException { + this.contentHandler.startElement(null, null, Tags.ORDER, attributesFor(order)); + + toSax((GroupedParameterizedElement) order); + + this.contentHandler.endElement(null, null, Tags.ORDER); + } + + protected void toSax(Activity activity) throws SAXException { + this.contentHandler.startElement(null, null, Tags.ACTIVITY, attributesFor(activity)); + toSax((GroupedParameterizedElement) activity); + + Iterator> iter = activity.elementIterator(); + while (iter.hasNext()) { + IActivityElement activityElement = iter.next().getValue(); + + if (activityElement instanceof Activity) { + toSax((Activity) activityElement); + } else if (activityElement instanceof Action) { + toSax((Action) activityElement); + } else { + throw new IllegalArgumentException("Unhandled element " + activityElement.getClass()); + } + } + + this.contentHandler.endElement(null, null, Tags.ACTIVITY); + } + + protected AttributesImpl attributesFor(Action action) { + AttributesImpl attributes = attributesFor((StrolchElement) action); + attributes.addAttribute(null, null, Tags.RESOURCE_ID, Tags.CDATA, action.getResourceId()); + attributes.addAttribute(null, null, Tags.RESOURCE_TYPE, Tags.CDATA, action.getResourceType()); + attributes.addAttribute(null, null, Tags.STATE, Tags.CDATA, action.getState().name()); + return attributes; + } + + protected AttributesImpl attributesFor(IValueChange> valueChange) { + AttributesImpl attributes = new AttributesImpl(); + attributes.addAttribute(null, null, Tags.STATE_ID, Tags.CDATA, valueChange.getStateId()); + attributes.addAttribute(null, null, Tags.TIME, Tags.CDATA, + ISO8601FormatFactory.getInstance().formatDate(valueChange.getTime())); + attributes.addAttribute(null, null, Tags.VALUE, Tags.CDATA, valueChange.getValue().getValueAsString()); + attributes.addAttribute(null, null, Tags.TYPE, Tags.CDATA, valueChange.getValue().getType()); + return attributes; + } + + protected void toSax(Action action) throws SAXException { + this.contentHandler.startElement(null, null, Tags.ACTION, attributesFor(action)); + toSax((GroupedParameterizedElement) action); + + Iterator>> iter = action.changesIterator(); + while (iter.hasNext()) { + IValueChange> valueChange = iter.next(); + this.contentHandler.startElement(null, null, Tags.VALUE_CHANGE, attributesFor(valueChange)); + this.contentHandler.endElement(null, null, Tags.VALUE_CHANGE); + } + + this.contentHandler.endElement(null, null, Tags.ACTION); } } diff --git a/li.strolch.model/src/main/java/li/strolch/model/xml/XmlModelSaxFileReader.java b/li.strolch.model/src/main/java/li/strolch/model/xml/XmlModelSaxFileReader.java index d805274f8..1c2d9be32 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/xml/XmlModelSaxFileReader.java +++ b/li.strolch.model/src/main/java/li/strolch/model/xml/XmlModelSaxFileReader.java @@ -76,8 +76,7 @@ public class XmlModelSaxFileReader extends XmlModelSaxReader { XmlModelSaxFileReader handler = new XmlModelSaxFileReader(this.listener, includeFile, this.allowInclude); handler.parseFile(); - this.statistics.nrOfOrders += handler.statistics.nrOfOrders; - this.statistics.nrOfResources += handler.statistics.nrOfResources; + this.statistics.add(handler.statistics); break; default: 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 e97751b15..9b7788794 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 @@ -16,9 +16,9 @@ package li.strolch.model.xml; import java.text.MessageFormat; +import java.util.ArrayDeque; import java.util.Date; -import java.util.HashSet; -import java.util.Set; +import java.util.Deque; import li.strolch.exception.StrolchException; import li.strolch.model.GroupedParameterizedElement; @@ -27,30 +27,14 @@ import li.strolch.model.Order; import li.strolch.model.ParameterBag; import li.strolch.model.Resource; import li.strolch.model.State; +import li.strolch.model.StrolchValueType; import li.strolch.model.Tags; -import li.strolch.model.parameter.BooleanParameter; -import li.strolch.model.parameter.DateParameter; -import li.strolch.model.parameter.DurationParameter; -import li.strolch.model.parameter.FloatListParameter; -import li.strolch.model.parameter.FloatParameter; -import li.strolch.model.parameter.IntegerListParameter; -import li.strolch.model.parameter.IntegerParameter; -import li.strolch.model.parameter.LongListParameter; -import li.strolch.model.parameter.LongParameter; +import li.strolch.model.activity.Action; +import li.strolch.model.activity.Activity; import li.strolch.model.parameter.Parameter; -import li.strolch.model.parameter.StringListParameter; -import li.strolch.model.parameter.StringParameter; -import li.strolch.model.timedstate.BooleanTimedState; -import li.strolch.model.timedstate.FloatTimedState; -import li.strolch.model.timedstate.IntegerTimedState; -import li.strolch.model.timedstate.StringSetTimedState; import li.strolch.model.timedstate.StrolchTimedState; import li.strolch.model.timevalue.IValue; -import li.strolch.model.timevalue.impl.AString; -import li.strolch.model.timevalue.impl.BooleanValue; -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 org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -72,13 +56,15 @@ public class XmlModelSaxReader extends DefaultHandler { protected ModelStatistics statistics; private GroupedParameterizedElement parameterizedElement; + private Deque activityStack; private ParameterBag pBag; private StrolchTimedState> state; - private String stateType; + private StrolchValueType stateType; public XmlModelSaxReader(StrolchElementListener listener) { this.listener = listener; this.statistics = new ModelStatistics(); + this.activityStack = new ArrayDeque<>(); } /** @@ -104,6 +90,50 @@ public class XmlModelSaxReader extends DefaultHandler { String resType = attributes.getValue(Tags.TYPE); Resource resource = new Resource(resId, resName, resType); this.parameterizedElement = resource; + + break; + + case Tags.ACTIVITY: + + String activityId = attributes.getValue(Tags.ID); + String activityName = attributes.getValue(Tags.NAME); + String activityType = attributes.getValue(Tags.TYPE); + Activity activity = new Activity(activityId, activityName, activityType); + this.parameterizedElement = activity; + this.activityStack.push(activity); + + break; + + case Tags.ACTION: + + String actionId = attributes.getValue(Tags.ID); + String actionName = attributes.getValue(Tags.NAME); + String actionType = attributes.getValue(Tags.TYPE); + String actionResourceId = attributes.getValue(Tags.RESOURCE_ID); + String actionResourceType = attributes.getValue(Tags.RESOURCE_TYPE); + String actionState = attributes.getValue(Tags.STATE); + Action action = new Action(actionId, actionName, actionType); + action.setResourceId(actionResourceId); + action.setResourceType(actionResourceType); + action.setState(State.valueOf(actionState)); + + this.parameterizedElement = action; + + break; + + case Tags.VALUE_CHANGE: + + String valueChangeStateId = attributes.getValue(Tags.STATE_ID); + String valueChangeTimeS = attributes.getValue(Tags.TIME); + String valueChangeValue = attributes.getValue(Tags.VALUE); + String valueChangeType = attributes.getValue(Tags.TYPE); + + IValue value = StrolchValueType.parse(valueChangeType).valueInstance(valueChangeValue); + long valueChangeTime = ISO8601FormatFactory.getInstance().getDateFormat().parse(valueChangeTimeS).getTime(); + ValueChange> valueChange = new ValueChange>(valueChangeTime, value, valueChangeStateId); + + ((Action) this.parameterizedElement).addChange(valueChange); + break; case Tags.ORDER: @@ -122,6 +152,7 @@ public class XmlModelSaxReader extends DefaultHandler { order.setState(orderState); } this.parameterizedElement = order; + break; case Tags.PARAMETER_BAG: @@ -130,13 +161,11 @@ public class XmlModelSaxReader extends DefaultHandler { String pBagType = attributes.getValue(Tags.TYPE); ParameterBag pBag = new ParameterBag(pBagId, pBagName, pBagType); this.pBag = pBag; - this.parameterizedElement.addParameterBag(pBag); + break; case Tags.PARAMETER: - // TODO refactor this code into using visitors - String paramId = attributes.getValue(Tags.ID); String paramName = attributes.getValue(Tags.NAME); String paramType = attributes.getValue(Tags.TYPE); @@ -149,110 +178,50 @@ public class XmlModelSaxReader extends DefaultHandler { .parseBoolean(paramHiddenS); String paramUom = attributes.getValue(Tags.UOM); String paramInterpretation = attributes.getValue(Tags.INTERPRETATION); - Parameter param; - switch (paramType) { - case StringParameter.TYPE: - param = new StringParameter(paramId, paramName, paramValue); - break; - case IntegerParameter.TYPE: - param = new IntegerParameter(paramId, paramName, IntegerParameter.parseFromString(paramValue)); - break; - case BooleanParameter.TYPE: - param = new BooleanParameter(paramId, paramName, BooleanParameter.parseFromString(paramValue)); - break; - case LongParameter.TYPE: - param = new LongParameter(paramId, paramName, LongParameter.parseFromString(paramValue)); - break; - case DateParameter.TYPE: - param = new DateParameter(paramId, paramName, DateParameter.parseFromString(paramValue)); - break; - case DurationParameter.TYPE: - param = new DurationParameter(paramId, paramName, DurationParameter.parseFromString(paramValue)); - break; - case StringListParameter.TYPE: - param = new StringListParameter(paramId, paramName, StringListParameter.parseFromString(paramValue)); - break; - case IntegerListParameter.TYPE: - param = new IntegerListParameter(paramId, paramName, - IntegerListParameter.parseFromString(paramValue)); - break; - case FloatListParameter.TYPE: - param = new FloatListParameter(paramId, paramName, FloatListParameter.parseFromString(paramValue)); - break; - case LongListParameter.TYPE: - param = new LongListParameter(paramId, paramName, LongListParameter.parseFromString(paramValue)); - break; - case FloatParameter.TYPE: - param = new FloatParameter(paramId, paramName, FloatParameter.parseFromString(paramValue)); - break; - default: - throw new UnsupportedOperationException(MessageFormat.format( - "Parameters of type {0} are not supported!", paramType)); //$NON-NLS-1$ - } + + StrolchValueType type = StrolchValueType.parse(paramType); + + Parameter param = type.parameterInstance(); + param.setId(paramId); + param.setName(paramName); + param.setValueFromString(paramValue); + param.setHidden(paramHidden); param.setUom(paramUom); param.setInterpretation(paramInterpretation); param.setIndex(index); + this.pBag.addParameter(param); + } catch (Exception e) { throw new StrolchException("Failed to instantiate parameter " + paramId + " for bag " + this.pBag.getLocator() + " due to " + e.getMessage(), e); } + break; case Tags.TIMED_STATE: + String stateId = attributes.getValue(Tags.ID); String stateName = attributes.getValue(Tags.NAME); - this.stateType = attributes.getValue(Tags.TYPE); + String stateType = attributes.getValue(Tags.TYPE); - switch (this.stateType) { - case FloatTimedState.TYPE: - this.state = new FloatTimedState(stateId, stateName); - break; - case IntegerTimedState.TYPE: - this.state = new IntegerTimedState(stateId, stateName); - break; - case BooleanTimedState.TYPE: - this.state = new BooleanTimedState(stateId, stateName); - break; - case StringSetTimedState.TYPE: - this.state = new StringSetTimedState(stateId, stateName); - break; - default: - break; - } + this.stateType = StrolchValueType.parse(stateType); + this.state = this.stateType.timedStateInstance(); + this.state.setId(stateId); + this.state.setName(stateName); break; case Tags.VALUE: + String valueTime = attributes.getValue(Tags.TIME); Date date = ISO8601FormatFactory.getInstance().parseDate(valueTime); long time = date.getTime(); String valueValue = attributes.getValue(Tags.VALUE); - switch (this.stateType) { - case FloatTimedState.TYPE: - ((FloatTimedState) this.state).getTimeEvolution().setValueAt(time, new FloatValue(valueValue)); - break; - case IntegerTimedState.TYPE: - ((IntegerTimedState) this.state).getTimeEvolution().setValueAt(time, new IntegerValue(valueValue)); - break; - case BooleanTimedState.TYPE: - ((BooleanTimedState) this.state).getTimeEvolution().setValueAt(time, new BooleanValue(valueValue)); - break; - case StringSetTimedState.TYPE: - Set value = new HashSet<>(); - String[] values = valueValue.split(","); - for (String s : values) { - value.add(new AString(s.trim())); - } + this.state.setStateFromStringAt(time, valueValue); - StringSetValue stringSetValue = new StringSetValue(value); - ((StringSetTimedState) this.state).getTimeEvolution().setValueAt(time, stringSetValue); - break; - default: - break; - } break; default: @@ -264,30 +233,62 @@ public class XmlModelSaxReader extends DefaultHandler { public void endElement(String uri, String localName, String qName) throws SAXException { switch (qName) { - case Tags.STROLCH_MODEL: - break; case Tags.RESOURCE: this.listener.notifyResource((Resource) this.parameterizedElement); this.statistics.nrOfResources++; this.parameterizedElement = null; + break; + + case Tags.ACTIVITY: + + Activity activity = this.activityStack.pop(); + if (this.activityStack.isEmpty()) { + this.listener.notifyActivity(activity); + this.statistics.nrOfActivities++; + } else { + this.activityStack.peek().addElement(activity); + } + this.parameterizedElement = null; + + break; + case Tags.ORDER: + this.listener.notifyOrder((Order) this.parameterizedElement); this.statistics.nrOfOrders++; this.parameterizedElement = null; + break; + + case Tags.ACTION: + + this.activityStack.peek().addElement((Action) parameterizedElement); + this.parameterizedElement = null; + + break; + case Tags.PARAMETER_BAG: + + this.parameterizedElement.addParameterBag(pBag); this.pBag = null; + break; - case Tags.PARAMETER: - break; - case Tags.INCLUDE_FILE: - break; + case Tags.TIMED_STATE: + ((Resource) this.parameterizedElement).addTimedState(this.state); + break; + + case Tags.PARAMETER: + case Tags.INCLUDE_FILE: case Tags.VALUE: + case Tags.VALUE_CHANGE: + case Tags.STROLCH_MODEL: + break; + default: throw new IllegalArgumentException(MessageFormat.format("The element ''{0}'' is unhandled!", qName)); //$NON-NLS-1$ } diff --git a/li.strolch.model/src/test/java/li/strolch/model/ModelTest.java b/li.strolch.model/src/test/java/li/strolch/model/ModelTest.java index 777a8a6dd..9d8178234 100644 --- a/li.strolch.model/src/test/java/li/strolch/model/ModelTest.java +++ b/li.strolch.model/src/test/java/li/strolch/model/ModelTest.java @@ -15,6 +15,8 @@ */ package li.strolch.model; +import static li.strolch.model.ModelGenerator.ACTION_RES_ID; +import static li.strolch.model.ModelGenerator.ACTION_RES_TYPE; import static li.strolch.model.ModelGenerator.BAG_ID; import static li.strolch.model.ModelGenerator.BAG_NAME; import static li.strolch.model.ModelGenerator.BAG_TYPE; @@ -52,6 +54,7 @@ import static li.strolch.model.ModelGenerator.STATE_TIME_0; import static li.strolch.model.ModelGenerator.STATE_TIME_10; import static li.strolch.model.ModelGenerator.STATE_TIME_20; import static li.strolch.model.ModelGenerator.STATE_TIME_30; +import static li.strolch.model.ModelGenerator.createActivity; import static li.strolch.model.ModelGenerator.createOrder; import static li.strolch.model.ModelGenerator.createResource; import static li.strolch.model.Tags.BAG; @@ -65,7 +68,10 @@ import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.Date; +import java.util.List; +import li.strolch.model.activity.Action; +import li.strolch.model.activity.Activity; import li.strolch.model.parameter.BooleanParameter; import li.strolch.model.parameter.DateParameter; import li.strolch.model.parameter.FloatListParameter; @@ -80,33 +86,116 @@ import li.strolch.model.timedstate.BooleanTimedState; import li.strolch.model.timedstate.FloatTimedState; import li.strolch.model.timedstate.IntegerTimedState; import li.strolch.model.timedstate.StringSetTimedState; +import li.strolch.model.timevalue.IValue; +import li.strolch.model.timevalue.IValueChange; import li.strolch.model.timevalue.impl.BooleanValue; +import li.strolch.model.timevalue.impl.IntegerValue; import li.strolch.model.timevalue.impl.ValueChange; +import li.strolch.model.visitor.ActivityDeepEqualsVisitor; import li.strolch.model.visitor.OrderDeepEqualsVisitor; import li.strolch.model.visitor.ResourceDeepEqualsVisitor; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; @SuppressWarnings("nls") public class ModelTest { + protected static final Logger logger = LoggerFactory.getLogger(ModelTest.class); + @Test public void shouldCreateResource() { Resource resource = createResource("@res01", "Test resource", "MyType"); + assertEquals("@res01", resource.getId()); + assertEquals("Test resource", resource.getName()); + assertEquals("MyType", resource.getType()); + ParameterBag bag = resource.getParameterBag(BAG_ID); validateBag(bag); + validateStates(resource); } @Test public void shouldCreateOrder() { - Order order = createOrder("@ord01", "Test Order", "MyType", new Date(), State.OPEN); + Date date = new Date(); + Order order = createOrder("@ord01", "Test Order", "MyType", date, State.OPEN); + assertEquals("@ord01", order.getId()); + assertEquals("Test Order", order.getName()); + assertEquals("MyType", order.getType()); + assertEquals(date, order.getDate()); + assertEquals(State.OPEN, order.getState()); + ParameterBag bag = order.getParameterBag(BAG_ID); validateBag(bag); } + @Test + public void shouldCreateActivity() { + + String actId = "@act01"; + String actName = "Test Activity"; + String actType = "MyType"; + + List>> changes = new ArrayList<>(); + changes.add(new ValueChange<>(0L, new IntegerValue(0), STATE_INTEGER_ID)); + changes.add(new ValueChange<>(10L, new IntegerValue(10), STATE_INTEGER_ID)); + changes.add(new ValueChange<>(20L, new IntegerValue(20), STATE_INTEGER_ID)); + changes.add(new ValueChange<>(30L, new IntegerValue(30), STATE_INTEGER_ID)); + changes.add(new ValueChange<>(40L, new IntegerValue(20), STATE_INTEGER_ID)); + changes.add(new ValueChange<>(50L, new IntegerValue(10), STATE_INTEGER_ID)); + changes.add(new ValueChange<>(60L, new IntegerValue(0), STATE_INTEGER_ID)); + + Activity activity = createActivity(actId, actName, actType); + assertEquals(actId, activity.getId()); + assertEquals(actName, activity.getName()); + assertEquals(actType, activity.getType()); + + ParameterBag bag = activity.getParameterBag(BAG_ID); + validateBag(bag); + + Action action = activity.getElement("act_" + actId); + assertEquals("act_" + actId, action.getId()); + assertEquals("Action " + actName, action.getName()); + assertEquals("Use", action.getType()); + assertEquals(ACTION_RES_ID, action.getResourceId()); + assertEquals(ACTION_RES_TYPE, action.getResourceType()); + assertEquals(changes, action.getChanges()); + + activity = activity.getElement("sub_" + actId); + assertEquals("sub_" + actId, activity.getId()); + assertEquals("sub_" + actName, activity.getName()); + assertEquals(actType, activity.getType()); + bag = activity.getParameterBag(BAG_ID); + validateBag(bag); + + action = activity.getElement("act_" + actId); + assertEquals("act_" + actId, action.getId()); + assertEquals("Action " + actName, action.getName()); + assertEquals("Use", action.getType()); + assertEquals(ACTION_RES_ID, action.getResourceId()); + assertEquals(ACTION_RES_TYPE, action.getResourceType()); + assertEquals(changes, action.getChanges()); + + activity = activity.getElement("subSub_" + actId); + assertEquals("subSub_" + actId, activity.getId()); + assertEquals("subSub_" + actName, activity.getName()); + assertEquals(actType, activity.getType()); + bag = activity.getParameterBag(BAG_ID); + validateBag(bag); + + action = activity.getElement("act_" + actId); + assertEquals("act_" + actId, action.getId()); + assertEquals("Action " + actName, action.getName()); + assertEquals("Use", action.getType()); + assertEquals(ACTION_RES_ID, action.getResourceId()); + assertEquals(ACTION_RES_TYPE, action.getResourceType()); + assertEquals(changes, action.getChanges()); + } + @Test public void shouldCreateLocators() { @@ -127,6 +216,71 @@ public class ModelTest { assertEquals(Locator.valueOf(ORDER, "MyType", "@ord01", BAG, BAG_ID, PARAM_STRING_ID), sP.getLocator()); } + @Test + public void shouldPerformDeepActivityEquals() { + Activity srcActivity = createActivity("@act01", "Test Activity", "MyType"); + Activity dstActivity = createActivity("@act01", "Test Activity", "MyType"); + ActivityDeepEqualsVisitor visitor = new ActivityDeepEqualsVisitor(srcActivity); + visitor.visit(dstActivity); + assertTrue("Same Activity should be deep equal!", visitor.isEqual()); + } + + @Test + public void shouldPerformActivityClone() { + Activity srcActivity = createActivity("@act01", "Test Activity", "MyType"); + Activity dstActivity = srcActivity.getClone(); + ActivityDeepEqualsVisitor visitor = new ActivityDeepEqualsVisitor(srcActivity); + visitor.visit(dstActivity); + assertTrue("Cloned Activity should be deep equal: " + visitor.getMismatchedLocators(), visitor.isEqual()); + } + + @Test + public void shouldFailDeepActivityEquals1() { + Activity srcActivity = createActivity("@act01", "Test Activity", "MyType"); + Activity dstActivity = createActivity("@act01", "Test Activity", "MyType"); + dstActivity.setName("Bla"); + dstActivity.setType("BlaBla"); + ParameterBag bag = dstActivity.getParameterBag(BAG_ID); + bag.setName("Bla bla"); + FloatParameter fParam = bag.getParameter(PARAM_FLOAT_ID); + fParam.setValue(23434234.234); + fParam.setName("Ohla"); + ActivityDeepEqualsVisitor visitor = new ActivityDeepEqualsVisitor(srcActivity); + visitor.visit(dstActivity); + assertFalse("Activity should not be same if something has been changed", visitor.isEqual()); + assertEquals("Multiple changes should be registered", 6, visitor.getMismatchedLocators().size()); + } + + @Test + public void shouldFailDeepActivityEquals2() { + Activity srcActivity = createActivity("@act01", "Test Activity", "MyType"); + Activity dstActivity = createActivity("@act01", "Test Activity", "MyType"); + + Action action = dstActivity.getElement("act_" + "@act01"); + action.setResourceId("Bla"); + action.setResourceType("Bla"); + action.setType("Bla"); + action.setState(State.CLOSED); + action.addChange(new ValueChange<>(1234567890L, new IntegerValue(12345), STATE_INTEGER_ID)); + + Activity activity = dstActivity.getElement("sub_" + "@act01"); + activity.addElement(new Action("bla", "Bla", "Bla")); + + action = activity.getElement("act_" + "@act01"); + action.addChange(new ValueChange<>(1234567890L, new IntegerValue(12345), STATE_INTEGER_ID)); + + activity = activity.getElement("subSub_" + "@act01"); + activity.addElement(new Action("bla", "Bla", "Bla")); + + action = activity.getElement("act_" + "@act01"); + action.addChange(new ValueChange<>(1234567890L, new IntegerValue(12345), STATE_INTEGER_ID)); + + ActivityDeepEqualsVisitor visitor = new ActivityDeepEqualsVisitor(srcActivity); + visitor.visit(dstActivity); + assertFalse("Activity should not be same if something has been changed", visitor.isEqual()); + assertEquals("Multiple changes should be registered", 9, visitor.getMismatchedLocators().size()); + } + @Test public void shouldPerformDeepResourceEquals() { Resource srcRes = createResource("@res01", "Test resource", "MyType"); @@ -145,16 +299,6 @@ public class ModelTest { assertTrue("Cloned Resource should be deep equal!", visitor.isEqual()); } - @Test - public void shouldPerformOrderClone() { - Date date = new Date(); - Order srcOrder = createOrder("@ord01", "Test Order", "MyType", date, State.OPEN); - Order dstOrder = srcOrder.getClone(); - OrderDeepEqualsVisitor visitor = new OrderDeepEqualsVisitor(srcOrder); - visitor.visit(dstOrder); - assertTrue("Cloned Order should be deep equal: " + visitor.getMismatchedLocators(), visitor.isEqual()); - } - @Test public void shouldFailDeepResourceEquals1() { Resource srcRes = createResource("@res01", "Test resource", "MyType"); @@ -167,7 +311,7 @@ public class ModelTest { ResourceDeepEqualsVisitor visitor = new ResourceDeepEqualsVisitor(srcRes); visitor.visit(dstRes); assertFalse("Resource should not be same if param is changed!", visitor.isEqual()); - assertEquals("Three changes should be registered", 3, visitor.getMismatchedLocators().size()); + assertEquals("Multiple changes should be registered", 3, visitor.getMismatchedLocators().size()); } @Test @@ -175,12 +319,12 @@ public class ModelTest { Resource srcRes = createResource("@res01", "Test resource", "MyType"); Resource dstRes = createResource("@res01", "Test resource", "MyType"); BooleanTimedState timedState = dstRes.getTimedState(STATE_BOOLEAN_ID); - timedState.applyChange(new ValueChange<>(System.currentTimeMillis(), new BooleanValue(Boolean.TRUE))); + timedState.applyChange(new ValueChange<>(System.currentTimeMillis(), new BooleanValue(Boolean.FALSE))); timedState.setName("Ohla"); ResourceDeepEqualsVisitor visitor = new ResourceDeepEqualsVisitor(srcRes); visitor.visit(dstRes); assertFalse("Resource should not be same if param is changed!", visitor.isEqual()); - assertEquals("One change should be registered!", 1, visitor.getMismatchedLocators().size()); + assertEquals("Multiple change should be registered!", 2, visitor.getMismatchedLocators().size()); } @Test @@ -193,6 +337,34 @@ public class ModelTest { assertTrue("Same Order should be deep equal: " + visitor.getMismatchedLocators(), visitor.isEqual()); } + @Test + public void shouldPerformOrderClone() { + Date date = new Date(); + Order srcOrder = createOrder("@ord01", "Test Order", "MyType", date, State.OPEN); + Order dstOrder = srcOrder.getClone(); + OrderDeepEqualsVisitor visitor = new OrderDeepEqualsVisitor(srcOrder); + visitor.visit(dstOrder); + assertTrue("Cloned Order should be deep equal: " + visitor.getMismatchedLocators(), visitor.isEqual()); + } + + @Test + public void shouldFailDeepOrderEquals1() { + Date date = new Date(); + Order srcOrder = createOrder("@ord01", "Test Order", "MyType", date, State.OPEN); + Order dstOrder = createOrder("@ord01", "Test Order", "MyType", date, State.OPEN); + dstOrder.setDate(new Date(1L)); + dstOrder.setState(State.CLOSED); + ParameterBag bag = dstOrder.getParameterBag(BAG_ID); + bag.setName("Bla bla"); + FloatParameter fParam = bag.getParameter(PARAM_FLOAT_ID); + fParam.setValue(23434234.234); + fParam.setName("Ohla"); + OrderDeepEqualsVisitor visitor = new OrderDeepEqualsVisitor(srcOrder); + visitor.visit(dstOrder); + assertFalse("Order should not be same if something has been changed", visitor.isEqual()); + assertEquals("Multiple changes should be registered", 5, visitor.getMismatchedLocators().size()); + } + public static void validateBag(ParameterBag bag) { assertNotNull(bag); diff --git a/li.strolch.model/src/test/java/li/strolch/model/XmlModelDefaultHandlerTest.java b/li.strolch.model/src/test/java/li/strolch/model/XmlModelDefaultHandlerTest.java index 24c845d66..2d698523f 100644 --- a/li.strolch.model/src/test/java/li/strolch/model/XmlModelDefaultHandlerTest.java +++ b/li.strolch.model/src/test/java/li/strolch/model/XmlModelDefaultHandlerTest.java @@ -21,6 +21,7 @@ import java.io.File; import java.util.HashMap; import java.util.Map; +import li.strolch.model.activity.Activity; import li.strolch.model.xml.StrolchElementListener; import li.strolch.model.xml.XmlModelSaxFileReader; @@ -32,7 +33,6 @@ import ch.eitchnet.utils.helper.StringHelper; /** * @author Robert von Burg - * */ @SuppressWarnings("nls") public class XmlModelDefaultHandlerTest { @@ -42,8 +42,9 @@ public class XmlModelDefaultHandlerTest { @Test public void shouldParseXmlModelFile() { - final Map resourceMap = new HashMap<>(); - final Map orderMap = new HashMap<>(); + Map resourceMap = new HashMap<>(); + Map orderMap = new HashMap<>(); + Map activityMap = new HashMap<>(); File file = new File("src/test/resources/data/StrolchModel.xml"); StrolchElementListener listener = new StrolchElementListener() { @@ -56,16 +57,24 @@ public class XmlModelDefaultHandlerTest { public void notifyOrder(Order order) { orderMap.put(order.getId(), order); } + + @Override + public void notifyActivity(Activity activity) { + activityMap.put(activity.getId(), activity); + } }; + XmlModelSaxFileReader handler = new XmlModelSaxFileReader(listener, file, true); handler.parseFile(); assertEquals(3, resourceMap.size()); assertEquals(3, orderMap.size()); + assertEquals(3, activityMap.size()); ModelStatistics statistics = handler.getStatistics(); logger.info("Parsing took " + StringHelper.formatNanoDuration(statistics.durationNanos)); assertEquals(3, statistics.nrOfOrders); assertEquals(3, statistics.nrOfResources); + assertEquals(3, statistics.nrOfActivities); } } 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 84f3438f0..9f6a652d8 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,14 +16,19 @@ package li.strolch.model; import static org.junit.Assert.assertTrue; +import li.strolch.model.activity.Activity; +import li.strolch.model.visitor.ActivityDeepEqualsVisitor; import li.strolch.model.visitor.OrderDeepEqualsVisitor; import li.strolch.model.visitor.ResourceDeepEqualsVisitor; +import li.strolch.model.xml.ActivityFromDomVisitor; +import li.strolch.model.xml.ActivityToDomVisitor; +import li.strolch.model.xml.OrderFromDomVisitor; 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; -import org.w3c.dom.Element; /** * @author Robert von Burg @@ -40,8 +45,7 @@ public class XmlToDomTest extends ModelTest { domVisitor.visit(order); Document document = domVisitor.getDocument(); - Element rootElement = document.getDocumentElement(); - Order parsedOrder = new Order(rootElement); + Order parsedOrder = new OrderFromDomVisitor().visit(document); OrderDeepEqualsVisitor visitor = new OrderDeepEqualsVisitor(order); visitor.visit(parsedOrder); @@ -57,11 +61,27 @@ public class XmlToDomTest extends ModelTest { domVisitor.visit(resource); Document document = domVisitor.getDocument(); - Element rootElement = document.getDocumentElement(); - Resource parsedResource = new Resource(rootElement); + Resource parsedResource = new ResourceFromDomVisitor().visit(document); ResourceDeepEqualsVisitor visitor = new ResourceDeepEqualsVisitor(resource); visitor.visit(parsedResource); assertTrue("To DOM and back should equal same Resource:\n" + visitor.getMismatchedLocators(), visitor.isEqual()); } + + @Test + public void shouldFormatAndParseActivity() { + + Activity activity = ModelGenerator.createActivity("@1", "My Activity 1", "Transport"); + + ActivityToDomVisitor domVisitor = new ActivityToDomVisitor(); + domVisitor.visit(activity); + Document document = domVisitor.getDocument(); + + Activity parsedActivity = new ActivityFromDomVisitor().visit(document); + + ActivityDeepEqualsVisitor visitor = new ActivityDeepEqualsVisitor(parsedActivity); + visitor.visit(parsedActivity); + assertTrue("To DOM and back should equal same Activity:\n" + visitor.getMismatchedLocators(), visitor.isEqual()); + } + } diff --git a/li.strolch.model/src/test/java/li/strolch/model/XmlToSaxTest.java b/li.strolch.model/src/test/java/li/strolch/model/XmlToSaxTest.java index b58baadc0..6336c538d 100644 --- a/li.strolch.model/src/test/java/li/strolch/model/XmlToSaxTest.java +++ b/li.strolch.model/src/test/java/li/strolch/model/XmlToSaxTest.java @@ -25,8 +25,12 @@ import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; +import li.strolch.model.activity.Activity; +import li.strolch.model.visitor.ActivityDeepEqualsVisitor; import li.strolch.model.visitor.OrderDeepEqualsVisitor; import li.strolch.model.visitor.ResourceDeepEqualsVisitor; +import li.strolch.model.xml.ActivityToSaxVisitor; +import li.strolch.model.xml.ActivityToSaxWriterVisitor; import li.strolch.model.xml.OrderToSaxVisitor; import li.strolch.model.xml.OrderToSaxWriterVisitor; import li.strolch.model.xml.ResourceToSaxVisitor; @@ -55,6 +59,7 @@ public class XmlToSaxTest extends ModelTest { assertEquals(1, listener.getOrders().size()); assertEquals(Collections.emptyList(), listener.getResources()); + assertEquals(Collections.emptyList(), listener.getActivities()); Order parsedOrder = listener.getOrders().get(0); OrderDeepEqualsVisitor visitor = new OrderDeepEqualsVisitor(order); @@ -74,6 +79,7 @@ public class XmlToSaxTest extends ModelTest { domVisitor.visit(resource); assertEquals(1, listener.getResources().size()); + assertEquals(Collections.emptyList(), listener.getActivities()); assertEquals(Collections.emptyList(), listener.getOrders()); Resource parsedResource = listener.getResources().get(0); @@ -82,6 +88,27 @@ public class XmlToSaxTest extends ModelTest { assertTrue("To DOM and back should equal same Resource:\n" + visitor.getMismatchedLocators(), visitor.isEqual()); } + @Test + public void shouldFormatAndParseActivity() { + + Activity activity = ModelGenerator.createActivity("@1", "My Activity 1", "MyActivity"); + + SimpleStrolchElementListener listener = new SimpleStrolchElementListener(); + XmlModelSaxReader saxReader = new XmlModelSaxReader(listener); + + ActivityToSaxVisitor domVisitor = new ActivityToSaxVisitor(saxReader); + domVisitor.visit(activity); + + assertEquals(1, listener.getActivities().size()); + assertEquals(Collections.emptyList(), listener.getResources()); + assertEquals(Collections.emptyList(), listener.getOrders()); + Activity parsedActivity = listener.getActivities().get(0); + + ActivityDeepEqualsVisitor visitor = new ActivityDeepEqualsVisitor(activity); + visitor.visit(parsedActivity); + assertTrue("To DOM and back should equal same Activity:\n" + visitor.getMismatchedLocators(), visitor.isEqual()); + } + @Test public void shouldToSaxOrder() throws XMLStreamException { Order order = ModelGenerator.createOrder("@1", "My Order 1", "MyOrder"); @@ -107,4 +134,17 @@ public class XmlToSaxTest extends ModelTest { toSax.visit(resource); writer.writeEndDocument(); } + + @Test + public void shouldToSaxActivity() throws XMLStreamException { + Activity activity = ModelGenerator.createActivity("@1", "My Activity 1", "MyActivity"); + XMLOutputFactory factory = XMLOutputFactory.newInstance(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + XMLStreamWriter writer = factory.createXMLStreamWriter(out, "UTF-8"); + writer.writeStartDocument(); + writer.writeStartElement(Tags.STROLCH_MODEL); + ActivityToSaxWriterVisitor toSax = new ActivityToSaxWriterVisitor(writer); + toSax.visit(activity); + writer.writeEndDocument(); + } } diff --git a/li.strolch.model/src/test/java/li/strolch/model/activity/ActionTest.java b/li.strolch.model/src/test/java/li/strolch/model/activity/ActionTest.java index d13369e62..a70751bf9 100644 --- a/li.strolch.model/src/test/java/li/strolch/model/activity/ActionTest.java +++ b/li.strolch.model/src/test/java/li/strolch/model/activity/ActionTest.java @@ -18,6 +18,7 @@ import javax.xml.transform.stream.StreamResult; import li.strolch.model.timevalue.IValueChange; import li.strolch.model.timevalue.impl.IntegerValue; import li.strolch.model.timevalue.impl.ValueChange; +import li.strolch.model.xml.ActivityToDomVisitor; import org.junit.Assert; import org.junit.Before; @@ -35,54 +36,54 @@ public class ActionTest { @Before public void init() { // create action - action = new Action("action_1", "Action 1", "Use"); - action.setResourceId("dummyRe"); - action.setResourceType("dummyReType"); - + this.action = new Action("action_1", "Action 1", "Use"); + this.action.setResourceId("dummyRe"); + this.action.setResourceType("dummyReType"); + IValueChange startChange = new ValueChange<>(STATE_TIME_10, new IntegerValue(1)); startChange.setStateId(STATE_INTEGER_ID); - action.addChange(startChange); + this.action.addChange(startChange); IValueChange endChange = new ValueChange<>(STATE_TIME_30, new IntegerValue(-1)); endChange.setStateId(STATE_INTEGER_ID); - action.addChange(endChange); + this.action.addChange(endChange); } - + @Test public void testGetStart() { - Assert.assertTrue(STATE_TIME_10 == action.getStart()); + Assert.assertTrue(STATE_TIME_10 == this.action.getStart()); } - + @Test public void testGetEnd() { - Assert.assertTrue(STATE_TIME_30 == action.getEnd()); + Assert.assertTrue(STATE_TIME_30 == this.action.getEnd()); } - @Test public void testClone() { - Action clone = (Action) action.getClone(); - Assert.assertEquals(action.toString(), clone.toString()); - Assert.assertEquals(action.changes.size(), clone.changes.size()); - for (int i = 0; i < action.changes.size(); i++) { - Assert.assertEquals(action.changes.get(i).getTime(), clone.changes.get(i).getTime()); + Action clone = (Action) this.action.getClone(); + Assert.assertEquals(this.action.toString(), clone.toString()); + Assert.assertEquals(this.action.changes.size(), clone.changes.size()); + for (int i = 0; i < this.action.changes.size(); i++) { + Assert.assertEquals(this.action.changes.get(i).getTime(), clone.changes.get(i).getTime()); } } - - @Test + + /** + * no test. Just to see the XML serialization in the console + */ + // @Test public void testToDOM() throws ParserConfigurationException, TransformerException { - + DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder(); - Document document = db.newDocument(); - Element dom = action.toDom(document); - document.appendChild(dom); - + Document document = db.newDocument(); + Element dom = new ActivityToDomVisitor().toDom(this.action); + document.appendChild(dom); + Transformer transformer = TransformerFactory.newInstance().newTransformer(); StringWriter stringWriter = new StringWriter(); transformer.transform(new DOMSource(document), new StreamResult(stringWriter)); String content = stringWriter.getBuffer().toString(); System.out.println(content); - } - } diff --git a/li.strolch.model/src/test/java/li/strolch/model/activity/ActivityTest.java b/li.strolch.model/src/test/java/li/strolch/model/activity/ActivityTest.java index c0570c0d6..95bf8847d 100644 --- a/li.strolch.model/src/test/java/li/strolch/model/activity/ActivityTest.java +++ b/li.strolch.model/src/test/java/li/strolch/model/activity/ActivityTest.java @@ -13,6 +13,7 @@ import javax.xml.transform.stream.StreamResult; import li.strolch.exception.StrolchException; import li.strolch.model.State; +import li.strolch.model.xml.ActivityToDomVisitor; import org.junit.Assert; import org.junit.Before; @@ -32,111 +33,109 @@ public class ActivityTest { public void init() { // create activity element - activity = new Activity("activity", "Activity", "parentType"); + this.activity = new Activity("activity", "Activity", "parentType"); // create action 1 - action_1 = new Action("action_1", "Action 1", "Use"); - action_1.setState(State.CREATED); - action_1.setResourceType("dummyType"); - action_1.setResourceId("dummyId"); + this.action_1 = new Action("action_1", "Action 1", "Use"); + this.action_1.setState(State.CREATED); + this.action_1.setResourceType("dummyType"); + this.action_1.setResourceId("dummyId"); - activity.addElement(action_1); - - childActivity = new Activity("child_activity", "Child Activity", "childType"); + this.activity.addElement(this.action_1); + + this.childActivity = new Activity("child_activity", "Child Activity", "childType"); // create action 2 - action_2 = new Action("action_2", "Action 2", "Use"); - action_2.setState(State.PLANNED); - action_2.setResourceType("dummyType"); - action_2.setResourceId("dummyId"); + this.action_2 = new Action("action_2", "Action 2", "Use"); + this.action_2.setState(State.PLANNED); + this.action_2.setResourceType("dummyType"); + this.action_2.setResourceId("dummyId"); + + this.childActivity.addElement(this.action_2); - childActivity.addElement(action_2); - // create action 3 - action_3 = new Action("action_3", "Action 3", "Use"); - action_3.setState(State.CREATED); - action_3.setResourceType("dummyType"); - action_3.setResourceId("dummyId"); - - childActivity.addElement(action_3); - - activity.addElement(childActivity); + this.action_3 = new Action("action_3", "Action 3", "Use"); + this.action_3.setState(State.CREATED); + this.action_3.setResourceType("dummyType"); + this.action_3.setResourceId("dummyId"); - Assert.assertEquals(2, activity.getElements().size()); - Assert.assertEquals(2, childActivity.getElements().size()); + this.childActivity.addElement(this.action_3); + + this.activity.addElement(this.childActivity); + + Assert.assertEquals(2, this.activity.getElements().size()); + Assert.assertEquals(2, this.childActivity.getElements().size()); } @Test public void testStart() { - Assert.assertEquals(action_1.getStart(), activity.getStart()); + Assert.assertEquals(this.action_1.getStart(), this.activity.getStart()); } @Test public void testEnd() { - Assert.assertEquals(action_3.getEnd(), activity.getEnd()); + Assert.assertEquals(this.action_3.getEnd(), this.activity.getEnd()); } @Test public void testState() { - Assert.assertEquals(State.CREATED, activity.getState()); + Assert.assertEquals(State.CREATED, this.activity.getState()); } - @Test (expected = StrolchException.class) + @Test(expected = StrolchException.class) public void testIdNull() { - activity.addElement(new Action(null, null, null)); + this.activity.addElement(new Action(null, null, null)); } - - @Test (expected = StrolchException.class) + + @Test(expected = StrolchException.class) public void testIdAlreadyExists() { - activity.addElement(new Action("action_1", "Action 1", "Use")); - } - - @Test - public void getElementTest(){ - Assert.assertNull(activity.getElement("not contained")); - Assert.assertEquals(action_1, activity.getElement(action_1.getId())); + this.activity.addElement(new Action("action_1", "Action 1", "Use")); } @Test - public void cloneTest(){ - Activity clone = (Activity) activity.getClone(); - Assert.assertEquals(activity.toString(), clone.toString()); - Assert.assertEquals(activity.getElements().size(), clone.getElements().size()); + public void getElementTest() { + Assert.assertNull(this.activity.getElement("not contained")); + Assert.assertEquals(this.action_1, this.activity.getElement(this.action_1.getId())); } - + @Test - public void parentTests(){ - Assert.assertNull(activity.getParent()); - Assert.assertEquals(activity, activity.getRootElement()); - Assert.assertTrue(activity.isRootElement()); - - Assert.assertEquals(activity, childActivity.getParent()); - Assert.assertEquals(activity, childActivity.getRootElement()); - Assert.assertFalse(childActivity.isRootElement()); - - Assert.assertEquals(childActivity, action_2.getParent()); - Assert.assertEquals(activity, action_2.getRootElement()); - Assert.assertFalse(action_2.isRootElement()); + public void cloneTest() { + Activity clone = (Activity) this.activity.getClone(); + Assert.assertEquals(this.activity.toString(), clone.toString()); + Assert.assertEquals(this.activity.getElements().size(), clone.getElements().size()); } - + + @Test + public void parentTests() { + Assert.assertNull(this.activity.getParent()); + Assert.assertEquals(this.activity, this.activity.getRootElement()); + Assert.assertTrue(this.activity.isRootElement()); + + Assert.assertEquals(this.activity, this.childActivity.getParent()); + Assert.assertEquals(this.activity, this.childActivity.getRootElement()); + Assert.assertFalse(this.childActivity.isRootElement()); + + Assert.assertEquals(this.childActivity, this.action_2.getParent()); + Assert.assertEquals(this.activity, this.action_2.getRootElement()); + Assert.assertFalse(this.action_2.isRootElement()); + } + /** * no test. Just to see the XML serialization in the console */ // @Test public void testToDOM() throws ParserConfigurationException, TransformerException { - + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - DocumentBuilder db = dbf.newDocumentBuilder(); - Document document = db.newDocument(); - Element dom = activity.toDom(document); - document.appendChild(dom); - + DocumentBuilder db = dbf.newDocumentBuilder(); + Document document = db.newDocument(); + Element dom = new ActivityToDomVisitor().toDom(this.activity); + document.appendChild(dom); + Transformer transformer = TransformerFactory.newInstance().newTransformer(); StringWriter writer = new StringWriter(); transformer.transform(new DOMSource(document), new StreamResult(writer)); String content = writer.getBuffer().toString(); System.out.println(content); - } - } diff --git a/li.strolch.model/src/test/resources/data/StrolchModel.xml b/li.strolch.model/src/test/resources/data/StrolchModel.xml index 818cccb2d..6016993e0 100644 --- a/li.strolch.model/src/test/resources/data/StrolchModel.xml +++ b/li.strolch.model/src/test/resources/data/StrolchModel.xml @@ -14,5 +14,6 @@ + \ No newline at end of file diff --git a/li.strolch.model/src/test/resources/data/activities/Activities.xml b/li.strolch.model/src/test/resources/data/activities/Activities.xml new file mode 100644 index 000000000..3efad9741 --- /dev/null +++ b/li.strolch.model/src/test/resources/data/activities/Activities.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/li.strolch.model/src/test/java/li/strolch/model/activity/action.xml b/li.strolch.model/src/test/resources/data/activities/action.xml similarity index 100% rename from li.strolch.model/src/test/java/li/strolch/model/activity/action.xml rename to li.strolch.model/src/test/resources/data/activities/action.xml diff --git a/li.strolch.model/src/test/java/li/strolch/model/activity/activity.xml b/li.strolch.model/src/test/resources/data/activities/activity.xml similarity index 100% rename from li.strolch.model/src/test/java/li/strolch/model/activity/activity.xml rename to li.strolch.model/src/test/resources/data/activities/activity.xml diff --git a/li.strolch.model/src/test/resources/data/resources/Resources.xml b/li.strolch.model/src/test/resources/data/resources/Resources.xml index fcbb0f7d2..a9efa557b 100644 --- a/li.strolch.model/src/test/resources/data/resources/Resources.xml +++ b/li.strolch.model/src/test/resources/data/resources/Resources.xml @@ -14,12 +14,12 @@ - + - + @@ -27,7 +27,7 @@ - + @@ -35,7 +35,7 @@ - + diff --git a/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlActivityDao.java b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlActivityDao.java new file mode 100644 index 000000000..000306ea0 --- /dev/null +++ b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlActivityDao.java @@ -0,0 +1,179 @@ +/* + * 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.persistence.postgresql; + +import java.io.IOException; +import java.io.InputStream; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.SQLXML; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.sax.SAXResult; + +import li.strolch.model.ActivityVisitor; +import li.strolch.model.Tags; +import li.strolch.model.activity.Activity; +import li.strolch.model.query.ActivityQuery; +import li.strolch.model.xml.ActivityToSaxVisitor; +import li.strolch.model.xml.SimpleStrolchElementListener; +import li.strolch.model.xml.XmlModelSaxReader; +import li.strolch.persistence.api.ActivityDao; +import li.strolch.persistence.api.StrolchPersistenceException; + +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; + +@SuppressWarnings("nls") +public class PostgreSqlActivityDao extends PostgresqlDao implements ActivityDao { + + public static final String ACTIVITIES = "activities"; + + protected PostgreSqlActivityDao(PostgreSqlStrolchTransaction tx) { + super(tx); + } + + @Override + protected String getClassName() { + return Tags.ACTIVITY; + } + + @Override + protected String getTableName() { + return ACTIVITIES; + } + + @Override + protected Activity parseFromXml(String id, String type, SQLXML sqlxml) { + SimpleStrolchElementListener listener = new SimpleStrolchElementListener(); + try (InputStream binaryStream = sqlxml.getBinaryStream()) { + SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); + parser.parse(binaryStream, new XmlModelSaxReader(listener)); + } catch (SQLException | IOException | SAXException | ParserConfigurationException e) { + throw new StrolchPersistenceException(MessageFormat.format( + "Failed to extract Activity from sqlxml value for {0} / {1}", id, type), e); + } + + if (listener.getActivities().size() == 0) + throw new StrolchPersistenceException(MessageFormat.format( + "No Activity parsed from sqlxml value for {0} / {1}", id, type)); + if (listener.getActivities().size() > 1) + throw new StrolchPersistenceException(MessageFormat.format( + "Multiple Activities parsed from sqlxml value for {0} / {1}", id, type)); + + return listener.getActivities().get(0); + } + + protected SQLXML createSqlXml(Activity activity, PreparedStatement preparedStatement) throws SQLException, + SAXException { + SQLXML sqlxml = tx().getConnection().createSQLXML(); + SAXResult saxResult = sqlxml.setResult(SAXResult.class); + ContentHandler contentHandler = saxResult.getHandler(); + contentHandler.startDocument(); + new ActivityToSaxVisitor(contentHandler).visit(activity); + contentHandler.endDocument(); + return sqlxml; + } + + @Override + protected void internalSave(final Activity activity) { + String sql = "insert into " + getTableName() + " (id, name, type, asxml) values (?, ?, ?, ?)"; + try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) { + preparedStatement.setString(1, activity.getId()); + preparedStatement.setString(2, activity.getName()); + preparedStatement.setString(3, activity.getType()); + + SQLXML sqlxml = createSqlXml(activity, preparedStatement); + preparedStatement.setSQLXML(4, sqlxml); + try { + int modCount = preparedStatement.executeUpdate(); + if (modCount != 1) { + String msg = "Expected to save 1 element with id {0} but SQL statement modified {1} elements!"; + msg = MessageFormat.format(msg, activity.getId(), modCount); + throw new StrolchPersistenceException(msg); + } + } finally { + sqlxml.free(); + } + + } catch (SQLException | SAXException e) { + throw new StrolchPersistenceException(MessageFormat.format("Failed to insert Activity {0} due to {1}", + activity.getLocator(), e.getLocalizedMessage()), e); + } + } + + @Override + protected void internalUpdate(final Activity activity) { + String sql = "update " + getTableName() + " set name = ?, type = ?, asxml = ? where id = ? "; + try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) { + + preparedStatement.setString(1, activity.getName()); + preparedStatement.setString(2, activity.getType()); + preparedStatement.setString(4, activity.getId()); + + SQLXML sqlxml = createSqlXml(activity, preparedStatement); + preparedStatement.setSQLXML(3, sqlxml); + try { + int modCount = preparedStatement.executeUpdate(); + if (modCount != 1) { + String msg = "Expected to update 1 element with id {0} but SQL statement modified {1} elements!"; + msg = MessageFormat.format(msg, activity.getId(), modCount); + throw new StrolchPersistenceException(msg); + } + } finally { + sqlxml.free(); + } + + } catch (SQLException | SAXException e) { + throw new StrolchPersistenceException(MessageFormat.format("Failed to update Activity {0} due to {1}", + activity.getLocator(), e.getLocalizedMessage()), e); + } + } + + @Override + public List doQuery(ActivityQuery query, ActivityVisitor activityVisitor) { + + PostgreSqlActivityQueryVisitor queryVisitor = new PostgreSqlActivityQueryVisitor("id, asxml"); + query.accept(queryVisitor); + queryVisitor.validate(); + + List list = new ArrayList<>(); + + String sql = queryVisitor.getSql(); + try (PreparedStatement ps = tx().getConnection().prepareStatement(sql)) { + queryVisitor.setValues(ps); + + try (ResultSet result = ps.executeQuery()) { + while (result.next()) { + String id = result.getString("id"); + SQLXML sqlxml = result.getSQLXML("asxml"); + Activity t = parseFromXml(id, queryVisitor.getType(), sqlxml); + list.add(activityVisitor.visit(t)); + } + } + } catch (SQLException e) { + throw new StrolchPersistenceException("Failed to perform query due to: " + e.getMessage(), e); + } + + return list; + } +} diff --git a/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlActivityQueryVisitor.java b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlActivityQueryVisitor.java new file mode 100644 index 000000000..ecee7b37d --- /dev/null +++ b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlActivityQueryVisitor.java @@ -0,0 +1,42 @@ +/* + * 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.persistence.postgresql; + +import li.strolch.model.Tags; +import li.strolch.model.query.ActivityQueryVisitor; + +/** + * @author Robert von Burg + */ +public class PostgreSqlActivityQueryVisitor extends PostgreSqlQueryVisitor implements ActivityQueryVisitor { + + /** + * @param fields + */ + public PostgreSqlActivityQueryVisitor(String fields) { + super(fields); + } + + @Override + protected String getClassName() { + return Tags.ACTIVITY; + } + + @Override + protected String getTableName() { + return PostgreSqlActivityDao.ACTIVITIES; + } +} diff --git a/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlOrderDao.java b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlOrderDao.java index 8f9bf42c7..1f8c3770b 100644 --- a/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlOrderDao.java +++ b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlOrderDao.java @@ -50,9 +50,6 @@ public class PostgreSqlOrderDao extends PostgresqlDao implements OrderDao public static final String ORDERS = "orders"; - /** - * @param tx - */ public PostgreSqlOrderDao(PostgreSqlStrolchTransaction tx) { super(tx); } @@ -89,7 +86,7 @@ public class PostgreSqlOrderDao extends PostgresqlDao implements OrderDao } protected SQLXML createSqlXml(Order order, PreparedStatement preparedStatement) throws SQLException, SAXException { - SQLXML sqlxml = this.tx.getConnection().createSQLXML(); + SQLXML sqlxml = tx().getConnection().createSQLXML(); SAXResult saxResult = sqlxml.setResult(SAXResult.class); ContentHandler contentHandler = saxResult.getHandler(); contentHandler.startDocument(); @@ -102,7 +99,7 @@ public class PostgreSqlOrderDao extends PostgresqlDao implements OrderDao protected void internalSave(final Order order) { String sql = "insert into " + getTableName() + " (id, name, type, state, date, asxml) values (?, ?, ?, ?::order_state, ?, ?)"; - try (PreparedStatement preparedStatement = PostgreSqlOrderDao.this.tx.getConnection().prepareStatement(sql)) { + try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) { preparedStatement.setString(1, order.getId()); preparedStatement.setString(2, order.getName()); preparedStatement.setString(3, order.getType()); @@ -132,7 +129,7 @@ public class PostgreSqlOrderDao extends PostgresqlDao implements OrderDao protected void internalUpdate(final Order order) { String sql = "update " + getTableName() + " set name = ?, type = ?, state = ?::order_state, date = ?, asxml = ? where id = ? "; - try (PreparedStatement preparedStatement = PostgreSqlOrderDao.this.tx.getConnection().prepareStatement(sql)) { + try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) { preparedStatement.setString(1, order.getName()); preparedStatement.setString(2, order.getType()); @@ -169,7 +166,7 @@ public class PostgreSqlOrderDao extends PostgresqlDao implements OrderDao List list = new ArrayList<>(); String sql = queryVisitor.getSql(); - try (PreparedStatement ps = PostgreSqlOrderDao.this.tx.getConnection().prepareStatement(sql)) { + try (PreparedStatement ps = tx().getConnection().prepareStatement(sql)) { queryVisitor.setValues(ps); try (ResultSet result = ps.executeQuery()) { diff --git a/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlPersistenceHandler.java b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlPersistenceHandler.java index 30d8ac8bc..157725484 100644 --- a/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlPersistenceHandler.java +++ b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlPersistenceHandler.java @@ -33,6 +33,7 @@ import li.strolch.agent.api.RealmHandler; import li.strolch.agent.api.StrolchAgent; import li.strolch.agent.api.StrolchComponent; import li.strolch.agent.api.StrolchRealm; +import li.strolch.persistence.api.ActivityDao; import li.strolch.persistence.api.AuditDao; import li.strolch.persistence.api.OrderDao; import li.strolch.persistence.api.PersistenceHandler; @@ -155,6 +156,11 @@ public class PostgreSqlPersistenceHandler extends StrolchComponent implements Pe return ((PostgreSqlStrolchTransaction) tx).getResourceDao(); } + @Override + public ActivityDao getActivityDao(StrolchTransaction tx) { + return ((PostgreSqlStrolchTransaction) tx).getActivityDao(); + } + @Override public AuditDao getAuditDao(StrolchTransaction tx) { return ((PostgreSqlStrolchTransaction) tx).getAuditDao(); diff --git a/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlResourceDao.java b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlResourceDao.java index 68268ef79..3a5c779ff 100644 --- a/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlResourceDao.java +++ b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlResourceDao.java @@ -84,7 +84,7 @@ public class PostgreSqlResourceDao extends PostgresqlDao implements Re } protected SQLXML createSqlXml(Resource res, PreparedStatement preparedStatement) throws SQLException, SAXException { - SQLXML sqlxml = this.tx.getConnection().createSQLXML(); + SQLXML sqlxml = tx().getConnection().createSQLXML(); SAXResult saxResult = sqlxml.setResult(SAXResult.class); ContentHandler contentHandler = saxResult.getHandler(); contentHandler.startDocument(); @@ -96,7 +96,7 @@ public class PostgreSqlResourceDao extends PostgresqlDao implements Re @Override protected void internalSave(final Resource res) { String sql = "insert into " + getTableName() + " (id, name, type, asxml) values (?, ?, ?, ?)"; - try (PreparedStatement preparedStatement = PostgreSqlResourceDao.this.tx.getConnection().prepareStatement(sql)) { + try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) { preparedStatement.setString(1, res.getId()); preparedStatement.setString(2, res.getName()); preparedStatement.setString(3, res.getType()); @@ -123,7 +123,7 @@ public class PostgreSqlResourceDao extends PostgresqlDao implements Re @Override protected void internalUpdate(final Resource resource) { String sql = "update " + getTableName() + " set name = ?, type = ?, asxml = ? where id = ? "; - try (PreparedStatement preparedStatement = PostgreSqlResourceDao.this.tx.getConnection().prepareStatement(sql)) { + try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) { preparedStatement.setString(1, resource.getName()); preparedStatement.setString(2, resource.getType()); @@ -158,7 +158,7 @@ public class PostgreSqlResourceDao extends PostgresqlDao implements Re List list = new ArrayList<>(); String sql = queryVisitor.getSql(); - try (PreparedStatement ps = PostgreSqlResourceDao.this.tx.getConnection().prepareStatement(sql)) { + try (PreparedStatement ps = tx().getConnection().prepareStatement(sql)) { queryVisitor.setValues(ps); try (ResultSet result = ps.executeQuery()) { diff --git a/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlStrolchTransaction.java b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlStrolchTransaction.java index 9fa65c181..059af7039 100644 --- a/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlStrolchTransaction.java +++ b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlStrolchTransaction.java @@ -19,6 +19,7 @@ import java.sql.Connection; import li.strolch.agent.api.StrolchRealm; import li.strolch.persistence.api.AbstractTransaction; +import li.strolch.persistence.api.ActivityDao; import li.strolch.persistence.api.AuditDao; import li.strolch.persistence.api.OrderDao; import li.strolch.persistence.api.PersistenceHandler; @@ -36,8 +37,9 @@ public class PostgreSqlStrolchTransaction extends AbstractTransaction { private static final Logger logger = LoggerFactory.getLogger(PostgreSqlStrolchTransaction.class); private PostgreSqlPersistenceHandler persistenceHandler; - private PostgresqlDao orderDao; - private PostgresqlDao resourceDao; + private PostgreSqlOrderDao orderDao; + private PostgreSqlResourceDao resourceDao; + private PostgreSqlActivityDao activityDao; private AuditDao auditDao; private Connection connection; @@ -94,9 +96,12 @@ public class PostgreSqlStrolchTransaction extends AbstractTransaction { return (ResourceDao) this.resourceDao; } - /** - * @return - */ + ActivityDao getActivityDao() { + if (this.activityDao == null) + this.activityDao = new PostgreSqlActivityDao(this); + return (ActivityDao) this.activityDao; + } + public AuditDao getAuditDao() { if (this.auditDao == null) this.auditDao = new PostgreSqlAuditDao(this); @@ -114,5 +119,4 @@ public class PostgreSqlStrolchTransaction extends AbstractTransaction { public PersistenceHandler getPersistenceHandler() { return this.persistenceHandler; } - } diff --git a/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgresqlDao.java b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgresqlDao.java index e033ba9a4..344beb203 100644 --- a/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgresqlDao.java +++ b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgresqlDao.java @@ -41,6 +41,10 @@ public abstract class PostgresqlDao implements Strolch this.commands = new ArrayList<>(); } + protected PostgreSqlStrolchTransaction tx() { + return this.tx; + } + protected abstract String getClassName(); protected abstract String getTableName(); @@ -50,7 +54,7 @@ public abstract class PostgresqlDao implements Strolch @Override public boolean hasElement(String type, String id) { String sql = "select count(*) from " + getTableName() + " where type = ? and id = ?"; - try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) { + try (PreparedStatement statement = tx().getConnection().prepareStatement(sql)) { statement.setString(1, type); statement.setString(2, id); try (ResultSet result = statement.executeQuery()) { @@ -72,7 +76,7 @@ public abstract class PostgresqlDao implements Strolch @Override public long querySize() { String sql = "select count(*) from " + getTableName(); - try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) { + try (PreparedStatement statement = tx().getConnection().prepareStatement(sql)) { try (ResultSet result = statement.executeQuery()) { result.next(); return result.getLong(1); @@ -85,7 +89,7 @@ public abstract class PostgresqlDao implements Strolch @Override public long querySize(String type) { String sql = "select count(*) from " + getTableName() + " where type = ?"; - try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) { + try (PreparedStatement statement = tx().getConnection().prepareStatement(sql)) { statement.setString(1, type); try (ResultSet result = statement.executeQuery()) { result.next(); @@ -102,7 +106,7 @@ public abstract class PostgresqlDao implements Strolch Set keySet = new HashSet<>(); String sql = "select id from " + getTableName(); - try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) { + try (PreparedStatement statement = tx().getConnection().prepareStatement(sql)) { try (ResultSet result = statement.executeQuery()) { while (result.next()) { keySet.add(result.getString("id")); @@ -120,7 +124,7 @@ public abstract class PostgresqlDao implements Strolch Set keySet = new HashSet<>(); String sql = "select id from " + getTableName() + " where type = ?"; - try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) { + try (PreparedStatement statement = tx().getConnection().prepareStatement(sql)) { statement.setString(1, type); try (ResultSet result = statement.executeQuery()) { while (result.next()) { @@ -139,7 +143,7 @@ public abstract class PostgresqlDao implements Strolch Set keySet = new HashSet<>(); String sql = "select distinct type from " + getTableName(); - try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) { + try (PreparedStatement statement = tx().getConnection().prepareStatement(sql)) { try (ResultSet result = statement.executeQuery()) { while (result.next()) { keySet.add(result.getString("type")); @@ -156,7 +160,7 @@ public abstract class PostgresqlDao implements Strolch public T queryBy(String type, String id) { String sql = "select id, name, type, asxml from " + getTableName() + " where id = ? and type = ?"; - try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) { + try (PreparedStatement statement = tx().getConnection().prepareStatement(sql)) { statement.setString(1, id); statement.setString(2, type); try (ResultSet result = statement.executeQuery()) { @@ -180,7 +184,7 @@ public abstract class PostgresqlDao implements Strolch List list = new ArrayList<>(); String sql = "select id, name, type, asxml from " + getTableName(); - try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) { + try (PreparedStatement statement = tx().getConnection().prepareStatement(sql)) { try (ResultSet result = statement.executeQuery()) { while (result.next()) { String id = result.getString("id"); @@ -202,7 +206,7 @@ public abstract class PostgresqlDao implements Strolch List list = new ArrayList<>(); String sql = "select id, name, type, asxml from " + getTableName() + " where type = ?"; - try (PreparedStatement statement = this.tx.getConnection().prepareStatement(sql)) { + try (PreparedStatement statement = tx().getConnection().prepareStatement(sql)) { statement.setString(1, type); try (ResultSet result = statement.executeQuery()) { while (result.next()) { @@ -335,7 +339,7 @@ public abstract class PostgresqlDao implements Strolch protected void internalRemove(final T element) { String sql = "delete from " + getTableName() + " where id = ?"; - try (PreparedStatement preparedStatement = this.tx.getConnection().prepareStatement(sql)) { + try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) { preparedStatement.setString(1, element.getId()); int modCount = preparedStatement.executeUpdate(); @@ -353,7 +357,7 @@ public abstract class PostgresqlDao implements Strolch protected void internalRemoveAll(final long toRemove) { String sql = "delete from " + getTableName(); - try (PreparedStatement preparedStatement = this.tx.getConnection().prepareStatement(sql)) { + try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) { int modCount = preparedStatement.executeUpdate(); if (modCount != toRemove) { String msg = "Expected to delete {0} elements but SQL statement removed {1} elements!"; @@ -369,7 +373,7 @@ public abstract class PostgresqlDao implements Strolch protected void internalRemoveAllBy(final long toRemove, String type) { String sql = "delete from " + getTableName() + " where type = ?"; - try (PreparedStatement preparedStatement = this.tx.getConnection().prepareStatement(sql)) { + try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) { preparedStatement.setString(1, type); int modCount = preparedStatement.executeUpdate(); if (modCount != toRemove) { diff --git a/li.strolch.persistence.postgresql/src/main/resources/strolch_db_schema_0.4.0_drop.sql b/li.strolch.persistence.postgresql/src/main/resources/strolch_db_schema_0.4.0_drop.sql new file mode 100644 index 000000000..0ff96e495 --- /dev/null +++ b/li.strolch.persistence.postgresql/src/main/resources/strolch_db_schema_0.4.0_drop.sql @@ -0,0 +1,11 @@ + +DROP TABLE IF EXISTS resources; +DROP TABLE IF EXISTS orders; +DROP TABLE IF EXISTS activities; + +DROP TABLE IF EXISTS audits; + +DROP TABLE IF EXISTS db_version; + +DROP TYPE IF EXISTS order_state; +DROP TYPE IF EXISTS access_type; diff --git a/li.strolch.persistence.postgresql/src/main/resources/strolch_db_schema_0.4.0_initial.sql b/li.strolch.persistence.postgresql/src/main/resources/strolch_db_schema_0.4.0_initial.sql new file mode 100644 index 000000000..2e0efce1b --- /dev/null +++ b/li.strolch.persistence.postgresql/src/main/resources/strolch_db_schema_0.4.0_initial.sql @@ -0,0 +1,101 @@ + +-- DB_VERSION +CREATE TABLE IF NOT EXISTS db_version ( + id SERIAL PRIMARY KEY, + app varchar(255), + version varchar(255), + description varchar(255), + created timestamp with time zone +); + +-- RESOURCES +CREATE TABLE IF NOT EXISTS resources ( + id varchar(255) PRIMARY KEY, + name VARCHAR(255), + type VARCHAR(255), + asxml xml +); + +-- ORDERS +CREATE TYPE order_state AS ENUM ('CREATED', 'OPEN', 'EXECUTION', 'CLOSED'); + +CREATE TABLE IF NOT EXISTS orders ( + id varchar(255) PRIMARY KEY, + name VARCHAR(255), + type VARCHAR(255), + state order_state, + date timestamp with time zone, + asxml xml +); + +-- ACTIVITIES +CREATE TABLE IF NOT EXISTS activities ( + id varchar(255) PRIMARY KEY, + name VARCHAR(255), + type VARCHAR(255), + asxml xml +); + +-- AUDITS +CREATE TYPE access_type AS ENUM ('READ', 'CREATE', 'UPDATE', 'DELETE'); +CREATE TABLE IF NOT EXISTS audits ( + id bigint PRIMARY KEY, + username VARCHAR(255) NOT NULL, + firstname VARCHAR(255) NOT NULL, + lastname VARCHAR(255) NOT NULL, + date timestamp with time zone NOT NULL, + + element_type VARCHAR(255) NOT NULL, + element_sub_type VARCHAR(255) NOT NULL, + element_accessed VARCHAR(255) NOT NULL, + new_version timestamp with time zone, + + action VARCHAR(255) NOT NULL, + access_type access_type NOT NULL +); + +-- set version +INSERT INTO db_version + (version, app, description, created) +values( + '0.1.0', + 'strolch', + 'Initial schema version', + CURRENT_TIMESTAMP +); + +INSERT INTO db_version + (version, app, description, created) +values( + '0.2.0', + 'strolch', + 'Added new table for audits', + CURRENT_TIMESTAMP +); + +INSERT INTO db_version + (version, app, description, created) +values( + '0.2.1', + 'strolch', + 'Added new column app to table table version', + CURRENT_TIMESTAMP +); + +INSERT INTO db_version + (version, app, description, created) +values( + '0.3.0', + 'strolch', + 'Added new column element_sub_type to table audits', + CURRENT_TIMESTAMP +); + +INSERT INTO db_version + (version, app, description, created) +values( + '0.4.0', + 'strolch', + 'Added new table activities', + CURRENT_TIMESTAMP +); diff --git a/li.strolch.persistence.postgresql/src/main/resources/strolch_db_schema_0.4.0_migration.sql b/li.strolch.persistence.postgresql/src/main/resources/strolch_db_schema_0.4.0_migration.sql new file mode 100644 index 000000000..3fd7d6801 --- /dev/null +++ b/li.strolch.persistence.postgresql/src/main/resources/strolch_db_schema_0.4.0_migration.sql @@ -0,0 +1,17 @@ + +-- ACTIVITIES +CREATE TABLE IF NOT EXISTS activities ( + id varchar(255) PRIMARY KEY, + name VARCHAR(255), + type VARCHAR(255), + asxml xml +); + +INSERT INTO db_version + (version, app, description, created) +values( + '0.4.0', + 'strolch', + 'Added new table activities', + CURRENT_TIMESTAMP +); diff --git a/li.strolch.persistence.postgresql/src/main/resources/strolch_db_version.properties b/li.strolch.persistence.postgresql/src/main/resources/strolch_db_version.properties index f2218709d..2560e0113 100644 --- a/li.strolch.persistence.postgresql/src/main/resources/strolch_db_version.properties +++ b/li.strolch.persistence.postgresql/src/main/resources/strolch_db_version.properties @@ -1,2 +1,2 @@ # Property file defining what the currently expected version is supposed to be -db_version=0.3.0 \ No newline at end of file +db_version=0.4.0 diff --git a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/XmlActivityDao.java b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/XmlActivityDao.java new file mode 100644 index 000000000..80a800652 --- /dev/null +++ b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/XmlActivityDao.java @@ -0,0 +1,43 @@ +/* + * Copyright 2013 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.persistence.xml; + +import java.util.List; + +import li.strolch.model.ActivityVisitor; +import li.strolch.model.Tags; +import li.strolch.model.activity.Activity; +import li.strolch.model.query.ActivityQuery; +import li.strolch.persistence.api.ActivityDao; +import li.strolch.persistence.api.StrolchTransaction; + +public class XmlActivityDao extends AbstractDao implements ActivityDao { + + protected XmlActivityDao(StrolchTransaction tx) { + super(tx); + } + + @Override + protected String getClassType() { + return Tags.ACTIVITY; + } + + @Override + public List doQuery(ActivityQuery query, ActivityVisitor activityVisitor) { + // TODO implement XML file based querying... + throw new UnsupportedOperationException("not yet implemented!"); + } +} diff --git a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/XmlPersistenceHandler.java b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/XmlPersistenceHandler.java index 95c7c2aa3..9cfb4d19e 100644 --- a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/XmlPersistenceHandler.java +++ b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/XmlPersistenceHandler.java @@ -25,6 +25,7 @@ import li.strolch.model.Order; import li.strolch.model.Resource; import li.strolch.model.Tags; import li.strolch.model.audit.Audit; +import li.strolch.persistence.api.ActivityDao; import li.strolch.persistence.api.AuditDao; import li.strolch.persistence.api.OrderDao; import li.strolch.persistence.api.PersistenceHandler; @@ -92,6 +93,11 @@ public class XmlPersistenceHandler extends StrolchComponent implements Persisten public ResourceDao getResourceDao(StrolchTransaction tx) { return new XmlResourceDao(tx); } + + @Override + public ActivityDao getActivityDao(StrolchTransaction tx) { + return new XmlActivityDao(tx); + } @Override public AuditDao getAuditDao(StrolchTransaction tx) { diff --git a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/ActivityContextFactory.java b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/ActivityContextFactory.java new file mode 100644 index 000000000..4b0a90b5a --- /dev/null +++ b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/ActivityContextFactory.java @@ -0,0 +1,42 @@ +/* + * Copyright 2013 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.persistence.xml.model; + +import li.strolch.model.Tags; +import li.strolch.model.activity.Activity; +import ch.eitchnet.xmlpers.api.PersistenceContext; +import ch.eitchnet.xmlpers.api.PersistenceContextFactory; +import ch.eitchnet.xmlpers.objref.IdOfSubTypeRef; +import ch.eitchnet.xmlpers.objref.ObjectRef; +import ch.eitchnet.xmlpers.objref.ObjectReferenceCache; + +public class ActivityContextFactory implements PersistenceContextFactory { + + @Override + public PersistenceContext createCtx(ObjectRef objectRef) { + PersistenceContext ctx = new PersistenceContext<>(objectRef); + ctx.setParserFactory(new ActivityParserFactory()); + return ctx; + } + + @Override + public PersistenceContext createCtx(ObjectReferenceCache objectRefCache, Activity t) { + IdOfSubTypeRef objectRef = objectRefCache.getIdOfSubTypeRef(Tags.ACTIVITY, t.getType(), t.getId()); + PersistenceContext ctx = createCtx(objectRef); + ctx.setObject(t); + return ctx; + } +} diff --git a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/ActivityDomParser.java b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/ActivityDomParser.java new file mode 100644 index 000000000..79105de0d --- /dev/null +++ b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/ActivityDomParser.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013 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.persistence.xml.model; + +import li.strolch.model.activity.Activity; +import li.strolch.model.xml.ActivityFromDomVisitor; +import li.strolch.model.xml.ActivityToDomVisitor; + +import org.w3c.dom.Document; + +import ch.eitchnet.xmlpers.api.DomParser; + +public class ActivityDomParser implements DomParser { + + private Activity activity; + + @Override + public Activity getObject() { + return this.activity; + } + + @Override + public void setObject(Activity activity) { + this.activity = activity; + } + + @Override + public Document toDom() { + ActivityToDomVisitor activityDomVisitor = new ActivityToDomVisitor(); + activityDomVisitor.visit(this.activity); + return activityDomVisitor.getDocument(); + } + + @Override + public void fromDom(Document document) { + Activity activity = new ActivityFromDomVisitor().visit(document); + this.activity = activity; + } +} diff --git a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/ActivityParserFactory.java b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/ActivityParserFactory.java new file mode 100644 index 000000000..40707611e --- /dev/null +++ b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/ActivityParserFactory.java @@ -0,0 +1,34 @@ +/* + * Copyright 2013 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.persistence.xml.model; + +import li.strolch.model.activity.Activity; +import ch.eitchnet.xmlpers.api.DomParser; +import ch.eitchnet.xmlpers.api.ParserFactory; +import ch.eitchnet.xmlpers.api.SaxParser; + +public class ActivityParserFactory implements ParserFactory { + + @Override + public DomParser getDomParser() { + return new ActivityDomParser(); + } + + @Override + public SaxParser getSaxParser() { + return new ActivitySaxParser(); + } +} diff --git a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/ActivitySaxParser.java b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/ActivitySaxParser.java new file mode 100644 index 000000000..0833017d5 --- /dev/null +++ b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/ActivitySaxParser.java @@ -0,0 +1,74 @@ +/* + * 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.persistence.xml.model; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; + +import li.strolch.model.Order; +import li.strolch.model.Resource; +import li.strolch.model.activity.Activity; +import li.strolch.model.xml.ActivityToSaxWriterVisitor; +import li.strolch.model.xml.StrolchElementListener; +import li.strolch.model.xml.XmlModelSaxReader; + +import org.xml.sax.helpers.DefaultHandler; + +import ch.eitchnet.xmlpers.api.SaxParser; + +/** + * @author Robert von Burg + */ +public class ActivitySaxParser implements SaxParser { + + protected Activity activity; + + @Override + public Activity getObject() { + return this.activity; + } + + @Override + public void setObject(Activity activity) { + this.activity = activity; + } + + @Override + public DefaultHandler getDefaultHandler() { + return new XmlModelSaxReader(new StrolchElementListener() { + + @Override + public void notifyResource(Resource resource) { + throw new IllegalArgumentException("Only expect Activities!"); + } + + @Override + public void notifyOrder(Order order) { + throw new IllegalArgumentException("Only expect Activities!"); + } + + @Override + public void notifyActivity(Activity activity) { + ActivitySaxParser.this.activity = activity; + } + }); + } + + @Override + public void write(XMLStreamWriter xmlWriter) throws XMLStreamException { + new ActivityToSaxWriterVisitor(xmlWriter); + } +} diff --git a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/OrderDomParser.java b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/OrderDomParser.java index 5abfece4a..8e0698a75 100644 --- a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/OrderDomParser.java +++ b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/OrderDomParser.java @@ -16,10 +16,10 @@ package li.strolch.persistence.xml.model; import li.strolch.model.Order; +import li.strolch.model.xml.OrderFromDomVisitor; import li.strolch.model.xml.OrderToDomVisitor; import org.w3c.dom.Document; -import org.w3c.dom.Element; import ch.eitchnet.xmlpers.api.DomParser; @@ -46,8 +46,7 @@ public class OrderDomParser implements DomParser { @Override public void fromDom(Document document) { - Element rootElement = document.getDocumentElement(); - Order order = new Order(rootElement); + Order order = new OrderFromDomVisitor().visit(document); this.order = order; } } diff --git a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/OrderParserFactory.java b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/OrderParserFactory.java index e7e38543c..f7fc92c66 100644 --- a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/OrderParserFactory.java +++ b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/OrderParserFactory.java @@ -29,6 +29,6 @@ public class OrderParserFactory implements ParserFactory { @Override public SaxParser getSaxParser() { - throw new UnsupportedOperationException("Not yet implemented!"); //$NON-NLS-1$ + return new OrderSaxParser(); } } diff --git a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/OrderSaxParser.java b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/OrderSaxParser.java new file mode 100644 index 000000000..f0f923801 --- /dev/null +++ b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/OrderSaxParser.java @@ -0,0 +1,74 @@ +/* + * 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.persistence.xml.model; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; + +import li.strolch.model.Order; +import li.strolch.model.Resource; +import li.strolch.model.activity.Activity; +import li.strolch.model.xml.OrderToSaxWriterVisitor; +import li.strolch.model.xml.StrolchElementListener; +import li.strolch.model.xml.XmlModelSaxReader; + +import org.xml.sax.helpers.DefaultHandler; + +import ch.eitchnet.xmlpers.api.SaxParser; + +/** + * @author Robert von Burg + */ +public class OrderSaxParser implements SaxParser { + + protected Order order; + + @Override + public Order getObject() { + return this.order; + } + + @Override + public void setObject(Order order) { + this.order = order; + } + + @Override + public DefaultHandler getDefaultHandler() { + return new XmlModelSaxReader(new StrolchElementListener() { + + @Override + public void notifyResource(Resource resource) { + throw new IllegalArgumentException("Only expect Orders!"); + } + + @Override + public void notifyOrder(Order order) { + OrderSaxParser.this.order = order; + } + + @Override + public void notifyActivity(Activity activity) { + throw new IllegalArgumentException("Only expect Orders!"); + } + }); + } + + @Override + public void write(XMLStreamWriter xmlWriter) throws XMLStreamException { + new OrderToSaxWriterVisitor(xmlWriter); + } +} diff --git a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/ResourceDomParser.java b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/ResourceDomParser.java index 4853df885..b79c423fe 100644 --- a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/ResourceDomParser.java +++ b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/ResourceDomParser.java @@ -16,10 +16,10 @@ package li.strolch.persistence.xml.model; import li.strolch.model.Resource; +import li.strolch.model.xml.ResourceFromDomVisitor; import li.strolch.model.xml.ResourceToDomVisitor; import org.w3c.dom.Document; -import org.w3c.dom.Element; import ch.eitchnet.xmlpers.api.DomParser; @@ -46,8 +46,7 @@ public class ResourceDomParser implements DomParser { @Override public void fromDom(Document document) { - Element rootElement = document.getDocumentElement(); - Resource resource = new Resource(rootElement); + Resource resource = new ResourceFromDomVisitor().visit(document); this.resource = resource; } } \ No newline at end of file diff --git a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/ResourceParserFactory.java b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/ResourceParserFactory.java index 197c6903e..a938584d6 100644 --- a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/ResourceParserFactory.java +++ b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/ResourceParserFactory.java @@ -29,6 +29,6 @@ public class ResourceParserFactory implements ParserFactory { @Override public SaxParser getSaxParser() { - throw new UnsupportedOperationException("Not yet implemented!"); //$NON-NLS-1$ + return new ResourceSaxParser(); } } \ No newline at end of file diff --git a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/ResourceSaxParser.java b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/ResourceSaxParser.java new file mode 100644 index 000000000..9755e6004 --- /dev/null +++ b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/model/ResourceSaxParser.java @@ -0,0 +1,74 @@ +/* + * 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.persistence.xml.model; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; + +import li.strolch.model.Order; +import li.strolch.model.Resource; +import li.strolch.model.activity.Activity; +import li.strolch.model.xml.ResourceToSaxWriterVisitor; +import li.strolch.model.xml.StrolchElementListener; +import li.strolch.model.xml.XmlModelSaxReader; + +import org.xml.sax.helpers.DefaultHandler; + +import ch.eitchnet.xmlpers.api.SaxParser; + +/** + * @author Robert von Burg + */ +public class ResourceSaxParser implements SaxParser { + + protected Resource resource; + + @Override + public Resource getObject() { + return this.resource; + } + + @Override + public void setObject(Resource resource) { + this.resource = resource; + } + + @Override + public DefaultHandler getDefaultHandler() { + return new XmlModelSaxReader(new StrolchElementListener() { + + @Override + public void notifyResource(Resource resource) { + ResourceSaxParser.this.resource = resource; + } + + @Override + public void notifyOrder(Order order) { + throw new IllegalArgumentException("Only expect Resources!"); + } + + @Override + public void notifyActivity(Activity activity) { + throw new IllegalArgumentException("Only expect Resources!"); + } + }); + } + + @Override + public void write(XMLStreamWriter xmlWriter) throws XMLStreamException { + new ResourceToSaxWriterVisitor(xmlWriter); + } +} diff --git a/li.strolch.service/src/main/java/li/strolch/command/ClearModelCommand.java b/li.strolch.service/src/main/java/li/strolch/command/ClearModelCommand.java index f2d935c9b..1bbbfb2ea 100644 --- a/li.strolch.service/src/main/java/li/strolch/command/ClearModelCommand.java +++ b/li.strolch.service/src/main/java/li/strolch/command/ClearModelCommand.java @@ -15,6 +15,7 @@ */ package li.strolch.command; +import li.strolch.agent.api.ActivityMap; import li.strolch.agent.api.ComponentContainer; import li.strolch.agent.api.OrderMap; import li.strolch.agent.api.ResourceMap; @@ -30,6 +31,7 @@ public class ClearModelCommand extends Command { // input private boolean clearOrders; private boolean clearResources; + private boolean clearActivities; // output private ModelStatistics statistics; @@ -62,6 +64,11 @@ public class ClearModelCommand extends Command { statistics.nrOfResources = resourceMap.removeAll(tx()); } + if (this.clearActivities) { + ActivityMap activitiesMap = tx().getActivityMap(); + statistics.nrOfActivities = activitiesMap.removeAll(tx()); + } + this.statistics = statistics; } @@ -86,6 +93,14 @@ public class ClearModelCommand extends Command { this.clearResources = clearResources; } + /** + * @param clearActivities + * the clearActivities to set + */ + public void setClearActivities(boolean clearActivities) { + this.clearActivities = clearActivities; + } + /** * @return the statistics */ diff --git a/li.strolch.service/src/main/java/li/strolch/command/XmlExportModelCommand.java b/li.strolch.service/src/main/java/li/strolch/command/XmlExportModelCommand.java index 7f2408b0c..52969fd42 100644 --- a/li.strolch.service/src/main/java/li/strolch/command/XmlExportModelCommand.java +++ b/li.strolch.service/src/main/java/li/strolch/command/XmlExportModelCommand.java @@ -34,16 +34,20 @@ import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; +import li.strolch.agent.api.ActivityMap; import li.strolch.agent.api.ComponentContainer; import li.strolch.agent.api.OrderMap; import li.strolch.agent.api.ResourceMap; import li.strolch.exception.StrolchException; +import li.strolch.model.ActivityVisitor; import li.strolch.model.ModelStatistics; import li.strolch.model.Order; import li.strolch.model.OrderVisitor; import li.strolch.model.Resource; import li.strolch.model.ResourceVisitor; import li.strolch.model.Tags; +import li.strolch.model.activity.Activity; +import li.strolch.model.xml.ActivityToSaxWriterVisitor; import li.strolch.model.xml.OrderToSaxWriterVisitor; import li.strolch.model.xml.ResourceToSaxWriterVisitor; import li.strolch.persistence.api.StrolchTransaction; @@ -65,8 +69,10 @@ public class XmlExportModelCommand extends Command { private boolean overwrite; private boolean doOrders; private boolean doResources; + private boolean doActivities; private Set orderTypes; private Set resourceTypes; + private Set activityTypes; // output private ModelStatistics statistics; @@ -74,6 +80,7 @@ public class XmlExportModelCommand extends Command { private int elementsToWrite; private int nrOfResourcesToExport; private int nrOfOrdersToExport; + private int nrOfActivitiesToExport; private long nextLogTime; @@ -137,10 +144,22 @@ public class XmlExportModelCommand extends Command { } } - this.elementsToWrite = this.nrOfResourcesToExport + this.nrOfOrdersToExport; + if (this.doActivities) { + ActivityMap activityMap = tx().getActivityMap(); + Set activityTypesToExport = activityMap.getTypes(tx()); + if (!this.activityTypes.isEmpty()) + activityTypesToExport.retainAll(this.activityTypes); + + for (String type : activityTypesToExport) { + this.nrOfActivitiesToExport += activityMap.querySize(tx(), type); + } + } + + this.elementsToWrite = this.nrOfResourcesToExport + this.nrOfOrdersToExport + this.nrOfActivitiesToExport; logger.info("Exporting " + this.elementsToWrite + " Elements..."); logger.info("Exporting " + this.nrOfResourcesToExport + " Resources..."); logger.info("Exporting " + this.nrOfOrdersToExport + " Orders..."); + logger.info("Exporting " + this.nrOfActivitiesToExport + " Activities..."); try (FileOutputStream out = new FileOutputStream(this.modelFile)) { createdFiles.add(this.modelFile); @@ -149,11 +168,10 @@ public class XmlExportModelCommand extends Command { if (this.doResources) { ResourceMap resourceMap = tx().getResourceMap(); - Set resourceTypesToExport = resourceMap.getTypes(tx()); + Set resourceTypesToExport = new TreeSet<>(resourceMap.getTypes(tx())); if (!this.resourceTypes.isEmpty()) resourceTypesToExport.retainAll(this.resourceTypes); - resourceTypesToExport = new TreeSet<>(resourceTypesToExport); for (String type : resourceTypesToExport) { if (!this.multiFile) { @@ -180,11 +198,10 @@ public class XmlExportModelCommand extends Command { if (this.doOrders) { OrderMap orderMap = tx().getOrderMap(); - Set orderTypesToExport = orderMap.getTypes(tx()); + Set orderTypesToExport = new TreeSet<>(orderMap.getTypes(tx())); if (!this.orderTypes.isEmpty()) orderTypesToExport.retainAll(this.orderTypes); - orderTypesToExport = new TreeSet<>(orderTypesToExport); for (String type : orderTypesToExport) { if (!this.multiFile) { @@ -208,6 +225,36 @@ public class XmlExportModelCommand extends Command { } } + if (this.doActivities) { + ActivityMap activityMap = tx().getActivityMap(); + Set activityTypesToExport = new TreeSet<>(activityMap.getTypes(tx())); + if (!this.activityTypes.isEmpty()) + activityTypesToExport.retainAll(this.activityTypes); + + for (String type : activityTypesToExport) { + + if (!this.multiFile) { + writeActivitiesByType(writer, activityMap, type); + } else { + String typeXmlFile = exportName + UNDERLINE + Tags.ACTIVITY + UNDERLINE + type + + XML_FILE_SUFFIX; + writer.writeEmptyElement(Tags.INCLUDE_FILE); + writer.writeAttribute(Tags.FILE, typeXmlFile); + + File typeXmlFileF = new File(this.modelFile.getParentFile(), typeXmlFile); + DBC.INTERIM.assertNotExists("The type file should not exist with name.", typeXmlFileF); + logger.info("Writing " + activityMap.querySize(tx(), type) + " " + type + + " Activities to path: " + typeXmlFileF.getAbsolutePath() + "..."); + try (FileOutputStream typeOut = new FileOutputStream(typeXmlFileF)) { + createdFiles.add(typeXmlFileF); + XMLStreamWriter typeWriter = openXmlStreamWriter(typeOut); + writeActivitiesByType(typeWriter, activityMap, type); + typeWriter.writeEndDocument(); + } + } + } + } + // and now end writer.writeEndElement(); writer.writeEndDocument(); @@ -262,6 +309,17 @@ public class XmlExportModelCommand extends Command { } } + private void writeActivitiesByType(XMLStreamWriter writer, ActivityMap activityMap, String type) { + ActivityVisitor visitor = new ActivityToSaxWriterVisitor(writer); + Set keysByType = new TreeSet<>(activityMap.getKeysBy(tx(), type)); + for (String id : keysByType) { + Activity activity = activityMap.getBy(tx(), type, id); + visitor.visit(activity); + this.statistics.nrOfActivities++; + logElementsWritten(); + } + } + private XMLStreamWriter openXmlStreamWriter(FileOutputStream out) throws FactoryConfigurationError, XMLStreamException { XMLOutputFactory factory = XMLOutputFactory.newInstance(); @@ -305,6 +363,14 @@ public class XmlExportModelCommand extends Command { this.doResources = doResources; } + /** + * @param doActivities + * the doActivities to set + */ + public void setDoActivities(boolean doActivities) { + this.doActivities = doActivities; + } + /** * @param orderTypes * the orderTypes to set @@ -321,6 +387,14 @@ public class XmlExportModelCommand extends Command { this.resourceTypes = resourceTypes; } + /** + * @param activityTypes + * the activityTypes to set + */ + public void setActivityTypes(Set activityTypes) { + this.activityTypes = activityTypes; + } + /** * @return the statistics */ diff --git a/li.strolch.service/src/main/java/li/strolch/command/XmlImportModelCommand.java b/li.strolch.service/src/main/java/li/strolch/command/XmlImportModelCommand.java index 8da39ca3a..ad2db34c3 100644 --- a/li.strolch.service/src/main/java/li/strolch/command/XmlImportModelCommand.java +++ b/li.strolch.service/src/main/java/li/strolch/command/XmlImportModelCommand.java @@ -35,10 +35,13 @@ public class XmlImportModelCommand extends Command { private File modelFile; private boolean addOrders; private boolean addResources; + private boolean addActivities; private boolean updateOrders; private boolean updateResources; + private boolean updateActivities; private Set orderTypes; private Set resourceTypes; + private Set activityTypes; // output private ModelStatistics statistics; @@ -64,10 +67,13 @@ public class XmlImportModelCommand extends Command { elementListener.setAddOrders(this.addOrders); elementListener.setAddResources(this.addResources); + elementListener.setAddActivities(this.addActivities); elementListener.setUpdateOrders(this.updateOrders); elementListener.setUpdateResources(this.updateResources); + elementListener.setUpdateActivities(this.updateActivities); elementListener.setOrderTypes(this.orderTypes); elementListener.setResourceTypes(this.resourceTypes); + elementListener.setActivityTypes(this.activityTypes); XmlModelSaxFileReader handler = new XmlModelSaxFileReader(elementListener, this.modelFile, this.allowInclude); handler.parseFile(); @@ -110,6 +116,14 @@ public class XmlImportModelCommand extends Command { this.addResources = addResources; } + /** + * @param addActivities + * the addActivities to set + */ + public void setAddActivities(boolean addActivities) { + this.addActivities = addActivities; + } + /** * @param updateOrders * the updateOrders to set @@ -126,6 +140,14 @@ public class XmlImportModelCommand extends Command { this.updateResources = updateResources; } + /** + * @param updateActivities + * the updateActivities to set + */ + public void setUpdateActivities(boolean updateActivities) { + this.updateActivities = updateActivities; + } + /** * @param orderTypes * the orderTypes to set @@ -142,6 +164,14 @@ public class XmlImportModelCommand extends Command { this.resourceTypes = resourceTypes; } + /** + * @param activityTypes + * the activityTypes to set + */ + public void setActivityTypes(Set activityTypes) { + this.activityTypes = activityTypes; + } + /** * @return the statistics */ diff --git a/li.strolch.service/src/main/java/li/strolch/command/plan/AbstractPlanCommand.java b/li.strolch.service/src/main/java/li/strolch/command/plan/AbstractPlanCommand.java index e3ca74e86..43eccf4d8 100644 --- a/li.strolch.service/src/main/java/li/strolch/command/plan/AbstractPlanCommand.java +++ b/li.strolch.service/src/main/java/li/strolch/command/plan/AbstractPlanCommand.java @@ -29,6 +29,7 @@ import li.strolch.model.activity.Action; import li.strolch.model.activity.Activity; import li.strolch.model.activity.IActivityElement; import li.strolch.model.timedstate.StrolchTimedState; +import li.strolch.model.timevalue.IValue; import li.strolch.model.timevalue.IValueChange; import li.strolch.persistence.api.StrolchTransaction; import li.strolch.service.api.Command; @@ -47,16 +48,16 @@ public abstract class AbstractPlanCommand extends Command { } /** - * plan an {@link Action}.It iterates the {@link IValueChange} operators and - * registers the changes on the {@link StrolchTimedState} objects assigned - * to the {@link Resource} referenced by type and id. + * plan an {@link Action}.It iterates the {@link IValueChange} operators and registers the changes on the + * {@link StrolchTimedState} objects assigned to the {@link Resource} referenced by type and id. * * @param action */ @SuppressWarnings({ "unchecked", "rawtypes" }) protected void plan(final Action action) { - final Locator locator = Locator.newBuilder(Tags.RESOURCE, action.getResourceType(), action.getResourceId()).build(); + final Locator locator = Locator.newBuilder(Tags.RESOURCE, action.getResourceType(), action.getResourceId()) + .build(); final Resource resource = tx().findElement(locator); if (resource == null) @@ -65,7 +66,7 @@ public abstract class AbstractPlanCommand extends Command { tx().lock(resource); - final List> changes = action.getChanges(); + final List>> changes = action.getChanges(); for (final IValueChange change : changes) { final StrolchTimedState timedState = resource.getTimedState(change.getStateId()); timedState.applyChange(change); @@ -75,10 +76,12 @@ public abstract class AbstractPlanCommand extends Command { } /** - * plan an {@link Activity} by navigating to the {#link Action} and - * delegating the planning depending on the {@link IActivityElement} class. + * plan an {@link Activity} by navigating to the {#link Action} and delegating the planning depending on the + * {@link IActivityElement} class. */ protected void plan(final Activity activity) { + + // TODO Martin: Use a visitor pattern so we don't start with instanceof again... final Iterator> elementIterator = activity.elementIterator(); @@ -94,10 +97,11 @@ public abstract class AbstractPlanCommand extends Command { @SuppressWarnings({ "unchecked", "rawtypes" }) protected void unplan(final Action action) { - final Locator locator = Locator.newBuilder(Tags.RESOURCE, action.getResourceType(), action.getResourceId()).build(); + final Locator locator = Locator.newBuilder(Tags.RESOURCE, action.getResourceType(), action.getResourceId()) + .build(); final Resource resource = tx().findElement(locator); - final List> changes = action.getChanges(); + final List>> changes = action.getChanges(); for (final IValueChange change : changes) { final StrolchTimedState timedState = resource.getTimedState(change.getStateId()); timedState.applyChange(change.getInverse()); @@ -117,8 +121,6 @@ public abstract class AbstractPlanCommand extends Command { unplan((Activity) activityElement); else if (activityElement instanceof Action) unplan((Action) activityElement); - } } - } diff --git a/li.strolch.service/src/main/java/li/strolch/command/plan/ShiftActionCommand.java b/li.strolch.service/src/main/java/li/strolch/command/plan/ShiftActionCommand.java index e94d476d0..84b1db80f 100644 --- a/li.strolch.service/src/main/java/li/strolch/command/plan/ShiftActionCommand.java +++ b/li.strolch.service/src/main/java/li/strolch/command/plan/ShiftActionCommand.java @@ -19,6 +19,7 @@ import java.util.List; import li.strolch.agent.api.ComponentContainer; import li.strolch.model.State; +import li.strolch.model.timevalue.IValue; import li.strolch.model.timevalue.IValueChange; import li.strolch.persistence.api.StrolchTransaction; import ch.eitchnet.utils.dbc.DBC; @@ -56,7 +57,7 @@ public class ShiftActionCommand extends PlanActionCommand { unplan(action); // iterate all changes and shift - final List> changes = action.getChanges(); + final List>> changes = action.getChanges(); for (final IValueChange change : changes) { change.setTime(change.getTime() + shift); } @@ -74,7 +75,7 @@ public class ShiftActionCommand extends PlanActionCommand { unplan(action); // iterate all changes and shift - final List> changes = action.getChanges(); + final List>> changes = action.getChanges(); for (final IValueChange change : changes) { change.setTime(change.getTime() - shift); } @@ -86,5 +87,4 @@ public class ShiftActionCommand extends PlanActionCommand { public void setShift(Long shift) { this.shift = shift; } - } diff --git a/li.strolch.service/src/main/java/li/strolch/service/XmlExportModelArgument.java b/li.strolch.service/src/main/java/li/strolch/service/XmlExportModelArgument.java index fc368bd80..a57df54f4 100644 --- a/li.strolch.service/src/main/java/li/strolch/service/XmlExportModelArgument.java +++ b/li.strolch.service/src/main/java/li/strolch/service/XmlExportModelArgument.java @@ -29,8 +29,10 @@ public class XmlExportModelArgument extends ServiceArgument { public boolean multiFile; public boolean doOrders = true; public boolean doResources = true; + public boolean doActivities = true; public Set orderTypes = new HashSet<>(); public Set resourceTypes = new HashSet<>(); + public Set activityTypes = new HashSet<>(); @Override public String toString() { @@ -52,6 +54,8 @@ public class XmlExportModelArgument extends ServiceArgument { builder.append(", resources"); if (this.doOrders) builder.append(", orders"); + if (this.doActivities) + builder.append(", activities"); if (this.resourceTypes != null && !this.resourceTypes.isEmpty()) { builder.append(", resourceTypes="); @@ -59,6 +63,7 @@ public class XmlExportModelArgument extends ServiceArgument { } else { builder.append(", resourceTypes=*"); } + if (this.orderTypes != null && !this.orderTypes.isEmpty()) { builder.append(", orderTypes="); builder.append(this.orderTypes); @@ -66,6 +71,13 @@ public class XmlExportModelArgument extends ServiceArgument { builder.append(", orderTypes=*"); } + if (this.activityTypes != null && !this.activityTypes.isEmpty()) { + builder.append(", activityTypes="); + builder.append(this.activityTypes); + } else { + builder.append(", activityTypes=*"); + } + builder.append("]"); return builder.toString(); } diff --git a/li.strolch.service/src/main/java/li/strolch/service/XmlExportModelService.java b/li.strolch.service/src/main/java/li/strolch/service/XmlExportModelService.java index 9e8a45c11..8a843e853 100644 --- a/li.strolch.service/src/main/java/li/strolch/service/XmlExportModelService.java +++ b/li.strolch.service/src/main/java/li/strolch/service/XmlExportModelService.java @@ -83,8 +83,10 @@ public class XmlExportModelService extends AbstractService orderTypes = new HashSet<>(); public Set resourceTypes = new HashSet<>(); + public Set activityTypes = new HashSet<>(); @Override public String toString() { @@ -40,7 +43,7 @@ public class XmlImportModelArgument extends ServiceArgument { builder.append("external="); builder.append(this.external); - + builder.append(", allowInclude="); builder.append(this.allowInclude); @@ -51,11 +54,15 @@ public class XmlImportModelArgument extends ServiceArgument { builder.append(", addOrders"); if (this.addResources) builder.append(", addResources"); + if (this.addActivities) + builder.append(", addActivities"); if (this.updateOrders) builder.append(", updateOrders"); if (this.updateResources) builder.append(", updateResources"); + if (this.updateActivities) + builder.append(", updateActivities"); if (this.resourceTypes != null && !this.resourceTypes.isEmpty()) { builder.append(", resourceTypes="); @@ -63,6 +70,7 @@ public class XmlImportModelArgument extends ServiceArgument { } else { builder.append(", resourceTypes=*"); } + if (this.orderTypes != null && !this.orderTypes.isEmpty()) { builder.append(", orderTypes="); builder.append(this.orderTypes); @@ -70,6 +78,13 @@ public class XmlImportModelArgument extends ServiceArgument { builder.append(", orderTypes=*"); } + if (this.activityTypes != null && !this.activityTypes.isEmpty()) { + builder.append(", activityTypes="); + builder.append(this.activityTypes); + } else { + builder.append(", activityTypes=*"); + } + builder.append("]"); return builder.toString(); } diff --git a/li.strolch.service/src/main/java/li/strolch/service/XmlImportModelService.java b/li.strolch.service/src/main/java/li/strolch/service/XmlImportModelService.java index 55e9f9234..f577b0a33 100644 --- a/li.strolch.service/src/main/java/li/strolch/service/XmlImportModelService.java +++ b/li.strolch.service/src/main/java/li/strolch/service/XmlImportModelService.java @@ -76,10 +76,13 @@ public class XmlImportModelService extends AbstractService - - + + - - + + - - + +