| /** |
| * Copyright (c) 2015, 2018 Willink Transformations and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v2.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v20.html |
| * |
| * Contributors: |
| * E.D.Willink - Initial API and implementation |
| */ |
| package org.eclipse.qvtd.xtext.qvtcore.tests; |
| |
| import java.util.ArrayList; |
| import java.util.Comparator; |
| import java.util.List; |
| |
| import org.eclipse.emf.common.util.ECollections; |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.emf.common.util.TreeIterator; |
| import org.eclipse.emf.ecore.EAttribute; |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EPackage; |
| import org.eclipse.emf.ecore.EReference; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.jdt.annotation.NonNull; |
| import org.eclipse.ocl.examples.xtext.tests.XtextTestCase.Normalizer; |
| import org.eclipse.ocl.pivot.utilities.ClassUtil; |
| import org.eclipse.qvtd.xtext.qvtbase.tests.ModelNormalizer; |
| import org.eclipse.qvtd.xtext.qvtcore.tests.upper2lower.simplegraph.SimplegraphPackage; |
| |
| /** |
| * Upper2LowerNormalizer normalises the results of the UpperToLower transformation. |
| * |
| * Even though everything is ordered in the input/output model, the edges/incoming/outgoing lists cn be independently ordered, and only |
| * the edges order is preserved in the middle model. |
| */ |
| public class Upper2LowerNormalizer implements ModelNormalizer |
| { |
| public static final @NonNull Upper2LowerNormalizer INSTANCE = new Upper2LowerNormalizer(); |
| |
| protected static class ElementComparator implements Comparator<EObject> |
| { |
| private final @NonNull EClass edgeClass; |
| private final @NonNull EReference edgeSource; |
| private final @NonNull EReference edgeTarget; |
| private final @NonNull EAttribute nodeLabel; |
| |
| public ElementComparator(@NonNull EClass edgeClass, @NonNull EReference edgeSource, @NonNull EReference edgeTarget, @NonNull EAttribute nodeLabel) { |
| this.edgeClass = edgeClass; |
| this.edgeSource = edgeSource; |
| this.edgeTarget = edgeTarget; |
| this.nodeLabel = nodeLabel; |
| } |
| |
| @Override |
| public int compare(EObject o1, EObject o2) { |
| String n1; |
| String n2; |
| if (edgeClass.isInstance(o1)) { |
| if (!edgeClass.isInstance(o2)) { |
| return 1; |
| } |
| n1 = (String) ((EObject)o1.eGet(edgeSource)).eGet(nodeLabel); |
| n2 = (String) ((EObject)o2.eGet(edgeSource)).eGet(nodeLabel); |
| if (ClassUtil.safeEquals(n1, n2)) { |
| n1 = (String) ((EObject)o1.eGet(edgeTarget)).eGet(nodeLabel); |
| n2 = (String) ((EObject)o2.eGet(edgeTarget)).eGet(nodeLabel); |
| } |
| } |
| else { |
| if (edgeClass.isInstance(o2)) { |
| return -1; |
| } |
| n1 = (String) o1.eGet(nodeLabel); |
| n2 = (String) o2.eGet(nodeLabel); |
| } |
| return ClassUtil.safeCompareTo(n1, n2); |
| } |
| } |
| |
| protected class GraphNormalizer implements Normalizer |
| { |
| protected final @NonNull EObject graph; |
| protected final @NonNull EReference graphElements; |
| protected final @NonNull ElementComparator elementComparator; |
| |
| public GraphNormalizer(@NonNull EObject graph, @NonNull EReference graphElements, @NonNull ElementComparator elementComparator) { |
| this.graph = graph; |
| this.graphElements = graphElements; |
| this.elementComparator = elementComparator; |
| } |
| |
| @Override |
| public void denormalize() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public void normalize() { |
| @SuppressWarnings("unchecked") |
| EList<EObject> elements = (EList<EObject>) graph.eGet(graphElements); |
| ECollections.sort(elements, elementComparator); |
| } |
| } |
| |
| protected class NodeNormalizer implements Normalizer |
| { |
| protected final @NonNull EObject node; |
| protected final @NonNull EReference incoming; |
| protected final @NonNull EReference outgoing; |
| protected final @NonNull ElementComparator elementComparator; |
| |
| public NodeNormalizer(@NonNull EObject node, @NonNull EReference incoming, @NonNull EReference outgoing, @NonNull ElementComparator elementComparator) { |
| this.node = node; |
| this.incoming = incoming; |
| this.outgoing = outgoing; |
| this.elementComparator = elementComparator; |
| } |
| |
| @Override |
| public void denormalize() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public void normalize() { |
| @SuppressWarnings("unchecked")EList<EObject> incomingEdges = (EList<EObject>) node.eGet(incoming); |
| ECollections.sort(incomingEdges, elementComparator); |
| @SuppressWarnings("unchecked")EList<EObject> outgoingEdges = (EList<EObject>) node.eGet(outgoing); |
| ECollections.sort(outgoingEdges, elementComparator); |
| } |
| } |
| |
| @Override |
| public @NonNull List<@NonNull Normalizer> normalize(@NonNull Resource resource) { |
| EObject eRoot = resource.getContents().get(0); |
| EPackage ePackage = eRoot.eClass().getEPackage(); |
| EClass graphClass = (EClass) ePackage.getEClassifier(SimplegraphPackage.Literals.GRAPH.getName()); |
| assert graphClass != null; |
| EClass elementClass = (EClass) ePackage.getEClassifier(SimplegraphPackage.Literals.ELEMENT.getName()); |
| assert elementClass != null; |
| EClass edgeClass = (EClass) ePackage.getEClassifier(SimplegraphPackage.Literals.EDGE.getName()); |
| assert edgeClass != null; |
| EClass nodeClass = (EClass) ePackage.getEClassifier(SimplegraphPackage.Literals.NODE.getName()); |
| assert nodeClass != null; |
| EReference graphElements = (EReference) graphClass.getEStructuralFeature(SimplegraphPackage.Literals.GRAPH__ELEMENT.getName()); |
| assert graphElements != null; |
| EAttribute nodeLabel = (EAttribute) nodeClass.getEStructuralFeature(SimplegraphPackage.Literals.NODE__LABEL.getName()); |
| assert nodeLabel != null; |
| EReference nodeIncoming = (EReference) nodeClass.getEStructuralFeature(SimplegraphPackage.Literals.NODE__INCOMING.getName()); |
| assert nodeIncoming != null; |
| EReference nodeOutgoing = (EReference) nodeClass.getEStructuralFeature(SimplegraphPackage.Literals.NODE__OUTGOING.getName()); |
| assert nodeOutgoing != null; |
| EReference edgeSource = (EReference) edgeClass.getEStructuralFeature(SimplegraphPackage.Literals.EDGE__SOURCE.getName()); |
| assert edgeSource != null; |
| EReference edgeTarget = (EReference) edgeClass.getEStructuralFeature(SimplegraphPackage.Literals.EDGE__TARGET.getName()); |
| assert edgeTarget != null; |
| ElementComparator elementComparator = new ElementComparator(edgeClass, edgeSource, edgeTarget, nodeLabel); |
| List<@NonNull Normalizer> normalizers = new ArrayList<>(); |
| for (TreeIterator<EObject> tit = resource.getAllContents(); tit.hasNext(); ) { |
| EObject eObject = tit.next(); |
| EClass eClass = eObject.eClass(); |
| if (graphClass.isSuperTypeOf(eClass)) { |
| normalizers.add(new GraphNormalizer(eObject, graphElements, elementComparator)); |
| } |
| if (nodeClass.isSuperTypeOf(eClass)) { |
| normalizers.add(new NodeNormalizer(eObject, nodeIncoming, nodeOutgoing, elementComparator)); |
| } |
| } |
| for (Normalizer normalizer : normalizers) { |
| normalizer.normalize(); |
| } |
| return normalizers; |
| } |
| } |