From 9b836dd45c705d8dc419f53cf25c884dac1ef075 Mon Sep 17 00:00:00 2001 From: Robert von Burg Date: Mon, 23 Dec 2013 01:52:50 +0100 Subject: [PATCH] [New] Added visitor pattern for Resources and Orders --- pom.xml | 5 +- .../model/GroupedParameterizedElement.java | 1 - .../java/li/strolch/model/OrderVisitor.java | 25 +++ .../li/strolch/model/ResourceVisitor.java | 25 +++ .../strolch/model/StrolchElementVisitor.java | 24 +++ src/main/java/li/strolch/model/Tags.java | 21 +-- .../model/visitor/OrderDeepEqualsVisitor.java | 36 +++++ .../visitor/ResourceDeepEqualsVisitor.java | 36 +++++ .../StrolchElementDeepEqualsVisitor.java | 146 ++++++++++++++++++ .../strolch/model/xml/OrderToDomVisitor.java | 51 ++++++ .../strolch/model/xml/OrderToSaxVisitor.java | 50 ++++++ .../model/xml/ResourceToDomVisitor.java | 51 ++++++ .../model/xml/ResourceToSaxVisitor.java | 50 ++++++ .../xml/SimpleStrolchElementListener.java | 59 +++++++ .../model/xml/StrolchElementToDomVisitor.java | 90 +++++++++++ .../model/xml/XmlModelDefaultHandler.java | 78 ++-------- .../model/xml/XmlModelFileHandler.java | 104 +++++++++++++ src/test/java/li/strolch/model/ModelTest.java | 42 ++++- .../model/XmlModelDefaultHandlerTest.java | 6 +- .../java/li/strolch/model/XmlToDomTest.java | 65 ++++++++ 20 files changed, 879 insertions(+), 86 deletions(-) create mode 100644 src/main/java/li/strolch/model/OrderVisitor.java create mode 100644 src/main/java/li/strolch/model/ResourceVisitor.java create mode 100644 src/main/java/li/strolch/model/StrolchElementVisitor.java create mode 100644 src/main/java/li/strolch/model/visitor/OrderDeepEqualsVisitor.java create mode 100644 src/main/java/li/strolch/model/visitor/ResourceDeepEqualsVisitor.java create mode 100644 src/main/java/li/strolch/model/visitor/StrolchElementDeepEqualsVisitor.java create mode 100644 src/main/java/li/strolch/model/xml/OrderToDomVisitor.java create mode 100644 src/main/java/li/strolch/model/xml/OrderToSaxVisitor.java create mode 100644 src/main/java/li/strolch/model/xml/ResourceToDomVisitor.java create mode 100644 src/main/java/li/strolch/model/xml/ResourceToSaxVisitor.java create mode 100644 src/main/java/li/strolch/model/xml/SimpleStrolchElementListener.java create mode 100644 src/main/java/li/strolch/model/xml/StrolchElementToDomVisitor.java create mode 100644 src/main/java/li/strolch/model/xml/XmlModelFileHandler.java create mode 100644 src/test/java/li/strolch/model/XmlToDomTest.java diff --git a/pom.xml b/pom.xml index 5c2d28c89..eb1289eff 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,10 @@ - + + ch.eitchnet + ch.eitchnet.utils + diff --git a/src/main/java/li/strolch/model/GroupedParameterizedElement.java b/src/main/java/li/strolch/model/GroupedParameterizedElement.java index 647092943..d09b973ed 100644 --- a/src/main/java/li/strolch/model/GroupedParameterizedElement.java +++ b/src/main/java/li/strolch/model/GroupedParameterizedElement.java @@ -32,7 +32,6 @@ import ch.eitchnet.utils.helper.StringHelper; /** * @author Robert von Burg - * */ public abstract class GroupedParameterizedElement extends AbstractStrolchElement { diff --git a/src/main/java/li/strolch/model/OrderVisitor.java b/src/main/java/li/strolch/model/OrderVisitor.java new file mode 100644 index 000000000..c076175e3 --- /dev/null +++ b/src/main/java/li/strolch/model/OrderVisitor.java @@ -0,0 +1,25 @@ +/* + * 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; + +/** + * @author Robert von Burg + */ +public interface OrderVisitor extends StrolchElementVisitor { + + @Override + public void visit(Order element); +} diff --git a/src/main/java/li/strolch/model/ResourceVisitor.java b/src/main/java/li/strolch/model/ResourceVisitor.java new file mode 100644 index 000000000..db8c78ba2 --- /dev/null +++ b/src/main/java/li/strolch/model/ResourceVisitor.java @@ -0,0 +1,25 @@ +/* + * 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; + +/** + * @author Robert von Burg + */ +public interface ResourceVisitor extends StrolchElementVisitor{ + + @Override + public void visit(Resource element); +} diff --git a/src/main/java/li/strolch/model/StrolchElementVisitor.java b/src/main/java/li/strolch/model/StrolchElementVisitor.java new file mode 100644 index 000000000..605f3014f --- /dev/null +++ b/src/main/java/li/strolch/model/StrolchElementVisitor.java @@ -0,0 +1,24 @@ +/* + * 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; + +/** + * @author Robert von Burg + */ +public interface StrolchElementVisitor { + + public void visit(T element); +} diff --git a/src/main/java/li/strolch/model/Tags.java b/src/main/java/li/strolch/model/Tags.java index 212d04f5e..e2d7b86a9 100644 --- a/src/main/java/li/strolch/model/Tags.java +++ b/src/main/java/li/strolch/model/Tags.java @@ -18,17 +18,18 @@ package li.strolch.model; @SuppressWarnings("nls") public class Tags { - public static final String ID="Id"; - public static final String NAME="Name"; + public static final String CDATA = "CDATA"; + public static final String ID = "Id"; + public static final String NAME = "Name"; public static final String TYPE = "Type"; - public static final String DATE="Date"; - public static final String STATE="State"; - public static final String VALUE="Value"; - public static final String INTERPRETATION="Interpretation"; - public static final String UOM="Uom"; - public static final String HIDDEN="Hidden"; - public static final String PARAMETER="Parameter"; - public static final String PARAMETERIZED_ELEMENT="ParameterizedElement"; + public static final String DATE = "Date"; + public static final String STATE = "State"; + public static final String VALUE = "Value"; + public static final String INTERPRETATION = "Interpretation"; + public static final String UOM = "Uom"; + public static final String HIDDEN = "Hidden"; + public static final String PARAMETER = "Parameter"; + public static final String PARAMETERIZED_ELEMENT = "ParameterizedElement"; public static final String RESOURCE = "Resource"; public static final String ORDER = "Order"; public static final String PARAMETER_BAG = "ParameterBag"; diff --git a/src/main/java/li/strolch/model/visitor/OrderDeepEqualsVisitor.java b/src/main/java/li/strolch/model/visitor/OrderDeepEqualsVisitor.java new file mode 100644 index 000000000..497c46e29 --- /dev/null +++ b/src/main/java/li/strolch/model/visitor/OrderDeepEqualsVisitor.java @@ -0,0 +1,36 @@ +/* + * 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 li.strolch.model.Order; +import li.strolch.model.OrderVisitor; + +/** + * @author Robert von Burg + */ +public class OrderDeepEqualsVisitor extends StrolchElementDeepEqualsVisitor implements OrderVisitor { + + private Order srcOrder; + + public OrderDeepEqualsVisitor(Order srcOrder) { + this.srcOrder = srcOrder; + } + + @Override + public void visit(Order dstOrder) { + deepEquals(this.srcOrder, dstOrder); + } +} diff --git a/src/main/java/li/strolch/model/visitor/ResourceDeepEqualsVisitor.java b/src/main/java/li/strolch/model/visitor/ResourceDeepEqualsVisitor.java new file mode 100644 index 000000000..d74918a6f --- /dev/null +++ b/src/main/java/li/strolch/model/visitor/ResourceDeepEqualsVisitor.java @@ -0,0 +1,36 @@ +/* + * 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 li.strolch.model.Resource; +import li.strolch.model.ResourceVisitor; + +/** + * @author Robert von Burg + */ +public class ResourceDeepEqualsVisitor extends StrolchElementDeepEqualsVisitor implements ResourceVisitor { + + private Resource srcRes; + + public ResourceDeepEqualsVisitor(Resource sourceRes) { + this.srcRes = sourceRes; + } + + @Override + public void visit(Resource dstRes) { + deepEquals(this.srcRes, dstRes); + } +} diff --git a/src/main/java/li/strolch/model/visitor/StrolchElementDeepEqualsVisitor.java b/src/main/java/li/strolch/model/visitor/StrolchElementDeepEqualsVisitor.java new file mode 100644 index 000000000..0b927fdcb --- /dev/null +++ b/src/main/java/li/strolch/model/visitor/StrolchElementDeepEqualsVisitor.java @@ -0,0 +1,146 @@ +/* + * 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.ArrayList; +import java.util.List; +import java.util.Set; + +import li.strolch.model.GroupedParameterizedElement; +import li.strolch.model.Locator; +import li.strolch.model.Order; +import li.strolch.model.ParameterBag; +import li.strolch.model.Resource; +import li.strolch.model.StrolchElement; +import li.strolch.model.parameter.Parameter; + +/** + * @author Robert von Burg + * + */ +public class StrolchElementDeepEqualsVisitor { + + private List mismatchedLocators; + + public StrolchElementDeepEqualsVisitor() { + this.mismatchedLocators = new ArrayList<>(); + } + + /** + * @return the mismatchedLocators + */ + public List getMismatchedLocators() { + return this.mismatchedLocators; + } + + public boolean isEqual() { + return this.mismatchedLocators.isEmpty(); + } + + protected void deepEquals(StrolchElement srcElement, StrolchElement dstElement) { + if (!srcElement.getName().equals(dstElement.getName())) + this.mismatchedLocators.add(dstElement.getLocator()); + if (!srcElement.getType().equals(dstElement.getType())) + this.mismatchedLocators.add(dstElement.getLocator()); + } + + protected void deepEquals(Order srcOrder, Order dstOrder) { + deepEquals((StrolchElement) srcOrder, (StrolchElement) dstOrder); + if (!srcOrder.getState().equals(dstOrder.getState())) + this.mismatchedLocators.add(dstOrder.getLocator()); + if (!srcOrder.getDate().equals(dstOrder.getDate())) + this.mismatchedLocators.add(dstOrder.getLocator()); + + deepEquals((GroupedParameterizedElement) srcOrder, (GroupedParameterizedElement) dstOrder); + } + + protected void deepEquals(Resource srcRes, Resource dstRes) { + deepEquals((StrolchElement) srcRes, (StrolchElement) dstRes); + deepEquals((GroupedParameterizedElement) srcRes, (GroupedParameterizedElement) dstRes); + } + + protected void deepEquals(GroupedParameterizedElement srcElement, GroupedParameterizedElement dstElement) { + Set srcBagKeySet = srcElement.getParameterBagKeySet(); + for (String bagKey : srcBagKeySet) { + ParameterBag srcBag = srcElement.getParameterBag(bagKey); + + if (!dstElement.hasParameterBag(bagKey)) { + this.mismatchedLocators.add(srcBag.getLocator()); + continue; + } + + ParameterBag dstBag = dstElement.getParameterBag(bagKey); + deepEquals(srcBag, dstBag); + } + + Set dstBagKeySet = dstElement.getParameterBagKeySet(); + for (String bagKey : dstBagKeySet) { + if (!srcElement.hasParameterBag(bagKey)) { + ParameterBag dstBag = dstElement.getParameterBag(bagKey); + this.mismatchedLocators.add(dstBag.getLocator()); + } + } + } + + protected void deepEquals(ParameterBag srcBag, ParameterBag dstBag) { + deepEquals((StrolchElement) srcBag, (StrolchElement) dstBag); + + Set srcParamKeySet = srcBag.getParameterKeySet(); + for (String paramKey : srcParamKeySet) { + Parameter srcParam = srcBag.getParameter(paramKey); + if (!dstBag.hasParameter(paramKey)) { + this.mismatchedLocators.add(srcParam.getLocator()); + continue; + } + + Parameter dstParam = dstBag.getParameter(paramKey); + deepEquals(srcParam, dstParam); + } + + Set dstParamKeySet = dstBag.getParameterKeySet(); + for (String paramKey : dstParamKeySet) { + if (!srcBag.hasParameter(paramKey)) { + Parameter dstParam = dstBag.getParameter(paramKey); + this.mismatchedLocators.add(dstParam.getLocator()); + } + } + } + + protected void deepEquals(Parameter srcParam, Parameter dstParam) { + deepEquals((StrolchElement) srcParam, (StrolchElement) dstParam); + if (!srcParam.getUom().equals(dstParam.getUom())) + this.mismatchedLocators.add(dstParam.getLocator()); + if (!srcParam.getInterpretation().equals(dstParam.getInterpretation())) + this.mismatchedLocators.add(dstParam.getLocator()); + if (srcParam.isHidden() != dstParam.isHidden()) + this.mismatchedLocators.add(dstParam.getLocator()); + + if (!srcParam.getValue().equals(dstParam.getValue())) + this.mismatchedLocators.add(dstParam.getLocator()); + } + + public static boolean isEqual(Order srcOrder, Order dstOrder) { + OrderDeepEqualsVisitor visitor = new OrderDeepEqualsVisitor(srcOrder); + visitor.visit(srcOrder); + return visitor.isEqual(); + } + + public static boolean isEqual(Resource srcRes, Resource dstRes) { + ResourceDeepEqualsVisitor visitor = new ResourceDeepEqualsVisitor(srcRes); + visitor.visit(srcRes); + return visitor.isEqual(); + } +} diff --git a/src/main/java/li/strolch/model/xml/OrderToDomVisitor.java b/src/main/java/li/strolch/model/xml/OrderToDomVisitor.java new file mode 100644 index 000000000..941f7d616 --- /dev/null +++ b/src/main/java/li/strolch/model/xml/OrderToDomVisitor.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.Order; +import li.strolch.model.OrderVisitor; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +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; + } + + @Override + public void visit(Order order) { + DocumentBuilder documentBuilder = DomUtil.createDocumentBuilder(); + Document document = documentBuilder.getDOMImplementation().createDocument(null, null, null); + + Element orderDom = order.toDom(document); + document.appendChild(orderDom); + this.document = document; + } +} diff --git a/src/main/java/li/strolch/model/xml/OrderToSaxVisitor.java b/src/main/java/li/strolch/model/xml/OrderToSaxVisitor.java new file mode 100644 index 000000000..428261ebe --- /dev/null +++ b/src/main/java/li/strolch/model/xml/OrderToSaxVisitor.java @@ -0,0 +1,50 @@ +/* + * 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 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; + +/** + * @author Robert von Burg + */ +public class OrderToSaxVisitor extends StrolchElementToDomVisitor implements OrderVisitor { + + public OrderToSaxVisitor(ContentHandler contentHandler) { + super(contentHandler); + } + + @Override + 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$ + msg = MessageFormat.format(msg, order.getLocator(), e.getMessage()); + throw new RuntimeException(msg, e); + } + } +} diff --git a/src/main/java/li/strolch/model/xml/ResourceToDomVisitor.java b/src/main/java/li/strolch/model/xml/ResourceToDomVisitor.java new file mode 100644 index 000000000..8585ecddf --- /dev/null +++ b/src/main/java/li/strolch/model/xml/ResourceToDomVisitor.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.Resource; +import li.strolch.model.ResourceVisitor; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +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; + } + + @Override + public void visit(Resource resource) { + DocumentBuilder documentBuilder = DomUtil.createDocumentBuilder(); + Document document = documentBuilder.getDOMImplementation().createDocument(null, null, null); + + Element resourceDom = resource.toDom(document); + document.appendChild(resourceDom); + this.document = document; + } +} diff --git a/src/main/java/li/strolch/model/xml/ResourceToSaxVisitor.java b/src/main/java/li/strolch/model/xml/ResourceToSaxVisitor.java new file mode 100644 index 000000000..3bafed894 --- /dev/null +++ b/src/main/java/li/strolch/model/xml/ResourceToSaxVisitor.java @@ -0,0 +1,50 @@ +/* + * 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 java.text.MessageFormat; + +import li.strolch.model.Resource; +import li.strolch.model.ResourceVisitor; +import li.strolch.model.Tags; + +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; + +/** + * @author Robert von Burg + */ +public class ResourceToSaxVisitor extends StrolchElementToDomVisitor implements ResourceVisitor { + + public ResourceToSaxVisitor(ContentHandler contentHandler) { + super(contentHandler); + } + + @Override + 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 (SAXException e) { + String msg = "Failed to transform Resource {0} to XML due to {1}"; //$NON-NLS-1$ + msg = MessageFormat.format(msg, res.getLocator(), e.getMessage()); + throw new RuntimeException(msg, e); + } + } +} diff --git a/src/main/java/li/strolch/model/xml/SimpleStrolchElementListener.java b/src/main/java/li/strolch/model/xml/SimpleStrolchElementListener.java new file mode 100644 index 000000000..79871b281 --- /dev/null +++ b/src/main/java/li/strolch/model/xml/SimpleStrolchElementListener.java @@ -0,0 +1,59 @@ +/* + * 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 java.util.ArrayList; +import java.util.List; + +import li.strolch.model.Order; +import li.strolch.model.Resource; + +/** + * @author Robert von Burg + */ +public class SimpleStrolchElementListener implements StrolchElementListener { + + private List resources; + private List orders; + + @Override + public void notifyResource(Resource resource) { + if (this.resources == null) + this.resources = new ArrayList<>(); + this.resources.add(resource); + } + + @Override + public void notifyOrder(Order order) { + if (this.orders == null) + this.orders = new ArrayList<>(); + this.orders.add(order); + } + + /** + * @return the resources + */ + public List getResources() { + return this.resources; + } + + /** + * @return the orders + */ + public List getOrders() { + return this.orders; + } +} diff --git a/src/main/java/li/strolch/model/xml/StrolchElementToDomVisitor.java b/src/main/java/li/strolch/model/xml/StrolchElementToDomVisitor.java new file mode 100644 index 000000000..dfd939880 --- /dev/null +++ b/src/main/java/li/strolch/model/xml/StrolchElementToDomVisitor.java @@ -0,0 +1,90 @@ +/* + * 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 java.util.Set; + +import li.strolch.model.GroupedParameterizedElement; +import li.strolch.model.Order; +import li.strolch.model.ParameterBag; +import li.strolch.model.StrolchElement; +import li.strolch.model.Tags; +import li.strolch.model.parameter.Parameter; + +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +import ch.eitchnet.utils.iso8601.ISO8601FormatFactory; + +/** + * @author Robert von Burg + */ +public abstract class StrolchElementToDomVisitor { + + protected ContentHandler contentHandler; + + protected StrolchElementToDomVisitor(ContentHandler contentHandler) { + this.contentHandler = contentHandler; + } + + protected AttributesImpl attributesFor(StrolchElement element) { + AttributesImpl attributes = new AttributesImpl(); + attributes.addAttribute(null, null, Tags.ID, Tags.CDATA, element.getId()); + attributes.addAttribute(null, null, Tags.NAME, Tags.CDATA, element.getName()); + attributes.addAttribute(null, null, Tags.TYPE, Tags.CDATA, element.getType()); + 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()); + + if (!Parameter.UOM_NONE.equals(parameter.getUom())) + attributes.addAttribute(null, null, Tags.UOM, Tags.CDATA, parameter.getUom()); + if (!Parameter.INTERPRETATION_NONE.equals(parameter.getInterpretation())) + attributes.addAttribute(null, null, Tags.INTERPRETATION, Tags.CDATA, parameter.getInterpretation()); + if (parameter.isHidden()) + attributes.addAttribute(null, null, Tags.HIDDEN, Tags.CDATA, Boolean.toString(parameter.isHidden())); + + return attributes; + } + + protected void toSax(GroupedParameterizedElement parameterizedElement) throws SAXException { + Set bagKeySet = parameterizedElement.getParameterBagKeySet(); + for (String bagKey : bagKeySet) { + ParameterBag parameterBag = parameterizedElement.getParameterBag(bagKey); + this.contentHandler.startElement(null, null, Tags.PARAMETER_BAG, attributesFor(parameterBag)); + + Set parameterKeySet = parameterBag.getParameterKeySet(); + for (String paramKey : parameterKeySet) { + Parameter parameter = parameterBag.getParameter(paramKey); + this.contentHandler.startElement(null, null, Tags.PARAMETER, attributesFor(parameter)); + this.contentHandler.endElement(null, null, Tags.PARAMETER); + } + + this.contentHandler.endElement(null, null, Tags.PARAMETER_BAG); + } + } +} diff --git a/src/main/java/li/strolch/model/xml/XmlModelDefaultHandler.java b/src/main/java/li/strolch/model/xml/XmlModelDefaultHandler.java index 0195c476f..c47649f2a 100644 --- a/src/main/java/li/strolch/model/xml/XmlModelDefaultHandler.java +++ b/src/main/java/li/strolch/model/xml/XmlModelDefaultHandler.java @@ -15,16 +15,10 @@ */ 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.GroupedParameterizedElement; import li.strolch.model.Order; import li.strolch.model.ParameterBag; import li.strolch.model.Resource; @@ -54,20 +48,16 @@ import ch.eitchnet.utils.iso8601.ISO8601FormatFactory; */ public class XmlModelDefaultHandler extends DefaultHandler { - private static final Logger logger = LoggerFactory.getLogger(XmlModelDefaultHandler.class); + protected static final Logger logger = LoggerFactory.getLogger(XmlModelDefaultHandler.class); - private StrolchElementListener listener; - private File modelFile; + protected StrolchElementListener listener; + protected XmlModelStatistics statistics; - private Resource resource; - private Order order; + private GroupedParameterizedElement parameterizedElement; private ParameterBag pBag; - private XmlModelStatistics statistics; - - public XmlModelDefaultHandler(StrolchElementListener listener, File modelFile) { + public XmlModelDefaultHandler(StrolchElementListener listener) { this.listener = listener; - this.modelFile = modelFile; this.statistics = new XmlModelStatistics(); } @@ -94,7 +84,7 @@ public class XmlModelDefaultHandler extends DefaultHandler { String resName = attributes.getValue(Tags.NAME); String resType = attributes.getValue(Tags.TYPE); Resource resource = new Resource(resId, resName, resType); - this.resource = resource; + this.parameterizedElement = resource; break; case Tags.ORDER: @@ -112,7 +102,7 @@ public class XmlModelDefaultHandler extends DefaultHandler { State orderState = State.valueOf(orderStateS); order.setState(orderState); } - this.order = order; + this.parameterizedElement = order; break; case Tags.PARAMETER_BAG: @@ -121,6 +111,7 @@ public class XmlModelDefaultHandler 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: @@ -165,25 +156,6 @@ public class XmlModelDefaultHandler extends DefaultHandler { 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$ } @@ -196,14 +168,14 @@ public class XmlModelDefaultHandler extends DefaultHandler { case Tags.STROLCH_MODEL: break; case Tags.RESOURCE: - this.listener.notifyResource(this.resource); + this.listener.notifyResource((Resource) this.parameterizedElement); this.statistics.nrOfResources++; - this.resource = null; + this.parameterizedElement = null; break; case Tags.ORDER: - this.listener.notifyOrder(this.order); + this.listener.notifyOrder((Order) this.parameterizedElement); this.statistics.nrOfOrders++; - this.order = null; + this.parameterizedElement = null; break; case Tags.PARAMETER_BAG: this.pBag = null; @@ -217,30 +189,6 @@ public class XmlModelDefaultHandler extends DefaultHandler { } } - 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; diff --git a/src/main/java/li/strolch/model/xml/XmlModelFileHandler.java b/src/main/java/li/strolch/model/xml/XmlModelFileHandler.java new file mode 100644 index 000000000..d75b1261f --- /dev/null +++ b/src/main/java/li/strolch/model/xml/XmlModelFileHandler.java @@ -0,0 +1,104 @@ +/* + * 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 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.Tags; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +import ch.eitchnet.utils.helper.StringHelper; + +/** + * @author Robert von Burg + * + */ +public class XmlModelFileHandler extends XmlModelDefaultHandler { + + private File modelFile; + + /** + * @param listener + * @param modelFile + */ + public XmlModelFileHandler(StrolchElementListener listener, File modelFile) { + super(listener); + this.modelFile = modelFile; + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + + switch (qName) { + + 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); + } + + XmlModelFileHandler handler = new XmlModelFileHandler(this.listener, includeFile); + handler.parseFile(); + this.statistics.nrOfOrders += handler.statistics.nrOfOrders; + this.statistics.nrOfResources += handler.statistics.nrOfResources; + + break; + default: + super.startElement(uri, localName, qName, attributes); + } + } + + 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); + } + } +} diff --git a/src/test/java/li/strolch/model/ModelTest.java b/src/test/java/li/strolch/model/ModelTest.java index cd2d4bc98..86f4cccd2 100644 --- a/src/test/java/li/strolch/model/ModelTest.java +++ b/src/test/java/li/strolch/model/ModelTest.java @@ -16,16 +16,13 @@ package li.strolch.model; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.Date; -import li.strolch.model.ModelGenerator; -import li.strolch.model.Order; -import li.strolch.model.ParameterBag; -import li.strolch.model.Resource; -import li.strolch.model.State; import li.strolch.model.parameter.BooleanParameter; import li.strolch.model.parameter.DateParameter; import li.strolch.model.parameter.FloatParameter; @@ -33,6 +30,8 @@ import li.strolch.model.parameter.IntegerParameter; import li.strolch.model.parameter.LongParameter; import li.strolch.model.parameter.StringListParameter; import li.strolch.model.parameter.StringParameter; +import li.strolch.model.visitor.OrderDeepEqualsVisitor; +import li.strolch.model.visitor.ResourceDeepEqualsVisitor; import org.junit.Test; @@ -55,6 +54,39 @@ public class ModelTest { validateBag(bag); } + @Test + public void shouldPerformDeepResourceEquals() { + Resource srcRes = ModelGenerator.createResource("@res01", "Test resource", "MyType"); + Resource dstRes = ModelGenerator.createResource("@res01", "Test resource", "MyType"); + ResourceDeepEqualsVisitor visitor = new ResourceDeepEqualsVisitor(srcRes); + visitor.visit(dstRes); + assertTrue("Same Resource should be deep equal!", visitor.isEqual()); + } + + @Test + public void shouldFailDeepResourceEquals1() { + Resource srcRes = ModelGenerator.createResource("@res01", "Test resource", "MyType"); + Resource dstRes = ModelGenerator.createResource("@res01", "Test resource", "MyType"); + ParameterBag bag = dstRes.getParameterBag(ModelGenerator.BAG_ID); + bag.setName("Bla bla"); + FloatParameter fParam = bag.getParameter(ModelGenerator.PARAM_FLOAT_ID); + fParam.setValue(23434234.234); + fParam.setName("Ohla"); + 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()); + } + + @Test + public void shouldPerformDeepOrderEquals() { + Order srcOrder = ModelGenerator.createOrder("@ord01", "Test Order", "MyType", new Date(), State.OPEN); + Order dstOrder = ModelGenerator.createOrder("@ord01", "Test Order", "MyType", new Date(), State.OPEN); + OrderDeepEqualsVisitor visitor = new OrderDeepEqualsVisitor(srcOrder); + visitor.visit(dstOrder); + assertTrue("Same Order should be deep equal!", visitor.isEqual()); + } + public static void validateBag(ParameterBag bag) { assertNotNull(bag); diff --git a/src/test/java/li/strolch/model/XmlModelDefaultHandlerTest.java b/src/test/java/li/strolch/model/XmlModelDefaultHandlerTest.java index 2326c7e1d..2a0ecb803 100644 --- a/src/test/java/li/strolch/model/XmlModelDefaultHandlerTest.java +++ b/src/test/java/li/strolch/model/XmlModelDefaultHandlerTest.java @@ -21,11 +21,9 @@ 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 li.strolch.model.xml.XmlModelFileHandler; import org.junit.Test; import org.slf4j.Logger; @@ -60,7 +58,7 @@ public class XmlModelDefaultHandlerTest { orderMap.put(order.getId(), order); } }; - XmlModelDefaultHandler handler = new XmlModelDefaultHandler(listener, file); + XmlModelFileHandler handler = new XmlModelFileHandler(listener, file); handler.parseFile(); assertEquals(3, resourceMap.size()); diff --git a/src/test/java/li/strolch/model/XmlToDomTest.java b/src/test/java/li/strolch/model/XmlToDomTest.java new file mode 100644 index 000000000..76e543665 --- /dev/null +++ b/src/test/java/li/strolch/model/XmlToDomTest.java @@ -0,0 +1,65 @@ +/* + * 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; + +import static org.junit.Assert.assertTrue; +import li.strolch.model.visitor.StrolchElementDeepEqualsVisitor; +import li.strolch.model.xml.OrderToDomVisitor; +import li.strolch.model.xml.ResourceToDomVisitor; + +import org.junit.Test; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * @author Robert von Burg + * + */ +@SuppressWarnings("nls") +public class XmlToDomTest extends ModelTest { + + @Test + public void shouldFormatAndParseOrder() { + + Order order = ModelGenerator.createOrder("@1", "My Order 1", "MyOrder"); + + OrderToDomVisitor domVisitor = new OrderToDomVisitor(); + domVisitor.visit(order); + Document document = domVisitor.getDocument(); + + Element rootElement = document.getDocumentElement(); + Order parsedOrder = new Order(rootElement); + + assertTrue("To DOM and back should equal same Order!", + StrolchElementDeepEqualsVisitor.isEqual(order, parsedOrder)); + } + + @Test + public void shouldFormatAndParseResource() { + + Resource resource = ModelGenerator.createResource("@1", "My Resource 1", "MyResource"); + + ResourceToDomVisitor domVisitor = new ResourceToDomVisitor(); + domVisitor.visit(resource); + Document document = domVisitor.getDocument(); + + Element rootElement = document.getDocumentElement(); + Resource parsedResource = new Resource(rootElement); + + assertTrue("To DOM and back should equal same Resource!", + StrolchElementDeepEqualsVisitor.isEqual(resource, parsedResource)); + } +}