org.geotools.feature.ComplexFeatureBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gt-main Show documentation
Show all versions of gt-main Show documentation
The main module contains the GeoTools public interfaces that are used by
other GeoTools modules (and GeoTools applications). Where possible we make
use industry standard terms as provided by OGC and ISO standards.
The formal GeoTools public api consists of gt-metadata, jts and the gt-main module.
The main module contains the default implementations that are available provided
to other GeoTools modules using our factory system. Factories are obtained from
an appropriate FactoryFinder, giving applications a chance configure the factory
used using the Factory Hints facilities.
FilterFactory ff = CommonFactoryFinder.getFilterFactory();
Expression expr = ff.add( expression1, expression2 );
If you find yourself using implementation specific classes chances are you doing it wrong:
Expression expr = new AddImpl( expression1, expressiom2 );
/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2012, 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.feature;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.geotools.factory.CommonFactoryFinder;
import org.opengis.feature.Feature;
import org.opengis.feature.FeatureFactory;
import org.opengis.feature.Property;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.feature.type.FeatureType;
import org.opengis.feature.type.Name;
import org.opengis.feature.type.PropertyDescriptor;
/**
* The complex feature builder allows the construction of features by progressively appending their
* components and deferring the construction till you're ready.
*
* @author Adam Brown (Curtin University of Technology)
*/
public class ComplexFeatureBuilder extends FeatureBuilder {
Map> values = new HashMap>();
AttributeDescriptor ad = null;
public ComplexFeatureBuilder(FeatureType featureType) {
this(featureType, CommonFactoryFinder.getFeatureFactory(null));
}
protected ComplexFeatureBuilder(FeatureType featureType, FeatureFactory factory) {
super(featureType, factory);
}
public ComplexFeatureBuilder(AttributeDescriptor ad) {
this(ad, CommonFactoryFinder.getFeatureFactory(null));
}
protected ComplexFeatureBuilder(AttributeDescriptor ad, FeatureFactory factory) {
super((FeatureType) ad.getType(), factory);
this.ad = ad;
}
/**
* Build and return the feature you've been constructing. If the id is null it will be assigned
* from FeatureBuilder.createDefaultFeatureId().
*/
@Override
public Feature buildFeature(String id) {
// Instantiate if null:
id = id == null ? FeatureBuilder.createDefaultFeatureId() : id;
// Validate the values against the featureType; we need to make sure
// that requirements are honoured:
for (PropertyDescriptor propertyDescriptor : super.featureType.getDescriptors()) {
Name name = propertyDescriptor.getName();
// Create a List of Properties for this name if we don't already
// have one:
if (!values.containsKey(name)) {
values.put(name, new ArrayList());
}
// Get the List of Properties:
List properties = values.get(name);
// See if there's a mismatch between the number of properties and
// minOccurs value:
int minOccurs = propertyDescriptor.getMinOccurs();
int numberOfProperties = properties.size();
if (numberOfProperties < minOccurs) {
// If the value is nillable anyway then just default it to null:
if (propertyDescriptor.isNillable()
&& AttributeDescriptor.class.isAssignableFrom(
propertyDescriptor.getClass())) {
do {
Property nullProperty =
new AttributeImpl(
propertyDescriptor.getType().getBinding().cast(null),
(AttributeDescriptor) propertyDescriptor,
null);
properties.add(nullProperty);
} while (++numberOfProperties < minOccurs);
}
// NOTE: I was wondering if you could have another if-else here
// to try to apply default values if they're set..
// it seems like a good idea but the only problem is that
// they're only present on the AttributeDescriptors...
else {
throw new IllegalStateException(
String.format(
"Failed to build feature '%s'; its property '%s' requires at least %s occurrence(s) but number of occurrences was %s.",
featureType.getName(), name, minOccurs, numberOfProperties));
}
}
}
// Merge the Map> into one collection of
// properties:
Collection properties = new ArrayList();
for (Name key : values.keySet()) {
properties.addAll(values.get(key));
}
this.values.clear();
if (ad != null) {
return factory.createFeature(properties, ad, id);
} else {
return factory.createFeature(properties, featureType, id);
}
}
/**
* Append a property value to the complex feature under construction and associate it with the
* name specified.
*
* @param name The name of the property you wish to set.
* @param value The value of the property to append.
*/
public void append(Name name, Property value) {
PropertyDescriptor propertyDescriptor = featureType.getDescriptor(name);
// The 'name' must exist in the type, if not, throw an exception:
if (propertyDescriptor == null) {
throw new IllegalArgumentException(
String.format(
"The name '%s' is not a valid descriptor name for the type '%s'.",
name, this.featureType.getName()));
}
Class> expectedClass = propertyDescriptor.getType().getBinding();
if (value != null) {
Class> providedClass = value.getType().getBinding();
// Make sure that the provided class and the expected class match or
// that the expectedClass is a base class of the providedClass:
if (!providedClass.equals(expectedClass)
&& !expectedClass.isAssignableFrom(providedClass)) {
throw new IllegalArgumentException(
String.format(
"The value provided contains an object of '%s' but the method expects an object of '%s'.",
providedClass, expectedClass));
}
} else { // value == null
if (propertyDescriptor.isNillable()) {
value = (Property) expectedClass.cast(null);
} else {
// NOTE: This could possibly to changed to allow for processing
// remote xlinks.
value = (Property) expectedClass.cast(null);
}
}
// At this point the converted value has been set so we must persist it
// to the object's state:
ArrayList valueList;
if (values.containsKey(name)) {
valueList = values.get(name);
// Make sure that the list isn't already at capacity:
int maxOccurs = propertyDescriptor.getMaxOccurs();
if (valueList.size() == maxOccurs) {
throw new IndexOutOfBoundsException(
String.format(
"You can't add another object with the name of '%s' because you already have the maximum number (%s) allowed by the property descriptor.",
name, maxOccurs));
}
} else {
valueList = new ArrayList();
values.put(name, valueList);
}
valueList.add(value);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy