/* * 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; import java.util.AbstractCollection; import java.util.AbstractList; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Queue; import org.geotools.factory.CommonFactoryFinder; import org.geotools.feature.FeatureCollection; import org.geotools.feature.FeatureIterator; import org.geotools.feature.NameImpl; import org.geotools.feature.collection.DecoratingFeatureCollection; import org.geotools.feature.type.FeatureTypeFactoryImpl; import org.geotools.gml3.v3_2.GML; import org.geotools.xs.XS; import org.opengis.feature.Attribute; import org.opengis.feature.Feature; import org.opengis.feature.FeatureFactory; import org.opengis.feature.Property; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.type.AttributeDescriptor; import org.opengis.feature.type.AttributeType; import org.opengis.feature.type.FeatureTypeFactory; import org.opengis.feature.type.Name; import org.opengis.feature.type.Schema; import org.opengis.filter.expression.PropertyName; /** * Wrapping feature collection used by GetPropertyValue operation. * <p> * This feature collection pulls only the specified property out of the delegate feature collection. * </p> * * @author Justin Deoliveira, OpenGeo * */ public class PropertyValueCollection extends AbstractCollection<Attribute> { static FeatureTypeFactory typeFactory = new FeatureTypeFactoryImpl(); static FeatureFactory factory = CommonFactoryFinder.getFeatureFactory(null); FeatureCollection delegate; AttributeDescriptor descriptor; List<Schema> typeMappingProfiles = new ArrayList(); PropertyName propertyName; public PropertyValueCollection(FeatureCollection delegate, AttributeDescriptor descriptor, PropertyName propName) { this.delegate = delegate; this.descriptor = descriptor; this.typeMappingProfiles.add(XS.getInstance().getTypeMappingProfile()); this.typeMappingProfiles.add(GML.getInstance().getTypeMappingProfile()); this.propertyName = propName; } @Override public int size() { // JD: this is a lie, since we skip over features without the attribute return delegate.size(); } @Override public Iterator iterator() { return new PropertyValueIterator(delegate.features()); } class PropertyValueIterator implements Iterator { FeatureIterator it; Feature next; Queue values = new LinkedList(); PropertyValueIterator(FeatureIterator it) { this.it = it; } @Override public boolean hasNext() { if (it == null) { return false; } if (values.isEmpty()) { Object value = null; while (it.hasNext()) { Feature f = (Feature) it.next(); value = propertyName.evaluate(f); if (value != null && !(value instanceof Collection && ((Collection) value).isEmpty())) { next = f; break; } } if (value != null) { if (value instanceof Collection) { values.addAll((Collection) value); } else { values.add(value); } } } if (!values.isEmpty()) { return true; } // close the iterator it.close(); it = null; return false; } @Override public Object next() { Object value = values.remove(); // create a new descriptor based on teh xml type AttributeType xmlType = findType(descriptor.getType().getBinding()); if (xmlType == null) { throw new RuntimeException("Unable to map attribute " + descriptor.getName() + " to xml type"); } // because simple features don't carry around their namespace, create a descritor name // that actually used the feature type schema namespace Name name = new NameImpl(next.getType().getName().getNamespaceURI(), descriptor.getLocalName()); AttributeDescriptor newDescriptor = typeFactory.createAttributeDescriptor(xmlType, name, descriptor.getMinOccurs(), descriptor.getMaxOccurs(), descriptor.isNillable(), descriptor.getDefaultValue()); if (next instanceof SimpleFeature) { return factory.createAttribute(value, newDescriptor, null); } else { return factory .createComplexAttribute( Collections.<Property> singletonList((Property) value), newDescriptor, null); } } @Override public void remove() { throw new UnsupportedOperationException(); } AttributeType findType(Class binding) { for (Schema schema : typeMappingProfiles) { for (Map.Entry<Name, AttributeType> e : schema.entrySet()) { AttributeType at = e.getValue(); if (at.getBinding() != null && at.getBinding().equals(binding)) { return at; } } for (AttributeType at : schema.values()) { if (binding.isAssignableFrom(at.getBinding())) { return at; } } } return null; } } }