Hey all,
I've been writing a little filtervisitor today, just to run through a filter
and collect some pertinent information.
Problem is, that 'little' filtervisitor is actually enormous, because there's
not type-generalization built into DefaultFilterVisitor.
Suppose I want to collect all the PropertyNames from a filter (so I can figure
out if someone has provided a filter but not asked for the propertyname in
their query). I write a little filtervisitor to check every node of the filter
and if it's a PropertyName expression, grab the property name.
My class gets really big really quick:
Filter f = ...
FilterVisitor pnCollector = new DefaultFilterVisitor() {
public Object visit(And a, Object o) {
Iterator ichildren = a.getChildren().iterator();
while (ichildren.hasNext()) {
((Filter)ichildren.next()).accept(this, o);
}
return null;
}
public Object visit (Or o, Object o) {
//duplicate method body of And, or else call to a shared function
}
public Object visit (PropertyIsEqualTo p, Object o) {
p.getExpression1().accept(this, o);
p.getExpression2().accept(this, o);
}
public Object visit(<every other BinaryComparisonOperator> p, Object o) {
//call to shared function that looks a lot like the above visit
PropIsEqualTo...
}
public Object visit(<every BinarySpatialOperator> so, Object o) {
//call to shared function from EVERY binaryspatialoperator...
}
... etc ...
};
f.accept(pnCollector);
That's a long implementation that could be considerably shoretened by including
a few convenience methods in DefaultFilterVisitor.
I propose the addition of methods like this:
public Object visit (BinarySpatialOperator o, Object o) {
...
}
and
public Object visit (BinaryComparisonOperator o, Object o) {
...
}
and
public Object visit (Filter f, Object o) {
...
}
and so on (for all the various intermediate interfaces in between
org.opengis.filter.Filter and org.opengis.filter.<leaf-filter-types>, up-to and
including Filter itself)
Further, I propose that DefaultFilterVisitor change its implementation of
'public visit(<Leaf-filter-type> f, Object o)' to call the 'next up the chain'
interface. So, for example, the DefaultFilterVisitor impl of 'visit(Touches f,
Object o)' would look like:
public Object visit(Touches t, Object o) {
return visit((BinarySpatialOperator)t, o);
}
also, visit(bso) would look like:
public Object visit(BinarySpatialOperator f, Object o) {
return visit((SpatialOperator)f, o);
}
etc.
All the way up to Filter, for each type.
This would make those writing FilterVisitors have to write MUCH MUCH less code,
and would allow for good type-based dispatching by allowing someone to interact
with EXACTLY the bits of the filter that they're interested in with much less
code.
If this is a bit confusing for DefaultFilterVisitor, perhaps this could go into
a DefaultFilterVisitor subclass? Perhaps 'HierarchicalFilterVisitor' or
something?
I chatted with aaime about this, and his only concern was that those using IDEs
might be lead astray by having to only implement ONE filter callback method
(visit(Filter f, Object o)) and just use a big switch statement. I agree this
is a risk, but perhaps could be alleviated with good documentation.
Thoughts anyone?
--saul
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Geotools-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/geotools-devel