I'm working on making a Swing application w/geotools.  As such, I am running
across various performance issues.
I am dynamically updating a layer's features(coloring features) and cannot iterate over the FeatureSource's FeatureCollection when applying the filter for Set<FeatureId> without the
attached code.

Would somebody check it out and commit if appropriate.
/*
 *    GeoTools - The Open Source Java GIS Toolkit
 *    http://geotools.org
 * 
 *    (C) 2002-2008, 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.filter;

// Geotools dependencies
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.geotools.factory.CommonFactoryFinder;
import org.geotools.filter.expression.PropertyAccessor;
import org.geotools.filter.expression.PropertyAccessors;
import org.geotools.filter.expression.SimpleFeaturePropertyAccessorFactory;
import org.opengis.filter.FilterVisitor;
import org.opengis.filter.identity.Identifier;

/**
 * Defines a ID filter, which holds a list of IDs ( usually feature id;s ). This
 * filter stores a series of IDs, which are used to distinguish features
 * uniquely.
 * <p>
 * Please note that addAllFids( Collection ) may be a performance hog; uDig
 * makes use of its own implementation of FidFilter in order to reuse the
 * internal set of fids between uses.
 * </p>
 * 
 * @author Rob Hranac, TOPP
 * @author Justin Deoliveira, TOPP
 * 
 * TODO: this class shoul be renamed to IdFilterImpl
 * 
 * @source $URL:
 *         
http://svn.geotools.org/geotools/trunk/gt/modules/library/main/src/main/java/org/geotools/filter/FidFilterImpl.java
 $
 * @version $Id: FidFilterImpl.java 31682 2008-10-19 13:23:25Z aaime $
 */
public class FidFilterImpl extends AbstractFilterImpl implements FidFilter {
        /** Logger for the default core module. */
        private static final Logger LOGGER = 
org.geotools.util.logging.Logging.getLogger("org.geotools.core");

        /** List of the Identifer. */
        private Set fids = new HashSet();
        private Set fidStrs = new HashSet();

        /**
         * Empty constructor.
         * 
         * @deprecated use {...@link #FidFilterImpl(Set)}
         */
        protected FidFilterImpl() {
                super(CommonFactoryFinder.getFilterFactory(null));
                filterType = AbstractFilter.FID;
        }

        /**
         * Constructor with first fid set
         * 
         * @param initialFid
         *            The type of comparison.
         * @deprecated use {...@link #FidFilterImpl(Set)}
         */
        protected FidFilterImpl(String initialFid) {
                super(CommonFactoryFinder.getFilterFactory(null));
                filterType = AbstractFilter.FID;
                addFid(initialFid);
        }

        /**
         * Constructor which takes {...@link 
org.opengis.filter.identity.Identifier},
         * not String.
         * 
         */
        protected FidFilterImpl(Set/* <Identiger> */fids) {
                super(CommonFactoryFinder.getFilterFactory(null));
                filterType = AbstractFilter.FID;
                // check these are really identifiers
                fidStrs = new HashSet() ;
                for (Iterator it = fids.iterator(); it.hasNext();) {
                        Object next = it.next();
                        if (!(next instanceof Identifier))
                                throw new ClassCastException("Fids must 
implement Identifier, "
                                                + next.getClass() + " does 
not");
                        fidStrs.add( ((Identifier)next).toString() ) ;
                }
                this.fids = fids;
        }

        /**
         * Returns all the fids in this filter.
         * 
         * @return An array of all the fids in this filter.
         * 
         * @deprecated use {...@link #getIDs()}
         */
        public final String[] getFids() {
                return (String[]) fids().toArray(new String[0]);
        }

        /**
         * @see org.opengis.filter.Id#getIDs()
         */
        public Set getIDs() {
                return getFidsSet();
        }

        /**
         * @see org.opengis.filter.Id#getIdentifiers()
         */
        public Set getIdentifiers() {
                return fids;
        }

        /**
         * @see org.opengis.filter.identity.FeatureId#setIDs(Set)
         */
        public void setIDs(Set ids) {
                fids = new HashSet();
                addAllFids(ids);
        }

        /**
         * Accessor method for fid set as Strings.
         * 
         * @return the internally stored fids.
         */
        public Set getFidsSet() {
                return fids();
        }

        /**
         * Helper method to pull out strings from featureId set.
         * 
         * @return
         */
        private Set fids() {
                return fidStrs;
                /*Set set = new TreeSet();
                for (Iterator i = fids.iterator(); i.hasNext();) {
                        Identifier id = (Identifier) i.next();
                        set.add(id.toString());
                }
                return set;*/
        }

        /**
         * Adds a feature ID to the filter.
         * 
         * @param fid
         *            A single feature ID.
         * @deprecated
         */
        public final void addFid(String fid) {
                if( LOGGER.isLoggable(Level.FINEST)) {
                        LOGGER.finest("got fid: " + fid);
                }
                fids.add(factory.featureId(fid));
                fidStrs.add( fid ) ;
        }

        /**
         * Adds a collection of feature IDs to the filter.
         * 
         * @param fidsToAdd
         *            A collection of feature IDs as strings.
         */
        public void addAllFids(Collection fidsToAdd) {
                if (fidsToAdd == null)
                        return;

                for (Iterator i = fidsToAdd.iterator(); i.hasNext();) {
                        String fid = (String) i.next();
                        addFid(fid);
                }
        }

        /**
         * Removes a feature ID from the filter.
         * 
         * @param fid
         *            A single feature ID.
         */
        public final void removeFid(String fid) {
                if (fid == null) {
                        return;
                }
                fidStrs.remove(fid);
                for (Iterator f = fids.iterator(); f.hasNext();) {
                        Identifier featureId = (Identifier) f.next();
                        if (fid.equals(featureId.toString())) {
                                f.remove();
                        }
                }

        }

        /**
         * Removes a collection of feature IDs from the filter.
         * 
         * @param fidsToRemove
         *            A collection of feature IDs.
         */
        public void removeAllFids(Collection fidsToRemove) {
                if (fidsToRemove == null)
                        return;
                fidStrs.removeAll(fidsToRemove);
                for (Iterator f = fidsToRemove.iterator(); f.hasNext();) {
                        String fid = (String) f.next();
                        removeFid(fid);
                }
        }

        /**
         * Determines whether or not the given feature's ID matches this filter.
         * <p>
         * In order to get the object's ID, the {...@link PropertyAccessor} 
capable of
         * dealing with <code>feature</code> has to support the request of the
         * expression <code>"@id"</code>
         * </p>
         * 
         * @param feature
         *            Specified feature to examine.
         * 
         * @return <tt>true</tt> if the feature's ID matches an fid held by this
         *         filter, <tt>false</tt> otherwise.
         * @see SimpleFeaturePropertyAccessorFactory
         */
        public boolean evaluate(Object feature) {
                if (feature == null) {
                        return false;
                }

                final Set fids = fids();
                final String attPath = "@id";
                
                PropertyAccessor accessor = 
PropertyAccessors.findPropertyAccessor(feature, attPath, null, null);

                if (accessor == null) {
                        return false;
                }
                Object id = accessor.get(feature, attPath, null);
                return fids.contains(id);
        }

        /**
         * Returns a string representation of this filter.
         * 
         * @return String representation of the compare filter.
         */
        public String toString() {
                StringBuilder fidFilter = new StringBuilder();

                Iterator fidIterator = fids.iterator();

                while (fidIterator.hasNext()) {
                        fidFilter.append(fidIterator.next().toString());

                        if (fidIterator.hasNext()) {
                                fidFilter.append(", ");
                        }
                }

                return "[ " + fidFilter.toString() + " ]";
        }

        /**
         * Used by FilterVisitors to perform some action on this filter 
instance.
         * Typicaly used by Filter decoders, but may also be used by any thing 
which
         * needs infomration from filter structure. Implementations should 
always
         * call: visitor.visit(this); It is importatant that this is not left 
to a
         * parent class unless the parents API is identical.
         * 
         * @param visitor
         *            The visitor which requires access to this filter, the 
method
         *            must call visitor.visit(this);
         */
        public Object accept(FilterVisitor visitor, Object extraData) {
                return visitor.visit(this, extraData);
        }

        /**
         * Returns a flag indicating object equality.
         * 
         * @param filter
         *            the filter to test equality on.
         * 
         * @return String representation of the compare filter.
         */
        public boolean equals(Object filter) {
                if( LOGGER.isLoggable( Level.FINEST) ) {
                        LOGGER.finest("condition: " + filter);
                }

                if ((filter != null) && (filter.getClass() == this.getClass())) 
{
                        if( LOGGER.isLoggable( Level.FINEST ) ) {
                                LOGGER.finest("condition: " + ((FidFilterImpl) 
filter).filterType);
                        }
                        if (((FidFilterImpl) filter).filterType == 
AbstractFilter.FID) {
                                return fids.equals(((FidFilterImpl) 
filter).fids);
                        } else {
                                return false;
                        }
                } else {
                        return false;
                }
        }

        /**
         * Override of hashCode method.
         * 
         * @return a hash code value for this fid filter object.
         */
        public int hashCode() {
                return fids.hashCode();
        }
}
------------------------------------------------------------------------------
_______________________________________________
Geotools-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/geotools-devel

Reply via email to