X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=org.simantics.district.selection%2Fsrc%2Forg%2Fsimantics%2Fdistrict%2Fselection%2FElementSelector.java;fp=org.simantics.district.selection%2Fsrc%2Forg%2Fsimantics%2Fdistrict%2Fselection%2FElementSelector.java;h=4143248214b97786661ae6465bf160dafec42a77;hb=1a232af9f794ce2a7fae808c207e28ac1af4bda3;hp=f0cbf4b1af9d02bfe0bee56b9eea098561e499be;hpb=a6aadb3e277051b23ea8c09e553c64098b152f84;p=simantics%2Fdistrict.git diff --git a/org.simantics.district.selection/src/org/simantics/district/selection/ElementSelector.java b/org.simantics.district.selection/src/org/simantics/district/selection/ElementSelector.java index f0cbf4b1..41432482 100644 --- a/org.simantics.district.selection/src/org/simantics/district/selection/ElementSelector.java +++ b/org.simantics.district.selection/src/org/simantics/district/selection/ElementSelector.java @@ -13,12 +13,20 @@ import java.util.Set; import java.util.stream.Collectors; import org.simantics.Simantics; +import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; import org.simantics.db.RequestProcessor; import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; import org.simantics.db.common.request.ResourceRead; import org.simantics.db.common.utils.ListUtils; +import org.simantics.db.exception.AssumptionException; import org.simantics.db.exception.DatabaseException; +import org.simantics.db.exception.DoesNotContainValueException; +import org.simantics.db.exception.ManyObjectsForFunctionalRelationException; +import org.simantics.db.exception.NoSingleResultException; +import org.simantics.db.exception.ServiceException; +import org.simantics.db.exception.ValidationException; import org.simantics.db.layer0.QueryIndexUtils; import org.simantics.db.layer0.request.ActiveModels; import org.simantics.db.layer0.request.ActiveRuns; @@ -31,7 +39,6 @@ import org.simantics.db.request.Read; import org.simantics.diagram.stubs.DiagramResource; import org.simantics.district.network.ontology.DistrictNetworkResource; import org.simantics.district.region.ontology.DiagramRegionsResource; -import org.simantics.district.selection.ElementSelector.AggregateCondition.Type; import org.simantics.layer0.Layer0; import org.simantics.modeling.ModelingResources; import org.simantics.structural.stubs.StructuralResource2; @@ -246,18 +253,14 @@ public class ElementSelector { if (!graph.isInstanceOf(resource, ES.Generator)) throw new IllegalArgumentException("Resource " + resource + " is not a valid generator"); - if (graph.isInstanceOf(resource, ES.Generator_Model)) { + if (graph.isInstanceOf(resource, ES.Generator_Model)) return new ModelGenerator(); - } - else if (graph.isInstanceOf(resource, ES.Generator_Diagram)) { + else if (graph.isInstanceOf(resource, ES.Generator_Diagram)) return new DiagramGenerator(graph.getSingleObject(resource, ES.Generator_HasDiagram)); - } - else if (graph.isInstanceOf(resource, ES.Generator_Explicit)) { + else if (graph.isInstanceOf(resource, ES.Generator_Explicit)) return new ExplicitGenerator(graph.getObjects(resource, ES.Generator_HasSelectedElement)); - } - else { + else throw new IllegalArgumentException("Unknown generator type " + graph.getURI(graph.getSingleType(resource))); - } } private static Selector buildSelector(ReadGraph graph, Resource resource) throws DatabaseException { @@ -265,18 +268,16 @@ public class ElementSelector { throw new IllegalArgumentException("Resource " + resource + " is not a valid selector"); Selector s; - if (graph.isInstanceOf(resource, ES.Selector_All)) { + if (graph.isInstanceOf(resource, ES.Selector_All)) s = new All(); - } - else if (graph.isInstanceOf(resource, ES.PropertySelector)) { - String propertyName = graph.getRelatedValue(resource, ES.PropertySelector_HasSelectionPropertyName); - Integer resultCount = graph.getRelatedValue(resource, ES.PropertySelector_HasResultCount); - boolean isSmallest = graph.isInstanceOf(resource, ES.Selector_NLowest); - s = new PropertySelector(isSmallest, propertyName, resultCount); - } - else { + else if (graph.isInstanceOf(resource, ES.PropertySelector)) + s = new PropertySelector(graph, resource); + else throw new IllegalArgumentException("Unknown selector type " + graph.getURI(graph.getSingleType(resource))); - } + + Resource mapping = graph.getPossibleObject(resource, ES.Selector_HasMapping); + s.componentType = mapping; + return s; } @@ -288,145 +289,179 @@ public class ElementSelector { throw new IllegalArgumentException("Resource " + resource + " is not a valid condition"); Condition cond; - if (graph.isInstanceOf(resource, ES.PropertyCondition)) { - String propertyName = graph.getRelatedValue(resource, ES.PropertyCondition_HasPropertyName); - Double lowerLimit = graph.getPossibleRelatedValue(resource, ES.PropertyCondition_HasLowerLimit); - Double upperLimit = graph.getPossibleRelatedValue(resource, ES.PropertyCondition_HasUpperLimit); - cond = new PropertyCondition(resource, propertyName, lowerLimit, upperLimit); + if (graph.isInstanceOf(resource, ES.PropertyCondition)) + cond = new PropertyCondition(graph, resource); + else if (graph.isInstanceOf(resource, ES.RegionCondition)) + cond = new RegionCondition(graph, resource); + else if (graph.isInstanceOf(resource, ES.RouteCondition)) + cond = new RouteCondition(graph, resource); + else if (graph.isInstanceOf(resource, ES.AggregateCondition)) + cond = new AggregateCondition(graph, resource); + else + throw new IllegalArgumentException("Unknown condition type " + graph.getURI(graph.getSingleType(resource))); + + return cond; + } + + private static String buildExpression(ReadGraph graph, Resource r) throws DatabaseException { + if (graph.isInstanceOf(r, ES.Selection)) + return buildSelectionExpression(graph, r); + else if (graph.isInstanceOf(r, ES.Condition)) + return buildConditionExpression(graph, r); + else if (graph.isInstanceOf(r, ES.Selector)) + return buildSelectorExpression(graph, r); + else if (graph.isInstanceOf(r, ES.Generator)) + return buildGeneratorExpression(graph, r); + else + throw new DatabaseException("Unsupported resource type <" + graph.getURI(graph.getSingleType(r)) + ">"); + } + + private static String buildSelectionExpression(ReadGraph graph, Resource r) throws DatabaseException, + NoSingleResultException, ManyObjectsForFunctionalRelationException, ServiceException { + String exp = "select " + getExpression(graph, graph.getSingleObject(r, ES.Selection_HasSelector)) + + " from " + getExpression(graph, graph.getSingleObject(r, ES.Selection_HasGenerator)); + + Resource cond = graph.getPossibleObject(r, ES.Selection_HasCondition); + return cond != null ? exp + " where {" + getExpression(graph, cond) + "}" : exp; + } + + private static String buildGeneratorExpression(ReadGraph graph, Resource r) + throws ServiceException, NoSingleResultException, DoesNotContainValueException, + ManyObjectsForFunctionalRelationException, DatabaseException, AssumptionException, ValidationException { + if (graph.isInstanceOf(r, ES.Generator_Model)) { + return "model"; } - else if (graph.isInstanceOf(resource, ES.RegionCondition)) { - DiagramRegionsResource DR = DiagramRegionsResource.getInstance(graph); - Resource regionResource = graph.getSingleObject(resource, ES.RegionCondition_HasRegion); - double[] region = graph.getRelatedValue(regionResource, DR.Region_area); - cond = new RegionCondition(resource, regionResource, region); + else if (graph.isInstanceOf(r, ES.Generator_Diagram)) { + return "diagram \"" + graph.getRelatedValue(graph.getSingleObject(r, ES.Generator_HasDiagram), L0.HasName) + "\""; } - else if (graph.isInstanceOf(resource, ES.RouteCondition)) { - Resource routeResource = graph.getSingleObject(resource, ES.RouteCondition_HasRoute); - Set routePoints = new HashSet<>(ListUtils.toList(graph, routeResource)); - cond = new RouteCondition(resource, routeResource, routePoints); + else if (graph.isInstanceOf(r, ES.Generator_Explicit)) { + return ""; } - else if (graph.isInstanceOf(resource, ES.AggregateCondition)) { - Collection conditionResources = graph.getObjects(resource, ES.HasSubcondition); - List conditions = new ArrayList<>(conditionResources.size()); - for (Resource c : conditionResources) { - conditions.add(buildCondition(graph, c)); - } - Type type; - if (graph.isInstanceOf(resource, ES.Conjunction)) - type = AggregateCondition.Type.CONJUNCTION; - else if (graph.isInstanceOf(resource, ES.Negation)) - type = AggregateCondition.Type.NEGATION; - else if (graph.isInstanceOf(resource, ES.Disjunction)) - type = AggregateCondition.Type.DISJUNCTION; - else - throw new IllegalArgumentException("Unknown aggreate condition type " + graph.getURI(graph.getSingleType(resource))); - - cond = new AggregateCondition(resource, type, conditions); + else { + throw new DatabaseException("Unsupported generator resource type <" + graph.getURI(graph.getSingleType(r)) + ">"); + } + } + + private static String buildSelectorExpression(ReadGraph graph, Resource r) + throws ServiceException, NoSingleResultException, DoesNotContainValueException, DatabaseException, + AssumptionException, ValidationException, ManyObjectsForFunctionalRelationException { + String exp; + if (graph.isInstanceOf(r, ES.Selector_All)) { + exp = "all"; + } + else if (graph.isInstanceOf(r, ES.PropertySelector)) { + Integer count = graph.getRelatedValue(r, ES.PropertySelector_HasResultCount); + exp = count.toString(); } else { - throw new IllegalArgumentException("Unknown condition type " + graph.getURI(graph.getSingleType(resource))); + throw new DatabaseException("Unsupported selector resource type <" + graph.getURI(graph.getSingleType(r)) + ">"); } - return cond; + Resource mapping = graph.getPossibleObject(r, ES.Selector_HasMapping); + if (mapping != null) { + String name = graph.getRelatedValue2(mapping, L0.HasName); + exp = exp + " " + name; + } else { + exp = exp + " elements"; + } + + if (graph.isInstanceOf(r, ES.PropertySelector)) { + String op; + if (graph.isInstanceOf(r, ES.Selector_NLowest)) + op = "lowest"; + else if (graph.isInstanceOf(r, ES.Selector_NHighest)) + op = "highest"; + else + throw new DatabaseException("Unsupported property selector resource type <" + graph.getURI(graph.getSingleType(r)) + ">"); + + String name = graph.getRelatedValue(r, ES.PropertySelector_HasSelectionPropertyName); + exp = exp + " with " + op + " " + name; + } + + return exp; } - private static String buildExpression(ReadGraph graph, Resource r) throws DatabaseException { - if (graph.isInstanceOf(r, ES.Selection)) { - String exp = "select " + getExpression(graph, graph.getSingleObject(r, ES.Selection_HasSelector)) + - " from " + getExpression(graph, graph.getSingleObject(r, ES.Selection_HasGenerator)); - - Resource cond = graph.getPossibleObject(r, ES.Selection_HasCondition); - return cond != null ? exp + " where {" + getExpression(graph, cond) + "}" : exp; + private static String buildConditionExpression(ReadGraph graph, Resource r) throws ServiceException, + DatabaseException, NoSingleResultException, ManyObjectsForFunctionalRelationException, + DoesNotContainValueException, AssumptionException, ValidationException { + String result; + boolean isInverse = graph.hasStatement(r, ES.Condition_IsInverse, r); + if (graph.isInstanceOf(r, ES.PropertyCondition)) { + result = buildPropertyConditionExpression(graph, r); } - else if (graph.isInstanceOf(r, ES.Condition)) { - if (graph.isInstanceOf(r, ES.PropertyCondition)) { - return buildPropertyConditionExpression(graph, r); - } - else if (graph.isInstanceOf(r, ES.RegionCondition)) { - Resource region = graph.getSingleObject(r, ES.RegionCondition_HasRegion); - String name = graph.getRelatedValue(region, L0.HasLabel); - return "in region " + name; - } - else if (graph.isInstanceOf(r, ES.RouteCondition)) { - Resource route = graph.getSingleObject(r, ES.RouteCondition_HasRoute); - String name = graph.getRelatedValue(route, L0.HasLabel); - return "in route " + name; - } - else if (graph.isInstanceOf(r, ES.AggregateCondition)) { - String op = graph.isInstanceOf(r, ES.Conjunction) ? " and " : " or "; - List exps = new ArrayList<>(); - Collection objects = graph.getObjects(r, ES.HasSubcondition); - for (Resource c : objects) { - String exp = getExpression(graph, c); - exps.add(objects.size() > 1 ? "{" + exp + "}" : exp); - } - String result = String.join(op, exps); - if (graph.isInstanceOf(r, ES.Negation)) - result = "not {" + result + "}"; - return result; - } - else { - throw new DatabaseException("Unsupported condition resource type <" + graph.getURI(graph.getSingleType(r)) + ">"); - } + else if (graph.isInstanceOf(r, ES.RegionCondition)) { + result = buildRegionConditionExpression(graph, r); } - else if (graph.isInstanceOf(r, ES.Selector)) { - if (graph.isInstanceOf(r, ES.Selector_All)) { - return "all"; - } - else if (graph.isInstanceOf(r, ES.PropertySelector)) { - String op; - if (graph.isInstanceOf(r, ES.Selector_NLowest)) - op = "bottom"; - else if (graph.isInstanceOf(r, ES.Selector_NHighest)) - op = "top"; - else - throw new DatabaseException("Unsupported property selector resource type <" + graph.getURI(graph.getSingleType(r)) + ">"); - - String name = graph.getRelatedValue(r, ES.PropertySelector_HasSelectionPropertyName); - Integer count = graph.getRelatedValue(r, ES.PropertySelector_HasResultCount); - return op + " " + count + " of " + name; - } - else { - throw new DatabaseException("Unsupported selector resource type <" + graph.getURI(graph.getSingleType(r)) + ">"); - } + else if (graph.isInstanceOf(r, ES.RouteCondition)) { + result = buildRouteConditionExpression(graph, r); } - else if (graph.isInstanceOf(r, ES.Generator)) { - if (graph.isInstanceOf(r, ES.Generator_Model)) { - return "model"; - } - else if (graph.isInstanceOf(r, ES.Generator_Diagram)) { - return "diagram \"" + graph.getRelatedValue(graph.getSingleObject(r, ES.Generator_HasDiagram), L0.HasName) + "\""; - } - else if (graph.isInstanceOf(r, ES.Generator_Explicit)) { - return ""; - } - else { - throw new DatabaseException("Unsupported generator resource type <" + graph.getURI(graph.getSingleType(r)) + ">"); - } + else if (graph.isInstanceOf(r, ES.AggregateCondition)) { + // This handles isInverse internally + return buildAggregateConditionExpression(graph, r, isInverse); } else { - throw new DatabaseException("Unsupported resource type <" + graph.getURI(graph.getSingleType(r)) + ">"); + throw new DatabaseException("Unsupported condition resource type <" + graph.getURI(graph.getSingleType(r)) + ">"); } + + if (isInverse) + result = "not {" + result + "}"; + + return result; + } + + private static String buildAggregateConditionExpression(ReadGraph graph, Resource r, boolean isInverse) + throws ServiceException, DatabaseException { + String result; + String op = graph.isInstanceOf(r, ES.Conjunction) ? " and " : " or "; + List exps = new ArrayList<>(); + Collection objects = graph.getObjects(r, ES.HasSubcondition); + for (Resource c : objects) { + String exp = getExpression(graph, c); + exps.add(objects.size() > 1 ? "{" + exp + "}" : exp); + } + result = String.join(op, exps); + if (graph.isInstanceOf(r, ES.Negation) ^ isInverse) + result = "not {" + result + "}"; + return result; + } + + private static String buildRouteConditionExpression(ReadGraph graph, Resource r) throws NoSingleResultException, + ManyObjectsForFunctionalRelationException, ServiceException, DoesNotContainValueException { + String result; + Resource route = graph.getSingleObject(r, ES.RouteCondition_HasRoute); + String name = graph.getRelatedValue(route, L0.HasLabel); + result = "in route " + name; + return result; + } + + private static String buildRegionConditionExpression(ReadGraph graph, Resource r) throws NoSingleResultException, + ManyObjectsForFunctionalRelationException, ServiceException, DoesNotContainValueException { + String result; + Resource region = graph.getSingleObject(r, ES.RegionCondition_HasRegion); + String name = graph.getRelatedValue(region, L0.HasLabel); + result = "in region " + name; + return result; } private static String buildPropertyConditionExpression(ReadGraph graph, Resource r) throws DatabaseException { String propertyName = graph.getRelatedValue(r, ES.PropertyCondition_HasPropertyName); Double lowerLimit = graph.getPossibleRelatedValue(r, ES.PropertyCondition_HasLowerLimit); Double upperLimit = graph.getPossibleRelatedValue(r, ES.PropertyCondition_HasUpperLimit); - if (lowerLimit == null && upperLimit == null) { - return "has property " + propertyName; - } - else { + if (upperLimit == null) { + if (lowerLimit == null) { + return "has property " + propertyName; + } else { + return propertyName + " \u2265 " + lowerLimit; + } + } else { StringBuilder result = new StringBuilder(); if (lowerLimit != null) { result.append(lowerLimit); - result.append(" < "); + result.append(" \u2264 "); } result.append(propertyName); - if (upperLimit != null) { - result.append(" < "); - result.append(upperLimit); - } + result.append(" \u2264 "); + result.append(upperLimit); return result.toString(); } } @@ -538,7 +573,26 @@ public class ElementSelector { } public static abstract class Selector { + public Resource componentType = null; + abstract SelectionResult select(ReadGraph graph, Collection elements); + + Collection filterElements(ReadGraph graph, Collection elements) { + if (componentType == null) + return elements; + + Collection selected = new HashSet<>(elements.size()); + for (Resource r : elements) { + try { + if (graph.hasStatement(r, DN.HasMapping, componentType)) + selected.add(r); + } catch (DatabaseException e) { + // Just leave it out of the result + } + } + + return selected; + } } public static class All extends Selector { @@ -547,7 +601,8 @@ public class ElementSelector { @Override SelectionResult select(ReadGraph graph, Collection elements) { - return new SelectionResult(elements, 0, 0); + Collection selected = filterElements(graph, elements); + return new SelectionResult(selected, 0, 0); } } @@ -558,12 +613,20 @@ public class ElementSelector { this.resultCount = resultCount; } + public PropertySelector(ReadGraph graph, Resource resource) throws DatabaseException { + this.propertyName = graph.getRelatedValue(resource, ES.PropertySelector_HasSelectionPropertyName); + this.resultCount = graph.getRelatedValue(resource, ES.PropertySelector_HasResultCount); + this.smallest = graph.isInstanceOf(resource, ES.Selector_NLowest); + } + public boolean smallest; public String propertyName; public int resultCount; @Override SelectionResult select(ReadGraph graph, Collection elements) { + elements = filterElements(graph, elements); + // Select sorting direction Comparator> comparator = smallest ? (p1, p2) -> Double.compare(p1.second, p2.second) : @@ -611,15 +674,38 @@ public class ElementSelector { public static abstract class Condition { public Resource resource; + public boolean isInverse; Condition(Resource r) { resource = r; + isInverse = false; } - abstract boolean match(ReadGraph graph, Resource r) throws DatabaseException; + Condition(ReadGraph graph, Resource r) throws DatabaseException { + this(r); + isInverse = graph.hasStatement(r, ES.Condition_IsInverse, r); + } + + public abstract boolean match(ReadGraph graph, Resource r) throws DatabaseException; + public Resource update(WriteGraph graph) throws DatabaseException { + assert(resource != null); + if (isInverse) + graph.claim(resource, ES.Condition_IsInverse, resource); + else + graph.deny(resource, ES.Condition_IsInverse, resource); + return resource; + } } public static class PropertyCondition extends Condition { + public PropertyCondition(ReadGraph graph, Resource r) throws DatabaseException { + super(graph, r); + + this.propertyName = graph.getRelatedValue(resource, ES.PropertyCondition_HasPropertyName); + this.lowerLimit = graph.getPossibleRelatedValue(resource, ES.PropertyCondition_HasLowerLimit); + this.upperLimit = graph.getPossibleRelatedValue(resource, ES.PropertyCondition_HasUpperLimit); + } + public PropertyCondition(Resource r, String propertyName, Double lowerLimit, Double upperLimit) { super(r); @@ -633,27 +719,67 @@ public class ElementSelector { public Double upperLimit; @Override - boolean match(ReadGraph graph, Resource r) { + public boolean match(ReadGraph graph, Resource r) { Double value = getPropertyValue(graph, r, propertyName); - return value != null && (lowerLimit == null || value >= lowerLimit) && (upperLimit == null || value <= upperLimit); + boolean result = value != null && (lowerLimit == null || value >= lowerLimit) && (upperLimit == null || value <= upperLimit); + return result ^ isInverse; + } + + @Override + public Resource update(WriteGraph graph) throws DatabaseException { + ElementSelectionResource ES = ElementSelectionResource.getInstance(graph); + Layer0 L0 = Layer0.getInstance(graph); + + if (resource == null) { + resource = graph.newResource(); + graph.claim(resource, L0.InstanceOf, ES.PropertyCondition); + } + + super.update(graph); + + graph.claimLiteral(resource, ES.PropertyCondition_HasPropertyName, propertyName); + if (lowerLimit != null) + graph.claimLiteral(resource, ES.PropertyCondition_HasLowerLimit, L0.Double, lowerLimit); + else + graph.deny(resource, ES.PropertyCondition_HasLowerLimit); + + if (upperLimit != null) + graph.claimLiteral(resource, ES.PropertyCondition_HasUpperLimit, L0.Double, upperLimit); + else + graph.deny(resource, ES.PropertyCondition_HasUpperLimit); + return resource; } } public static class RegionCondition extends Condition { - public RegionCondition(Resource r, Resource regionResoruce, double[] region) { + public RegionCondition(Resource r, Resource regionResource, double[] region) { super(r); this.region = region; + this.path = createPathForRegion(region); + this.regionResource = regionResource; + } + + public RegionCondition(ReadGraph graph, Resource r) throws DatabaseException { + super(graph, r); + DiagramRegionsResource DR = DiagramRegionsResource.getInstance(graph); + this.regionResource = graph.getPossibleObject(resource, ES.RegionCondition_HasRegion); + this.region = regionResource != null ? graph.getRelatedValue(regionResource, DR.Region_area) : null; + this.path = createPathForRegion(region); + } + + public static Path2D createPathForRegion(double[] region) { Path2D path = new Path2D.Double(); - double startX = region[0]; - double startY = region[1]; - path.moveTo(startX, startY); - for (int i = 2; i < region.length; i+=2) - path.lineTo(region[i], region[i+1]); - path.closePath(); + if (region != null) { + double startX = region[0]; + double startY = region[1]; + path.moveTo(startX, startY); + for (int i = 2; i < region.length; i+=2) + path.lineTo(region[i], region[i+1]); + path.closePath(); + } - this.path = path; - this.regionResource = regionResoruce; + return path; } public Resource regionResource; @@ -661,12 +787,34 @@ public class ElementSelector { Path2D path; @Override - boolean match(ReadGraph graph, Resource r) throws DatabaseException { + public boolean match(ReadGraph graph, Resource r) throws DatabaseException { double[] transform = graph.getRelatedValue(r, DIA.HasTransform); double x = transform[4]; double y = transform[5]; - return path.contains(x, y); - } + return path.contains(x, y) ^ isInverse; + } + + @Override + public Resource update(WriteGraph graph) throws DatabaseException { + ElementSelectionResource ES = ElementSelectionResource.getInstance(graph); + Layer0 L0 = Layer0.getInstance(graph); + + if (resource == null) { + resource = graph.newResource(); + graph.claim(resource, L0.InstanceOf, ES.RegionCondition); + } + + super.update(graph); + + graph.claim(resource, ES.RegionCondition_HasRegion, regionResource); + + // Re-read region data to match DB + DiagramRegionsResource DR = DiagramRegionsResource.getInstance(graph); + this.region = regionResource != null ? graph.getRelatedValue(regionResource, DR.Region_area, Bindings.DOUBLE_ARRAY) : null; + this.path = createPathForRegion(region); + + return resource; + } } public static class RouteCondition extends Condition { @@ -676,12 +824,44 @@ public class ElementSelector { this.routeResource = routeResource; } + public RouteCondition(ReadGraph graph, Resource r) throws DatabaseException { + super(graph, r); + this.routeResource = graph.getPossibleObject(resource, ES.RouteCondition_HasRoute); + this.routePoints = getRoutePoints(graph, routeResource); + } + + public static Set getRoutePoints(ReadGraph graph, Resource routeResource) throws DatabaseException { + return routeResource != null ? + new HashSet<>(ListUtils.toList(graph, routeResource)) : + Collections.emptySet(); + } + public Resource routeResource; Set routePoints; @Override - boolean match(ReadGraph graph, Resource r) throws DatabaseException { - return routePoints.contains(r); + public boolean match(ReadGraph graph, Resource r) throws DatabaseException { + return routePoints.contains(r) ^ isInverse; + } + + @Override + public Resource update(WriteGraph graph) throws DatabaseException { + ElementSelectionResource ES = ElementSelectionResource.getInstance(graph); + Layer0 L0 = Layer0.getInstance(graph); + + if (resource == null) { + resource = graph.newResource(); + graph.claim(resource, L0.InstanceOf, ES.RouteCondition); + } + + super.update(graph); + + if (routeResource != null) + graph.claim(resource, ES.RouteCondition_HasRoute, routeResource); + + this.routePoints = getRoutePoints(graph, routeResource); + + return resource; } } @@ -694,11 +874,32 @@ public class ElementSelector { this.conditions = conditions; } + public AggregateCondition(ReadGraph graph, Resource r) throws DatabaseException { + super(graph, r); + Collection conditionResources = graph.getObjects(resource, ES.HasSubcondition); + conditions = new ArrayList<>(conditionResources.size()); + for (Resource c : conditionResources) { + conditions.add(buildCondition(graph, c)); + } + if (graph.isInstanceOf(resource, ES.Conjunction)) + this.type = AggregateCondition.Type.CONJUNCTION; + else if (graph.isInstanceOf(resource, ES.Negation)) + this.type = AggregateCondition.Type.NEGATION; + else if (graph.isInstanceOf(resource, ES.Disjunction)) + this.type = AggregateCondition.Type.DISJUNCTION; + else + throw new IllegalArgumentException("Unknown aggreate condition type " + graph.getURI(graph.getSingleType(resource))); + } + public Type type; public List conditions; @Override - boolean match(ReadGraph graph, Resource r) throws DatabaseException { + public boolean match(ReadGraph graph, Resource r) throws DatabaseException { + return doMatch(graph, r) ^ isInverse; + } + + private boolean doMatch(ReadGraph graph, Resource r) throws DatabaseException { switch (type) { case DISJUNCTION: for (Condition c : conditions) @@ -717,6 +918,41 @@ public class ElementSelector { throw new IllegalArgumentException("Unknown aggregate condition type " + type); } } + + @Override + public Resource update(WriteGraph graph) throws DatabaseException { + ElementSelectionResource ES = ElementSelectionResource.getInstance(graph); + Layer0 L0 = Layer0.getInstance(graph); + + if (resource == null) { + resource = graph.newResource(); + } else { + graph.deny(resource, L0.InstanceOf); + graph.deny(resource, ES.HasSubcondition); + } + + Resource type; + switch (this.type) { + case CONJUNCTION: + type = ES.Conjunction; break; + case DISJUNCTION: + type = ES.Disjunction; break; + case NEGATION: + type = ES.Negation; break; + default: + throw new IllegalStateException("Unknown condition type " + this.type); + } + + graph.claim(resource, L0.InstanceOf, type); + + super.update(graph); + + for (Condition c : conditions) { + graph.claim(resource, ES.HasSubcondition, c.update(graph)); + } + + return resource; + } } public static class ElementSelectorQuery extends ResourceRead {