package 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 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 =
"" +
"" + lon + " " + lat +
"" +
"";
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 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") ? "" : "" );
String p2 = (nodeName.equals("Polygon") ? "" : "" );
nodeValue =
"" + p1 +
"" + fixCoords(nodeValue) +
"" + p2 +
"";
}
//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");
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