JavaXT
|
|
Parser Classpackage javaxt.geospatial.coordinate; import javaxt.geospatial.geometry.Box; import javaxt.geospatial.geometry.Geometry; import javaxt.geospatial.geometry.Line; import javaxt.geospatial.geometry.MultiLine; import javaxt.geospatial.geometry.MultiPoint; import javaxt.geospatial.geometry.MultiPolygon; import javaxt.geospatial.geometry.Point; import javaxt.geospatial.geometry.Points; import javaxt.geospatial.geometry.Polygon; import org.w3c.dom.*; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; //****************************************************************************** //** CoordinateParser Class - By Peter Borissow //****************************************************************************** /** * Used to parse a string containing coordinate tuples. Currently limited to * 2D geometries. Optimized for Lat/Long tuples. * ******************************************************************************/ public class Parser { private Geometry Geometry = null; //************************************************************************** //** Creates a new instance of CoordinateParser //************************************************************************** public Parser(String Coordinates){ Geometry = getGeometry(Coordinates); } //************************************************************************** //** getGeometry //************************************************************************** public Geometry getGeometry(){ return Geometry; } //************************************************************************** //** getGeometry //************************************************************************** /** Private function that tries to convert a string of coordinates into a * Geometry. The string may contain coordinate tuples or gml. */ private Geometry getGeometry(String Coordinates){ Coordinates = Coordinates.trim(); if (Coordinates.startsWith("<")){ //GML or GeoRSS input? try{ //Convert Coordinates (String) into a DOM Document org.w3c.dom.Document doc = Parser.createDocument(Coordinates); //Get Outer Node Node OuterNode = Parser.getOuterNode(doc); //Get Name of the First Node String nodeName = getNodeName(OuterNode); //Get the srsName Attribute (may return a value if gml) String srsName = Parser.getAttributeValue(OuterNode,"srsName"); //Point if (nodeName.equalsIgnoreCase("Point")){ if (Parser.hasChildren(OuterNode)==false){ Coordinates = Parser.getNodeValue(OuterNode); return getGeometry(Coordinates.trim()); } else{ //gml Point[] Points = getGMLCoordinates(OuterNode.getChildNodes()); return Points[0]; } } //Line if (nodeName.equalsIgnoreCase("Line")){ if (Parser.hasChildren(OuterNode)==false){ Coordinates = Parser.getNodeValue(OuterNode); return getGeometry(Coordinates.trim()); } else{ //gml? is there such a thing a "line" } } //LineString if (nodeName.equalsIgnoreCase("LineString")){ if (Parser.hasChildren(OuterNode)==false){ Coordinates = Parser.getNodeValue(OuterNode); return getGeometry(Coordinates.trim()); } else{ //gml Point[] Points = getGMLCoordinates(OuterNode.getChildNodes()); Line line = new Line(Points); line.setSRS(Parser.getAttributeValue(OuterNode,"srsName")); return line; } } //Polygon if (nodeName.equalsIgnoreCase("Polygon")){ if (Parser.hasChildren(OuterNode)==false){ Coordinates = Parser.getNodeValue(OuterNode); return getGeometry(Coordinates.trim()); } else{ //gml polygon NodeList outerBoundary = OuterNode.getChildNodes(); Polygon polygon = getGMLPolygon(outerBoundary); polygon.setSRS(Parser.getAttributeValue(OuterNode,"srsName")); return polygon; } } //Box/Envelope if (nodeName.equalsIgnoreCase("Box") || nodeName.equalsIgnoreCase("Envelope")){ Points Points = null; if (Parser.hasChildren(OuterNode)==false){ //georss box Coordinates = Parser.getNodeValue(OuterNode); Points = getPoints(Coordinates); } else{ //gml envelope or box Points = new Points(); NodeList PointMembers = OuterNode.getChildNodes(); //Try to retrieve points defined by upper/lower corners for (int i=0; i<PointMembers.getLength(); i++){ Node node = PointMembers.item(i); nodeName = getNodeName(node); if (nodeName.equalsIgnoreCase("lowerCorner")){ Points.addPoints(getPoints(Parser.getNodeValue(node))); } else if (nodeName.equalsIgnoreCase("upperCorner")){ Points.addPoints(getPoints(Parser.getNodeValue(node))); } } //If no upper/lower tags found, try extracting coordinates using default parser if (Points.getLength()<=0){ Points.addPoints(getGMLCoordinates(PointMembers)); } } if (Points!=null) { if (Points.getLength()==2){ Box box = new Box(Points.getFirstPoint(), Points.getLastPoint()); box.setSRS(Parser.getAttributeValue(OuterNode,"srsName")); return box; } } } //MultiPoint if (nodeName.equalsIgnoreCase("MultiPoint")){ if (Parser.hasChildren(OuterNode)==false){ //what to do? } else{ //gml multipoint MultiPoint MultiPoint = new MultiPoint(); NodeList PointMembers = OuterNode.getChildNodes(); for (int i=0; i<PointMembers.getLength(); i++){ Node node = PointMembers.item(i); if (getNodeName(node).equalsIgnoreCase("PointMember")){ NodeList Points = node.getChildNodes(); for (int j=0; j<Points.getLength(); j++){ if (getNodeName(Points.item(j)).equalsIgnoreCase("Point")){ Point[] arrPoints = getGMLCoordinates(Points.item(j).getChildNodes()); MultiPoint.addPoint(arrPoints[0]); } } } } MultiPoint.setSRS(Parser.getAttributeValue(OuterNode,"srsName")); return MultiPoint; } } //MultiLine if (nodeName.equalsIgnoreCase("MultiLineString")){ if (Parser.hasChildren(OuterNode)==false){ //what to do? } else{ //gml MultiLine MultiLine multiLine = new MultiLine(); NodeList LineMembers = OuterNode.getChildNodes(); for (int i=0; i<LineMembers.getLength(); i++){ Node node = LineMembers.item(i); nodeName = getNodeName(node); if (nodeName.equalsIgnoreCase("lineStringMember")){ NodeList Lines = node.getChildNodes(); for (int j=0; j<Lines.getLength(); j++){ node = Lines.item(j); if (getNodeName(node).equalsIgnoreCase("LineString")){ Point[] points = getGMLCoordinates(node.getChildNodes()); Line line = new Line(points); multiLine.addLine(line); } } } } multiLine.setSRS(Parser.getAttributeValue(OuterNode,"srsName")); return multiLine; } } //MultiPolygon if (nodeName.equalsIgnoreCase("MultiPolygon")){ if (Parser.hasChildren(OuterNode)==false){ //what to do? } else{ //gml MultiPolygon MultiPolygon multiPolygon = new MultiPolygon(); multiPolygon.setSRS(srsName); NodeList PolygonMembers = OuterNode.getChildNodes(); for (int i=0; i<PolygonMembers.getLength(); i++){ Node node = PolygonMembers.item(i); nodeName = getNodeName(node); if (nodeName.equalsIgnoreCase("polygonMember")){ NodeList Polygons = node.getChildNodes(); for (int j=0; j<Polygons.getLength(); j++){ node = Polygons.item(j); nodeName = getNodeName(node); if (nodeName.equalsIgnoreCase("Polygon")){ Polygon polygon = getGMLPolygon(node.getChildNodes()); multiPolygon.addPolygon(polygon); } } } } return multiPolygon; } } } catch(Exception e){ e.printStackTrace(); } } else{ Coordinates = Coordinates.toUpperCase(); if (Coordinates.startsWith("POINT")){ String[] pt = Coordinates.substring(Coordinates.indexOf("(")+1, Coordinates.indexOf(")")).trim().split(" "); return new Point(cdbl(pt[0]), cdbl(pt[1])); } else if (Coordinates.startsWith("POLYGON")){ Coordinates = Coordinates.substring(Coordinates.indexOf("(")+1, Coordinates.indexOf(")")).trim(); Coordinates = Coordinates.substring(Coordinates.indexOf("(")+1).trim(); Points points = new Points(); for (String coord : Coordinates.split(",")){ String[] pt = coord.trim().split(" "); points.addPoint(cdbl(pt[0]), cdbl(pt[1])); } return new Polygon(points); } else if (Coordinates.startsWith("LINESTRING")){ Coordinates = Coordinates.substring(Coordinates.indexOf("(")+1, Coordinates.indexOf(")")).trim(); Coordinates = Coordinates.substring(Coordinates.indexOf("(")+1).trim(); Points points = new Points(); for (String coord : Coordinates.split(",")){ String[] pt = coord.trim().split(" "); points.addPoint(cdbl(pt[0]), cdbl(pt[1])); } return new Line(points); } else{ Points Points = getPoints(Coordinates); if (Points.getLength()==1){ return Points.getFirstPoint(); } else{ if (Points.getFirstPoint().equals(Points.getLastPoint())){ return new Polygon(Points); } else{ return new Line(Points); } } } } return null; } //************************************************************************** //** getGMLPolygon //************************************************************************** /** Used to convert a gml nodelist into a polygon */ private Polygon getGMLPolygon(NodeList outerBoundary){ for (int i=0; i<outerBoundary.getLength(); i++){ Node node = outerBoundary.item(i); String nodeName = getNodeName(node); if (nodeName.equalsIgnoreCase("outerBoundaryIs") || nodeName.equalsIgnoreCase("exterior")){ NodeList LinearRing = node.getChildNodes(); for (int j=0; j<LinearRing.getLength(); j++){ node = LinearRing.item(i); nodeName = getNodeName(node); Point[] Points = getGMLCoordinates(node.getChildNodes()); return new Polygon(Points); } } else if(nodeName.equalsIgnoreCase("LinearRing")){ return new Polygon(getGMLCoordinates(node.getChildNodes())); } } return null; } //************************************************************************** //** getGMLCoordinates //************************************************************************** /** Used to convert a gml nodelist containing coordinates to a Point array */ private Point[] getGMLCoordinates(org.w3c.dom.NodeList ChildNodes){ String CoordinateSeparator = ","; String TupleSeparator = " "; Points Points = new Points(); for (int i=0; i<ChildNodes.getLength(); i++){ Node Node = ChildNodes.item(i); String NodeName = getNodeName(Node); //Parse Coordinate List if (NodeName.equalsIgnoreCase("coordinates")){ String cs = Parser.getAttributeValue(Node, "cs"); String ts = Parser.getAttributeValue(Node, "ts"); if (cs.length()>0) CoordinateSeparator = cs; if (ts.length()>0) TupleSeparator = ts; String Coordinates = Parser.getNodeValue(Node).trim(); String[] points = Coordinates.split(TupleSeparator); for (int j=0; j<points.length; j++){ String point = points[j].trim(); if (point.length()>0){ String[] pt = point.split(CoordinateSeparator); if (pt.length==2){ point = pt[0].trim() + "," + pt[1].trim(); Points.addPoints(getPoints(point)); } } } } //Parse Position List else if(NodeName.equalsIgnoreCase("pos") || NodeName.equalsIgnoreCase("posList")){ String Coordinates = Parser.getNodeValue(Node).trim(); //Points.addPoints(Coordinates); Points.addPoints(getPoints(Coordinates)); } //Parse Nested Coordinates else if (NodeName.equalsIgnoreCase("coord")){ NodeList Coords = Node.getChildNodes(); String x = ""; String y = ""; for (int j=0; j<Coords.getLength(); j++){ Node Coord = Coords.item(j); String CoordName = getNodeName(Coord); if (CoordName.equalsIgnoreCase("x")){ x = Parser.getNodeValue(Coord).trim(); } if (CoordName.equalsIgnoreCase("y")){ y = Parser.getNodeValue(Coord).trim(); } } if (x.length()>0 && y.length()>0){ Points.addPoints(getPoints(x + "," + y)); } } else{ //throw an error? System.out.println(NodeName); } } return Points.getArray(); } //************************************************************************** //** getPoints //************************************************************************** /** Used to convert a string containing coordinate tuples (x,y) into an * array of points. Only use with Lat/Long coordinate tuples. */ private Points getPoints(String strGeometry) { strGeometry = replace(strGeometry,"\t"," "); strGeometry = replace(strGeometry,"\n"," "); strGeometry = replace(strGeometry,"\r"," "); strGeometry = strGeometry.trim(); if (strGeometry.length() == 0) return null; //Convert Degrees, minutes, seconds symbols (37° 23" 12') strGeometry = replace(strGeometry,"°",":"); strGeometry = replace(strGeometry,"\"",":"); strGeometry = replace(strGeometry,"'",""); //Convert All Deliminators into Whitespaces String wd = ""; String Char = ""; for (int i=0; i<strGeometry.length(); i++){ //i=1; i<=len(strGeometry) Char = strGeometry.substring(i, i+1); //mid(strGeometry,i,1); if (Case(Char.toLowerCase(), new String[]{":", ".", "+", "-", "n", "s", "e", "w", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"})){ wd = wd + Char; } else { wd = wd + " "; } } strGeometry = wd; //System.out.println("[" + strGeometry + "]"); //Compress WhiteSpaces wd = ""; String prevChar = ""; for (int i=0; i<strGeometry.length(); i++){ //i=1; i<=len(strGeometry) Char = strGeometry.substring(i, i+1); //mid(strGeometry,i,1); if (i>0) prevChar = strGeometry.substring(i-1, i); //mid(strGeometry,i-1,1); if (Char.equals(" ") && prevChar.equals(" ")) {} //'do nothing else{ wd = wd + Char; } } strGeometry = wd.trim(); //System.out.println("[" + strGeometry + "]"); //Create an Array String[] arr = split(strGeometry," "); Points points = new Points(); double x=0; double y=0; for (int i=0; i<arr.length; i++){ //i<=ubound(pt) if (isEven(i)) { //'(x,y) //System.out.println("x=" + pt[i]); x = Formatter.ConvertDMStoDD(arr[i]); } else{ //System.out.println("y=" + pt[i]); y = Formatter.ConvertDMStoDD(arr[i]); points.addPoint(x,y); } } return points; } //************************************************************************** //** isEven //************************************************************************** /** Used to determine whether a integer is even or odd. */ private boolean isEven(int n) { return (n % 2 == 0); } //************************************************************************** //** Case //************************************************************************** private boolean Case(String SearchCondition, String[] SearchParameters){ for (int i=0; i<SearchParameters.length; i++){ if (SearchParameters[i].equals(SearchCondition)) return true; } return false; } //************************************************************************** //** getNodeName //************************************************************************** /** Used to retrieve the name of a given node. Removes namespace prefix. */ private String getNodeName(org.w3c.dom.Node Node){ String nodeName = Node.getNodeName(); //Strip Namespace if (nodeName.contains((CharSequence)":")){ nodeName = nodeName.substring(nodeName.indexOf(":")+1); } return nodeName; } //************************************************************************** //** cdbl //************************************************************************** /** Used to convert a string to a double */ private double cdbl(String str){ return Double.valueOf(str).doubleValue(); } //************************************************************************** //** String Utils - Artifacts from VB Port //************************************************************************** private String replace(String str, String find, String replacement){ return str.replace((CharSequence)find,(CharSequence)replacement); } private String[] split(String str, String ch){ //String metaChars = "([{\^-$|])?*+."; String inValidChars = "\\.[]|(){^-$?*+"; for (int i=0; i < inValidChars.length(); i++){ String target = inValidChars.charAt(i) + ""; ch = replace(ch,target,"\\" + target); } return str.split(ch); } // <editor-fold defaultstate="collapsed" desc="XML parsing methods copied from javaxt.xml.DOM"> //************************************************************************** //** createDocument //************************************************************************** /** Used to create a DOM document from a String. */ private static Document createDocument(String xml){ xml = xml.trim(); String encoding = "UTF-8"; try{ String xmlHeader = xml.substring(xml.indexOf("<?"), xml.indexOf("?>")); if (xmlHeader.contains(" encoding")){ encoding = xmlHeader.substring(xmlHeader.indexOf(" encoding")+" encoding".length()); encoding = encoding.substring(encoding.indexOf("=")+1); while(encoding.substring(0, 1).equals(" ")){ encoding = encoding.substring(1); } if (encoding.substring(0, 1).equals("\"")){ encoding = encoding.substring(1); encoding = encoding.substring(0, encoding.indexOf("\"")).trim(); } else{ encoding = encoding.substring(0, encoding.indexOf(" ")).trim(); } } } catch(Exception e){} java.io.InputStream is; try{ is = (new java.io.ByteArrayInputStream(xml.getBytes(encoding))); } catch(Exception e){ is = (new java.io.ByteArrayInputStream(xml.getBytes())); } try{ DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = builderFactory.newDocumentBuilder(); return builder.parse(is); } catch(Exception e){ return null; } } //************************************************************************** //** getOuterNode //************************************************************************** /** Returns the outer node for a given xml document. * @param xml A org.w3c.dom.Document */ private static Node getOuterNode(Document xml){ if (xml==null) return null; NodeList OuterNodes = xml.getChildNodes(); for (int i=0; i<OuterNodes.getLength(); i++ ) { if (OuterNodes.item(i).getNodeType() == 1){ return OuterNodes.item(i); } } return null; } //************************************************************************** //** getAttributeValue //************************************************************************** /** Used to return the value of a given node attribute. The search is case * insensitive. If no match is found, returns an empty string. */ private static String getAttributeValue(Node node, String attrName){ NamedNodeMap attrCollection = node.getAttributes(); if (attrCollection!=null){ for (int i=0; i < attrCollection.getLength(); i++ ) { Node attr = attrCollection.item(i); if (attr.getNodeName().equalsIgnoreCase(attrName)) { return attr.getNodeValue(); } } } return ""; } //************************************************************************** //** getNodeValue //************************************************************************** /** Returns the value of a given node as text. */ private static String getNodeValue(Node node){ String nodeValue = ""; if (hasChildren(node)) { StringBuffer xmlTree = new StringBuffer(); traverse(node, xmlTree); nodeValue = xmlTree.toString(); } else{ nodeValue = node.getTextContent(); } if (nodeValue == null){ return ""; } else{ return nodeValue; } } private static void traverse(Node tree, StringBuffer xmlTree){ if (tree.getNodeType()==1){ String Attributes = getAttributes(tree); xmlTree.append("<" + tree.getNodeName() + Attributes + ">"); if (hasChildren(tree)) { NodeList xmlNodeList = tree.getChildNodes(); for (int i=0; i<xmlNodeList.getLength(); i++){ traverse(xmlNodeList.item(i), xmlTree); } } else{ String nodeValue = tree.getTextContent(); if (nodeValue == null){ nodeValue = ""; } xmlTree.append(nodeValue); } xmlTree.append("</" + tree.getNodeName() + ">"); } } //************************************************************************** //** getAttributes //************************************************************************** /** Used to retrieve all of the attributes for a given node. */ private static String getAttributes(Node node){ if (node==null) return ""; NamedNodeMap attr = node.getAttributes(); String Attributes = ""; if (attr!=null){ for (int j=0; j<attr.getLength(); j++){ String name = attr.item(j).getNodeName(); String value = attr.item(j).getTextContent(); if (value==null) value = attr.item(j).getNodeValue(); if (value==null) value = ""; //System.out.println(name + "=" + attr.item(j).getNodeValue()); Attributes += " " + name + "=\"" + value + "\""; } } return Attributes; } //************************************************************************** //** hasChildren //************************************************************************** /** Used to determine whether a given node has any children. Differs from the * native DOM implementation in that this function only considers child * nodes that have a node type value equal to 1. */ private static boolean hasChildren(Node node){ NodeList nodeList = node.getChildNodes(); for (int i=0; i<nodeList.getLength(); i++ ) { if (nodeList.item(i).getNodeType()==1){ return true; } } return false; } // </editor-fold> } |