diff --git a/src/main/java/li/strolch/model/Tags.java b/src/main/java/li/strolch/model/Tags.java
index 53c192074..1b7904e5f 100644
--- a/src/main/java/li/strolch/model/Tags.java
+++ b/src/main/java/li/strolch/model/Tags.java
@@ -17,5 +17,8 @@ public class Tags {
public static final String RESOURCE = "Resource";
public static final String ORDER = "Order";
public static final String PARAMETER_BAG = "ParameterBag";
+ public static final String STROLCH_MODEL = "StrolchModel";
+ public static final String INCLUDE_FILE = "IncludeFile";
+ public static final String FILE = "file";
}
diff --git a/src/main/java/li/strolch/model/xml/StrolchElementListener.java b/src/main/java/li/strolch/model/xml/StrolchElementListener.java
new file mode 100644
index 000000000..24adba720
--- /dev/null
+++ b/src/main/java/li/strolch/model/xml/StrolchElementListener.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, Robert von Burg
+ *
+ * All rights reserved.
+ *
+ * This file is part of the XXX.
+ *
+ * XXX is free software: you can redistribute
+ * it and/or modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * XXX is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XXX. If not, see
+ * .
+ */
+package li.strolch.model.xml;
+
+import li.strolch.model.Order;
+import li.strolch.model.Resource;
+
+/**
+ * @author Robert von Burg
+ *
+ */
+public interface StrolchElementListener {
+
+ public void notifyResource(Resource resource);
+
+ public void notifyOrder(Order order);
+}
diff --git a/src/main/java/li/strolch/model/xml/XmlModelDefaultHandler.java b/src/main/java/li/strolch/model/xml/XmlModelDefaultHandler.java
new file mode 100644
index 000000000..ad088ad0f
--- /dev/null
+++ b/src/main/java/li/strolch/model/xml/XmlModelDefaultHandler.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2012, Robert von Burg
+ *
+ * All rights reserved.
+ *
+ * This file is part of the XXX.
+ *
+ * XXX is free software: you can redistribute
+ * it and/or modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * XXX is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XXX. If not, see
+ * .
+ */
+package li.strolch.model.xml;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Date;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import li.strolch.exception.StrolchException;
+import li.strolch.model.Order;
+import li.strolch.model.ParameterBag;
+import li.strolch.model.Resource;
+import li.strolch.model.State;
+import li.strolch.model.Tags;
+import li.strolch.model.parameter.BooleanParameter;
+import li.strolch.model.parameter.DateParameter;
+import li.strolch.model.parameter.FloatParameter;
+import li.strolch.model.parameter.IntegerParameter;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import ch.eitchnet.utils.helper.StringHelper;
+import ch.eitchnet.utils.iso8601.ISO8601FormatFactory;
+
+/**
+ * @author Robert von Burg
+ *
+ */
+public class XmlModelDefaultHandler extends DefaultHandler {
+
+ private static final Logger logger = LoggerFactory.getLogger(XmlModelDefaultHandler.class);
+
+ private StrolchElementListener listener;
+ private File modelFile;
+
+ private Resource resource;
+ private Order order;
+ private ParameterBag pBag;
+
+ private XmlModelStatistics statistics;
+
+ public XmlModelDefaultHandler(StrolchElementListener listener, File modelFile) {
+ this.listener = listener;
+ this.modelFile = modelFile;
+ this.statistics = new XmlModelStatistics();
+ }
+
+ /**
+ * @return the statistics
+ */
+ public XmlModelStatistics getStatistics() {
+ return this.statistics;
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+
+ // TODO split each root object into its own file
+
+ switch (qName) {
+
+ case Tags.STROLCH_MODEL:
+ break;
+
+ case Tags.RESOURCE:
+
+ String resId = attributes.getValue(Tags.ID);
+ String resName = attributes.getValue(Tags.NAME);
+ String resType = attributes.getValue(Tags.TYPE);
+ Resource resource = new Resource(resId, resName, resType);
+ this.resource = resource;
+ break;
+
+ case Tags.ORDER:
+ String orderId = attributes.getValue(Tags.ID);
+ String orderName = attributes.getValue(Tags.NAME);
+ String orderType = attributes.getValue(Tags.TYPE);
+ String orderDateS = attributes.getValue(Tags.DATE);
+ String orderStateS = attributes.getValue(Tags.STATE);
+ Order order = new Order(orderId, orderName, orderType);
+ if (orderDateS != null) {
+ Date orderDate = ISO8601FormatFactory.getInstance().getDateFormat().parse(orderDateS);
+ order.setDate(orderDate);
+ }
+ if (orderDateS != null) {
+ State orderState = State.valueOf(orderStateS);
+ order.setState(orderState);
+ }
+ this.order = order;
+ break;
+
+ case Tags.PARAMETER_BAG:
+ String pBagId = attributes.getValue(Tags.ID);
+ String pBagName = attributes.getValue(Tags.NAME);
+ String pBagType = attributes.getValue(Tags.TYPE);
+ ParameterBag pBag = new ParameterBag(pBagId, pBagName, pBagType);
+ this.pBag = pBag;
+ break;
+
+ case Tags.PARAMETER:
+ String paramId = attributes.getValue(Tags.ID);
+ String paramName = attributes.getValue(Tags.NAME);
+ String paramType = attributes.getValue(Tags.TYPE);
+ String paramValue = attributes.getValue(Tags.VALUE);
+ String paramHiddenS = attributes.getValue(Tags.HIDDEN);
+ boolean paramHidden = paramHiddenS == null ? false : StringHelper.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 StringListParameter.TYPE:
+ param = new StringListParameter(paramId, paramName, StringListParameter.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$
+ }
+ param.setHidden(paramHidden);
+ param.setUom(paramUom);
+ param.setInterpretation(paramInterpretation);
+ this.pBag.addParameter(param);
+ break;
+
+ case Tags.INCLUDE_FILE:
+
+ String includeFileS = attributes.getValue(Tags.FILE);
+ if (StringHelper.isEmpty(includeFileS))
+ throw new IllegalArgumentException(MessageFormat.format(
+ "The attribute {0} is missing for IncludeFile!", Tags.FILE)); //$NON-NLS-1$
+ File includeFile = new File(this.modelFile.getParentFile(), includeFileS);
+ if (!includeFile.exists() || !includeFile.canRead()) {
+ String msg = "The IncludeFile does not exist, or is not readable. Source model: {0} with IncludeFile: {1}"; //$NON-NLS-1$
+ msg = MessageFormat.format(msg, this.modelFile.getName(), includeFileS);
+ throw new IllegalArgumentException(msg);
+ }
+
+ XmlModelDefaultHandler handler = new XmlModelDefaultHandler(this.listener, includeFile);
+ handler.parseFile();
+ this.statistics.nrOfOrders += handler.statistics.nrOfOrders;
+ this.statistics.nrOfResources += handler.statistics.nrOfResources;
+
+ break;
+ default:
+ throw new IllegalArgumentException(MessageFormat.format("The element ''{0}'' is unhandled!", qName)); //$NON-NLS-1$
+ }
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+
+ switch (qName) {
+ case Tags.STROLCH_MODEL:
+ break;
+ case Tags.RESOURCE:
+ this.listener.notifyResource(this.resource);
+ this.statistics.nrOfResources++;
+ this.resource = null;
+ break;
+ case Tags.ORDER:
+ this.listener.notifyOrder(this.order);
+ this.statistics.nrOfOrders++;
+ this.order = null;
+ break;
+ case Tags.PARAMETER_BAG:
+ this.pBag = null;
+ break;
+ case Tags.PARAMETER:
+ break;
+ case Tags.INCLUDE_FILE:
+ break;
+ default:
+ throw new IllegalArgumentException(MessageFormat.format("The element ''{0}'' is unhandled!", qName)); //$NON-NLS-1$
+ }
+ }
+
+ public void parseFile() {
+
+ try {
+ long startNanos = System.nanoTime();
+ this.statistics.startTime = new Date();
+
+ SAXParserFactory spf = SAXParserFactory.newInstance();
+ SAXParser sp = spf.newSAXParser();
+
+ sp.parse(this.modelFile, this);
+
+ long endNanos = System.nanoTime();
+ this.statistics.durationNanos = endNanos - startNanos;
+ String msg = "SAX parsed model file {0} took {1}"; //$NON-NLS-1$
+ logger.info(MessageFormat.format(msg, this.modelFile.getAbsolutePath(),
+ StringHelper.formatNanoDuration(this.statistics.durationNanos)));
+
+ } catch (ParserConfigurationException | SAXException | IOException e) {
+
+ String msg = "Parsing failed due to internal error: {0}"; //$NON-NLS-1$
+ throw new StrolchException(MessageFormat.format(msg, e.getMessage()), e);
+ }
+ }
+
+ public static class XmlModelStatistics {
+ public Date startTime;
+ public long durationNanos;
+ public int nrOfResources;
+ public int nrOfOrders;
+ }
+}
diff --git a/src/test/java/li/strolch/test/model/ModelTest.java b/src/test/java/li/strolch/model/test/ModelTest.java
similarity index 99%
rename from src/test/java/li/strolch/test/model/ModelTest.java
rename to src/test/java/li/strolch/model/test/ModelTest.java
index a7197216a..f5de4dee3 100644
--- a/src/test/java/li/strolch/test/model/ModelTest.java
+++ b/src/test/java/li/strolch/model/test/ModelTest.java
@@ -1,4 +1,4 @@
-package li.strolch.test.model;
+package li.strolch.model.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
diff --git a/src/test/java/li/strolch/test/model/ModelTestHelper.java b/src/test/java/li/strolch/model/test/ModelTestHelper.java
similarity index 99%
rename from src/test/java/li/strolch/test/model/ModelTestHelper.java
rename to src/test/java/li/strolch/model/test/ModelTestHelper.java
index 7610db82a..280c37bee 100644
--- a/src/test/java/li/strolch/test/model/ModelTestHelper.java
+++ b/src/test/java/li/strolch/model/test/ModelTestHelper.java
@@ -19,7 +19,7 @@
* along with li.strolch.model. If not, see
* .
*/
-package li.strolch.test.model;
+package li.strolch.model.test;
import java.util.ArrayList;
import java.util.Date;
diff --git a/src/test/java/li/strolch/model/test/XmlModelDefaultHandlerTest.java b/src/test/java/li/strolch/model/test/XmlModelDefaultHandlerTest.java
new file mode 100644
index 000000000..cbd26a62e
--- /dev/null
+++ b/src/test/java/li/strolch/model/test/XmlModelDefaultHandlerTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2012, Robert von Burg
+ *
+ * All rights reserved.
+ *
+ * This file is part of the XXX.
+ *
+ * XXX is free software: you can redistribute
+ * it and/or modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * XXX is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XXX. If not, see
+ * .
+ */
+package li.strolch.model.test;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+import li.strolch.model.Order;
+import li.strolch.model.Resource;
+import li.strolch.model.xml.StrolchElementListener;
+import li.strolch.model.xml.XmlModelDefaultHandler;
+import li.strolch.model.xml.XmlModelDefaultHandler.XmlModelStatistics;
+
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import ch.eitchnet.utils.helper.StringHelper;
+
+/**
+ * @author Robert von Burg
+ *
+ */
+@SuppressWarnings("nls")
+public class XmlModelDefaultHandlerTest {
+
+ private static final Logger logger = LoggerFactory.getLogger(XmlModelDefaultHandlerTest.class);
+
+ @Test
+ public void shouldParseXmlModelFile() {
+
+ final Map resourceMap = new HashMap<>();
+ final Map orderMap = new HashMap<>();
+
+ File file = new File("src/test/resources/data/StrolchModel.xml");
+ StrolchElementListener listener = new StrolchElementListener() {
+ @Override
+ public void notifyResource(Resource resource) {
+ resourceMap.put(resource.getId(), resource);
+ }
+
+ @Override
+ public void notifyOrder(Order order) {
+ orderMap.put(order.getId(), order);
+ }
+ };
+ XmlModelDefaultHandler handler = new XmlModelDefaultHandler(listener, file);
+ handler.parseFile();
+
+ assertEquals(3, resourceMap.size());
+ assertEquals(3, orderMap.size());
+
+ XmlModelStatistics statistics = handler.getStatistics();
+ logger.info("Parsing took " + StringHelper.formatNanoDuration(statistics.durationNanos));
+ assertEquals(3, statistics.nrOfOrders);
+ assertEquals(3, statistics.nrOfResources);
+ }
+}
diff --git a/src/test/java/li/strolch/model/timedstate/TimeStateTest.java b/src/test/java/li/strolch/model/test/timedstate/TimeStateTest.java
similarity index 95%
rename from src/test/java/li/strolch/model/timedstate/TimeStateTest.java
rename to src/test/java/li/strolch/model/test/timedstate/TimeStateTest.java
index 8c685ca50..e2182fba8 100644
--- a/src/test/java/li/strolch/model/timedstate/TimeStateTest.java
+++ b/src/test/java/li/strolch/model/test/timedstate/TimeStateTest.java
@@ -1,8 +1,10 @@
-package li.strolch.model.timedstate;
+package li.strolch.model.test.timedstate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import li.strolch.model.timedstate.ITimedState;
+import li.strolch.model.timedstate.TimedState;
import li.strolch.model.timevalue.ITimeValue;
import li.strolch.model.timevalue.IValueChange;
import li.strolch.model.timevalue.impl.DoubleValue;
diff --git a/src/test/java/li/strolch/model/timevalue/FloatTimeVariableTest.java b/src/test/java/li/strolch/model/test/timevalue/FloatTimeVariableTest.java
similarity index 95%
rename from src/test/java/li/strolch/model/timevalue/FloatTimeVariableTest.java
rename to src/test/java/li/strolch/model/test/timevalue/FloatTimeVariableTest.java
index 2a0cb99df..fd09d465a 100644
--- a/src/test/java/li/strolch/model/timevalue/FloatTimeVariableTest.java
+++ b/src/test/java/li/strolch/model/test/timevalue/FloatTimeVariableTest.java
@@ -1,4 +1,4 @@
-package li.strolch.model.timevalue;
+package li.strolch.model.test.timevalue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -7,6 +7,9 @@ import static org.junit.Assert.assertTrue;
import java.util.Collection;
import java.util.SortedSet;
+import li.strolch.model.timevalue.ITimeValue;
+import li.strolch.model.timevalue.IValue;
+import li.strolch.model.timevalue.IValueChange;
import li.strolch.model.timevalue.impl.DoubleValue;
import li.strolch.model.timevalue.impl.TimeVariable;
import li.strolch.model.timevalue.impl.ValueChange;
diff --git a/src/test/java/li/strolch/model/timevalue/IntegerTimeVariableTest.java b/src/test/java/li/strolch/model/test/timevalue/IntegerTimeVariableTest.java
similarity index 95%
rename from src/test/java/li/strolch/model/timevalue/IntegerTimeVariableTest.java
rename to src/test/java/li/strolch/model/test/timevalue/IntegerTimeVariableTest.java
index cd3156221..d11460032 100644
--- a/src/test/java/li/strolch/model/timevalue/IntegerTimeVariableTest.java
+++ b/src/test/java/li/strolch/model/test/timevalue/IntegerTimeVariableTest.java
@@ -1,4 +1,4 @@
-package li.strolch.model.timevalue;
+package li.strolch.model.test.timevalue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -8,6 +8,9 @@ import java.util.HashMap;
import java.util.Map;
import java.util.SortedSet;
+import li.strolch.model.timevalue.ITimeValue;
+import li.strolch.model.timevalue.IValue;
+import li.strolch.model.timevalue.IValueChange;
import li.strolch.model.timevalue.impl.IntegerValue;
import li.strolch.model.timevalue.impl.TimeVariable;
import li.strolch.model.timevalue.impl.ValueChange;
diff --git a/src/test/java/li/strolch/model/timevalue/StringTimeVariableTest.java b/src/test/java/li/strolch/model/test/timevalue/StringTimeVariableTest.java
similarity index 95%
rename from src/test/java/li/strolch/model/timevalue/StringTimeVariableTest.java
rename to src/test/java/li/strolch/model/test/timevalue/StringTimeVariableTest.java
index 6efefa42b..18f801549 100644
--- a/src/test/java/li/strolch/model/timevalue/StringTimeVariableTest.java
+++ b/src/test/java/li/strolch/model/test/timevalue/StringTimeVariableTest.java
@@ -1,4 +1,4 @@
-package li.strolch.model.timevalue;
+package li.strolch.model.test.timevalue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -10,6 +10,9 @@ import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
+import li.strolch.model.timevalue.ITimeValue;
+import li.strolch.model.timevalue.IValue;
+import li.strolch.model.timevalue.IValueChange;
import li.strolch.model.timevalue.impl.AString;
import li.strolch.model.timevalue.impl.StringSetValue;
import li.strolch.model.timevalue.impl.TimeVariable;
diff --git a/src/test/java/li/strolch/model/timevalue/ValueTests.java b/src/test/java/li/strolch/model/test/timevalue/ValueTests.java
similarity index 96%
rename from src/test/java/li/strolch/model/timevalue/ValueTests.java
rename to src/test/java/li/strolch/model/test/timevalue/ValueTests.java
index 45fe25fec..a6489fac8 100644
--- a/src/test/java/li/strolch/model/timevalue/ValueTests.java
+++ b/src/test/java/li/strolch/model/test/timevalue/ValueTests.java
@@ -1,10 +1,11 @@
-package li.strolch.model.timevalue;
+package li.strolch.model.test.timevalue;
import static org.junit.Assert.assertEquals;
import java.util.HashSet;
import java.util.Set;
+import li.strolch.model.timevalue.IValue;
import li.strolch.model.timevalue.impl.AString;
import li.strolch.model.timevalue.impl.DoubleValue;
import li.strolch.model.timevalue.impl.IntegerValue;
diff --git a/src/test/resources/data/StrolchModel.xml b/src/test/resources/data/StrolchModel.xml
new file mode 100644
index 000000000..818cccb2d
--- /dev/null
+++ b/src/test/resources/data/StrolchModel.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/data/orders/Orders.xml b/src/test/resources/data/orders/Orders.xml
new file mode 100644
index 000000000..1e4b66d00
--- /dev/null
+++ b/src/test/resources/data/orders/Orders.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/test/resources/data/orders/Templates.xml b/src/test/resources/data/orders/Templates.xml
new file mode 100644
index 000000000..bd86a6925
--- /dev/null
+++ b/src/test/resources/data/orders/Templates.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/test/resources/data/resources/Resources.xml b/src/test/resources/data/resources/Resources.xml
new file mode 100644
index 000000000..9ac7b632a
--- /dev/null
+++ b/src/test/resources/data/resources/Resources.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/test/resources/data/resources/Templates.xml b/src/test/resources/data/resources/Templates.xml
new file mode 100644
index 000000000..f122f0346
--- /dev/null
+++ b/src/test/resources/data/resources/Templates.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+