diff options
author | Ed Willink | 2016-06-20 07:58:11 +0000 |
---|---|---|
committer | Ed Willink | 2016-06-29 10:56:05 +0000 |
commit | dfb81028bdd968ed2e3390170ad3f20fc3bbe264 (patch) | |
tree | 4d6abeda63f26d9948a22087e081409fb3cafc2c | |
parent | fa18504a0b97126077cc3da1255d65e3443fd82b (diff) | |
download | org.eclipse.qvtd-dfb81028bdd968ed2e3390170ad3f20fc3bbe264.tar.gz org.eclipse.qvtd-dfb81028bdd968ed2e3390170ad3f20fc3bbe264.tar.xz org.eclipse.qvtd-dfb81028bdd968ed2e3390170ad3f20fc3bbe264.zip |
[492255] Introduce Predicate edges for <<includes>> etc
9 files changed, 115 insertions, 25 deletions
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/AbstractEdge.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/AbstractEdge.java index 2fb25618f..23334e92a 100644 --- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/AbstractEdge.java +++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/AbstractEdge.java @@ -223,6 +223,11 @@ public abstract class AbstractEdge implements Edge//, GraphStringBuilder.GraphNo } @Override + public boolean isPredicate() { + return edgeRole.isPredicate(); + } + + @Override public boolean isPredicated() { return edgeRole.isPredicated(); } diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/AbstractEdgeRole.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/AbstractEdgeRole.java index 57f6d7110..7fdf3e5d3 100644 --- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/AbstractEdgeRole.java +++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/AbstractEdgeRole.java @@ -70,6 +70,11 @@ public abstract class AbstractEdgeRole extends AbstractRole implements EdgeRole } @Override + public boolean isPredicate() { + return false; + } + + @Override public boolean isRecursion() { return false; } diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Edge.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Edge.java index 855fa9b47..cff8d51d2 100644 --- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Edge.java +++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Edge.java @@ -116,6 +116,11 @@ public interface Edge extends GraphStringBuilder.GraphEdge, Nameable /** * Return true if this edge is for a predicate. */ + boolean isPredicate(); + + /** + * Return true if this edge is for a predicated relationship. + */ boolean isPredicated(); /** diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/EdgeRole.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/EdgeRole.java index d24db0653..7714d4f2f 100644 --- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/EdgeRole.java +++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/EdgeRole.java @@ -71,6 +71,7 @@ public interface EdgeRole extends Role * Return true if this edge represents a property navigation. */ boolean isNavigation(); + boolean isPredicate(); boolean isRecursion(); boolean isResult(); diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Edges.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Edges.java index d11014e8c..75fecfd43 100644 --- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Edges.java +++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Edges.java @@ -109,8 +109,11 @@ public class Edges { public static class ArgumentEdgeRole extends AbstractComputationEdgeRole { - protected ArgumentEdgeRole(@NonNull Phase phase) { + private final boolean isPredicate; + + protected ArgumentEdgeRole(@NonNull Phase phase, boolean isPredicate) { super(phase); + this.isPredicate = isPredicate; } @Override @@ -122,25 +125,40 @@ public class Edges public boolean isMergeable() { return true; } + + @Override + public boolean isPredicate() { + return isPredicate; + } } - private static final @NonNull ArgumentEdgeRole CONSTANT_ARGUMENT = new ArgumentEdgeRole(Role.Phase.CONSTANT); - private static final @NonNull ArgumentEdgeRole LOADED_ARGUMENT = new ArgumentEdgeRole(Role.Phase.LOADED); - private static final @NonNull ArgumentEdgeRole PREDICATED_ARGUMENT = new ArgumentEdgeRole(Role.Phase.PREDICATED); - public static final @NonNull ArgumentEdgeRole REALIZED_ARGUMENT = new ArgumentEdgeRole(Role.Phase.REALIZED); + private static final @NonNull ArgumentEdgeRole CONSTANT_ARGUMENT = new ArgumentEdgeRole(Role.Phase.CONSTANT, false); + private static final @NonNull ArgumentEdgeRole CONSTANT_PREDICATE = new ArgumentEdgeRole(Role.Phase.CONSTANT, true); + private static final @NonNull ArgumentEdgeRole LOADED_ARGUMENT = new ArgumentEdgeRole(Role.Phase.LOADED, false); + private static final @NonNull ArgumentEdgeRole LOADED_PREDICATE = new ArgumentEdgeRole(Role.Phase.LOADED, true); + private static final @NonNull ArgumentEdgeRole PREDICATED_ARGUMENT = new ArgumentEdgeRole(Role.Phase.PREDICATED, false); + private static final @NonNull ArgumentEdgeRole PREDICATED_PREDICATE = new ArgumentEdgeRole(Role.Phase.PREDICATED, true); + public static final @NonNull ArgumentEdgeRole REALIZED_ARGUMENT = new ArgumentEdgeRole(Role.Phase.REALIZED, false); + public static final @NonNull ArgumentEdgeRole REALIZED_PREDICATE = new ArgumentEdgeRole(Role.Phase.REALIZED, true); + + private final boolean isPredicate; + + public ArgumentEdgeRoleFactory(boolean isPredicate) { + this.isPredicate = isPredicate; + } public @NonNull SimpleEdge createSimpleEdge(@NonNull SimpleRegion region, @NonNull SimpleNode sourceNode, @Nullable String name, @NonNull SimpleNode targetNode) { if (sourceNode.isConstant()) { - return new BasicSimpleEdge(CONSTANT_ARGUMENT, region, sourceNode, name, targetNode); + return new BasicSimpleEdge(isPredicate ? CONSTANT_PREDICATE : CONSTANT_ARGUMENT, region, sourceNode, name, targetNode); } else if (sourceNode.isLoaded()) { - return new BasicSimpleEdge(LOADED_ARGUMENT, region, sourceNode, name, targetNode); + return new BasicSimpleEdge(isPredicate ? LOADED_PREDICATE : LOADED_ARGUMENT, region, sourceNode, name, targetNode); } else if (sourceNode.isPredicated()) { - return new BasicSimpleEdge(PREDICATED_ARGUMENT, region, sourceNode, name, targetNode); + return new BasicSimpleEdge(isPredicate ? PREDICATED_PREDICATE : PREDICATED_ARGUMENT, region, sourceNode, name, targetNode); } else if (sourceNode.isRealized()) { - return new BasicSimpleEdge(REALIZED_ARGUMENT, region, sourceNode, name, targetNode); + return new BasicSimpleEdge(isPredicate ? REALIZED_PREDICATE : REALIZED_ARGUMENT, region, sourceNode, name, targetNode); } else { throw new UnsupportedOperationException(); @@ -434,13 +452,14 @@ public class Edges } } - public static final @NonNull ArgumentEdgeRoleFactory ARGUMENT = new ArgumentEdgeRoleFactory(); + public static final @NonNull ArgumentEdgeRoleFactory ARGUMENT = new ArgumentEdgeRoleFactory(false); public static final @NonNull CastEdgeRoleFactory CAST = new CastEdgeRoleFactory(null); public static final @NonNull IteratedEdgeRoleFactory ITERATED = new IteratedEdgeRoleFactory(); // public static final @NonNull IteratingEdgeRoleFactory ITERATING = new IteratingEdgeRoleFactory(); // public static final @NonNull CastEdgeRoleFactory NAVIGABLE_CAST = new CastEdgeRoleFactory(true); public static final @NonNull NavigationEdgeRoleFactory NAVIGABLE_NAVIGATION = new NavigationEdgeRoleFactory(true); public static final @NonNull NavigationEdgeRoleFactory NAVIGATION = new NavigationEdgeRoleFactory(null); + public static final @NonNull ArgumentEdgeRoleFactory PREDICATE = new ArgumentEdgeRoleFactory(true); public static final EdgeRole.@NonNull Recursion PRIMARY_RECURSION = new RecursionEdgeRole(true); public static final EdgeRole.@NonNull Navigation REALIZED = new RealizedNavigationEdgeRole(); public static final @NonNull ResultEdgeRoleFactory RESULT = new ResultEdgeRoleFactory(); diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/ExpressionAnalyzer.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/ExpressionAnalyzer.java index 308bad98c..ac120b124 100644 --- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/ExpressionAnalyzer.java +++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/ExpressionAnalyzer.java @@ -22,6 +22,7 @@ import org.eclipse.ocl.pivot.CollectionItem; import org.eclipse.ocl.pivot.CollectionLiteralExp; import org.eclipse.ocl.pivot.CollectionLiteralPart; import org.eclipse.ocl.pivot.CollectionRange; +import org.eclipse.ocl.pivot.CollectionType; import org.eclipse.ocl.pivot.CompleteClass; import org.eclipse.ocl.pivot.DataType; import org.eclipse.ocl.pivot.Element; @@ -53,6 +54,7 @@ import org.eclipse.ocl.pivot.internal.prettyprint.PrettyPrinter; import org.eclipse.ocl.pivot.util.Visitable; import org.eclipse.ocl.pivot.utilities.ClassUtil; import org.eclipse.ocl.pivot.utilities.PivotUtil; +import org.eclipse.qvtd.pivot.qvtbase.Predicate; import org.eclipse.qvtd.pivot.qvtbase.Transformation; import org.eclipse.qvtd.pivot.qvtbase.TypedModel; import org.eclipse.qvtd.pivot.qvtbase.utilities.QVTbaseUtil; @@ -114,6 +116,13 @@ public class ExpressionAnalyzer extends AbstractExtendingQVTimperativeVisitor<@N return accept; } + private @NonNull SimpleNode analyzeOperationCallExp_includes(@NonNull SimpleNode sourceNode, @NonNull OperationCallExp operationCallExp) { + SimpleNode targetNode = analyze(operationCallExp.getOwnedArguments().get(0)); + String name = operationCallExp.getReferredOperation().getName(); + createPredicateEdge(sourceNode, "«" + name + "»", targetNode); + return Nodes.TRUE.createSimpleNode(sourceNode.getRegion()); + } + private @NonNull SimpleNode analyzeOperationCallExp_oclAsType(@NonNull SimpleNode sourceNode, @NonNull OperationCallExp operationCallExp) { // if ((operationCallExp.getOwnedSource() instanceof CallExp) && sourceNode.refineClassDatumAnalysis(scheduler.getClassDatumAnalysis(operationCallExp))) { // return sourceNode; @@ -255,6 +264,10 @@ public class ExpressionAnalyzer extends AbstractExtendingQVTimperativeVisitor<@N return Edges.ARGUMENT.createSimpleEdge(context, sourceNode, name, targetNode); } + protected @NonNull SimpleEdge createPredicateEdge(@NonNull SimpleNode sourceNode, @Nullable String name, @NonNull SimpleNode targetNode) { + return Edges.PREDICATE.createSimpleEdge(context, sourceNode, name, targetNode); + } + protected @NonNull SimpleEdge createCastEdge(@NonNull SimpleNode sourceNode, @NonNull Property castProperty, @NonNull SimpleNode castNode) { return Edges.CAST.createSimpleEdge(context, sourceNode, castProperty, castNode); } @@ -625,7 +638,7 @@ public class ExpressionAnalyzer extends AbstractExtendingQVTimperativeVisitor<@N } } } - String name = referredOperation.getName(); + String operationName = ClassUtil.nonNullState(referredOperation.getName()); if (ownedSource == null) { List<OCLExpression> ownedArguments = operationCallExp.getOwnedArguments(); int iSize = ownedArguments.size(); @@ -633,7 +646,7 @@ public class ExpressionAnalyzer extends AbstractExtendingQVTimperativeVisitor<@N for (int i = 0; i < iSize; i++) { argNodes[i] = analyze(ownedArguments.get(i)); } - SimpleNode operationNode = createOperationNode(ClassUtil.nonNullState(name), operationCallExp, argNodes); + SimpleNode operationNode = createOperationNode(operationName, operationCallExp, argNodes); for (int i = 0; i < iSize; i++) { createArgumentEdge(ClassUtil.nonNullState(argNodes[i]), /*iSize > 1 ?*/ "«arg" + i + "»"/*: null*/, operationNode); } @@ -652,6 +665,11 @@ public class ExpressionAnalyzer extends AbstractExtendingQVTimperativeVisitor<@N else if (PivotUtil.isSameOperation(operationId, scheduler.getOclAnyOclIsKindOfId())) { return analyzeOperationCallExp_oclIsKindOf(sourceNode, operationCallExp); } + else if ((operationCallExp.eContainer() instanceof Predicate) + && (sourceNode.getCompleteClass().getPrimaryClass() instanceof CollectionType) + && ("includes".equals(operationName) || "includesAll".equals(operationName))) { + return analyzeOperationCallExp_includes(sourceNode, operationCallExp); + } else { List<OCLExpression> ownedArguments = operationCallExp.getOwnedArguments(); int iSize = ownedArguments.size(); @@ -660,7 +678,7 @@ public class ExpressionAnalyzer extends AbstractExtendingQVTimperativeVisitor<@N for (int i = 0; i < iSize; i++) { argNodes[i+1] = analyze(ownedArguments.get(i)); } - SimpleNode operationNode = createOperationNode(ClassUtil.nonNullState(name), operationCallExp, argNodes); + SimpleNode operationNode = createOperationNode(operationName, operationCallExp, argNodes); for (int i = 0; i <= iSize; i++) { createArgumentEdge(ClassUtil.nonNullState(argNodes[i]), /*iSize > 1 ?*/ "«arg" + i + "»"/*: null*/, operationNode); } diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Node.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Node.java index 509689da6..bc2fd5c25 100644 --- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Node.java +++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/Node.java @@ -186,6 +186,7 @@ public interface Node extends ConnectionEnd, GraphStringBuilder.GraphNode, Namea * Return true if this node is an output port of a nested region. */ // boolean isOutput(); + /** * Return true if the value of this node is part of the navigation path that must be validated * by predicate matching prior to execution of a mapping. diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/SimpleMappingRegion.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/SimpleMappingRegion.java index 6d4e094f1..5277cd44b 100644 --- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/SimpleMappingRegion.java +++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/SimpleMappingRegion.java @@ -143,8 +143,13 @@ public class SimpleMappingRegion extends AbstractMappingRegion implements Simple } else { */ SimpleNode resultNode = expressionAnalyzer.analyze(conditionExpression); - SimpleNode trueNode = Nodes.TRUE.createSimpleNode(this); - Edges.ARGUMENT.createSimpleEdge(this, resultNode, null, trueNode); + if (!resultNode.isTrue()) { + SimpleNode trueNode = Nodes.TRUE.createSimpleNode(this); + Edges.PREDICATE.createSimpleEdge(this, resultNode, null, trueNode); + } + else { // FIXME ?? do includes() here explicitly + resultNode.destroy(); + } // } } // diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvti/BasicRegion2Mapping.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvti/BasicRegion2Mapping.java index 8b748696b..cb13001b6 100644 --- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvti/BasicRegion2Mapping.java +++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvti/BasicRegion2Mapping.java @@ -278,6 +278,12 @@ public class BasicRegion2Mapping extends AbstractRegion2Mapping if (variable != null) { return PivotUtil.createVariableExp(variable); } + if (node.isOperation()) { + Iterable<@NonNull TypedElement> typedElements = node.getTypedElements(); + assert Iterables.size(typedElements) >= 1; + return typedElements.iterator().next().accept(inlineExpressionCreator); + + } for (@NonNull Edge edge : node.getArgumentEdges()) { Node expNode = edge.getSource(); // TypedElement oldTypedElement = expNode.getTypedElements().iterator().next(); @@ -484,6 +490,11 @@ public class BasicRegion2Mapping extends AbstractRegion2Mapping return helper.createTypeExp(referredType); } +// @Override -- should not be invoked; results in use of input not output variable +// public @NonNull OCLExpression visitVariable(@NonNull Variable pVariable) { +// return helper.createVariableExp(pVariable); +// } + @Override public @NonNull OCLExpression visitVariableExp(@NonNull VariableExp pVariableExp) { VariableDeclaration pVariable = pVariableExp.getReferredVariable(); @@ -803,24 +814,44 @@ public class BasicRegion2Mapping extends AbstractRegion2Mapping ImperativeDomain oldDomain = typedModel2domain.put(qvtiTypedModel, domain); assert oldDomain == null; } - ECollections.sort(ClassUtil.nullFree(mapping.getDomain()), DomainNameComparator.INSTANCE); + EList<@NonNull Domain> domains = ClassUtil.nullFree(mapping.getDomain()); + ECollections.sort(domains, DomainNameComparator.INSTANCE); } /** * Create a predicate expression for each TRUE 'head'. */ private void createExternalPredicates() { - for (@NonNull Node node : region.getNodes()) { - if (node.isTrue()) { - for (@NonNull Edge edge : node.getArgumentEdges()) { - Node predicateNode = edge.getSource(); - for (@NonNull TypedElement typedElement : predicateNode.getTypedElements()) { - OCLExpression conditionExpression = typedElement.accept(inlineExpressionCreator); - Predicate asPredicate = QVTbaseFactory.eINSTANCE.createPredicate(); - asPredicate.setConditionExpression(conditionExpression); - addPredicate(asPredicate); + /* for (@NonNull Node node : region.getNodes()) { + if (node.isTrue()) { + for (@NonNull Edge edge : node.getArgumentEdges()) { + Node predicateNode = edge.getSource(); + for (@NonNull TypedElement typedElement : predicateNode.getTypedElements()) { + OCLExpression conditionExpression = typedElement.accept(inlineExpressionCreator); + Predicate asPredicate = QVTbaseFactory.eINSTANCE.createPredicate(); + asPredicate.setConditionExpression(conditionExpression); + addPredicate(asPredicate); + } + } + } */ + for (@NonNull Edge edge : region.getEdges()) { + if (edge.isPredicate()) { + Node sourceNode = edge.getSource(); + Node targetNode = edge.getTarget(); + OCLExpression conditionExpression = inlineExpressionCreator.getExpression(sourceNode); + assert conditionExpression != null; + if (!targetNode.isTrue()) { + String name = ClassUtil.nonNullState(edge.getName()).trim(); + if (name.length() >= 2) { + name = name.substring(1, name.length()-1); // Lose guillemets } + OCLExpression targetExpression = inlineExpressionCreator.getExpression(targetNode); + assert targetExpression != null; + conditionExpression = helper.createOperationCallExp(conditionExpression, name, targetExpression); } + Predicate asPredicate = QVTbaseFactory.eINSTANCE.createPredicate(); + asPredicate.setConditionExpression(conditionExpression); + addPredicate(asPredicate); } } } |