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)