/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved. * This code is licensed under the GPL 2.0 license, availible at the root * application directory. */ package org.geoserver.wfs.xml.v1_1_0; import java.util.Iterator; import javax.xml.namespace.QName; import net.opengis.wfs.FeatureCollectionType; import net.opengis.wfs.WfsFactory; import org.geoserver.catalog.Catalog; import org.geoserver.catalog.FeatureTypeInfo; import org.geoserver.feature.CompositeFeatureCollection; import org.geotools.feature.FeatureCollection; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.gml3.GML; import org.geotools.gml3.GMLConfiguration; import org.geotools.xml.AbstractComplexEMFBinding; import org.geotools.xml.Configuration; import org.geotools.xml.ElementInstance; import org.geotools.xml.Node; import org.opengis.referencing.crs.CoordinateReferenceSystem; /** * Binding object for the type http://www.opengis.net/wfs:FeatureCollectionType. * * <p> * <pre> * <code> * <xsd:complexType name="FeatureCollectionType"> * <xsd:annotation> * <xsd:documentation> * This type defines a container for the response to a * GetFeature or GetFeatureWithLock request. If the * request is GetFeatureWithLock, the lockId attribute * must be populated. The lockId attribute can otherwise * be safely ignored. * </xsd:documentation> * </xsd:annotation> * <xsd:complexContent> * <xsd:extension base="gml:AbstractFeatureCollectionType"> * <xsd:attribute name="lockId" type="xsd:string" use="optional"> * <xsd:annotation> * <xsd:documentation> * The value of the lockId attribute is an identifier * that a Web Feature Service generates when responding * to a GetFeatureWithLock request. A client application * can use this value in subsequent operations (such as a * Transaction request) to reference the set of locked * features. * </xsd:documentation> * </xsd:annotation> * </xsd:attribute> * <xsd:attribute name="timeStamp" type="xsd:dateTime" use="optional"> * <xsd:annotation> * <xsd:documentation> * The timeStamp attribute should contain the date and time * that the response was generated. * </xsd:documentation> * </xsd:annotation> * </xsd:attribute> * <xsd:attribute name="numberOfFeatures" * type="xsd:nonNegativeInteger" use="optional"> * <xsd:annotation> * <xsd:documentation> * The numberOfFeatures attribute should contain a * count of the number of features in the response. * That is a count of all features elements dervied * from gml:AbstractFeatureType. * </xsd:documentation> * </xsd:annotation> * </xsd:attribute> * </xsd:extension> * </xsd:complexContent> * </xsd:complexType> * * </code> * </pre> * </p> * * @generated */ public class FeatureCollectionTypeBinding extends AbstractComplexEMFBinding { WfsFactory wfsfactory; Catalog catalog; boolean generateBounds; /** * Boolean property which controls whether the FeatureCollection should be encoded with multiple featureMember * as opposed to a single featureMembers */ boolean encodeFeatureMember; public FeatureCollectionTypeBinding(WfsFactory wfsfactory, Catalog catalog, Configuration configuration) { this.wfsfactory = wfsfactory; this.catalog = catalog; this.generateBounds = !configuration.getProperties().contains(GMLConfiguration.NO_FEATURE_BOUNDS); this.encodeFeatureMember = configuration.getProperties().contains(GMLConfiguration.ENCODE_FEATURE_MEMBER); } public int getExecutionMode() { return OVERRIDE; } /** * @generated */ public QName getTarget() { return WFS.FEATURECOLLECTIONTYPE; } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> * * @generated modifiable */ public Class getType() { return FeatureCollectionType.class; } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> * * @generated modifiable */ public Object parse(ElementInstance instance, Node node, Object value) throws Exception { return value; } public Object getProperty(Object object, QName name) throws Exception { //check for feature collection members if (GML.featureMembers.equals(name)) { // check the WFS configuration, if encode featureMember is selected on WFS configuration // page, return null; if (encodeFeatureMember) { return null; } FeatureCollectionType featureCollection = (FeatureCollectionType) object; if (!featureCollection.getFeature().isEmpty()) { if (featureCollection.getFeature().size() > 1) { // wrap in a single return new CompositeFeatureCollection(featureCollection.getFeature()); } // just return the single return featureCollection.getFeature().iterator().next(); } } else if (GML.featureMember.equals(name)) { // check the WFS configuration, if encode featureMembers is selected on WFS // configuration page, return null; if (!encodeFeatureMember) { return null; } FeatureCollectionType featureCollection = (FeatureCollectionType) object; if (!featureCollection.getFeature().isEmpty()) { if (featureCollection.getFeature().size() > 1) { // wrap in a single return new CompositeFeatureCollection(featureCollection.getFeature()); } // just return the single return featureCollection.getFeature().iterator().next(); } } else if (GML.boundedBy.equals(name) && generateBounds) { FeatureCollectionType featureCollection = (FeatureCollectionType) object; ReferencedEnvelope env = null; for (Iterator it = featureCollection.getFeature().iterator(); it.hasNext();) { FeatureCollection fc = (FeatureCollection) it.next(); if(env == null) { env = fc.getBounds(); } else { env.expandToInclude(fc.getBounds()); } // workaround bogus collection implementation that won't return the crs if(env != null && env.getCoordinateReferenceSystem() == null) { CoordinateReferenceSystem crs = fc.getSchema().getCoordinateReferenceSystem(); if ( crs == null ) { //fall back on catalog FeatureTypeInfo info = catalog.getFeatureTypeByName(fc.getSchema().getName()); if ( info != null ) { crs = info.getCRS(); } } env = new ReferencedEnvelope(env, crs); } if ( env != null ) { //JD: here we don't return the envelope if it is null or empty, this is to work // around and issue with validation in the cite engine. I have opened a jira task // to track this, and hopefully eventually fix the cite engine // http://jira.codehaus.org/browse/GEOS-2700 return !( env.isNull() || env.isEmpty() ) ? env : null; } } } //delegate to parent lookup return super.getProperty(object, name); } }