Package org.geotools.feature

Source Code of org.geotools.feature.ComplexFeatureBuilder

/*
*    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.geotools.feature.AttributeImpl;
import org.geotools.feature.FeatureBuilder;
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 bro879
*
*/
public class ComplexFeatureBuilder extends FeatureBuilder<FeatureType, Feature> {
  Map<Name, ArrayList<Property>> values = new HashMap<Name, ArrayList<Property>>();
 
  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<Property>());
      }

      // Get the List of Properties:
      List<Property> 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<String, ArrayList<Property>> into one collection of
    // properties:
    Collection<Property> properties = new ArrayList<Property>();
    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<Property> 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<Property>();
      values.put(name, valueList);
    }

    valueList.add(value);
  }
}
TOP

Related Classes of org.geotools.feature.ComplexFeatureBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.