From: Chris H. <ch...@op...> - 2005-07-04 10:15:52
|
Well, you missed a couple things. > not(), and(Filter), or(Filter) These are all implemented by AbstractFilterImpl, which you should extend with your Filter. http://svn.geotools.org/geotools/trunk/gt/module/main/src/org/geotools/filter/AbstractFilterImpl.java Then you don't have to implement them > accept(FilterVisitor). This just needs one line. From the compare filter: /** * 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 void accept(FilterVisitor visitor) { visitor.visit(this); } This javadoc comment is the same as in the Filter interface - you just need to add one line, and it's important we don't just use the parent. The reason we use the visitor pattern is so that we're not loading the implementations with a bunch of encoding specific code. We have visitors to write filters as XML (filter spec) and into various sql formats. So instead of having to fill in code to make a multiple of 400 sql statement in your class, we keep it seperate, in the SQLEncoder: http://svn.geotools.org/geotools/trunk/gt/module/main/src/org/geotools/filter/SQLEncoder.java You don't _have_ to implement your filter in all the encoders, but it allows for nice optimizations and the like. If you have a sql encoder then it will evaluate it in the database, if not then it will just slurp every possible thing from the db, and evaluate it in java code. I think I may agree with your getFilterType criticism. The Filter package needs some good redoing - it's one of our oldest, and hasn't gotten a good rewrite since the initial version was better than the initial data and feature packages. But it needs improvements. We'll probably make use of the geoapi interfaces: http://geoapi.sourceforge.net/snapshot/javadoc/ Which go the more object oriented route you talk about. Also, I think there's a decent chance you should implement your filter as a Function. See the filter spec for more information on functions, and a sample of the functions we implement: http://svn.geotools.org/geotools/trunk/gt/module/main/src/org/geotools/filter/function/ Most are autogenerated, but the ones that aren't prepended by FilterFunction are not. Going a function route means that you won't have to deal with the FilterType stuff, and keeps us more in line with the Filter spec. You're allowed to add as many additional functions as you'd like, but you can't add more Filters. We also should then be able to parse your function, using it against a WFS or in SLD, ect. Does this all make sense? Why don't you try to do it with a function? And if it works out and you have some time add this information to a tutorial on writing your own filter/function. best regards, Chris Quoting Ve...@nu...: > For my application, I need to load in part of a large shape file. > The obvious way to do this is to use a org.geotools.filter.Filter. > I first tried to create the filter in code, by using FilterFactory. > I decided I wanted to load only those features with a DEPTH attribute > with a value equal to a multiple of 400. > There is no MultipleOfFilter, so I thought I'd make one myself. > It is not difficult to implement, something like > > import org.geotools.feature.Feature; > import org.geotools.filter.Expression; > import org.geotools.filter.Filter; > > public class MultipleOfFilter implements Filter > { > private final Expression leftExpression; > private final Expression rightExpression; > > public MultipleOfFilter (final Expression leftExpression, final > Expression rightExpression) > { > this.leftExpression = leftExpression; > this.rightExpression = rightExpression; > } > > public boolean contains (final Feature feature) > { > return contains (leftExpression.getValue (feature), > rightExpression.getValue (feature)); > } > > private boolean contains (final Object leftValue, final Object > rightValue) > { > return > ((leftValue instanceof Number) > && (rightValue instanceof Number) > && ((((Number) leftValue).intValue () % ((Number) > rightValue).intValue ()) == 0)); > } > } > > If only life were so simple. > It turns out that the Filter interface declares not one method, but > six. > The five others are not(), and(Filter), or(Filter), getFilterType(), > and > accept(FilterVisitor). > I thought about implementing these methods, but what filter type to > use? > And why do I need to accept a FilterVistor? > I browsed the docs, then the source code, got lost, and gave up. > > Then I tried to define the filter in xml and read it with a > FilterDOMParser. > I replaced my 'multiple of 400' criterium by a logical or of the > values > I was interested in. > This works fine. > Excellent, problem solved. > > However, the question why I cannot easily implement my > MultipleOfFilter, > keeps bugging me. > The purpose of an interface is, after all, to allow application code > to > create its own implementations of that interface. > A good interface is easy to implement. > The Filter interface, in my humble opinion, is not. > That is unfortunate, because the Filter interface is one of the more > important interfaces in geotools. > > If you are still with me, then I would like to go on with some > thoughts > on how the Filter interface can be made easier to implement. > First, the not() method. > Why does every implementation have to implement this method? > It does not seem too difficult to write a NegateFilter, something > like > > import org.geotools.feature.Feature; > import org.geotools.filter.Expression; > import org.geotools.filter.Filter; > > class NegateFilter implements Filter > { > private final Filter negatedFilter; > > public NegateFilter (final Filter negatedFilter) > { > this.negatedFilter = negatedFilter; > } > > public boolean contains (final Feature feature) > { > return (! this.negatedFilter.contains (feature)); > } > } > > For the and() method, an AllOfFilter could be made in a similar > fashion. > For the or() method, a OneOfFilter or, for the sake of genericity, > N_OfFilter could be made, also in a similar fashion. > > The getFilterType method is a peculiar one. > It is used in constructs such as these in CompareFilterImpl: > > if (filterType == COMPARE_LESS_THAN) { > return (comparison < 0); > } > if (filterType == COMPARE_GREATER_THAN) { > return (comparison > 0); > } > > This, in again my humble opinion, defeats the purpose of object > orientedness. > If there were a LessThanFilter implemented as > > return (comparison < 0); > > and a GreaterThanFilter implemented as > > return (comparison > 0); > > then there is no need for the getFilterType method. > > Finally, the accept method. > This method is used to iterate over a filter and all its subfilters. > It is used mainly in database related code, where filters need to be > converted to the syntax of the database. > Now, I found it a lot easier to implement my filter in xml. > If I have an xml description of my filter, then there is a natural > alternative to convert my filter to another syntax: through an xsl > transformation. > > I am sure I overlooked and/or oversimplified a few things. > Still, I hope some of you find my comments useful. > > As a bonus, the example Filter implementations above are immutable, > which addresses a '@task REVISIT: make immutable' in several filter > related source files. > > Arjan. > > > ***PRIVILEGED AND CONFIDENTIAL*** > The information contained in this e-mail message (including any > attached files) > is intended for the use of the addressee(s) only and is privileged > information. > The information should neither be posted to the Internet, nor > published in any > other public domain, without the express permission of the sender. If > you are > not the intended recipient(s) or the recipient's representative, you > are hereby > notified that any use, disclosure, copying or distribution of this > communication > is prohibited. If you have received this communication in error > please notify us > immediately at pos...@nu..., and remove this message from > your system. > > > ------------------------------------------------------- > SF.Net email is sponsored by: Discover Easy Linux Migration > Strategies > from IBM. Find simple to follow Roadmaps, straightforward articles, > informative Webcasts and more! Get everything you need to get up to > speed, fast. http://ads.osdn.com/?ad_idt77&alloc_id492&op=click > _______________________________________________ > Geotools-gt2-users mailing list > Geo...@li... > https://lists.sourceforge.net/lists/listinfo/geotools-gt2-users > ---------------------------------------------------------- This mail sent through IMP: https://webmail.limegroup.com/ |