Skip to end of metadata
Go to start of metadata
import java.io.IOException;
import java.util.ArrayList;
import java.util.Hashtable;
import org.geotools.data.FeatureResults;
import org.geotools.data.FeatureSource;
import org.geotools.feature.Feature;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;

/**
 * This class creates an in-memory cache of all features in
 * a FeatureSource.  The cache is keyed on the value of the
 * specified attribute.  This implies that a user can randomly
 * access any feature in the cache by simply passing the value
 * of the key attribute.
 * 
 * @author Scott Melby (www.turnkey-technology.com)
 */
public final class FeatureCache
{
   /**
    * The key attribute name.
    */
   private String m_keyAttr = null;
   
   /**
    * The feature cache.
    * 
    * key - Object: Value of the key attribute that was
    *               specified at construction time.
    * Value - Feature: The feature.
    */
   private Hashtable m_cache = new Hashtable();
   
   /**
    * Features that have duplicate keys.
    */
   private ArrayList m_dupKeyFeatures = new ArrayList();
   
   /**
    * Features that have no value for the key attribute.
    */
   private ArrayList m_noKeyFeatures = new ArrayList();
   
   
   /**
    * Creates a new FeatureCache that stores all features in
    * memory using the value of the specified attribute as
    * the key.
    * 
    * @param source - The feature source to obtain features from.
    * @param keyAttr - The attribute that this cache will be keyed
    *                  on.
    */
   public FeatureCache(FeatureSource source, String keyAttr)
      throws IOException
   {      
      m_keyAttr = keyAttr;
      
      FeatureResults results = source.getFeatures();
      FeatureCollection collection = results.collection();
      FeatureIterator iterator = collection.features();
      while(iterator.hasNext())
      {
         Feature feature = iterator.next();
         
         Object key = feature.getAttribute(keyAttr);
         if(key instanceof String)
         {
            String keyStr = (String)key;
            if(keyStr.trim().length() == 0)
            {
               key = null;
            }             
         }
         

         if(key != null)
         {
            //Found a value for the key attribute, cache the feature
            Feature test  = (Feature)m_cache.put(key, feature);
            if(test != null)
            {
               //cache already had a feature with the specified key,
               //store the one we replaced off for data debugging
               m_dupKeyFeatures.add(test);
            }
         }
         else
         {
            //can't cache the feature since no good value for key attr
            //store the feature off for data debugging
            m_noKeyFeatures.add(feature);
         }
      }           
   }
   
   /**
    * Returns the Feature with the specified attribute value if
    * any feature has this value, null if no features match.
    * 
    * @param attrValue - The value of the key attribute for the
    *                    desired feature.
    */
   public Feature getFeature(Object attrValue)
   {
      return (Feature)m_cache.get(attrValue);
   }

   /**
    * Convenience method that will return the WKT feature
    * geometry for the feature with the specified attribute
    * value if a matching feature is cached, null otherwise.
    * 
    * @param attrValue - The value of the key attribute for the
    *                    desired feature.
    */
   public String getFeatureGeometryWKT(Object attrValue)
   {
      String ret = null;
            
      Feature feature = getFeature(attrValue);
      if(feature != null)
      {
         ret = feature.getDefaultGeometry().toText();
      }
                  
      return ret;
   }

   /**
    * Returns the key attribute for this cache.
    */
   public String getKeyAttr()
   {
      return m_keyAttr;
   }
   
   /**
    * Returns the total number of features in the cache.
    */
   public int getFeatureCount()
   {
      return m_cache.size();
   }
   
   /**
    * Returns all features that were removed from the cache
    * because another feature with the same key value was added.
    * This will be a zero length array if no duplicate key values
    * were encountered.
    */
   public Feature[] getDupKeyFeatures()
   {
      return (Feature[])m_dupKeyFeatures.toArray(new Feature[0]);
   }
   
   /**
    * Returns all features that were not cached because they returned
    * no value (null or zero length string) for the key attribute.
    * This will be a zero length array if all Features had a valid
    * value for the key attribute.
    */
   public Feature[] getNoKeyFeatures()
   {
      return (Feature[])m_noKeyFeatures.toArray(new Feature[0]);
   }   
   
   /**
    * Returns all cached features.  Note: this does not include features
    * that did not have a value for the key attribute etc. 
    */
   public Feature[] getCachedFeatures()
   {
      return (Feature[])m_cache.values().toArray(new Feature[0]);
   }
}

  • No labels