/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 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.geotools.xacml.geoxacml.attr;
import java.io.ByteArrayInputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.sun.xacml.attr.AttributeValue;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
/**
* This class is the implemtation of a XACML geometry attribute as described in the GeoXACML
* specification
*
*
* @author Christian Mueller
*
*/
public class GeometryAttribute extends AttributeValue {
// GeoXACML type
public static final String identifier = "urn:ogc:def:dataType:geoxacml:1.0:geometry";
private Geometry geometry;
private String srsName, gid, gmlType;
private GMLVersion gmlVersion;
private int srsDimension = 2; // default Value
/**
* Constructor
*
* @param geometry
* the jts geometry
* @param srsName
* the srsName, derived from the GML srsName attribute, may be null
* @param gid
* the gid (GML global identifier, my be null)
* @param gmlVersion
* gmlVersion (Version2 or Version3)
* @param gmlType
* the gml type encoded as xml type
* @throws URISyntaxException
*/
public GeometryAttribute(Geometry geometry, String srsName, String gid, GMLVersion gmlVersion,
String gmlType) throws URISyntaxException {
super(new URI(identifier));
this.geometry = geometry;
this.srsName = srsName;
this.gid = gid;
this.gmlVersion = gmlVersion;
this.gmlType = gmlType;
}
/*
* @see com.sun.xacml.attr.AttributeValue#encode()
*
* encodes the attribue as XML Fragment, dependent on the gmlVersion inst var
*/
@Override
public String encode() {
GMLSupport gmlSupport = GMLSupportFactory.getGMLSupport(this);
StringBuffer buff = new StringBuffer();
gmlSupport.encodeASGML(this, buff);
return buff.toString();
}
/**
* @param root
* GML node from an GML DOM
* @return instance of this class or null if there is no Node in the GML namespace
* @throws Exception
* Thrown if GML tree could not be interpreted
*/
public static GeometryAttribute getInstance(Node root) throws Exception {
Node gmlNode = GMLSupport.GMLNS.equals(root.getNamespaceURI()) ? root : null;
if (gmlNode == null) {
NodeList nodelist = root.getChildNodes();
for (int i = 0; i < nodelist.getLength(); i++) {
Node n = nodelist.item(i);
if (GMLSupport.GMLNS.equals(n.getNamespaceURI())) {
gmlNode = n;
break;
}
}
}
if (gmlNode == null) {
Logger.getLogger(GeometryAttribute.class.getName()).severe("No GML node found");
return null;
}
GMLSupport gmlSupport = GMLSupportFactory.getGMLSupport(gmlNode);
GeometryAttribute retval = gmlSupport.buildFromGML(gmlNode);
// System.out.println(retval.getGeometry().getClass()+"\t"+retval.getSrsName()+"\t"+retval.
// hashCode()+"\t"+retval.getGeometry());
return retval;
}
/**
* @param value
* The gml string of a geometry
* @return instance of this class or null if there is no Node in the GML namespace
* @throws Exception
* Thrown if GML String is not valid or GML tree could not be interpreted
*/
public static GeometryAttribute getInstance(String value) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setIgnoringComments(true);
factory.setNamespaceAware(true);
// factory.setIgnoringElementContentWhitespace(true);
factory.setValidating(false);
// create a builder based on the factory & try to parse the GML String
DocumentBuilder db = factory.newDocumentBuilder();
Document doc = db.parse(new ByteArrayInputStream(value.getBytes()));
// handle the policy, if it's a known type
Element root = doc.getDocumentElement();
return getInstance(root);
}
public String getSrsName() {
return srsName;
}
public Geometry getGeometry() {
return geometry;
}
public String getGid() {
return gid;
}
public GMLVersion getGmlVersion() {
return gmlVersion;
}
public String getGmlType() {
return gmlType;
}
public int getSrsDimension() {
return srsDimension;
}
public void setSrsDimension(int crsDimension) {
this.srsDimension = crsDimension;
}
/*
* @see java.lang.Object#equals(java.lang.Object) Must behave like the equals function in the
* GeoXACML specification. Check for SRS and check the coordinates
*/
public boolean equals(Object o) {
if (!(o instanceof GeometryAttribute))
return false;
GeometryAttribute other = (GeometryAttribute) o;
if (srsName == null && other.srsName != null)
return false;
if (srsName != null && srsName.equals(other.srsName) == false)
return false;
return geometry.equalsExact(other.geometry);
}
private int hashCodeForDouble(double value) {
long v = Double.doubleToLongBits(value);
return (int) (v ^ (v >>> 32));
}
/*
* @see java.lang.Object#hashCode()
*
* procues an hash value, the following rule is important if 2 instances of this class are
* compared with equal and the result is true, the hasCodes must be identical
*/
public int hashCode() {
int hashValue = 1;
if (srsName != null)
hashValue = srsName.hashCode();
Envelope env = geometry.getEnvelopeInternal();
if (env.isNull())
return hashValue;
hashValue = hashValue * 31 + hashCodeForDouble(env.getMinX());
hashValue = hashValue * 31 + hashCodeForDouble(env.getMinY());
hashValue = hashValue * 31 + hashCodeForDouble(env.getMaxX());
hashValue = hashValue * 31 + hashCodeForDouble(env.getMaxY());
return hashValue;
}
}