GeoTools : Expr Examples

Have the first cut of a progamatically doing Joins at an API level between DataStores...

My test for sucess is:

  • Can make SQL out of this for Postgis
  • Can postprocess this for Shapefiles
  • Can do cross DataStore opperations
  • Can do Catalog Queries

Others have other goals ... like

 FeatureType RIVER = river.getSchema();         // schema=[MultilineString:geom,String:name]
 FeatureType HAZZARD = hazard.getSchema(); // schema=[Polygon:geom,String:river,int:category]

 Expr joinExpr = Exprs.attribute("river/name").eq( Exprs.attribute("hazzard/river") );

 FeatureReader reader = river.getFeatures().reader();
 while( reader.hasNext() ){
     Feature aRiver =;

     Expr expr1 = joinExpr.resolve( "river", aRiver ); // bind to a specific Feature
     Expr expr2 = expr2.reduce( "hazzard" ); // modify all hazzard/x to x
     Filter filter = expr2.filter( HAZZARD ); // create a Filter against FeatureType
     FeatureReader reader2 = district.getFeatures( filter );
     while( reader2.hasNext() ){
         Feature aHazzard =;
           // code here has access to both aRiver and aHazzard
           // where = aHazzard.river

The idea is that the Expr is defined to reference attibutes via XPath expressions.
We then "resolve" a named thing (Map, Feature, or Metadata) against the Expr - replacing the AttributeExpr with LiteralExpr
When everything is literal we can evaulate for an answer.

Handling of metadata is done in a similar fashion....

Metadata meta = feature.getMetadata();
Expr query = Exprs.meta("contact/organization").eq( "topp" ).and( Exprs.geom().disjoint( extent ).not() );
if( meta != null ){
    query = expr.resolve( meta );
else {
    query = expr;
Filter filter = query.filter( feature.getFeatureType() );
return filter.contains( feature ); 

h3 Q: What does reduce do?

jrmacgill: what does reduce do?
Jody Garnett: The other thing that Expr does nicely is "flow" when you are writing it as a Java programmer. A couple lines of Expr code is similar to a page of using the FilterFactory.
Jody Garnett: Reduce knocked off a level of xpath. Reducing the expression to something that could be used directly.
Jody Garnett: So Exprs.attribute("river/name").reduce("river") == Exprs.attribute("name")
Jody Garnett: Basically this is used when untangling a Join so we can make a Filter.
Jody Garnett: Could combine the "reduce" and Filter into one opperation. Hey wait that is a great idea.
Jody Garnett: Much clearer.
Jody Garnett: Turn it into something like Exprs.attribute("river/name").filter( "river") would create a Filter that opperated against the "river" FeatureType.
Jody Garnett: Hmm could be done more simply - Need to pass in the FeatureType for late binding, could automatically "reduce" based on the typeName.
Jody Garnett: (As you can see James this is still a work in progress)

And now an idea from RobA:

FeatureView interoperableFeatureType = myConfig.getType("navigableRiver")
FeatureType outer = interoperableFeatureType.getOuter().getSchema();
joinExpr = interoperableFeatureType.getJoinExpressions()[0]