So got a chance to review your code; the tutorial where you register your
function is actually what you need; in your code it looks like you are trying
to cheat the system a bit ... ie so the function is not purely functional - but
is in part configured by an object you passed in. Indeed the object you passed
in looked almost exactly like the function interface so I am not sure what you
are up to...
public static class FunctionWrapper extends FunctionExpressionImpl {
private ISimpleFeatureFilter simpleFeatureFilter;
public FunctionWrapper(ISimpleFeatureFilter simpleFeatureFilter) {
super(simpleFeatureFilter.getName());
this.simpleFeatureFilter = simpleFeatureFilter;
}
@Override
public int getArgCount() {
return 0;
}
@Override
public Object evaluate(Object feature) {
return simpleFeatureFilter.evaluate((SimpleFeature)feature);
}
}
public interface ISimpleFeatureFilter {
public String getName();
public boolean evaluate(SimpleFeature feature);
}
You see how the argument count is 0? This is a sign it is trying to be a
function like random that is volatile in nature; that is the answer is not
strictly dependent on its inputs. With that in mind my original suggestion
still stands - we should have duplicate filter visitor *not* duplicate volatile
functions.
Also if you look in the tutorial you will see a base class AbstractFunction
which should allow the definition of a function with a minimum fuss and bother
if all you are looking to do is save a couple lines of coding with your
ISimpleFeatureFilter interface? I suspect that you have a user interface or
other class that implements ISimpleFeatureFilter and would like to go the
volatile function route ...
Finally you *can* use the Env function to solve this one ...
// this factory needs to be registered with geotools using META_INF/services
etc... as per the tutorial
//
public class FunctionWrapperFactory implements FunctionFactory {
private ArrayList<FunctionName> functionList;
private static FunctionName WRAPPER = new
FunctionNameImpl("wrapper","simpleFeatureFilter");
public synchronized List<FunctionName> getFunctionNames() {
if( functionList == null ){
functionList = new ArrayList<FunctionName>();
functionList.add( WRAPPER );
}
return Collections.unmodifiableList( functionList );
}
public Function function(String name, List<Expression> args, Literal fallback) {
if( "wrapper".equals(name)){
return new AbstractFunction( WRAPPER, args, fallback ){
public Geometry evaluate(Object object) {
Geometry geom = eval(object, 0, Geometry.class );
ISimpleFeatureFilter simpleFeatureFilter = eval( object,0, ISimpleFeatureFilter
);
if( object instanceof SimpleFeatureFilter ){
return simpleFeatureFilter.evaualte( (SimpleFeature) object );
}
else {
return false; // not a simple feature so we cannot filter
}
}
};
}
return null; // we do not implement that function
}
}
public interface ISimpleFeatureFilter {
public String getName();
public boolean evaluate(SimpleFeature feature);
}
In your calling code you have a choice....
static ISimpleFeatureFilter SIMPLE_FILTER = ....
Filter filter = ff.equals( ff.function( "wrapper", ff.literal( SIMPLE_FILTER )
), ff.literal( Boolean.TRUE ) );
1) Your ISimpleFeatureFilter is handed as an literal and thus can be copied
when Style needs to look at it
2) It does not (and your original does not) indicate to the rendering system
what attributes it wants the feature to have; so they may not be requested (and
the feature could be full of empty null values at runtime). Just so you know ...
The other thing you could do is use an environment variable ...
http://docs.geotools.org/latest/javadocs/org/geotools/filter/function/EnvFunction.html
This is a good choice if you want want to change the value over time (perhaps
as your user interacts?).
EnvFunction.setGlobalValue("simple", simpleFeatureFilter );
Filter filter = ff.equals( ff.function( "wrapper", ff.function( "env", "simple"
) ), ff.literal( Boolean.TRUE ) );
.. later ...
EnvFunction.setGlobalValue("simple", simpleFeatureFilter2 );
Do you have a JIRA issue open on this topic? It would be good to record some
ideas and actually solve this; and it would be nice if you can tell me if the
above ideas work (perhaps I can get a blog post or a tutorial out of this
discussion).
--
Jody Garnett
On Tuesday, 5 July 2011 at 8:12 PM, Jody Garnett wrote:
> There is hope :-) Please try the Env function; the javadocs should be enough
> to get you going. I think the idea is:
> 1) construct your filter once using the Env function to refer to your
> selection (perhaps as "selection")
> 2) when the user clicks on something set the "selection" to the appropriate
> value
>
> --
> Jody Garnett
>
>
> On Tuesday, 5 July 2011 at 5:43 PM, LSA wrote:
>
> > Any hope for me? My application is stuck to geotools 2.6.3, just because
> > of that.
> >
> > I even ready for some crippled workaround solution.
> >
> > Sergey
> >
> > On 01.07.2011 10:40, Michael Bedward wrote:
> > > Or are you talking about another example ?
> > > Meanwhile, for Sergey's problem perhaps we could add a function
> > > function to GeoTools: ie. a filter function that takes a user supplied
> > > function, implementing some simple interface, as a parameter.
> > >
> > > Michael
> > >
>
------------------------------------------------------------------------------
All of the data generated in your IT infrastructure is seriously valuable.
Why? It contains a definitive record of application performance, security
threats, fraudulent activity, and more. Splunk takes this data and makes
sense of it. IT sense. And common sense.
http://p.sf.net/sfu/splunk-d2d-c2
_______________________________________________
Geotools-gt2-users mailing list
Geotools-gt2-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geotools-gt2-users