/* * Geotoolkit - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library 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 * Lesser General Public License for more details. */ package org.geotoolkit.geometry.isoonjts.spatialschema.geometry; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; import java.text.ParseException; import java.util.logging.Level; import java.util.logging.Logger; import org.geotoolkit.geometry.isoonjts.spatialschema.geometry.geometry.JTSGeometryFactory; import org.geotoolkit.geometry.isoonjts.spatialschema.geometry.primitive.JTSPrimitiveFactory; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.xml.sax.SAXException; import org.xml.sax.InputSource; import org.opengis.geometry.coordinate.GeometryFactory; import org.opengis.geometry.primitive.PrimitiveFactory; import org.opengis.geometry.Geometry; import org.opengis.geometry.PositionFactory; import org.apache.sis.referencing.CommonCRS; import org.apache.sis.util.logging.Logging; import org.geotoolkit.geometry.isoonjts.GeometryParser; /** * @author Jody Garnett * @author Joel Skelton * @module */ public class GeometryTestParser { private static final Logger LOGGER = Logging.getLogger("org.geotoolkit.geometry.isoonjts.spatialschema.geometry"); private DocumentBuilderFactory documentBuilderFactory; private DocumentBuilder documentBuilder; private GeometryParser wktFactory; /** * Constructor */ public GeometryTestParser() { documentBuilderFactory = DocumentBuilderFactory.newInstance(); try { documentBuilder = documentBuilderFactory.newDocumentBuilder(); } catch (ParserConfigurationException e) { throw new RuntimeException("", e); } GeometryFactory geomFact = new JTSGeometryFactory(CommonCRS.WGS84.normalizedGeographic()); PrimitiveFactory primFact = new JTSPrimitiveFactory(CommonCRS.WGS84.normalizedGeographic()); PositionFactory posFact = null; wktFactory = new GeometryParser(geomFact, primFact, posFact, null ); } /** * * @param inputSource * @return */ public GeometryTestContainer parseTestDefinition(final InputSource inputSource) { Document doc = null; try { doc = documentBuilder.parse(inputSource); } catch (SAXException e) { LOGGER.log(Level.WARNING,"", e); throw new RuntimeException("", e); } catch (IOException e) { LOGGER.log(Level.WARNING,"", e); throw new RuntimeException("", e); } Element element = doc.getDocumentElement(); GeometryTestContainer test = null; try { test = processRootNode(element); } catch (ParseException e) { LOGGER.log(Level.WARNING,"", e); throw new RuntimeException("", e); } return test; } /** * Processes the root "run" node * @param node * @return * @throws ParseException */ public GeometryTestContainer processRootNode(final Node node) throws ParseException { if (!node.getNodeName().equalsIgnoreCase("run")) { throw new ParseException("Expected run tag, found " + node.getNodeName(), 0); } GeometryTestContainer test = new GeometryTestContainer(); Node child = node.getFirstChild(); String precisionModel = "FLOATING"; while (child != null) { if (child.getNodeType() == Node.ELEMENT_NODE) { String name = child.getNodeName(); if (name.equalsIgnoreCase("case")) { GeometryTestCase testCase = readTestCase(child); test.addTestCase(testCase); } else if (name.equalsIgnoreCase("precisionmodel")) { precisionModel = getPrecisionModel(child); } else { throw new ParseException("Unexpected: " + name, 0); } } child = child.getNextSibling(); } return test; } /** * parse a single test case * * From looking at various JTS test cases and seeing how their * testbuilder program works, I think its safe to assume that * there will always be just one or two objects, named a and * b. * * @param testCaseNode * @return */ private GeometryTestCase readTestCase(final Node testCaseNode) throws ParseException { Node child = testCaseNode.getFirstChild(); GeometryTestOperation operation = null; GeometryTestCase testCase = new GeometryTestCase(); while (child != null) { if (child.getNodeType() == Node.ELEMENT_NODE) { String name = child.getNodeName(); if (name.equalsIgnoreCase("test")) { testCase.addTestOperation(loadTestOperation(child)); } else if (name.equalsIgnoreCase("a")) { testCase.setGeometryA(loadTestGeometry(child)); } else if (name.equalsIgnoreCase("b")) { testCase.setGeometryB(loadTestGeometry(child)); } else if (name.equalsIgnoreCase("desc")) { testCase.setDescription(getNodeText(child)); } else { throw new ParseException("Unexpected: " + name, 0); } } child = child.getNextSibling(); } return testCase; } /** * Loads a test operation. Assumes that there _must_ be a name attribute, * and looks for arg1, arg2, and arg3. The value of the text subnode is * the value of the expected result * @param testNode a test node from the xml file * @return */ private GeometryTestOperation loadTestOperation(final Node testNode) { Node node = getNamedChild(testNode, "op"); if (node == null) { throw new RuntimeException("<test> element must have <op> subelement"); } String operation = getNodeAttribute(node, "name"); String arg1 = getNodeAttribute(node, "arg1"); String arg2 = getNodeAttribute(node, "arg2"); String arg3 = getNodeAttribute(node, "arg3"); Object expectedResult; String expectedString = getNodeText(node); if (expectedString.trim().equalsIgnoreCase("true")) { expectedResult = Boolean.TRUE; } else if (expectedString.trim().equalsIgnoreCase("false")) { expectedResult = Boolean.FALSE; } else { try { expectedResult = wktFactory.parse(expectedString); } catch (ParseException e) { LOGGER.log(Level.WARNING,"Couldn't parse [" + expectedString + "]", e); throw new RuntimeException("Couldn't parse [" + expectedString + "]", e); } } return new GeometryTestOperation(operation, arg1, arg2, arg3, expectedResult); } private Geometry loadTestGeometry(final Node node) { String wktString = getNodeText(node); Geometry geom = null; try { geom = wktFactory.parse(wktString); } catch (ParseException e) { LOGGER.log(Level.WARNING,"Can't parse [" + wktString + "]", e); throw new RuntimeException("Can't parse [" + wktString + "]", e); } return geom; } private String getPrecisionModel(final Node child) { return getNodeAttribute(child, "type"); } private String getNodeAttribute(final Node node, final String attrName) { String emptyString = ""; NamedNodeMap attrs = node.getAttributes(); if (attrs == null) { return emptyString; } Node attrNode = attrs.getNamedItem(attrName); if (attrNode == null) { return emptyString; } return attrNode.getNodeValue(); } private String getNodeText(final Node node) { Node child = node.getFirstChild(); while (child != null) { if (child.getNodeType() == Node.TEXT_NODE) { return child.getNodeValue(); } } return ""; } private Node getNamedChild(final Node node, final String name) { Node child = node.getFirstChild(); while (child != null) { if (name.equalsIgnoreCase(child.getNodeName())) { return child; } child = child.getNextSibling(); } return null; } }