001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2002-2006, GeoTools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.filter;
017:
018: // Geotools dependencies
019: import java.util.Collection;
020: import java.util.HashSet;
021: import java.util.Iterator;
022: import java.util.Set;
023: import java.util.logging.Logger;
024:
025: import org.geotools.filter.expression.PropertyAccessor;
026: import org.geotools.filter.expression.PropertyAccessors;
027: import org.geotools.filter.expression.SimpleFeaturePropertyAccessorFactory;
028: import org.opengis.filter.FilterVisitor;
029: import org.opengis.filter.identity.Identifier;
030:
031: /**
032: * Defines a ID filter, which holds a list of IDs ( usually feature id;s ). This
033: * filter stores a series of IDs, which are used to distinguish features
034: * uniquely.
035: * <p>
036: * Please note that addAllFids( Collection ) may be a performance hog; uDig
037: * makes use of its own implementation of FidFilter in order to reuse the
038: * internal set of fids between uses.
039: * </p>
040: *
041: * @author Rob Hranac, TOPP
042: * @author Justin Deoliveira, TOPP
043: *
044: * TODO: this class shoul be renamed to IdFilterImpl
045: *
046: * @source $URL:
047: * http://svn.geotools.org/geotools/trunk/gt/modules/library/main/src/main/java/org/geotools/filter/FidFilterImpl.java $
048: * @version $Id: FidFilterImpl.java 27862 2007-11-12 19:51:19Z desruisseaux $
049: */
050: public class FidFilterImpl extends AbstractFilterImpl implements
051: FidFilter {
052: /** Logger for the default core module. */
053: private static final Logger LOGGER = org.geotools.util.logging.Logging
054: .getLogger("org.geotools.core");
055:
056: /** List of the Identifer. */
057: private Set fids = new HashSet();
058:
059: /**
060: * Empty constructor.
061: *
062: * @deprecated use {@link #FidFilterImpl(Set)}
063: */
064: protected FidFilterImpl() {
065: super (FilterFactoryFinder.createFilterFactory());
066: filterType = AbstractFilter.FID;
067: }
068:
069: /**
070: * Constructor with first fid set
071: *
072: * @param initialFid
073: * The type of comparison.
074: * @deprecated use {@link #FidFilterImpl(Set)}
075: */
076: protected FidFilterImpl(String initialFid) {
077: super (FilterFactoryFinder.createFilterFactory());
078: filterType = AbstractFilter.FID;
079: addFid(initialFid);
080: }
081:
082: /**
083: * Constructor which takes {@link org.opengis.filter.identity.Identifier},
084: * not String.
085: *
086: */
087: protected FidFilterImpl(Set/* <Identiger> */fids) {
088: super (FilterFactoryFinder.createFilterFactory());
089: filterType = AbstractFilter.FID;
090: // check these are really identifiers
091: for (Iterator it = fids.iterator(); it.hasNext();) {
092: Object next = it.next();
093: if (!(next instanceof Identifier))
094: throw new ClassCastException(
095: "Fids must implement Identifier, "
096: + next.getClass() + " does not");
097: }
098: this .fids = fids;
099: }
100:
101: /**
102: * Returns all the fids in this filter.
103: *
104: * @return An array of all the fids in this filter.
105: *
106: * @deprecated use {@link #getIDs()}
107: */
108: public final String[] getFids() {
109: return (String[]) fids().toArray(new String[0]);
110: }
111:
112: /**
113: * @see org.opengis.filter.Id#getIDs()
114: */
115: public Set getIDs() {
116: return getFidsSet();
117: }
118:
119: /**
120: * @see org.opengis.filter.Id#getIdentifiers()
121: */
122: public Set getIdentifiers() {
123: return fids;
124: }
125:
126: /**
127: * @see org.opengis.filter.identity.FeatureId#setIDs(Set)
128: */
129: public void setIDs(Set ids) {
130: fids = new HashSet();
131: addAllFids(ids);
132: }
133:
134: /**
135: * Accessor method for fid set as Strings.
136: *
137: * @return the internally stored fids.
138: */
139: public Set getFidsSet() {
140: return fids();
141: }
142:
143: /**
144: * Helper method to pull out strings from featureId set.
145: *
146: * @return
147: */
148: private Set fids() {
149: HashSet set = new HashSet();
150: for (Iterator i = fids.iterator(); i.hasNext();) {
151: Identifier id = (Identifier) i.next();
152: set.add(id.toString());
153: }
154:
155: return set;
156: }
157:
158: /**
159: * Adds a feature ID to the filter.
160: *
161: * @param fid
162: * A single feature ID.
163: * @deprecated
164: */
165: public final void addFid(String fid) {
166: LOGGER.finest("got fid: " + fid);
167: fids.add(factory.featureId(fid));
168: }
169:
170: /**
171: * Adds a collection of feature IDs to the filter.
172: *
173: * @param fidsToAdd
174: * A collection of feature IDs as strings.
175: */
176: public void addAllFids(Collection fidsToAdd) {
177: if (fidsToAdd == null)
178: return;
179:
180: for (Iterator i = fidsToAdd.iterator(); i.hasNext();) {
181: String fid = (String) i.next();
182: addFid(fid);
183: }
184: }
185:
186: /**
187: * Removes a feature ID from the filter.
188: *
189: * @param fid
190: * A single feature ID.
191: */
192: public final void removeFid(String fid) {
193: if (fid == null) {
194: return;
195: }
196:
197: for (Iterator f = fids.iterator(); f.hasNext();) {
198: Identifier featureId = (Identifier) f.next();
199: if (fid.equals(featureId.toString())) {
200: f.remove();
201: }
202: }
203:
204: }
205:
206: /**
207: * Removes a collection of feature IDs from the filter.
208: *
209: * @param fidsToRemove
210: * A collection of feature IDs.
211: */
212: public void removeAllFids(Collection fidsToRemove) {
213: if (fidsToRemove == null)
214: return;
215:
216: for (Iterator f = fidsToRemove.iterator(); f.hasNext();) {
217: String fid = (String) f.next();
218: removeFid(fid);
219: }
220: }
221:
222: /**
223: * Determines whether or not the given feature's ID matches this filter.
224: * <p>
225: * In order to get the object's ID, the {@link PropertyAccessor} capable of
226: * dealing with <code>feature</code> has to support the request of the
227: * expression <code>"@id"</code>
228: * </p>
229: *
230: * @param feature
231: * Specified feature to examine.
232: *
233: * @return <tt>true</tt> if the feature's ID matches an fid held by this
234: * filter, <tt>false</tt> otherwise.
235: * @see SimpleFeaturePropertyAccessorFactory
236: */
237: public boolean evaluate(Object feature) {
238: if (feature == null) {
239: return false;
240: }
241:
242: final Set fids = fids();
243: final String attPath = "@id";
244:
245: PropertyAccessor accessor = PropertyAccessors
246: .findPropertyAccessor(feature, attPath, null, null);
247:
248: if (accessor == null) {
249: return false;
250: }
251: Object id = accessor.get(feature, attPath, null);
252: return fids.contains(id);
253: }
254:
255: /**
256: * Returns a string representation of this filter.
257: *
258: * @return String representation of the compare filter.
259: */
260: public String toString() {
261: StringBuffer fidFilter = new StringBuffer();
262:
263: Iterator fidIterator = fids.iterator();
264:
265: while (fidIterator.hasNext()) {
266: fidFilter.append(fidIterator.next().toString());
267:
268: if (fidIterator.hasNext()) {
269: fidFilter.append(", ");
270: }
271: }
272:
273: return "[ " + fidFilter.toString() + " ]";
274: }
275:
276: /**
277: * Used by FilterVisitors to perform some action on this filter instance.
278: * Typicaly used by Filter decoders, but may also be used by any thing which
279: * needs infomration from filter structure. Implementations should always
280: * call: visitor.visit(this); It is importatant that this is not left to a
281: * parent class unless the parents API is identical.
282: *
283: * @param visitor
284: * The visitor which requires access to this filter, the method
285: * must call visitor.visit(this);
286: */
287: public Object accept(FilterVisitor visitor, Object extraData) {
288: return visitor.visit(this , extraData);
289: }
290:
291: /**
292: * Returns a flag indicating object equality.
293: *
294: * @param filter
295: * the filter to test equality on.
296: *
297: * @return String representation of the compare filter.
298: */
299: public boolean equals(Object filter) {
300: LOGGER.finest("condition: " + filter);
301:
302: if ((filter != null) && (filter.getClass() == this .getClass())) {
303: LOGGER.finest("condition: "
304: + ((FidFilterImpl) filter).filterType);
305:
306: if (((FidFilterImpl) filter).filterType == AbstractFilter.FID) {
307: return fids.equals(((FidFilterImpl) filter).fids);
308: } else {
309: return false;
310: }
311: } else {
312: return false;
313: }
314: }
315:
316: /**
317: * Override of hashCode method.
318: *
319: * @return a hash code value for this fid filter object.
320: */
321: public int hashCode() {
322: return fids.hashCode();
323: }
324: }
|