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 @@ + + + + + + + + + + + + + +