/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2002-2011, 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.wfs.bindings;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
import javax.xml.namespace.QName;
import net.opengis.wfs20.FeatureCollectionType;
import net.opengis.wfs20.Wfs20Factory;
import org.eclipse.emf.ecore.EObject;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.feature.DefaultFeatureCollection;
import org.geotools.feature.FeatureCollection;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.wfs.CompositeFeatureCollection;
import org.geotools.wfs.v2_0.WFS;
import org.geotools.xml.EMFUtils;
import org.geotools.xml.ElementInstance;
import org.geotools.xml.Node;
import org.opengis.feature.simple.SimpleFeature;
public class WFSParsingUtils {
public static EObject FeatureCollectionType_parse(EObject fct, ElementInstance instance, Node node) {
SimpleFeatureCollection fc = null;
//gml:featureMembers
fc = (SimpleFeatureCollection) node.getChildValue(FeatureCollection.class);
if (fc == null) {
fc = new DefaultFeatureCollection(null, null);
}
//check for an array
SimpleFeature[] featureMembers = (SimpleFeature[]) node.getChildValue(SimpleFeature[].class);
if (featureMembers != null) {
for (int i = 0; i < featureMembers.length; i++) {
fc.add(featureMembers[i]);
}
}
else {
//gml:featureMember
List<SimpleFeature> featureMember = node.getChildValues( SimpleFeature.class );
for (SimpleFeature f : featureMember ) {
fc.add( f );
}
}
if ( !fc.isEmpty() ) {
if (EMFUtils.has(fct, "feature")) {
//wfs 1.0, 1.1
EMFUtils.add(fct, "feature", fc);
}
else {
//wfs 2.0
EMFUtils.add(fct, "member", fc);
}
}
return fct;
}
public static Object FeatureCollectionType_getProperty(EObject fc, QName name) {
List<FeatureCollection> features = features(fc);
FeatureCollection first = features.get( 0 );
if( "boundedBy".equals( name.getLocalPart() ) ) {
ReferencedEnvelope bounds = null;
if ( features.size() == 1 ) {
bounds = first.getBounds();
}
else {
//aggregate
bounds = new ReferencedEnvelope(first.getBounds());
for ( int i = 1; i < features.size(); i++ ) {
bounds.expandToInclude( features.get( i ).getBounds() );
}
}
if (bounds == null || bounds.isNull()) {
//wfs 2.0 does not allow for "gml:Null"
if (WFS.NAMESPACE.equals(name.getNamespaceURI())) {
return null;
}
}
return bounds;
}
if ( "featureMember".equals( name.getLocalPart() ) || "member".equals(name.getLocalPart())) {
if (features.size() == 1) {
//just return the single
return first;
}
//different behaviour across versions, in wfs < 2.0 we merge all the features into
// a single collection, wfs 2.0+ we create a feature collection that contains multiple
// feature collections
if ("featureMember".equals(name.getLocalPart())) {
//wrap in a single
return new CompositeFeatureCollection(features);
}
//we need to recalculate numberMatched, and numberRetunred
int numberMatched = -1;
if (EMFUtils.has(fc, "numberMatched")) {
Number n = (Number) EMFUtils.get(fc, "numberMatched");
numberMatched = n != null ? n.intValue() : -1;
}
else if (EMFUtils.has(fc, "numberOfFeatures")) {
Number n = (Number)EMFUtils.get(fc, "numberOfFeatures");
numberMatched = n != null ? n.intValue() : -1;
}
//create new feature collections
List<FeatureCollectionType> members = new ArrayList(features.size());
for (Iterator<FeatureCollection> it = features.iterator(); it.hasNext(); ) {
FeatureCollection featureCollection = it.next();
FeatureCollectionType member = Wfs20Factory.eINSTANCE.createFeatureCollectionType();
member.setTimeStamp((Calendar) EMFUtils.get(fc, "timeStamp"));
member.getMember().add(featureCollection);
members.add(member);
if (numberMatched == -1) {
continue;
}
//TODO: calling size() here is bad because it requires a nother trip to the
//underlying datastore... perhaps try to keep count of the size of each feature
// collection at a higher level
int size = featureCollection.size();
member.setNumberReturned(BigInteger.valueOf(size));
if (it.hasNext()) {
numberMatched -= size;
member.setNumberMatched(BigInteger.valueOf(size));
}
else {
member.setNumberMatched(BigInteger.valueOf(numberMatched));
}
}
return members;
}
return null;
}
public static List<FeatureCollection> features(EObject obj) {
return (List) (EMFUtils.has(obj, "feature")
? EMFUtils.get(obj, "feature") : EMFUtils.get(obj, "member"));
}
}