/*
* Copyright (c) 2006 Borland Software Corporation
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Artem Tikhomirov (Borland) - initial API and implementation
*/
package org.eclipse.gmf.tests.setup;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.gmf.mappings.CanvasMapping;
import org.eclipse.gmf.mappings.ChildReference;
import org.eclipse.gmf.mappings.GMFMapFactory;
import org.eclipse.gmf.mappings.LinkMapping;
import org.eclipse.gmf.mappings.Mapping;
import org.eclipse.gmf.mappings.NodeMapping;
import org.eclipse.gmf.mappings.TopNodeReference;
/**
* IMPORTANT: {@link GenModelTransformerSimpleTest} havily relies on the structure of this setup.
* You may use this setup for your needs unless you modify it.
* @author artem
*/
public class MapDefWithReuseSetup implements MapDefSource {
private Mapping myMap;
private NodeMapping myNodeA;
private NodeMapping myNodeB;
public MapDefWithReuseSetup() {
}
/**
* (*) Top NodeA has single child that references NodeA.
* DGMT in it's current state can't reuse GenTopLevelNode for GenChildNode, thus
* creating separate child node with same attributes as top-level one.
* (*) Top NodeB has child that references itself. DGMT should reuse child's mapping,
* and child's children should point to itself.
*
* NOTE, gmfgen structures for both NodeA and NodeB will be similar, the difference is
* in the mapping declaration and in the DGMT code we actually check. The only difference
* between genNodeAChild and genNodeBChild would be different viewmap allowed for latter
* (due to additional, bNodeFirstLevel, mapping that may reference another graphdef figure.
*
* (*) Top NodeB has another child, NodeC (via bOwnsC), that references itself, but with
* containment feature (cOwnsC) that is (of course) different from bOwnsC. We use this
* to check case from https://bugs.eclipse.org/bugs/show_bug.cgi?id=129552 - same node
* but different containments doesn't allow us to reuse GenChildNode (which has single ModelFacet
* attached to it, with single containment feature)
*/
public MapDefWithReuseSetup init(DiaDefSource ddSource) {
final EPackage domainPack = EcoreFactory.eINSTANCE.createEPackage();
domainPack.setName("DomainPack");
final EClass domainA = EcoreFactory.eINSTANCE.createEClass();
domainA.setName("DomainA");
final EClass domainB = EcoreFactory.eINSTANCE.createEClass();
domainB.setName("DomainB");
final EClass domainC = EcoreFactory.eINSTANCE.createEClass();
domainC.setName("DomainC");
final EReference aOwnsA = newContainment("aOwnsA", domainA);
domainA.getEStructuralFeatures().add(aOwnsA);
final EReference aOwnsB = newContainment("aOwnsB", domainB);
domainA.getEStructuralFeatures().add(aOwnsB);
final EReference bOwnsB = newContainment("bOwnsB", domainB);
domainB.getEStructuralFeatures().add(bOwnsB);
final EReference bOwnsC = newContainment("bOwnsC", domainC);
domainB.getEStructuralFeatures().add(bOwnsC);
final EReference cOwnsC = newContainment("cOwnsC", domainC);
domainC.getEStructuralFeatures().add(cOwnsC);
final EReference bRefsC = newContainment("bRefsC", domainC);
bRefsC.setContainment(false);
domainB.getEStructuralFeatures().add(bRefsC);
domainPack.getEClassifiers().add(domainA);
domainPack.getEClassifiers().add(domainB);
domainPack.getEClassifiers().add(domainC);
myMap = GMFMapFactory.eINSTANCE.createMapping();
CanvasMapping cme = GMFMapFactory.eINSTANCE.createCanvasMapping();
cme.setDiagramCanvas(ddSource.getCanvasDef());
cme.setDomainModel(domainPack);
myMap.setDiagram(cme);
myNodeA = GMFMapFactory.eINSTANCE.createNodeMapping();
myNodeA.setDiagramNode(ddSource.getNodeDef());
myNodeA.setDomainMetaElement(domainA);
myNodeA.getChildren().add(newChildReference(aOwnsA, myNodeA, false));
myNodeB = GMFMapFactory.eINSTANCE.createNodeMapping();
myNodeB.setDiagramNode(ddSource.getNodeDef());
myNodeB.setDomainMetaElement(domainB);
NodeMapping bNodeFirstLevel = GMFMapFactory.eINSTANCE.createNodeMapping();
bNodeFirstLevel.setDiagramNode(ddSource.getNodeDef());
bNodeFirstLevel.setDomainMetaElement(domainB);
// cycle to bFirstLevel itself
bNodeFirstLevel.getChildren().add(newChildReference(bOwnsB, bNodeFirstLevel, false));
// nodeB owns bFirstLevel
myNodeB.getChildren().add(newChildReference(bOwnsB, bNodeFirstLevel, true));
NodeMapping cNodeFirstLevel = GMFMapFactory.eINSTANCE.createNodeMapping();
cNodeFirstLevel.setDiagramNode(ddSource.getNodeDef());
cNodeFirstLevel.setDomainMetaElement(domainC);
myNodeB.getChildren().add(newChildReference(bOwnsC, cNodeFirstLevel, true));
// cycle, NodeC from second level reuses NodeC from first level, but with different containment feature
cNodeFirstLevel.getChildren().add(newChildReference(cOwnsC, cNodeFirstLevel, false));
// render some C child of B (namely, those references with bRefsC)
// as separate children. There should be separate GenChildNode because
// distinct childrenFeature is in use
ChildReference dd = newChildReference(bOwnsC, cNodeFirstLevel, false);
dd.setChildrenFeature(bRefsC);
myNodeB.getChildren().add(dd);
TopNodeReference tnr = GMFMapFactory.eINSTANCE.createTopNodeReference();
tnr.setOwnedChild(myNodeA);
tnr.setContainmentFeature(aOwnsA);
myMap.getNodes().add(tnr);
tnr = GMFMapFactory.eINSTANCE.createTopNodeReference();
tnr.setOwnedChild(myNodeB);
tnr.setContainmentFeature(aOwnsB);
myMap.getNodes().add(tnr);
return this;
}
private ChildReference newChildReference(final EReference containmentRef, NodeMapping reusedNode, boolean own) {
ChildReference childRef;
childRef = GMFMapFactory.eINSTANCE.createChildReference();
childRef.setContainmentFeature(containmentRef);
if (own) {
childRef.setOwnedChild(reusedNode);
} else {
childRef.setReferencedChild(reusedNode);
}
return childRef;
}
private static EReference newContainment(String name, final EClass domainClass) {
final EReference ref = EcoreFactory.eINSTANCE.createEReference();
ref.setName(name);
ref.setContainment(true);
ref.setUpperBound(-1);
ref.setEType(domainClass);
return ref;
}
public final Mapping getMapping() {
return myMap;
}
public NodeMapping getNodeA() {
return myNodeA;
}
public NodeMapping getNodeB() {
return myNodeB;
}
public LinkMapping getClassLink() {
throw new UnsupportedOperationException();
}
public LinkMapping getReferenceLink() {
throw new UnsupportedOperationException();
}
}