/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2002-2016, 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.gml2.bindings;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import javax.xml.namespace.QName;
import org.eclipse.xsd.XSDElementDeclaration;
import org.eclipse.xsd.XSDTypeDefinition;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.geometry.jts.coordinatesequence.CoordinateSequences;
import org.geotools.gml2.GML;
import org.geotools.gml2.GMLConfiguration;
import org.geotools.gml2.SrsSyntax;
import org.geotools.metadata.iso.citation.Citations;
import org.geotools.referencing.CRS;
import org.geotools.referencing.CRS.AxisOrder;
import org.geotools.util.logging.Logging;
import org.geotools.xml.Configuration;
import org.geotools.xml.SchemaIndex;
import org.opengis.feature.Feature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.FeatureType;
import org.opengis.metadata.Identifier;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import com.vividsolutions.jts.geom.Geometry;
/**
* Utility methods used by gml2 bindigns when encodding.
*
* @author Justin Deoliveira, The Open Planning Project, jdeolive@openplans.org
* @author Ben Caradoc-Davies, CSIRO Exploration and Mining
*
*
*
* @source $URL$
*/
public class GML2EncodingUtils {
/** logging instance */
static Logger LOGGER = Logging.getLogger( "org.geotools.gml");
static GMLEncodingUtils e = new GMLEncodingUtils(GML.getInstance());
public static String epsgCode(CoordinateReferenceSystem crs) {
if (crs == null) {
return null;
}
for (Iterator i = crs.getIdentifiers().iterator(); i.hasNext();) {
Identifier id = (Identifier) i.next();
//return "EPSG:" + id.getCode();
if ((id.getAuthority() != null)
&& id.getAuthority().getTitle().equals(Citations.EPSG.getTitle())) {
return id.getCode();
}
}
return null;
}
/**
* @deprecated use {@link #toURI(CoordinateReferenceSystem)}.
*/
public static String crs(CoordinateReferenceSystem crs) {
return toURI(crs);
}
/**
* Encodes the crs object as a uri.
*/
public static String toURI(CoordinateReferenceSystem crs) {
return toURI(crs,false);
}
/**
* Encodes the crs object as a uri.
* <p>
* The axis order of the crs determines which form of uri is used.
* </p>
*/
public static String toURI(CoordinateReferenceSystem crs, boolean forceOldStyle) {
return toURI(crs, forceOldStyle ? SrsSyntax.OGC_HTTP_URL : SrsSyntax.OGC_URN_EXPERIMENTAL);
}
/**
* Encodes the crs object as a uri using the specified syntax.
* <p>
* The axis order of the crs is taken into account. In cases where
* </p>
*/
public static String toURI(CoordinateReferenceSystem crs, SrsSyntax srsSyntax) {
String code = epsgCode(crs);
AxisOrder axisOrder = CRS.getAxisOrder(crs, true);
if (code != null) {
//do an axis order check, if axisOrder is east/north or inapplicable force the legacy
// syntax since the newer syntaxes define a different axis ordering
//JD: TODO: perhaps we don't want to do this override and just want to use the specified
// syntax verbatim, maintaining this check for to maintain the excision behavior of this
// method
if (axisOrder == AxisOrder.EAST_NORTH || axisOrder == AxisOrder.INAPPLICABLE) {
srsSyntax = SrsSyntax.OGC_HTTP_URL;
}
return srsSyntax.getPrefix() + code;
}
// if crs has no EPSG code but its identifier is a URI, then use its identifier
if (crs != null && crs.getName() != null && crs.getName().getCode() != null) {
try {
// test whether identifier is a valid URI
new URI(crs.getName().getCode());
// acceptable to java.net.URI so return it
return crs.getName().getCode();
} catch (URISyntaxException e) {
// not a valid URI so ignore
}
}
return null;
}
/**
* Determines the crs of the geometry by checking {@link Geometry#getUserData()}.
* <p>
* This method returns <code>null</code> when no crs can be found.
* </p>
*/
public static CoordinateReferenceSystem getCRS(Geometry g) {
if (g.getUserData() == null) {
return null;
}
if (g.getUserData() instanceof CoordinateReferenceSystem) {
return (CoordinateReferenceSystem) g.getUserData();
}
if (g.getUserData() instanceof Map) {
Map userData = (Map) g.getUserData();
return (CoordinateReferenceSystem) userData.get(CoordinateReferenceSystem.class);
}
return null;
}
/**
* Determines the identifier (gml:id) of the geometry by checking
* {@link Geometry#getUserData()}.
* <p>
* This method returns <code>null</code> when no id can be found.
* </p>
*/
public static String getID(Geometry g) {
return e.getMetadata( g, "gml:id" );
}
/**
* Set the identifier (gml:id) of the geometry as a key in the user data map
* {@link Geometry#getUserData()} (creating it with{@link Geometry#getUserData()}
* if it does not already exist). If the user data exists and is not a
* {@link Map}, this method has no effect.
*
* @param g the geometry
* @param id the gml:id to be set
*/
public static void setID(Geometry g, String id) {
e.setMetadata(g, "gml:id", id);
}
/**
* Determines the description (gml:description) of the geometry by checking
* {@link Geometry#getUserData()}.
* <p>
* This method returns <code>null</code> when no name can be found.
* </p>
*/
public static String getName(Geometry g) {
return e.getMetadata( g, "gml:name" );
}
/**
* Set the name (gml:name) of the geometry as a key in the user data map
* {@link Geometry#getUserData()} (creating it with{@link Geometry#getUserData()}
* if it does not already exist). If the user data exists and is not a
* {@link Map}, this method has no effect.
*
* @param g the geometry
* @param name the gml:name to be set
*/
public static void setName(Geometry g, String name) {
e.setMetadata(g, "gml:name", name);
}
/**
* Determines the name (gml:name) of the geometry by checking
* {@link Geometry#getUserData()}.
* <p>
* This method returns <code>null</code> when no description can be found.
* </p>
*/
public static String getDescription(Geometry g) {
return e.getMetadata( g, "gml:description" );
}
/**
* Set the description (gml:description) of the geometry as a key in the user data map
* {@link Geometry#getUserData()} (creating it with{@link Geometry#getUserData()}
* if it does not already exist). If the user data exists and is not a
* {@link Map}, this method has no effect.
*
* @param g the geometry
* @param description the gml:description to be set
*/
public static void setDescription(Geometry g, String description) {
e.setMetadata(g, "gml:description", description);
}
public static Element AbstractFeatureType_encode(Object object, Document document, Element value) {
Feature feature = (Feature) object;
FeatureType featureType = feature.getType();
String namespace = featureType.getName().getNamespaceURI();
String typeName = featureType.getName().getLocalPart();
Element encoding = document.createElementNS(namespace, typeName);
encoding.setAttributeNS(null, "fid", feature.getIdentifier().getID());
return encoding;
}
public static List AbstractFeatureType_getProperties(Object object,
XSDElementDeclaration element, SchemaIndex schemaIndex, Set<String> toFilter,
Configuration configuration) {
return e.AbstractFeatureType_getProperties(object, element, schemaIndex, toFilter, configuration);
}
public static XSDTypeDefinition createXmlTypeFromFeatureType(SimpleFeatureType featureType, SchemaIndex schemaIndex, Set<String> toFilter ) {
return e.createXmlTypeFromFeatureType(featureType, schemaIndex, toFilter);
}
public static Object GeometryPropertyType_getProperty(Geometry geometry,
QName name) {
return e.GeometryPropertyType_getProperty(geometry,name);
}
public static Object GeometryPropertyType_getProperty(Geometry geometry,
QName name, boolean includeAbstractGeometry ) {
return e.GeometryPropertyType_getProperty(geometry, name, includeAbstractGeometry);
}
public static List GeometryPropertyType_getProperties(Geometry geometry) {
return e.GeometryPropertyType_getProperties(geometry);
}
/**
* Returns the geometry dimension, either as forced in the configuration, or the geometry
* natural one
*
* @param geometry
* @param config
* @return
*/
public static Integer getGeometryDimension(Geometry geometry, Configuration config) {
if (GMLEncodingUtils.isEmpty(geometry)) {
return null;
}
// check if srsDimension is turned off
if (config.hasProperty(GMLConfiguration.NO_SRS_DIMENSION)) {
return null;
}
/**
* For the dimension, use the actual dimension of the geometry. Using the dimension of the
* CRS is not sufficient, since currently CRSes don't support 3D.
*/
return CoordinateSequences.coordinateDimension(geometry);
}
public static Integer getEnvelopeDimension(ReferencedEnvelope e, Configuration configuration) {
if (e == null || e.isNull() || e.getCoordinateReferenceSystem() == null) {
return null;
}
// check if srsDimension is turned off
if (configuration.hasProperty(GMLConfiguration.NO_SRS_DIMENSION)) {
return null;
}
return e.getCoordinateReferenceSystem().getCoordinateSystem().getDimension();
}
}