JavaXT
|
|
Location Classpackage javaxt.rss; import org.w3c.dom.*; import java.math.BigDecimal; //****************************************************************************** //** Location Class //****************************************************************************** /** * Used to represent a location information associated with an RSS feed or * entry. Supports GeoRSS and W3C Basic Geometry. * ******************************************************************************/ public class Location { private org.w3c.dom.Node node; private Object geometry; private BigDecimal lat; private BigDecimal lon; private Boolean hasGeometry = null; //Has 3 states: true, false, and null private static String[] SupportedGeometryTypes = new String[]{ "Point", "Line", "Polygon", "LineString", "Box", "Envelope", "MultiPoint", "MultiLine", "MultiPolygon", "MultiLineString" }; /** GeoRSS NameSpace */ private String georss = "georss"; /** GML NameSpace */ private String gml = "gml"; //************************************************************************** //** Constructor //************************************************************************** /** Creates a new instance of this class using an XML node. */ protected Location(org.w3c.dom.Node node, java.util.HashMap<String, String> namespaces) { this.node = node; String georss = namespaces.get("http://www.georss.org/georss"); if (georss!=null) this.georss = georss; String gml = namespaces.get("http://www.opengis.net/gml"); if (gml==null) this.gml = gml; } //************************************************************************** //** Constructor //************************************************************************** /** Creates a new instance of this class using a point. */ public Location(BigDecimal lat, BigDecimal lon){ this.lat = lat; this.lon = lon; } protected Location(String lat, String lon){ this(new BigDecimal(lat), new BigDecimal(lon)); } /* public String toGML(){ return null; }*/ //************************************************************************** //** toWKT //************************************************************************** /** Used to return a Well-known Text (WKT) representation of the location. */ public String toWKT(){ if (lat!=null && lon!=null){ return "POINT(" + lon + " " + lat + ")"; } return (getGeometry()==null ? null : getGeometry().toString()); } //************************************************************************** //** toString //************************************************************************** /** Used to return a Well-known Text (WKT) representation of the location. */ public String toString(){ return toWKT(); } //************************************************************************** //** getGeometry //************************************************************************** /** Used convert the location into a geometry object. * @return Returns a javaxt.geospatial.geometry.Geometry or a * com.vividsolutions.jts.geom.Geometry, depending on which library is found * in the classpath. If both libraries are present, will return a * javaxt.geospatial.geometry.Geometry object. */ public Object getGeometry(){ if (hasGeometry==null){ if (lat!=null && lon!=null){ String nodeName = "Point"; String nodeValue = "<gml:" + nodeName + ">" + "<gml:coordinates cs=\" \" ts=\",\">" + lon + " " + lat + "</gml:coordinates>" + "</gml:" + nodeName + ">"; geometry = getGeometry(nodeName, nodeValue); } else{ String nodeName = node.getNodeName().toLowerCase(); String nodeValue = Parser.getNodeValue(node).trim(); if (nodeName.equals("where") || nodeName.equals(georss + ":where")){ NodeList nodes = node.getChildNodes(); for (int j=0; j<nodes.getLength(); j++){ node = nodes.item(j); if (node.getNodeType()==1){ nodeName = node.getNodeName(); if (isGeometryNode(nodeName.toLowerCase(), gml, georss)){ geometry = getGeometry(nodeName, Parser.getNodeValue(node)); if (geometry!=null) break; } } } } else if(isGeometryNode(nodeName, gml, georss)){ geometry = getGeometry(nodeName, nodeValue); } } hasGeometry = (geometry==null); } return geometry; } //************************************************************************** //** isLocationNode //************************************************************************** /** Protected method used to help determine whether a node represents a * location. */ protected static boolean isLocationNode(String nodeName, java.util.HashMap<String, String> namespaces){ String georss = namespaces.get("http://www.georss.org/georss"); if (georss==null) georss = "georss"; String gml = namespaces.get("http://www.opengis.net/gml"); if (gml==null) gml = "gml"; return (nodeName.equals("where") || nodeName.equals(georss + ":where") || isGeometryNode(nodeName, gml, georss)); } //************************************************************************** //** isGeometryNode //************************************************************************** /** Private method used to determine whether a node represents a geometry. * @param gml GML NameSpace * @param georss GeoRSS NameSpace */ private static boolean isGeometryNode(String nodeName, String gml, String georss){ String namespace = null; if (nodeName.contains(":")){ namespace = nodeName.substring(0, nodeName.lastIndexOf(":")); nodeName = nodeName.substring(nodeName.lastIndexOf(":")+1); } if (namespace==null || namespace.equals(gml) || namespace.equals(georss)){ for (String geometryType : SupportedGeometryTypes){ if (nodeName.equalsIgnoreCase(geometryType)) return true; } } return false; } //************************************************************************** //** getGeometry //************************************************************************** /** Calls javaxt-gis or jts to try to parse location information. * @param nodeName XML node name (e.g. "gml:Point" or "Point"). This * parameter is required to instantiate the JTS Parser. Note that the * namespace is ignored. */ private Object getGeometry(String nodeName, String nodeValue){ if (nodeValue!=null){ nodeValue = nodeValue.trim(); if (nodeValue.length()==0) nodeValue = null; } if (nodeValue==null) return null; try{ //Try to parse the geometry using the javaxt-gis library Class CoordinateParser = new ClassLoader("javaxt.geospatial.coordinate.Parser", "javaxt-gis.jar").load(); java.lang.reflect.Constructor constructor = CoordinateParser.getDeclaredConstructor(new Class[] {String.class}); java.lang.reflect.Method method = CoordinateParser.getDeclaredMethod("getGeometry"); Object instance = constructor.newInstance(new Object[] { nodeValue }); return method.invoke(instance); } catch(java.lang.ClassNotFoundException e){ //Try to parse the geometry using JTS try{ //Hack for JTS Parser to deal with GeoRSS Simple Geometries if (!nodeValue.startsWith("<")){ String Attributes = ""; if (nodeName.contains(":")){ nodeName = nodeName.substring(nodeName.indexOf(":")+1); } if (nodeName.equals("point")) nodeName = "Point"; else if(nodeName.equals("line")) nodeName = "LineString"; else if(nodeName.equals("polygon")) nodeName = "Polygon"; String p1 = (nodeName.equals("Polygon") ? "<gml:outerBoundaryIs><gml:LinearRing>" : "" ); String p2 = (nodeName.equals("Polygon") ? "</gml:LinearRing></gml:outerBoundaryIs>" : "" ); nodeValue = "<gml:" + nodeName + Attributes + ">" + p1 + "<gml:coordinates cs=\" \" ts=\",\">" + fixCoords(nodeValue) + "</gml:coordinates>" + p2 + "</gml:" + nodeName + ">"; } //Hack for JTS Parser to deal with GML pos and posList tags for (String pos : new String[]{"pos>", "posList>"}){ if (nodeValue.contains(pos)){ StringBuffer str = new StringBuffer(); String[] arr = nodeValue.split(pos); for (int n=0; n<arr.length; n++){ str.append(arr[n]); if (n<arr.length-1){ if ((n % 2 == 0)){ str.append("coordinates cs=\" \" ts=\",\">"); String coords = arr[n+1]; arr[n+1] = coords.substring(coords.indexOf("<")); str.append(fixCoords(coords.substring(0, coords.indexOf("<")))); } else str.append("coordinates>"); } } nodeValue = str.toString().trim(); } } if (nodeValue.startsWith("<")){ //GML Class GMLReader = new ClassLoader("com.vividsolutions.jts.io.gml2.GMLReader", "jts").load(); for (java.lang.reflect.Method method : GMLReader.getDeclaredMethods()){ if (method.getName().equals("read")){ Class[] parameters = method.getParameterTypes(); if (parameters.length==2){ if (parameters[0].getCanonicalName().equals("java.lang.String") && parameters[1].getCanonicalName().equals("com.vividsolutions.jts.geom.GeometryFactory") ){ Object instance = GMLReader.newInstance(); return method.invoke(instance, new Object[] { nodeValue, parameters[1].newInstance() }); } } } } } } catch(java.lang.reflect.InvocationTargetException ex){ Throwable cause = ex.getCause(); if (cause != null){ String msg = cause.getLocalizedMessage(); if (msg!=null) System.err.println(cause.getLocalizedMessage()); } } catch(Exception ex){ //ex.printStackTrace(); } } catch(java.lang.InstantiationException e){} catch(java.lang.NoSuchMethodException e){} catch(java.lang.IllegalAccessException e){} catch(java.lang.reflect.InvocationTargetException e){} return null; } //************************************************************************** //** fixCoords //************************************************************************** /** Used to add commas between coordinate tuples. */ private static String fixCoords(String coords){ coords = coords.trim(); StringBuffer str = new StringBuffer(); String[] arr = coords.split(" "); for (int n=0; n<arr.length; n++){ str.append(arr[n]); if (n<arr.length-1){ if ((n % 2 == 0)) str.append(" "); else str.append(", "); } } return str.toString().trim(); } } //****************************************************************************** //** ClassLoader //****************************************************************************** /** * Simple class loader. Loads a class with a given name. * ******************************************************************************/ class ClassLoader { private String className; private String jarFile; public ClassLoader(String className){ this.className = className; } //************************************************************************** //** Constructor //************************************************************************** /** Used to dynamically Load a jar file along with the the given a class. * @param jarFile Base file name of a jar file. Assumes the file location * is in the same directory as this jar file. */ public ClassLoader(String className, String jarFile){ this.className = className; this.jarFile = jarFile; } public Class load() throws java.lang.ClassNotFoundException { try{ return Class.forName(className); } catch(java.lang.ClassNotFoundException e){ if (jarFile!=null){ try{ java.io.File jar = findJar(jarFile); java.net.URLClassLoader child = new java.net.URLClassLoader( new java.net.URL[]{jar.toURL()}, this.getClass().getClassLoader()); return Class.forName(className, true, child); } catch(Exception ex){} } throw e; } } private java.io.File findJar(String prefix){ java.lang.Class Class = this.getClass(); java.lang.Package Package = Class.getPackage(); java.io.File file = null; //Find physical path of this jar file String path = Package.getName().replace((CharSequence)".",(CharSequence)"/"); String url = Class.getClassLoader().getResource(path).toString(); url = url.replace((CharSequence)" ",(CharSequence)"%20"); try{ java.net.URI uri = new java.net.URI(url); if (uri.getPath()==null){ path = uri.toString(); if (path.startsWith("jar:file:")){ //Update Path and Define Zipped File path = path.substring(path.indexOf("file:/")); path = path.substring(0,path.toLowerCase().indexOf(".jar")+4); if (path.startsWith("file://")){ //UNC Path path = "C:/" + path.substring(path.indexOf("file:/")+7); path = "/" + new java.net.URI(path).getPath(); } else{ path = new java.net.URI(path).getPath(); } file = new java.io.File(path); } } else{ file = new java.io.File(uri); } } catch(Exception e){ e.printStackTrace(); } for (String fileName : file.getParentFile().list()){ if (fileName.toLowerCase().startsWith(prefix.toLowerCase()) && fileName.toLowerCase().endsWith(".jar")) { return new java.io.File(file.getParentFile(), fileName); } } return null; } } |