/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2015 - 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.gml3.simple;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import org.eclipse.xsd.XSDElementDeclaration;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.geometry.jts.CircularRing;
import org.geotools.geometry.jts.CircularString;
import org.geotools.geometry.jts.CompoundCurve;
import org.geotools.geometry.jts.CompoundRing;
import org.geotools.geometry.jts.MultiCurve;
import org.geotools.gml2.SrsSyntax;
import org.geotools.gml2.simple.GMLWriter;
import org.geotools.gml2.simple.GeometryEncoder;
import org.geotools.gml2.simple.QualifiedName;
import org.geotools.gml3.GML;
import org.geotools.gml3.GMLConfiguration;
import org.geotools.gml3.bindings.GML3EncodingUtils;
import org.geotools.xml.Configuration;
import org.geotools.xml.Encoder;
import org.geotools.xml.XSD;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.xml.sax.helpers.AttributesImpl;
import com.vividsolutions.jts.geom.GeometryCollection;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.MultiPoint;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;
import org.xml.sax.helpers.NamespaceSupport;
/**
* {@link SimpleFeatureCollection} encoder delegate for fast GML3 encoding
*
* @author Andrea Aime - GeoSolutions
*
*/
public class GML3FeatureCollectionEncoderDelegate extends
org.geotools.gml2.simple.FeatureCollectionEncoderDelegate {
public GML3FeatureCollectionEncoderDelegate(SimpleFeatureCollection features, Encoder encoder) {
super(features, encoder, new GML3Delegate(encoder));
}
static class GML3Delegate implements org.geotools.gml2.simple.GMLDelegate {
SrsSyntax srsSyntax;
static final QualifiedName FEATURE_MEMBERS = new QualifiedName(GML.NAMESPACE,
GML.featureMembers.getLocalPart(), "gml");
static final QualifiedName FEATURE_MEMBER = new QualifiedName(GML.NAMESPACE,
GML.featureMember.getLocalPart(), "gml");
QualifiedName featureMembers;
QualifiedName featureMember;
private String gmlPrefix;
private String gmlUri;
private int numDecimals;
private boolean encodeSeparateMember;
public GML3Delegate(Encoder encoder) {
this.gmlPrefix = findGMLPrefix(encoder);
String gmlURI = encoder.getNamespaces().getURI(gmlPrefix);
this.gmlUri = gmlURI != null ? gmlURI : GML.NAMESPACE;
this.featureMembers = FEATURE_MEMBERS.derive(gmlPrefix, gmlURI);
this.featureMember = FEATURE_MEMBER.derive(gmlPrefix, gmlURI);
this.srsSyntax = (SrsSyntax) encoder.getContext().getComponentInstanceOfType(
SrsSyntax.class);
this.numDecimals = getNumDecimals(encoder.getConfiguration());
this.encodeSeparateMember = encoder.getConfiguration().hasProperty(
GMLConfiguration.ENCODE_FEATURE_MEMBER);
}
String findGMLPrefix(Encoder encoder) {
NamespaceSupport ns = encoder.getNamespaces();
Enumeration<String> p = ns.getPrefixes();
while (p.hasMoreElements()) {
String prefix = p.nextElement();
String uri = ns.getURI(prefix);
if (uri.startsWith(GML.NAMESPACE)) {
return prefix;
}
}
return "gml";
}
private int getNumDecimals(Configuration configuration) {
GMLConfiguration config;
if (configuration instanceof GMLConfiguration) {
config = (GMLConfiguration) configuration;
} else {
config = configuration.getDependency(GMLConfiguration.class);
}
if (config == null) {
return 6;
} else {
return config.getNumDecimals();
}
}
public List getFeatureProperties(SimpleFeature f, XSDElementDeclaration element, Encoder e) {
return GML3EncodingUtils.INSTANCE.AbstractFeatureTypeGetProperties(f, element,
e.getSchemaIndex(), e.getConfiguration());
}
public EnvelopeEncoder createEnvelopeEncoder(Encoder e) {
return new EnvelopeEncoder(e, gmlPrefix, gmlUri);
}
public void setSrsNameAttribute(AttributesImpl atts, CoordinateReferenceSystem crs) {
atts.addAttribute(null, "srsName", "srsName", null,
GML3EncodingUtils.toURI(crs, srsSyntax).toString());
}
@Override
public void setGeometryDimensionAttribute(AttributesImpl atts, int dimension) {
atts.addAttribute(null, "srsDimension", "srsDimension", null, String.valueOf(dimension));
}
public void initFidAttribute(AttributesImpl atts) {
atts.addAttribute(GML.NAMESPACE, "id", "gml:id", null, "");
}
public void startFeatures(GMLWriter handler) throws Exception {
if (!encodeSeparateMember) {
handler.startElement(featureMembers, null);
}
}
public void startFeature(GMLWriter handler) throws Exception {
if (encodeSeparateMember) {
handler.startElement(featureMember, null);
}
}
public void endFeature(GMLWriter handler) throws Exception {
if (encodeSeparateMember) {
handler.endElement(featureMember);
}
}
public void endFeatures(GMLWriter handler) throws Exception {
if (!encodeSeparateMember) {
handler.endElement(featureMembers);
}
}
@Override
public void registerGeometryEncoders(Map<Class, GeometryEncoder> encoders, Encoder encoder) {
encoders.put(Point.class, new PointEncoder(encoder, gmlPrefix, gmlUri));
encoders.put(MultiPoint.class, new MultiPointEncoder(encoder, gmlPrefix, gmlUri));
encoders.put(LineString.class, new LineStringEncoder(encoder, gmlPrefix, gmlUri));
encoders.put(LinearRing.class, new LinearRingEncoder(encoder, gmlPrefix, gmlUri));
encoders.put(MultiLineString.class, new MultiLineStringEncoder(encoder, gmlPrefix, gmlUri, false));
encoders.put(MultiCurve.class, new MultiLineStringEncoder(encoder, gmlPrefix, gmlUri, true));
encoders.put(Polygon.class, new PolygonEncoder(encoder, gmlPrefix, gmlUri));
encoders.put(MultiPolygon.class, new MultiPolygonEncoder(encoder, gmlPrefix, gmlUri));
encoders.put(CircularString.class, new CurveEncoder(encoder, gmlPrefix, gmlUri));
encoders.put(CompoundCurve.class, new CurveEncoder(encoder, gmlPrefix, gmlUri));
encoders.put(CircularRing.class, new CurveEncoder(encoder, gmlPrefix, gmlUri));
encoders.put(CompoundRing.class, new CurveEncoder(encoder, gmlPrefix, gmlUri));
encoders.put(GeometryCollection.class, new GeometryCollectionEncoder(encoder, gmlPrefix, gmlUri));
}
@Override
public String getGmlPrefix() throws Exception {
return gmlPrefix;
}
@Override
public boolean supportsTuples() {
return false;
}
@Override
public void startTuple(GMLWriter output) {
}
@Override
public void endTuple(GMLWriter output) {
}
@Override
public XSD getSchema() {
return GML.getInstance();
}
@Override
public int getNumDecimals() {
return numDecimals;
}
@Override
public boolean forceDecimalEncoding() {
return false;
}
}
}