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 http://docs.codehaus.org/display/GEOTOOLS/Community+Schema+Support+and+Complex+Types.
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 = reader.next(); 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 = reader2.next(); // code here has access to both aRiver and aHazzard // where aRiver.name = aHazzard.river } reader2.close(); } reader.close();
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]