--- /dev/null
+package org.simantics.modeling.scl;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.scl.compiler.common.names.Name;\r
+import org.simantics.scl.compiler.elaboration.expressions.EApply;\r
+import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant;\r
+import org.simantics.scl.compiler.elaboration.expressions.EVariable;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+import org.simantics.scl.compiler.elaboration.expressions.Variable;\r
+import org.simantics.scl.compiler.elaboration.query.compilation.EnforcingContext;\r
+import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationContext;\r
+import org.simantics.scl.compiler.elaboration.relations.SCLRelation;\r
+import org.simantics.scl.compiler.errors.Locations;\r
+import org.simantics.scl.compiler.types.TVar;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.Types;\r
+\r
+public class GraphRelation implements SCLRelation {\r
+\r
+ Resource relation;\r
+ double relationSelectivity;\r
+ Resource inverseRelation;\r
+ double inverseRelationSelectivity;\r
+ \r
+ public GraphRelation(Resource relation, double relationSelectivity,\r
+ Resource inverseRelation, double inverseRelationSelectivity) {\r
+ this.relation = relation;\r
+ this.relationSelectivity = relationSelectivity;\r
+ this.inverseRelation = inverseRelation;\r
+ this.inverseRelationSelectivity = inverseRelationSelectivity;\r
+ }\r
+\r
+ @Override\r
+ public TVar[] getTypeVariables() {\r
+ return TVar.EMPTY_ARRAY;\r
+ }\r
+ \r
+ private static final Type[] PARAMETER_TYPES = new Type[] { Types.RESOURCE, Types.RESOURCE };\r
+ \r
+ @Override\r
+ public Type[] getParameterTypes() {\r
+ return PARAMETER_TYPES;\r
+ }\r
+\r
+ @Override\r
+ public double getSelectivity(int boundVariables) {\r
+ switch(boundVariables) {\r
+ case FF: return Double.POSITIVE_INFINITY;\r
+ case BF: return relationSelectivity;\r
+ case FB: return inverseRelation == null ? Double.POSITIVE_INFINITY : inverseRelationSelectivity;\r
+ case BB: return 0.1;\r
+ default: throw new IllegalArgumentException();\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public int getRequiredVariablesMask() {\r
+ return inverseRelation == null ? BF : FF;\r
+ }\r
+ \r
+ private static final Name GET_OBJECTS = Name.create("Simantics/DB", "#");\r
+ private static final Name HAS_STATEMENT = Name.create("Simantics/DB", "existsStatement3");\r
+ \r
+ @Override\r
+ public void generate(long location, QueryCompilationContext context,\r
+ Type[] typeParameters, Variable[] parameters, int boundVariables) {\r
+ switch(boundVariables) {\r
+ case BF: \r
+ context.iterateList(parameters[1], new EApply(\r
+ Locations.NO_LOCATION,\r
+ Types.READ_GRAPH,\r
+ context.getTypingContext().getConstant(GET_OBJECTS),\r
+ new EVariable(parameters[0]),\r
+ new EExternalConstant(relation, Types.RESOURCE)\r
+ ));\r
+ break;\r
+ case FB:\r
+ if(inverseRelation == null)\r
+ throw new IllegalArgumentException();\r
+ context.iterateList(parameters[0], new EApply(\r
+ Locations.NO_LOCATION,\r
+ Types.READ_GRAPH,\r
+ context.getTypingContext().getConstant(GET_OBJECTS),\r
+ new EVariable(parameters[1]),\r
+ new EExternalConstant(inverseRelation, Types.RESOURCE)\r
+ ));\r
+ break;\r
+ case BB:\r
+ context.condition(\r
+ inverseRelation == null || relationSelectivity <= inverseRelationSelectivity\r
+ ? new EApply(\r
+ Locations.NO_LOCATION,\r
+ Types.READ_GRAPH,\r
+ context.getTypingContext().getConstant(HAS_STATEMENT),\r
+ new Expression[] {\r
+ new EVariable(parameters[0]),\r
+ new EExternalConstant(relation, Types.RESOURCE),\r
+ new EVariable(parameters[1])\r
+ }\r
+ )\r
+ : new EApply(\r
+ Locations.NO_LOCATION,\r
+ Types.READ_GRAPH,\r
+ context.getTypingContext().getConstant(HAS_STATEMENT),\r
+ new Expression[] {\r
+ new EVariable(parameters[1]),\r
+ new EExternalConstant(inverseRelation, Types.RESOURCE),\r
+ new EVariable(parameters[0])\r
+ }\r
+ ));\r
+ break;\r
+ default: throw new IllegalArgumentException();\r
+ }\r
+ }\r
+\r
+ private static final Name CLAIM = Name.create("Simantics/DB", "claim");\r
+ \r
+ @Override\r
+ public Expression generateEnforce(long location, EnforcingContext context,\r
+ Type[] typeParameters, Variable[] parameters) {\r
+ return new EApply(\r
+ Locations.NO_LOCATION,\r
+ Types.WRITE_GRAPH,\r
+ context.getTypingContext().getConstant(CLAIM),\r
+ new EVariable(parameters[0]),\r
+ new EExternalConstant(relation, Types.RESOURCE),\r
+ new EVariable(parameters[1])\r
+ );\r
+ }\r
+\r
+ @Override\r
+ public int getPhase() {\r
+ return 0;\r
+ }\r
+\r
+}\r