001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2004-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; either
009: * version 2.1 of the License, or (at your option) any later version.
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.data.wfs;
017:
018: import java.util.Iterator;
019: import java.util.Map;
020: import java.util.Stack;
021:
022: import org.geotools.filter.AttributeExpression;
023: import org.geotools.filter.BetweenFilter;
024: import org.geotools.filter.CompareFilter;
025: import org.geotools.filter.Expression;
026: import org.geotools.filter.FidFilter;
027: import org.geotools.filter.Filter;
028: import org.geotools.filter.FilterFactoryFinder;
029: import org.geotools.filter.FilterType;
030: import org.geotools.filter.FilterVisitor;
031: import org.geotools.filter.FilterVisitor2;
032: import org.geotools.filter.FunctionExpression;
033: import org.geotools.filter.GeometryFilter;
034: import org.geotools.filter.LikeFilter;
035: import org.geotools.filter.LiteralExpression;
036: import org.geotools.filter.LogicFilter;
037: import org.geotools.filter.MathExpression;
038: import org.geotools.filter.NullFilter;
039: import org.opengis.filter.ExcludeFilter;
040: import org.opengis.filter.IncludeFilter;
041:
042: /**
043: * Changes all the Fids in FidFilters to be translated to the concrete fid.
044: * <p>
045: * WFS has a difficult situation where FIDs are not assigned until after a commit.
046: * So in order to make it easier for the end programmer this visitor will convert any fids
047: * that were returned to client programs before the commit to the final FID after the commit
048: * was made.
049: * </p>
050: *
051: * @author Jesse
052: */
053: public class FidFilterVisitor implements FilterVisitor, FilterVisitor2 {
054:
055: private Stack current = new Stack();
056: private Map fidMap;
057:
058: public FidFilterVisitor(Map fidMap) {
059: this .fidMap = fidMap;
060: }
061:
062: public void visit(ExcludeFilter filter) {
063: current.push(filter);
064: }
065:
066: public void visit(IncludeFilter filter) {
067: current.push(filter);
068: }
069:
070: public void visit(Filter filter) {
071: if (filter instanceof FidFilter) {
072: FidFilter ff = (FidFilter) filter;
073: visit(ff);
074: } else if (filter instanceof LogicFilter) {
075: LogicFilter lf = (LogicFilter) filter;
076: visit(lf);
077: } else
078: current.push(filter);
079: }
080:
081: public void visit(LogicFilter filter) {
082: int stop = current.size();
083: for (Iterator iter = filter.getFilterIterator(); iter.hasNext();) {
084: ((Filter) iter.next()).accept(this );
085: }
086: Filter newFilter;
087: switch (filter.getFilterType()) {
088: case FilterType.LOGIC_AND: {
089: newFilter = (Filter) current.pop();
090: while (current.size() > stop) {
091: newFilter = newFilter.and((Filter) current.pop());
092: }
093: break;
094: }
095: case FilterType.LOGIC_OR: {
096: newFilter = (Filter) current.pop();
097: while (current.size() > stop) {
098: newFilter = newFilter.or((Filter) current.pop());
099: }
100: break;
101: }
102: case FilterType.LOGIC_NOT: {
103: assert current.size() - stop == 1;
104: newFilter = (Filter) current.pop();
105: newFilter = newFilter.not();
106: break;
107: }
108: default:
109: throw new IllegalArgumentException(
110: "Bug in FidFilterVisitor. " + filter
111: + " was not correctly handled by visitor");
112: }
113:
114: current.push(newFilter);
115: }
116:
117: public void visit(FidFilter filter) {
118: String[] fids = filter.getFids();
119: FidFilter newFilter = FilterFactoryFinder.createFilterFactory()
120: .createFidFilter();
121: for (int i = 0; i < fids.length; i++) {
122: String target = getFinalFid(fids[i]);
123: newFilter.addFid(target);
124: }
125: current.push(newFilter);
126: }
127:
128: /**
129: * Returns the final version of the FID. If a commit has changed the FID the new fid will be returned otherwise the same fid will be returned.
130: *
131: * @return the final version of the FID
132: */
133: public synchronized String getFinalFid(String fid) {
134: String finalFid = (String) fidMap.get(fid);
135: if (finalFid == null)
136: return fid;
137: return finalFid;
138: }
139:
140: public void visit(BetweenFilter filter) {
141: current.push(filter);
142: }
143:
144: public void visit(CompareFilter filter) {
145: current.push(filter);
146: }
147:
148: public void visit(GeometryFilter filter) {
149: current.push(filter);
150: }
151:
152: public void visit(LikeFilter filter) {
153: current.push(filter);
154: }
155:
156: public void visit(NullFilter filter) {
157: current.push(filter);
158: }
159:
160: public void visit(LiteralExpression expression) {
161: // nothing todo
162: }
163:
164: public void visit(AttributeExpression expression) {
165: // nothing todo
166: }
167:
168: public void visit(Expression expression) {
169: // nothing todo
170: }
171:
172: public void visit(MathExpression expression) {
173: // nothing todo
174: }
175:
176: public void visit(FunctionExpression expression) {
177: // nothing todo
178: }
179:
180: public org.opengis.filter.Filter getProcessedFilter() {
181: assert current.size() == 1;
182: return (org.opengis.filter.Filter) current.peek();
183: }
184: }
|