Strabon
changeset 1171:2edfddc24e0d temporals
Forgot to add file and caused compilation error
author | Konstantina Bereta <Konstantina.Bereta@di.uoa.gr> |
---|---|
date | Sun May 12 14:52:16 2013 +0300 (2013-05-12) |
parents | 2aaa9fc419cf |
children | af08fcd44b18 |
files | evaluation/src/main/java/org/openrdf/query/algebra/evaluation/impl/SpatioTemporalJoinOptimizer.java |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/evaluation/src/main/java/org/openrdf/query/algebra/evaluation/impl/SpatioTemporalJoinOptimizer.java Sun May 12 14:52:16 2013 +0300 1.3 @@ -0,0 +1,766 @@ 1.4 +/** 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. 1.8 + * 1.9 + * Copyright (C) 2013 Pyravlos Team 1.10 + * 1.11 + * http://www.strabon.di.uoa.gr/ 1.12 + */ 1.13 +package org.openrdf.query.algebra.evaluation.impl; 1.14 + 1.15 +import java.util.ArrayList; 1.16 +import java.util.HashMap; 1.17 +import java.util.Iterator; 1.18 +import java.util.LinkedHashSet; 1.19 +import java.util.List; 1.20 +import java.util.Map; 1.21 +import java.util.Set; 1.22 + 1.23 +import org.openrdf.query.BindingSet; 1.24 +import org.openrdf.query.Dataset; 1.25 +import org.openrdf.query.algebra.Compare; 1.26 +import org.openrdf.query.algebra.Extension; 1.27 +import org.openrdf.query.algebra.Filter; 1.28 +import org.openrdf.query.algebra.FunctionCall; 1.29 +import org.openrdf.query.algebra.Join; 1.30 +import org.openrdf.query.algebra.LeftJoin; 1.31 +import org.openrdf.query.algebra.MathExpr; 1.32 +import org.openrdf.query.algebra.Or; 1.33 +import org.openrdf.query.algebra.QueryModelNode; 1.34 +import org.openrdf.query.algebra.StatementPattern; 1.35 +import org.openrdf.query.algebra.StatementPattern.Scope; 1.36 +import org.openrdf.query.algebra.TupleExpr; 1.37 +import org.openrdf.query.algebra.ValueExpr; 1.38 +import org.openrdf.query.algebra.Var; 1.39 +import org.openrdf.query.algebra.evaluation.function.Function; 1.40 +import org.openrdf.query.algebra.evaluation.function.FunctionRegistry; 1.41 +import org.openrdf.query.algebra.evaluation.function.spatial.SpatialConstructFunc; 1.42 +import org.openrdf.query.algebra.evaluation.function.spatial.SpatialMetricFunc; 1.43 +import org.openrdf.query.algebra.evaluation.function.spatial.SpatialPropertyFunc; 1.44 +import org.openrdf.query.algebra.evaluation.function.spatial.SpatialRelationshipFunc; 1.45 +import org.openrdf.query.algebra.evaluation.function.temporal.stsparql.relation.TemporalRelationFunc; 1.46 +import org.openrdf.query.algebra.helpers.QueryModelVisitorBase; 1.47 +import org.openrdf.query.algebra.helpers.StatementPatternCollector; 1.48 + 1.49 +/** 1.50 + * A query optimizer that re-orders nested Joins. 1.51 + * 1.52 + * @author Konstantina Bereta <Konstantina.Bereta@di.uoa.gr> 1.53 + * 1.54 + * This is an abstract class of an optimizer that eliminates the production of cross joins in 1.55 + * the SQL query. It generalizes the behaviour of the SpatialJoinOptimizer by @author manolee. 1.56 + * The SpatialJoinOptimizer and the TemporalJoinOptimizer are now extension of this class. 1.57 + */ 1.58 + 1.59 +public abstract class SpatioTemporalJoinOptimizer 1.60 +//implements QueryOptimizer //Removed it consciously 1.61 +{ 1.62 + 1.63 + 1.64 + //private Set<String> existingVars = new TreeSet<String>(); 1.65 + /** 1.66 + * Applies generally applicable optimizations: path expressions are sorted 1.67 + * from more to less specific. 1.68 + * 1.69 + * @param tupleExpr 1.70 + */ 1.71 + 1.72 + public abstract String getClassName(); 1.73 + 1.74 + public void optimize(TupleExpr tupleExpr, Dataset dataset, BindingSet bindings, List<TupleExpr> spatialJoins) { 1.75 + tupleExpr.visit(new JoinVisitor(spatialJoins)); 1.76 + } 1.77 + 1.78 + protected class JoinVisitor extends QueryModelVisitorBase<RuntimeException> { 1.79 + 1.80 + 1.81 + 1.82 + public JoinVisitor(List<TupleExpr> spatialJoins) { 1.83 + super(); 1.84 + this.spatialJoins = spatialJoins; 1.85 + } 1.86 + 1.87 + 1.88 + private List<TupleExpr> spatialJoins; 1.89 + //buffer with a var as a second argument 1.90 + private boolean problematicBuffer = false; 1.91 + 1.92 + //indicates whether a metric expression contains a spatial function call 1.93 + private boolean containsSpatial = false; 1.94 + private boolean optimizableMetricOrProperty = true; 1.95 + 1.96 + private int thematicJoinsSize = 0; 1.97 + 1.98 + //List<SpatialFilterInfo> allSFilters = new ArrayList<SpatialFilterInfo>(); 1.99 + Map<TupleExpr, List<Var>> allSFilters = new HashMap<TupleExpr, List<Var>>(); 1.100 + 1.101 + @Override 1.102 + public void meet(Join node) { 1.103 + 1.104 + //XXX NOTE: NOT OPTIMIZING CONTENTS OF OPTIONAL CLAUSE!!! 1.105 + //Reason1: Errors occurred in the condition of the LeftJoin containing the optional subgraph 1.106 + 1.107 + //Not as successful as I hoped. Some OPTIONAL clauses may pass 1.108 + if(parentIsOptional(node)) 1.109 + { 1.110 + return; 1.111 + } 1.112 + // if(node.getParentNode() instanceof LeftJoin) 1.113 + // { 1.114 + // return; 1.115 + // } 1.116 + 1.117 + // Recursively get the join arguments 1.118 + List<TupleExpr> joinArgs = getJoinArgs(node, new ArrayList<TupleExpr>()); 1.119 + 1.120 + if(joinArgs == null) 1.121 + { 1.122 + //2nd mechanism to avoid OPTIONAL clauses from passing 1.123 + return; 1.124 + } 1.125 + 1.126 + 1.127 + Map<TupleExpr, List<Var>> varsMap = new /*Linked*/HashMap<TupleExpr, List<Var>>(); 1.128 + 1.129 + for (TupleExpr tupleExpr : joinArgs) { 1.130 + varsMap.put(tupleExpr, getStatementPatternVars(tupleExpr)); 1.131 + 1.132 + } 1.133 + 1.134 + //Now I have all the info I need. Just need to structure it efficiently 1.135 + int allNodes = varsMap.size() + allSFilters.size(); 1.136 + thematicJoinsSize = varsMap.size(); 1.137 + //careful with positions on the diagonal! Do not utilize them! 1.138 + int joinsGraph[][] = new int[allNodes][allNodes]; 1.139 + 1.140 + //prints for debug 1.141 + // Set<TupleExpr> allExprs = varsMap.keySet(); 1.142 + // System.out.println(allExprs.toString()); 1.143 + // 1.144 + // Set<TupleExpr> allFilters = allSFilters.keySet(); 1.145 + // System.out.println(allFilters.toString()); 1.146 + 1.147 + //Thematic part first 1.148 + int i = 0; 1.149 + 1.150 + for(List<Var> listHorizontal : varsMap.values()) 1.151 + { 1.152 + int j = 0; 1.153 + int k = 0; 1.154 + 1.155 + //Other thematics 1.156 + for(List<Var> listVertical : varsMap.values()) 1.157 + { 1.158 + if(i==j) 1.159 + { 1.160 + j++; 1.161 + continue; 1.162 + } 1.163 + 1.164 + 1.165 + joinsGraph[i][j] = sameVar(listHorizontal, listVertical); 1.166 + 1.167 + j++; 1.168 + } 1.169 + 1.170 + //Spatials 1.171 + for(List<Var> listVertical : allSFilters.values()) 1.172 + { 1.173 + 1.174 + joinsGraph[i][k+varsMap.size()] = sameVar(listHorizontal, listVertical); 1.175 + 1.176 + k++; 1.177 + } 1.178 + 1.179 + i++; 1.180 + } 1.181 + 1.182 + //Now for the spatial horizontal nodes 1.183 + i = varsMap.size(); 1.184 + for(List<Var> listHorizontal : allSFilters.values()) 1.185 + { 1.186 + int j = 0; 1.187 + int k = 0; 1.188 + 1.189 + //Other thematics 1.190 + for(List<Var> listVertical : varsMap.values()) 1.191 + { 1.192 + 1.193 + joinsGraph[i][j] = sameVar(listHorizontal, listVertical); 1.194 + 1.195 + j++; 1.196 + } 1.197 + 1.198 + //Spatials 1.199 + for(List<Var> listVertical : allSFilters.values()) 1.200 + { 1.201 + if(i==k+varsMap.size()) 1.202 + { 1.203 + k++; 1.204 + continue; 1.205 + } 1.206 + 1.207 + joinsGraph[i][k+varsMap.size()] =sameVar(listHorizontal, listVertical); 1.208 + 1.209 + k++; 1.210 + } 1.211 + 1.212 + i++; 1.213 + } 1.214 + 1.215 + //Checking graph to be sure 1.216 + /* 1.217 + for(int a = 0; a < allNodes; a++) 1.218 + { 1.219 + for(int b = 0; b < allNodes; b++) 1.220 + { 1.221 + System.out.print(joinsGraph[a][b]+" "); 1.222 + 1.223 + } 1.224 + System.out.println(""); 1.225 + } 1.226 + */ 1.227 + 1.228 + //Time to construct ordered sequence of joins + filters 1.229 + List<TupleExpr> orderedJoinArgs = new ArrayList<TupleExpr>(allNodes); 1.230 + //maybe I won't need all the positions -> some spatial joins may not be utilized 1.231 + List<Integer> tempList = new ArrayList<Integer>(allNodes); 1.232 + List<Integer> pathList = new ArrayList<Integer>(); 1.233 + List<Integer> finalList = new ArrayList<Integer>(); 1.234 + Set<Var> varsTillNow = new LinkedHashSet<Var>(); 1.235 + for(int row = 0 ; row < allNodes ; row++) 1.236 + { 1.237 + tempList.add(row); 1.238 + createOrderedJoins(joinsGraph, row, row, 1, varsTillNow, tempList, pathList, finalList); 1.239 + pathList.clear(); 1.240 + if(finalList.size() == allNodes) 1.241 + { 1.242 + break; 1.243 + } 1.244 + 1.245 + } 1.246 + 1.247 + /* 1.248 + System.out.println("*--REWRITTEN TREE--**"); 1.249 + System.out.println(finalList.toString()); 1.250 + */ 1.251 + 1.252 + int varsMapSize = varsMap.size(); 1.253 + for(Integer position : finalList) 1.254 + { 1.255 + if(position<varsMapSize)//thematic! 1.256 + { 1.257 + int count = 0; 1.258 + Iterator it = varsMap.entrySet().iterator(); 1.259 + 1.260 + while (it.hasNext()) 1.261 + { 1.262 + { 1.263 + Map.Entry entry = (Map.Entry)it.next(); 1.264 + if(count == position) 1.265 + { 1.266 + orderedJoinArgs.add((TupleExpr) entry.getKey()); 1.267 + 1.268 + it.remove(); 1.269 + varsMapSize--; 1.270 + 1.271 + for(int fix = 0 ; fix < finalList.size(); fix++) 1.272 + { 1.273 + if(finalList.get(fix) > position) 1.274 + { 1.275 + int reduced = finalList.get(fix) - 1; 1.276 + finalList.set(fix, reduced); 1.277 + 1.278 + } 1.279 + } 1.280 + break; 1.281 + } 1.282 + count++; 1.283 + } 1.284 + } 1.285 + } 1.286 + else//spatial! 1.287 + { 1.288 + int count = 0; 1.289 + Iterator it = allSFilters.entrySet().iterator(); 1.290 + while (it.hasNext()) 1.291 + { 1.292 + { 1.293 + Map.Entry entry = (Map.Entry)it.next(); 1.294 + if(count == position - varsMapSize) 1.295 + { 1.296 + //If I keep record of this entry, I can use the info later to avoid duplicate filters 1.297 + spatialJoins.add((TupleExpr) entry.getKey()); 1.298 + // 1.299 + orderedJoinArgs.add((TupleExpr) entry.getKey()); 1.300 + it.remove(); 1.301 + for(int fix = 0 ; fix < finalList.size(); fix++) 1.302 + { 1.303 + if(finalList.get(fix) > position) 1.304 + { 1.305 + int reduced = finalList.get(fix) - 1; 1.306 + finalList.set(fix, reduced); 1.307 + } 1.308 + } 1.309 + break; 1.310 + } 1.311 + count++; 1.312 + } 1.313 + } 1.314 + } 1.315 + 1.316 + } 1.317 + //Must take care of the remainders as well! 1.318 + Iterator it = varsMap.entrySet().iterator(); 1.319 + while (it.hasNext()) 1.320 + { 1.321 + Map.Entry entry = (Map.Entry)it.next(); 1.322 + orderedJoinArgs.add((TupleExpr) entry.getKey()); 1.323 + it.remove(); 1.324 + } 1.325 + 1.326 + TupleExpr replacement = orderedJoinArgs.get(0); 1.327 + for (int ii = 1; ii < orderedJoinArgs.size(); ii++) { 1.328 + replacement = new Join(replacement, orderedJoinArgs.get(ii)); 1.329 + } 1.330 + 1.331 + // Replace old join hierarchy 1.332 + node.replaceWith(replacement); 1.333 + 1.334 + } 1.335 + 1.336 + 1.337 + public boolean parentIsOptional(QueryModelNode node) 1.338 + { 1.339 + if(node.getParentNode() == null) 1.340 + { 1.341 + return false; 1.342 + } 1.343 + else if(node.getParentNode() instanceof LeftJoin) 1.344 + { 1.345 + return true; 1.346 + } 1.347 + else 1.348 + { 1.349 + return parentIsOptional(node.getParentNode()); 1.350 + } 1.351 + } 1.352 + 1.353 + /** 1.354 + * General Comment: If more than one function exists in the query and can be used to perform the join, no preference is shown 1.355 + * on which function will actually be used for this purpose. This could cause an issue if ST_Disjoint is the one finally used, 1.356 + * as the index won't be used for the evaluation in this case. Perhaps I should include some 'priority' 1.357 + */ 1.358 + @Override 1.359 + public void meet(Filter node) { 1.360 + 1.361 + /** 1.362 + * Filter node must not be in OPTIONAL clause! 1.363 + * After all, unneeded check. If an optional exists, the 'Filter' tuple expression 1.364 + * is removed and only the Function Calls remain 1.365 + */ 1.366 + if(!withinHaving(node)) 1.367 + { 1.368 + //if(!(node.getParentNode() instanceof LeftJoin)) 1.369 + //{ 1.370 + //XXX Ignore OR in Filters for now! (perhaps permanently) 1.371 + if(!(node.getCondition() instanceof Or)) 1.372 + { 1.373 + if(node.getCondition() instanceof FunctionCall) 1.374 + { 1.375 + //Only interested in spatial ones 1.376 + if(isRelevantSTFunc((FunctionCall) node.getCondition())) 1.377 + { 1.378 + //Have to retrieve all nested variables and other info 1.379 + 1.380 + //1.Retrieve varNames 1.381 + List<Var> varList = getFunctionCallVars((FunctionCall) node.getCondition()); 1.382 + 1.383 + //Cannot optimize buffer constructs when their 2nd argument is a 1.384 + //thematic var, because I can't manipulate the order of the 1.385 + //numeric_values table 1.386 + if(!problematicBuffer) 1.387 + { 1.388 + //XXX I cannot process cases involving more than 2 arguments in the spatial join! 1.389 + // They transcend the theta join level! 1.390 + // if(varList.size()<3) 1.391 + 1.392 + //if the arguments are not 2, I am essentially doing a selection! 1.393 + //No reason to push into optimizer then 1.394 + if(varList.size()==2) 1.395 + { 1.396 + //Add all important info about this spatial relationship to the appropriate structure 1.397 + //allSFilters.add(new SpatialFilterInfo(varList, (FunctionCall) node.getCondition())); 1.398 + Filter toEnter = node.clone(); 1.399 + 1.400 + /** 1.401 + * VERY CAREFUL HERE! 1.402 + * Reason I did this: If not, I would carry a copy of the whole expression for 1.403 + * every extra filter of my query! 1.404 + * -DUMMY-!!! 1.405 + */ 1.406 + 1.407 + StatementPattern t = new StatementPattern(); 1.408 + String className = getClassName(); 1.409 + if(className.equals("org.openrdf.query.algebra.evaluation.impl.SpatialJoinOptimizer")) 1.410 + { 1.411 + t.setSubjectVar(new Var("-dummy-")); 1.412 + t.setPredicateVar(new Var("-dummy-")); 1.413 + t.setObjectVar(new Var("-dummy-")); 1.414 + } 1.415 + else //TemporalJoinOptimizer case 1.416 + { 1.417 + t.setSubjectVar(new Var("-dummy-temporal")); 1.418 + t.setPredicateVar(new Var("-dummy-temporal")); 1.419 + t.setObjectVar(new Var("-dummy-temporal")); 1.420 + } 1.421 + 1.422 + t.setScope(Scope.DEFAULT_CONTEXTS); 1.423 + toEnter.setArg(t); 1.424 + 1.425 + if(!allSFilters.containsKey(toEnter)) 1.426 + { 1.427 + allSFilters.put(toEnter,varList); 1.428 + } 1.429 + } 1.430 + problematicBuffer = false; 1.431 + } 1.432 + } 1.433 + } 1.434 + //Metrics 1.435 + //I have a similar problematic case with the one occurring in Buffer! 1.436 + //Cannot manipulate the join order when I am dealing with numerics! 1.437 + //Therefore, I cannot use a numeric field (a numeric var) to alter the join sequence 1.438 + else if(node.getCondition() instanceof Compare) 1.439 + { 1.440 + containsSpatial = false; 1.441 + List<Var> allVars = new ArrayList<Var>(getVarsInMetricOrProperty(node.getCondition())); 1.442 + if(containsSpatial&&optimizableMetricOrProperty) 1.443 + { 1.444 + //if the arguments are not 2, I am essentially doing a selection! 1.445 + //No reason to push into optimizer then 1.446 + if(allVars.size()==2) 1.447 + //if(allVars.size()<3) 1.448 + { 1.449 + //Add all important info about this spatial relationship to the appropriate structure 1.450 + //allSFilters.add(new SpatialFilterInfo(varList, (FunctionCall) node.getCondition())); 1.451 + Filter toEnter = node.clone(); 1.452 + 1.453 + StatementPattern t = new StatementPattern(); 1.454 + t.setSubjectVar(new Var("-dummy-")); 1.455 + t.setPredicateVar(new Var("-dummy-")); 1.456 + t.setObjectVar(new Var("-dummy-")); 1.457 + t.setScope(Scope.DEFAULT_CONTEXTS); 1.458 + toEnter.setArg(t); 1.459 + 1.460 + if(!allSFilters.containsKey(toEnter)) 1.461 + { 1.462 + allSFilters.put(toEnter,allVars); 1.463 + } 1.464 + } 1.465 + containsSpatial = false; 1.466 + } 1.467 + optimizableMetricOrProperty = true; 1.468 + } 1.469 + 1.470 + } 1.471 + //} 1.472 + } 1.473 + 1.474 + //Last thing to do is ensuring the entire tree is traversed 1.475 + node.visitChildren(this); 1.476 + 1.477 + } 1.478 + 1.479 + 1.480 + /** 1.481 + * Helper Functions 1.482 + */ 1.483 + 1.484 + /** 1.485 + * Used to find out whether the Filter expr we are currently visiting is located inside 1.486 + * a HAVING clause. 1.487 + * 1.488 + * From what I have seen so far, it seems that if this is the case, its arg (or one of the following FILTER args in 1.489 + * the case of disjunction/conjunction) will be an Extension expr followed by a GROUP expr 1.490 + */ 1.491 + private boolean withinHaving(Filter expr) 1.492 + { 1.493 + if(expr.getArg() instanceof Extension) 1.494 + { 1.495 + return true; 1.496 + } 1.497 + else if(expr.getArg() instanceof Filter) 1.498 + { 1.499 + return withinHaving((Filter) expr.getArg()); 1.500 + } 1.501 + else 1.502 + { 1.503 + return false; 1.504 + } 1.505 + } 1.506 + 1.507 + private <L extends List<TupleExpr>> L getJoinArgs(TupleExpr tupleExpr, L joinArgs) { 1.508 + if (tupleExpr instanceof Join) { 1.509 + Join join = (Join)tupleExpr; 1.510 + if(getJoinArgs(join.getLeftArg(), joinArgs) == null) 1.511 + return null; 1.512 + if(getJoinArgs(join.getRightArg(), joinArgs) == null) 1.513 + return null; 1.514 + } 1.515 + else if(tupleExpr instanceof LeftJoin) 1.516 + { 1.517 + //Trying to avoid OPTIONAL clauses from passing 1.518 + return null; 1.519 + } 1.520 + else 1.521 + { 1.522 + joinArgs.add(tupleExpr); 1.523 + } 1.524 + 1.525 + return joinArgs; 1.526 + } 1.527 + 1.528 + private List<Var> getStatementPatternVars(TupleExpr tupleExpr) { 1.529 + List<StatementPattern> stPatterns = StatementPatternCollector.process(tupleExpr); 1.530 + List<Var> varList = new ArrayList<Var>(stPatterns.size() * 4); 1.531 + for (StatementPattern sp : stPatterns) { 1.532 + sp.getVars(varList); 1.533 + } 1.534 + return varList; 1.535 + } 1.536 + 1.537 + /** 1.538 + * spatialContent: Used to declare that this expression does include some spatial 1.539 + * content and an attempt should be made to use it in the joins' optimization process 1.540 + */ 1.541 + private Set<Var> getVarsInMetricOrProperty(ValueExpr expr) 1.542 + { 1.543 + Set<Var> allVars = new LinkedHashSet<Var>(); 1.544 + 1.545 + if(expr instanceof Compare) 1.546 + { 1.547 + allVars.addAll(getVarsInMetricOrProperty(((Compare) expr).getLeftArg())); 1.548 + allVars.addAll(getVarsInMetricOrProperty(((Compare) expr).getRightArg())); 1.549 + } 1.550 + else if(expr instanceof MathExpr) 1.551 + { 1.552 + allVars.addAll(getVarsInMetricOrProperty(((MathExpr) expr).getLeftArg())); 1.553 + allVars.addAll(getVarsInMetricOrProperty(((MathExpr) expr).getRightArg())); 1.554 + } 1.555 + else if(expr instanceof FunctionCall ) 1.556 + { 1.557 + if(isRelevantSTFunc((FunctionCall) expr)) 1.558 + { 1.559 + /** 1.560 + * There is a point in continuing the search recursively ONLY 1.561 + * if I reach this case. Otherwise, the function call 1.562 + * may not refer to a spatial function 1.563 + */ 1.564 + this.containsSpatial = true; 1.565 + allVars.addAll(getFunctionCallVars((FunctionCall) expr)); 1.566 + 1.567 + } 1.568 + } 1.569 + else if(expr instanceof Var) 1.570 + { 1.571 + if(!(expr.getParentNode() instanceof FunctionCall)) 1.572 + { 1.573 + //Cannot manipulate the join order when I am dealing with numerics! 1.574 + //Therefore, I cannot use a numeric field (a numeric var) to alter the join sequence 1.575 + this.optimizableMetricOrProperty = false; 1.576 + } 1.577 + if(!allVars.contains(expr)) 1.578 + { 1.579 + allVars.add((Var) expr); 1.580 + } 1.581 + } 1.582 + 1.583 + return allVars; 1.584 + } 1.585 + 1.586 + 1.587 + 1.588 + private List<Var> getFunctionCallVars(FunctionCall functionCall) { 1.589 + List<Var> varList = new ArrayList<Var>(); 1.590 + int argList = 0; 1.591 + for(ValueExpr expr : functionCall.getArgs()) 1.592 + { 1.593 + argList++; 1.594 + if(expr instanceof Var) 1.595 + { 1.596 + // if(!existingVars.contains(((Var) expr).getName())) 1.597 + // { 1.598 + // existingVars.add(((Var) expr).getName()); 1.599 + // } 1.600 + 1.601 + if(!varList.contains(expr)) 1.602 + { 1.603 + //Was using this code when I tried to incorporate the Buffer case buffer(?Spatial,?thematic) 1.604 + if(argList == 2 && functionCall.getURI().equals("http://strdf.di.uoa.gr/ontology#buffer")) 1.605 + { 1.606 + problematicBuffer = true; 1.607 + } 1.608 + varList.add((Var) expr); 1.609 + } 1.610 + 1.611 + } 1.612 + else if(expr instanceof FunctionCall) 1.613 + { 1.614 + varList.addAll(getFunctionCallVars((FunctionCall) expr)); 1.615 + } 1.616 + //TODO Should I add any additional cases? I don't think so 1.617 + else 1.618 + { 1.619 + continue; 1.620 + } 1.621 + } 1.622 + return varList; 1.623 + } 1.624 + 1.625 + /** 1.626 + * Both lists belong to either a thematic node (St.Pattern) or a spatial node (Filter) 1.627 + * Comparing the vars with each other to discover links of the query graph 1.628 + * @param list1 1.629 + * @param list2 1.630 + * @return 1.631 + */ 1.632 + private int sameVar(List<Var> list1, List<Var> list2) 1.633 + { 1.634 + for(Var var : list1) 1.635 + { 1.636 + if(list2.contains(var)) 1.637 + { 1.638 + return 1; 1.639 + } 1.640 + } 1.641 + 1.642 + return 0; 1.643 + } 1.644 + 1.645 + 1.646 + 1.647 + 1.648 + 1.649 + //Input: a single line of the table 1.650 + //NOTE: NO LOOPS! CAREFUL!! 1.651 + private boolean createOrderedJoins(int table[][], int lineToScan,int columnToSkip, 1.652 + int pathLen, Set<Var> varsTillNow, List<Integer> tempList, List<Integer> pathList, List<Integer> finalList) 1.653 + { 1.654 + boolean success = false; 1.655 + int dims = table.length; 1.656 + 1.657 + int j; 1.658 + 1.659 + //dims: all arguments 1.660 + for(j = 0; j < dims; j++) 1.661 + { 1.662 + if(j == columnToSkip) 1.663 + { 1.664 + continue; 1.665 + } 1.666 + 1.667 + //A connection exists! 1.668 + if(table[lineToScan][j]>0) 1.669 + { 1.670 + //Don't want my graph to have circles!!! 1.671 + if(!tempList.contains(j)&&!pathList.contains(j)) 1.672 + { 1.673 + if(j >= thematicJoinsSize) //aka if(allSFilters.size() > 0) 1.674 + { 1.675 + List<Var> thisFilterVars = null; 1.676 + int count = 0; 1.677 + for(List<Var> vars : allSFilters.values()) 1.678 + { 1.679 + if(count == j - thematicJoinsSize) 1.680 + { 1.681 + thisFilterVars = vars; 1.682 + break; 1.683 + } 1.684 + count++; 1.685 + } 1.686 + if(!varsTillNow.isEmpty()) 1.687 + { 1.688 + if(varsTillNow.containsAll(thisFilterVars)) 1.689 + { 1.690 + continue; 1.691 + } 1.692 + } 1.693 + 1.694 + //varsTillNow.add(thisFilterVars.get(1)); 1.695 + varsTillNow.addAll(thisFilterVars); 1.696 + 1.697 + } 1.698 + 1.699 + tempList.add((Integer)j); 1.700 + pathLen++; 1.701 + if(pathLen == dims) 1.702 + { 1.703 + //End of recursion 1.704 + pathList.addAll(tempList); 1.705 + tempList.clear(); 1.706 + finalList.clear(); 1.707 + finalList.addAll(pathList); 1.708 + 1.709 + return true; 1.710 + } 1.711 + 1.712 + //Recurse 1.713 + success = createOrderedJoins(table, j, lineToScan, pathLen, varsTillNow, tempList, pathList, finalList); 1.714 + 1.715 + //Success = true => recursion ended with pathLen = maxLen 1.716 + if(success) 1.717 + { 1.718 + return true; 1.719 + } 1.720 + else 1.721 + { 1.722 + //end of a path originating from this node was found -> find an additional path (if exists) 1.723 + continue; 1.724 + } 1.725 + } 1.726 + } 1.727 + } 1.728 + //To reach this place means the end of a path was found 1.729 + pathList.addAll(tempList); 1.730 + tempList.clear(); 1.731 + if(pathList.size() > finalList.size()) 1.732 + { 1.733 + finalList.clear(); 1.734 + finalList.addAll(pathList); 1.735 + if(finalList.size() == dims) 1.736 + { 1.737 + return true; 1.738 + } 1.739 + } 1.740 + return false; 1.741 + } 1.742 + 1.743 + } 1.744 + 1.745 + protected abstract boolean isRelevantSTFunc(FunctionCall functionCall); 1.746 + /*{ 1.747 + Function function = FunctionRegistry.getInstance().get(functionCall.getURI()); 1.748 + if(function instanceof SpatialConstructFunc) 1.749 + { 1.750 + //TODO may have to comment this part again 1.751 + //uncommented because I use this function in the case of metrics 1.752 + return true; 1.753 + } 1.754 + else if(function instanceof SpatialRelationshipFunc) 1.755 + { 1.756 + return true; 1.757 + } 1.758 + else if(function instanceof SpatialPropertyFunc) //1 argument 1.759 + { 1.760 + return true; 1.761 + } 1.762 + else if(function instanceof SpatialMetricFunc) //Arguments # depends on the function selected 1.763 + { 1.764 + return true; 1.765 + } 1.766 + return false; 1.767 + }*/ 1.768 + 1.769 +}