Strabon
changeset 1403:66958cde6661
Fixed bug #72. The same bug applies to other functions apart from these that return the SRID, such as all the property functions, postgis functions, etc.
author | Babis Nikolaou <charnik@di.uoa.gr> |
---|---|
date | Sat Sep 20 19:36:24 2014 +0300 (2014-09-20) |
parents | 1f2f22747854 |
children | 1b3558b9e2e8 |
files | evaluation/src/main/java/org/openrdf/query/algebra/evaluation/function/spatial/SpatialPropertyFunc.java evaluation/src/main/java/org/openrdf/query/algebra/evaluation/util/JTSWrapper.java generaldb/src/main/java/org/openrdf/sail/generaldb/evaluation/GeneralDBEvaluation.java generaldb/src/main/java/org/openrdf/sail/generaldb/optimizers/GeneralDBSelectQueryOptimizer.java |
line diff
1.1 --- a/evaluation/src/main/java/org/openrdf/query/algebra/evaluation/function/spatial/SpatialPropertyFunc.java Sat Sep 20 15:08:58 2014 +0300 1.2 +++ b/evaluation/src/main/java/org/openrdf/query/algebra/evaluation/function/spatial/SpatialPropertyFunc.java Sat Sep 20 19:36:24 2014 +0300 1.3 @@ -9,6 +9,7 @@ 1.4 */ 1.5 package org.openrdf.query.algebra.evaluation.function.spatial; 1.6 1.7 +import org.apache.log4j.Logger; 1.8 import org.openrdf.model.Value; 1.9 import org.openrdf.model.ValueFactory; 1.10 import org.openrdf.query.algebra.evaluation.ValueExprEvaluationException; 1.11 @@ -28,13 +29,14 @@ 1.12 */ 1.13 public abstract class SpatialPropertyFunc implements Function { 1.14 1.15 + private static Logger logger = Logger.getLogger(org.openrdf.query.algebra.evaluation.function.spatial.SpatialPropertyFunc.class); 1.16 + 1.17 //No need for any implementation, I will have replaced this class's presence before reaching this place 1.18 public Value evaluate(ValueFactory valueFactory, Value... args) 1.19 throws ValueExprEvaluationException { 1.20 - 1.21 + logger.error(this.getURI() + ": I should have been taken care of before in GeneralDBEvaluation.evaluate(FunctionCall, BindingSet)."); 1.22 return null; 1.23 } 1.24 1.25 - // charnik: made method (and hence the class) abstract 1.26 public abstract String getURI(); 1.27 }
2.1 --- a/evaluation/src/main/java/org/openrdf/query/algebra/evaluation/util/JTSWrapper.java Sat Sep 20 15:08:58 2014 +0300 2.2 +++ b/evaluation/src/main/java/org/openrdf/query/algebra/evaluation/util/JTSWrapper.java Sat Sep 20 19:36:24 2014 +0300 2.3 @@ -34,6 +34,7 @@ 2.4 import com.vividsolutions.jts.io.WKTReader; 2.5 import com.vividsolutions.jts.io.WKTWriter; 2.6 import com.vividsolutions.jts.io.gml2.GMLReader; 2.7 +import com.vividsolutions.jts.io.gml2.GMLWriter; 2.8 2.9 import eu.earthobservatory.constants.GeoConstants; 2.10 2.11 @@ -42,7 +43,6 @@ 2.12 * of Java Topology Suite. 2.13 * 2.14 * @author Charalampos Nikolaou <charnik@di.uoa.gr> 2.15 - * 2.16 */ 2.17 public class JTSWrapper { 2.18 2.19 @@ -73,6 +73,11 @@ 2.20 */ 2.21 private WKBWriter wkbw; 2.22 2.23 + /** 2.24 + * Writer for GML 2.25 + */ 2.26 + private GMLWriter gmlw; 2.27 + 2.28 private JTSWrapper() { 2.29 // use a private constructor to force call of getInstance method and forbid subclassing 2.30 wktr = new WKTReader(); 2.31 @@ -80,6 +85,7 @@ 2.32 wkbr = new WKBReader(); 2.33 wkbw = new WKBWriter(); // PostGIS 2.34 // wkbw = new WKBWriter(2, WKBConstants.wkbXDR); // MonetDB 2.35 + gmlw = new GMLWriter(); 2.36 } 2.37 2.38 public static synchronized JTSWrapper getInstance() { 2.39 @@ -195,4 +201,8 @@ 2.40 reader.close(); 2.41 return geometry; 2.42 } 2.43 + 2.44 + public synchronized String GMLWrite(Geometry geom) { 2.45 + return gmlw.write(geom); 2.46 + } 2.47 }
3.1 --- a/generaldb/src/main/java/org/openrdf/sail/generaldb/evaluation/GeneralDBEvaluation.java Sat Sep 20 15:08:58 2014 +0300 3.2 +++ b/generaldb/src/main/java/org/openrdf/sail/generaldb/evaluation/GeneralDBEvaluation.java Sat Sep 20 19:36:24 2014 +0300 3.3 @@ -22,6 +22,7 @@ 3.4 import org.openrdf.model.Value; 3.5 import org.openrdf.model.impl.BooleanLiteralImpl; 3.6 import org.openrdf.model.impl.LiteralImpl; 3.7 +import org.openrdf.model.impl.NumericLiteralImpl; 3.8 import org.openrdf.model.impl.URIImpl; 3.9 import org.openrdf.query.BindingSet; 3.10 import org.openrdf.query.Dataset; 3.11 @@ -42,12 +43,23 @@ 3.12 import org.openrdf.query.algebra.evaluation.ValueExprEvaluationException; 3.13 import org.openrdf.query.algebra.evaluation.function.Function; 3.14 import org.openrdf.query.algebra.evaluation.function.FunctionRegistry; 3.15 +import org.openrdf.query.algebra.evaluation.function.spatial.AbstractWKT; 3.16 import org.openrdf.query.algebra.evaluation.function.spatial.SpatialConstructFunc; 3.17 import org.openrdf.query.algebra.evaluation.function.spatial.SpatialMetricFunc; 3.18 +import org.openrdf.query.algebra.evaluation.function.spatial.SpatialPropertyFunc; 3.19 import org.openrdf.query.algebra.evaluation.function.spatial.SpatialRelationshipFunc; 3.20 import org.openrdf.query.algebra.evaluation.function.spatial.StrabonPolyhedron; 3.21 +import org.openrdf.query.algebra.evaluation.function.spatial.WKTHelper; 3.22 +import org.openrdf.query.algebra.evaluation.function.spatial.geosparql.property.GeoSparqlGetSRIDFunc; 3.23 import org.openrdf.query.algebra.evaluation.function.spatial.stsparql.metric.AreaFunc; 3.24 import org.openrdf.query.algebra.evaluation.function.spatial.stsparql.metric.DistanceFunc; 3.25 +import org.openrdf.query.algebra.evaluation.function.spatial.stsparql.property.AsGMLFunc; 3.26 +import org.openrdf.query.algebra.evaluation.function.spatial.stsparql.property.AsTextFunc; 3.27 +import org.openrdf.query.algebra.evaluation.function.spatial.stsparql.property.DimensionFunc; 3.28 +import org.openrdf.query.algebra.evaluation.function.spatial.stsparql.property.GeometryTypeFunc; 3.29 +import org.openrdf.query.algebra.evaluation.function.spatial.stsparql.property.IsEmptyFunc; 3.30 +import org.openrdf.query.algebra.evaluation.function.spatial.stsparql.property.IsSimpleFunc; 3.31 +import org.openrdf.query.algebra.evaluation.function.spatial.stsparql.property.SridFunc; 3.32 import org.openrdf.query.algebra.evaluation.function.spatial.stsparql.relation.AboveFunc; 3.33 import org.openrdf.query.algebra.evaluation.function.spatial.stsparql.relation.BelowFunc; 3.34 import org.openrdf.query.algebra.evaluation.function.spatial.stsparql.relation.ContainsFunc; 3.35 @@ -116,6 +128,7 @@ 3.36 import org.slf4j.LoggerFactory; 3.37 3.38 import com.vividsolutions.jts.geom.Geometry; 3.39 +import com.vividsolutions.jts.io.ParseException; 3.40 3.41 import eu.earthobservatory.constants.GeoConstants; 3.42 3.43 @@ -123,8 +136,9 @@ 3.44 * Extends the default strategy by accepting {@link GeneralDBSelectQuery} and evaluating 3.45 * them on a database. 3.46 * 3.47 + * @author Dimitrianos Savva <dimis@di.uoa.gr> 3.48 + * @author Charalampos Nikolaou <charnik@di.uoa.gr> 3.49 * @author Manos Karpathiotakis <mk@di.uoa.gr> 3.50 - * @author Dimitrianos Savva <dimis@di.uoa.gr> 3.51 */ 3.52 public abstract class GeneralDBEvaluation extends EvaluationStrategyImpl { 3.53 3.54 @@ -285,7 +299,11 @@ 3.55 3.56 // having evaluated the arguments of the function, evaluate the function 3.57 try { 3.58 - if(function instanceof SpatialMetricFunc) 3.59 + 3.60 + // 3.61 + // SPATIAL METRIC FUNCTIONS 3.62 + // 3.63 + if (function instanceof SpatialMetricFunc) 3.64 { 3.65 double funcResult = 0; 3.66 Geometry leftGeom = null; 3.67 @@ -323,43 +341,45 @@ 3.68 { //SHOULD NEVER REACH THIS CASE! 3.69 return null; 3.70 } 3.71 + 3.72 + 3.73 if(rightResult != null) 3.74 { 3.75 - if(rightResult instanceof StrabonPolyhedron) 3.76 - { 3.77 - rightGeom = ((StrabonPolyhedron) rightResult).getGeometry(); 3.78 - } 3.79 - else if(rightResult instanceof GeneralDBPolyhedron) 3.80 - { 3.81 - rightGeom = ((GeneralDBPolyhedron) rightResult).getPolyhedron().getGeometry(); 3.82 - } 3.83 - else if(rightResult instanceof Literal) 3.84 - { 3.85 - /** 3.86 - * Duplicate work done here in order to retain the literal's datatype... 3.87 - * Instead of only utilizing StrabonPolyhedron items, I converted them to Literals 3.88 - * in order to have them appear in Select Clause along with the appropriate datatype. 3.89 - */ 3.90 - rightGeom = new StrabonPolyhedron(((Literal) rightResult).getLabel()).getGeometry(); 3.91 - int sridPosition = ((Literal) rightResult).getLabel().indexOf(';'); 3.92 - //Default case 3.93 - if(sridPosition == -1) 3.94 + if(rightResult instanceof StrabonPolyhedron) 3.95 { 3.96 - rightGeom.setSRID(GeoConstants.defaultSRID); 3.97 + rightGeom = ((StrabonPolyhedron) rightResult).getGeometry(); 3.98 + } 3.99 + else if(rightResult instanceof GeneralDBPolyhedron) 3.100 + { 3.101 + rightGeom = ((GeneralDBPolyhedron) rightResult).getPolyhedron().getGeometry(); 3.102 + } 3.103 + else if(rightResult instanceof Literal) 3.104 + { 3.105 + /** 3.106 + * Duplicate work done here in order to retain the literal's datatype... 3.107 + * Instead of only utilizing StrabonPolyhedron items, I converted them to Literals 3.108 + * in order to have them appear in Select Clause along with the appropriate datatype. 3.109 + */ 3.110 + rightGeom = new StrabonPolyhedron(((Literal) rightResult).getLabel()).getGeometry(); 3.111 + int sridPosition = ((Literal) rightResult).getLabel().indexOf(';'); 3.112 + //Default case 3.113 + if(sridPosition == -1) 3.114 + { 3.115 + rightGeom.setSRID(GeoConstants.defaultSRID); 3.116 + } 3.117 + else 3.118 + { 3.119 + sridPosition = ((Literal) rightResult).getLabel().lastIndexOf('/'); 3.120 + int srid = Integer.parseInt(((Literal) rightResult).getLabel().substring(sridPosition+1)); 3.121 + rightGeom.setSRID(srid); 3.122 + } 3.123 } 3.124 else 3.125 - { 3.126 - sridPosition = ((Literal) rightResult).getLabel().lastIndexOf('/'); 3.127 - int srid = Integer.parseInt(((Literal) rightResult).getLabel().substring(sridPosition+1)); 3.128 - rightGeom.setSRID(srid); 3.129 + { //SHOULD NEVER REACH THIS CASE! 3.130 + return null; 3.131 } 3.132 } 3.133 else 3.134 - { //SHOULD NEVER REACH THIS CASE! 3.135 - return null; 3.136 - } 3.137 - } 3.138 - else 3.139 { 3.140 //it's ok, maybe this is a non-binary function! 3.141 } 3.142 @@ -379,10 +399,19 @@ 3.143 return org.openrdf.model.impl.ValueFactoryImpl.getInstance().createLiteral(funcResult); 3.144 3.145 } 3.146 + 3.147 + // 3.148 + // SPATIAL CONSTRUCT FUNCTIONS 3.149 + // 3.150 else if ( function instanceof SpatialConstructFunc ) { 3.151 return spatialConstructPicker(function, leftResult, rightResult); 3.152 3.153 - } else if(function instanceof SpatialRelationshipFunc) { 3.154 + } 3.155 + 3.156 + // 3.157 + // SPATIAL RELATIONSHIP FUNCTIONS 3.158 + // 3.159 + else if(function instanceof SpatialRelationshipFunc) { 3.160 // Any boolean function present in HAVING - Must evaluate here! 3.161 3.162 boolean funcResult = false; 3.163 @@ -573,8 +602,45 @@ 3.164 } 3.165 3.166 return funcResult ? BooleanLiteralImpl.TRUE : BooleanLiteralImpl.FALSE; 3.167 + 3.168 } 3.169 - else { 3.170 + 3.171 + // 3.172 + // SPATIAL PROPERTY FUNCTIONS 3.173 + // 3.174 + else if (function instanceof SpatialPropertyFunc) { 3.175 + 3.176 + if (function instanceof GeoSparqlGetSRIDFunc) { 3.177 + return new URIImpl(WKTHelper.getURI_forSRID(getSRIDFromValue(leftResult))); 3.178 + 3.179 + } else if (function instanceof SridFunc) { 3.180 + return new NumericLiteralImpl(getSRIDFromValue(leftResult)); 3.181 + 3.182 + } else if (function instanceof IsSimpleFunc) { 3.183 + return new BooleanLiteralImpl(getGeometryFromValue(leftResult).isSimple()); 3.184 + 3.185 + } else if (function instanceof IsEmptyFunc) { 3.186 + return new BooleanLiteralImpl(getGeometryFromValue(leftResult).isEmpty()); 3.187 + 3.188 + } else if (function instanceof GeometryTypeFunc) { 3.189 + return new LiteralImpl(getGeometryFromValue(leftResult).getGeometryType()); 3.190 + 3.191 + } else if (function instanceof DimensionFunc) { 3.192 + return new NumericLiteralImpl(getGeometryFromValue(leftResult).getDimension()); 3.193 + 3.194 + } else if (function instanceof AsTextFunc) { 3.195 + // already handled 3.196 + return leftResult; 3.197 + 3.198 + } else if (function instanceof AsGMLFunc) { 3.199 + return new LiteralImpl(JTSWrapper.getInstance().GMLWrite(getGeometryFromValue(leftResult))); 3.200 + 3.201 + } else { 3.202 + logger.error("[Strabon.evaluate(FunctionCall)] Function {} has not been implemented yet. ", function.getURI()); 3.203 + return null; 3.204 + } 3.205 + 3.206 + } else { 3.207 //Default Sesame Behavior 3.208 List<ValueExpr> args = fc.getArgs(); 3.209 3.210 @@ -586,11 +652,11 @@ 3.211 3.212 return function.evaluate(tripleSource.getValueFactory(), argValues); 3.213 } 3.214 + 3.215 } catch (Exception e) { 3.216 - logger.error("Strabon.evaluate(FunctionCall)] Error during evaluation of extension function.", e); 3.217 + logger.error("[Strabon.evaluate(FunctionCall)] Error during evaluation of extension function.", e); 3.218 return null; 3.219 } 3.220 - 3.221 } 3.222 3.223 public StrabonPolyhedron spatialConstructPicker(Function function, Value left, Value right) throws Exception 3.224 @@ -1075,6 +1141,47 @@ 3.225 //return allVars; 3.226 } 3.227 3.228 + 3.229 + public int getSRIDFromValue(Value value) { 3.230 + if (value instanceof GeneralDBPolyhedron) { 3.231 + return ((GeneralDBPolyhedron) value).getPolyhedron().getGeometry().getSRID(); 3.232 + 3.233 + } else if (value instanceof StrabonPolyhedron) { 3.234 + return ((StrabonPolyhedron) value).getGeometry().getSRID(); 3.235 + 3.236 + } else if (value instanceof Literal) { 3.237 + return (new AbstractWKT(((Literal) value).stringValue())).getSRID(); 3.238 + 3.239 + } else { // default error SRID value 3.240 + return -1; 3.241 + } 3.242 + } 3.243 + 3.244 + public Geometry getGeometryFromValue(Value value) throws ParseException { 3.245 + if (value instanceof GeneralDBPolyhedron) { 3.246 + return ((GeneralDBPolyhedron) value).getPolyhedron().getGeometry(); 3.247 + 3.248 + } else if (value instanceof StrabonPolyhedron) { 3.249 + return ((StrabonPolyhedron) value).getGeometry(); 3.250 + 3.251 + } else if (value instanceof Literal) { 3.252 + Literal literal = (Literal) value; 3.253 + AbstractWKT wkt = null; 3.254 + 3.255 + if (literal.getDatatype() == null) { 3.256 + wkt = new AbstractWKT(literal.stringValue()); 3.257 + 3.258 + } else { 3.259 + wkt = new AbstractWKT(literal.stringValue(), literal.getDatatype().stringValue()); 3.260 + } 3.261 + 3.262 + return JTSWrapper.getInstance().WKTread(wkt.getWKT()); 3.263 + 3.264 + } else { 3.265 + return null; 3.266 + } 3.267 + } 3.268 + 3.269 /** 3.270 * Given an expression get the type of the result. 3.271 *
4.1 --- a/generaldb/src/main/java/org/openrdf/sail/generaldb/optimizers/GeneralDBSelectQueryOptimizer.java Sat Sep 20 15:08:58 2014 +0300 4.2 +++ b/generaldb/src/main/java/org/openrdf/sail/generaldb/optimizers/GeneralDBSelectQueryOptimizer.java Sat Sep 20 19:36:24 2014 +0300 4.3 @@ -104,6 +104,7 @@ 4.4 /** 4.5 * Rewrites the core algebra model with a relation optimised model, using SQL. 4.6 * 4.7 + * @author Charalampos Nikolaou <charnik@di.uoa.gr> 4.8 * @author Manos Karpathiotakis <mk@di.uoa.gr. 4.9 */ 4.10 public class GeneralDBSelectQueryOptimizer extends GeneralDBQueryModelVisitorBase<RuntimeException> 4.11 @@ -994,8 +995,9 @@ 4.12 ValueExpr expr = elem.getExpr(); 4.13 GeneralDBSqlExpr sqlExpr = null; 4.14 String name = elem.getName(); 4.15 - if(expr instanceof FunctionCall) 4.16 - { 4.17 + 4.18 + if(expr instanceof FunctionCall && !isFuncExprGrounded(expr)) 4.19 + { // if the expr is grounded we are going to evaluate it in Java 4.20 if(!evaluateInJava(expr)) 4.21 { 4.22 Function function = FunctionRegistry.getInstance().get(((FunctionCall) expr).getURI()); 4.23 @@ -1064,14 +1066,37 @@ 4.24 } 4.25 } 4.26 } 4.27 - /** 4.28 - * 4.29 - */ 4.30 - 4.31 - 4.32 } 4.33 } 4.34 4.35 + /** 4.36 + * Checks whether the given value expression contains only grounded 4.37 + * terms (constants). 4.38 + * 4.39 + * This should work for the spatial case, but I am not 100% sure whether 4.40 + * it is going to work for whole SPARQL 1.1. 4.41 + * 4.42 + * @param funcExpr 4.43 + * @return 4.44 + */ 4.45 + private boolean isFuncExprGrounded(ValueExpr funcExpr) { 4.46 + if (funcExpr instanceof FunctionCall) { 4.47 + // recursively check its arguments 4.48 + boolean groundedChildren = true; 4.49 + for (int i = 0; i < ((FunctionCall) funcExpr).getArgs().size(); i++) { 4.50 + groundedChildren &= isFuncExprGrounded(((FunctionCall) funcExpr).getArgs().get(i)); 4.51 + } 4.52 + 4.53 + return groundedChildren; 4.54 + 4.55 + } else if (funcExpr instanceof Var) { // variable 4.56 + return false; 4.57 + 4.58 + } else { // all other cases (constant, UnaryExpressions, etc...) -> dodgy! 4.59 + return true; 4.60 + } 4.61 + } 4.62 + 4.63 //Checking that no spatial function exists in this metric expression 4.64 private boolean thematicExpression(ValueExpr expr) 4.65 { 4.66 @@ -1196,7 +1221,8 @@ 4.67 4.68 /** 4.69 * Function used recursively to specify whether the function call present in the select clause contains an aggregate 4.70 - * of the form strdf:union(?aggrValue) or strdf:intersection(?aggrValue). 4.71 + * of the form strdf:union(?aggrValue) or strdf:intersection(?aggrValue). 4.72 + * 4.73 * @param expr 4.74 * @return true if no aggregate is present, false otherwise. 4.75 */ 4.76 @@ -1231,9 +1257,6 @@ 4.77 } 4.78 4.79 } 4.80 - /** 4.81 - * 4.82 - */ 4.83 4.84 @Override 4.85 public void meet(Slice node)