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

Reply via email to