diff options
6 files changed, 358 insertions, 18 deletions
diff --git a/plugins/org.eclipse.gmf.bridge/src/org/eclipse/gmf/bridge/genmodel/DiagramGenModelTransformer.java b/plugins/org.eclipse.gmf.bridge/src/org/eclipse/gmf/bridge/genmodel/DiagramGenModelTransformer.java index 30b55a3c2..a8892215f 100644 --- a/plugins/org.eclipse.gmf.bridge/src/org/eclipse/gmf/bridge/genmodel/DiagramGenModelTransformer.java +++ b/plugins/org.eclipse.gmf.bridge/src/org/eclipse/gmf/bridge/genmodel/DiagramGenModelTransformer.java @@ -62,6 +62,7 @@ import org.eclipse.gmf.codegen.gmfgen.TypeModelFacet; import org.eclipse.gmf.gmfgraph.Alignment; import org.eclipse.gmf.gmfgraph.AlignmentFacet; import org.eclipse.gmf.gmfgraph.Compartment; +import org.eclipse.gmf.internal.bridge.History; import org.eclipse.gmf.internal.bridge.NaiveIdentifierDispenser; import org.eclipse.gmf.internal.bridge.VisualIdentifierDispenser; import org.eclipse.gmf.internal.bridge.naming.gen.GenModelNamingMediator; @@ -96,10 +97,11 @@ import org.eclipse.gmf.tooldef.ToolContainer; public class DiagramGenModelTransformer extends MappingTransformer { private GenEditorGenerator myGenModel; - private GenModelMatcher myGenModelMatch; + protected GenModelMatcher myGenModelMatch; private final DiagramRunTimeModelHelper myDRTHelper; private final ViewmapProducer myViewmaps = new InnerClassViewmapProducer(); private final VisualIdentifierDispenser myVisualIDs; + private final History myHistory; private final GenModelNamingMediator myNamingStrategy; @@ -107,6 +109,7 @@ public class DiagramGenModelTransformer extends MappingTransformer { myDRTHelper = drtHelper; myNamingStrategy = namingStrategy; myVisualIDs = new NaiveIdentifierDispenser(); + myHistory = new History(); } /** @@ -163,6 +166,7 @@ public class DiagramGenModelTransformer extends MappingTransformer { if (myGenModelMatch == null) { myGenModelMatch = new GenModelMatcher(mapping.getDomainModel()); } + myHistory.purge(); GenPackage primaryPackage = findGenPackage(mapping.getDomainModel()); getGenEssence().setDomainGenModel(primaryPackage == null ? null : primaryPackage.getGenModel()); if (getGenEssence().getDomainGenModel() != null) { @@ -205,32 +209,39 @@ public class DiagramGenModelTransformer extends MappingTransformer { processAbstractNode(nme, genNode); } - // FIXME keep track of processed ChildReferences and don't create two identical for referenced private void process(ChildReference childNodeRef, GenChildContainer container) { final NodeMapping childNodeMapping = childNodeRef.getChild(); assert childNodeMapping != null; assertNodeMapping(childNodeMapping); assert childNodeMapping.getDiagramNode() != null; - GenChildNode childNode = GMFGenFactory.eINSTANCE.createGenChildNode(); - childNode.setModelFacet(createModelFacet(childNodeRef)); - - childNode.setDiagramRunTimeClass(findRunTimeClass(childNodeMapping)); - childNode.setViewmap(myViewmaps.create(childNodeMapping.getDiagramNode())); - childNode.setVisualID(myVisualIDs.get(childNode)); + GenChildNode childNode; + if (myHistory.isKnown(childNodeMapping)) { + // we can't reuse top-level GenNodes + childNode = myHistory.find(childNodeMapping); + } else { + childNode = GMFGenFactory.eINSTANCE.createGenChildNode(); + myHistory.log(childNodeMapping, childNode); + getGenDiagram().getChildNodes().add(childNode); - // set class names - myNamingStrategy.feed(childNode, childNodeMapping); + childNode.setModelFacet(createModelFacet(childNodeRef)); + + childNode.setDiagramRunTimeClass(findRunTimeClass(childNodeMapping)); + childNode.setViewmap(myViewmaps.create(childNodeMapping.getDiagramNode())); + childNode.setVisualID(myVisualIDs.get(childNode)); - container.getChildNodes().add(childNode); - getGenDiagram().getChildNodes().add(childNode); - handleNodeTool(childNodeMapping, childNode); - processAbstractNode(childNodeMapping, childNode); - - if (childNodeMapping.getChildren().size() > 0) { - // TODO just layout from childNodeMapping.getDiagramNode() - container.setListLayout(false); + // set class names + myNamingStrategy.feed(childNode, childNodeMapping); + + handleNodeTool(childNodeMapping, childNode); + processAbstractNode(childNodeMapping, childNode); + + if (childNodeMapping.getChildren().size() > 0) { + // TODO just layout from childNodeMapping.getDiagramNode() + container.setListLayout(false); + } } + container.getChildNodes().add(childNode); } private void processAbstractNode(NodeMapping mapping, GenNode genNode) { diff --git a/plugins/org.eclipse.gmf.bridge/src/org/eclipse/gmf/internal/bridge/History.java b/plugins/org.eclipse.gmf.bridge/src/org/eclipse/gmf/internal/bridge/History.java new file mode 100644 index 000000000..24dd19c13 --- /dev/null +++ b/plugins/org.eclipse.gmf.bridge/src/org/eclipse/gmf/internal/bridge/History.java @@ -0,0 +1,76 @@ +/* + * 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.internal.bridge; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.gmf.codegen.gmfgen.GenChildNode; +import org.eclipse.gmf.codegen.gmfgen.GenLink; +import org.eclipse.gmf.mappings.LinkMapping; +import org.eclipse.gmf.mappings.NodeMapping; + +/** + * We don't suppose to reuse GenTopLevelNodes, thus API references GenChildNodes + * @author artem + */ +public class History { + private final Map/*<NodeMapping, GenChildNode>*/ myNodeMap; + private final Map/*<LinkMapping, GenLink>*/ myLinkMap; + + public History() { + myNodeMap = new HashMap(); + myLinkMap = new HashMap(); + } + + public void log(NodeMapping nodeMap, GenChildNode genNode) { + assert nodeMap != null && genNode != null && !myNodeMap.containsKey(nodeMap); + // TODO leave only asserts + if (nodeMap == null || genNode == null) { + throw new NullPointerException(); + } + if (myNodeMap.containsKey(nodeMap)) { + throw new IllegalArgumentException(nodeMap.toString()); + } + myNodeMap.put(nodeMap, genNode); + } + + public void log(LinkMapping linkMap, GenLink genLink) { + assert linkMap != null && genLink != null && !myLinkMap.containsKey(linkMap); + myLinkMap.put(linkMap, genLink); + } + + public boolean isKnown(NodeMapping nodeMap) { + assert nodeMap != null; + return myNodeMap.containsKey(nodeMap); + } + + public boolean isKnown(LinkMapping linkMap) { + assert linkMap != null; + return myLinkMap.containsKey(linkMap); + } + + public GenChildNode find(NodeMapping nodeMap) { + assert nodeMap != null; + return (GenChildNode) myNodeMap.get(nodeMap); + } + + public GenLink find(LinkMapping linkMap) { + assert linkMap != null; + return (GenLink) myLinkMap.get(linkMap); + } + + public void purge() { + myNodeMap.clear(); + myLinkMap.clear(); + } +} diff --git a/plugins/org.eclipse.gmf.bridge/src/org/eclipse/gmf/internal/bridge/naming/gen/GenModelNamingMediator.java b/plugins/org.eclipse.gmf.bridge/src/org/eclipse/gmf/internal/bridge/naming/gen/GenModelNamingMediator.java index abbdf3a7a..a82343f30 100644 --- a/plugins/org.eclipse.gmf.bridge/src/org/eclipse/gmf/internal/bridge/naming/gen/GenModelNamingMediator.java +++ b/plugins/org.eclipse.gmf.bridge/src/org/eclipse/gmf/internal/bridge/naming/gen/GenModelNamingMediator.java @@ -43,4 +43,23 @@ public interface GenModelNamingMediator { void feed(GenLinkLabel label, LabelMapping labelMapping); + /** + * No-op implementation + */ + public class Empty implements GenModelNamingMediator { + public void feed(GenDiagram genDiagram, CanvasMapping cme) { + } + public void feed(GenTopLevelNode genNode, NodeMapping nme) { + } + public void feed(GenChildNode childNode, NodeMapping nme) { + } + public void feed(GenLink genLink, LinkMapping lme) { + } + public void feed(GenCompartment genCompartment, CompartmentMapping mapping) { + } + public void feed(GenNodeLabel label, LabelMapping labelMapping) { + } + public void feed(GenLinkLabel label, LabelMapping labelMapping) { + } + } }
\ No newline at end of file diff --git a/tests/org.eclipse.gmf.tests/src/org/eclipse/gmf/tests/AllTests.java b/tests/org.eclipse.gmf.tests/src/org/eclipse/gmf/tests/AllTests.java index 1e2c031ff..1c7fdf26c 100644 --- a/tests/org.eclipse.gmf.tests/src/org/eclipse/gmf/tests/AllTests.java +++ b/tests/org.eclipse.gmf.tests/src/org/eclipse/gmf/tests/AllTests.java @@ -36,6 +36,7 @@ import org.eclipse.gmf.tests.setup.LinksSessionSetup; import org.eclipse.gmf.tests.setup.SessionSetup; import org.eclipse.gmf.tests.setup.TestSetupTest; import org.eclipse.gmf.tests.tr.GenModelTransformerBasicRTTest; +import org.eclipse.gmf.tests.tr.GenModelTransformerSimpleTest; import org.eclipse.gmf.tests.tr.NamingStrategyTest; public class AllTests { @@ -53,6 +54,8 @@ public class AllTests { suite.addTest(feed(HandcodedImplTest.class, sessionSetup)); // then, check handcoded implementations are in place suite.addTestSuite(HandcodedGraphDefTest.class); + suite.addTest(feed(GenModelTransformerSimpleTest.class, sessionSetup)); + suite.addTestSuite(FigureCodegenTest.class); suite.addTestSuite(FigureLayoutTest.class); // suite.addTestSuite(RTFigureTest.class); diff --git a/tests/org.eclipse.gmf.tests/src/org/eclipse/gmf/tests/setup/MapDefWithReuseSetup.java b/tests/org.eclipse.gmf.tests/src/org/eclipse/gmf/tests/setup/MapDefWithReuseSetup.java new file mode 100644 index 000000000..7534364dd --- /dev/null +++ b/tests/org.eclipse.gmf.tests/src/org/eclipse/gmf/tests/setup/MapDefWithReuseSetup.java @@ -0,0 +1,140 @@ +/* + * 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; + +/** + * @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 (?) + */ + public MapDefWithReuseSetup init(DiaDefSource ddSource) { + final EPackage domainPack = EcoreFactory.eINSTANCE.createEPackage(); + final EClass domainA = EcoreFactory.eINSTANCE.createEClass(); + domainA.setName("DomainA"); + final EClass domainB = EcoreFactory.eINSTANCE.createEClass(); + domainB.setName("DomainB"); + + 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); + + domainPack.getEClassifiers().add(domainA); + domainPack.getEClassifiers().add(domainB); + + 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); + ChildReference childRef = GMFMapFactory.eINSTANCE.createChildReference(); + childRef.setContainmentFeature(aOwnsA); + childRef.setReferencedChild(myNodeA); + myNodeA.getChildren().add(childRef); + + myNodeB = GMFMapFactory.eINSTANCE.createNodeMapping(); + myNodeB.setDiagramNode(ddSource.getNodeDef()); + myNodeB.setDomainMetaElement(domainB); + + NodeMapping bFirstLevel = GMFMapFactory.eINSTANCE.createNodeMapping(); + bFirstLevel.setDiagramNode(ddSource.getNodeDef()); + bFirstLevel.setDomainMetaElement(domainB); + + // cycle to bFirstLevel itself + childRef = GMFMapFactory.eINSTANCE.createChildReference(); + childRef.setContainmentFeature(bOwnsB); + childRef.setReferencedChild(bFirstLevel); + bFirstLevel.getChildren().add(childRef); + + // nodeB owns bFirstLevel + childRef = GMFMapFactory.eINSTANCE.createChildReference(); + childRef.setContainmentFeature(bOwnsB); + childRef.setOwnedChild(bFirstLevel); + myNodeB.getChildren().add(childRef); + + 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 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 final CanvasMapping getCanvas() { + return getMapping().getDiagram(); + } + + public NodeMapping getNodeA() { + return myNodeA; + } + + public NodeMapping getNodeB() { + return myNodeB; + } + + public LinkMapping getClassLink() { + throw new UnsupportedOperationException(); + } + + public LinkMapping getReferenceLink() { + throw new UnsupportedOperationException(); + } +} diff --git a/tests/org.eclipse.gmf.tests/src/org/eclipse/gmf/tests/tr/GenModelTransformerSimpleTest.java b/tests/org.eclipse.gmf.tests/src/org/eclipse/gmf/tests/tr/GenModelTransformerSimpleTest.java new file mode 100644 index 000000000..a7001f3cc --- /dev/null +++ b/tests/org.eclipse.gmf.tests/src/org/eclipse/gmf/tests/tr/GenModelTransformerSimpleTest.java @@ -0,0 +1,91 @@ +/* + * 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.tr; + +import java.util.Iterator; + +import org.eclipse.emf.ecore.EClass; +import org.eclipse.gmf.bridge.genmodel.BasicDiagramRunTimeModelHelper; +import org.eclipse.gmf.bridge.genmodel.DiagramGenModelTransformer; +import org.eclipse.gmf.codegen.gmfgen.GenChildNode; +import org.eclipse.gmf.codegen.gmfgen.GenEditorGenerator; +import org.eclipse.gmf.codegen.gmfgen.GenNode; +import org.eclipse.gmf.codegen.gmfgen.GenTopLevelNode; +import org.eclipse.gmf.internal.bridge.naming.gen.GenModelNamingMediator; +import org.eclipse.gmf.mappings.TopNodeReference; +import org.eclipse.gmf.tests.Utils; +import org.eclipse.gmf.tests.setup.DiaDefSource; +import org.eclipse.gmf.tests.setup.MapDefSource; +import org.eclipse.gmf.tests.setup.MapDefWithReuseSetup; + +/** + * @author artem + */ +public class GenModelTransformerSimpleTest extends AbstractMappingTransformerTest { + private GenEditorGenerator transformationResult; + + public GenModelTransformerSimpleTest(String name) { + super(name); + } + + protected void setUp() throws Exception { + super.setUp(); + DiagramGenModelTransformer t = new DiagramGenModelTransformer(new BasicDiagramRunTimeModelHelper(), new GenModelNamingMediator.Empty()); + t.setEMFGenModel(Utils.createGenModel(getCanvasMapping().getDomainModel(), Utils.createUniquePluginID())); + t.transform(getMapping()); + transformationResult = t.getResult(); + assertNotNull(transformationResult); + } + + protected MapDefSource initMapModel(DiaDefSource graphDef) { + return new MapDefWithReuseSetup().init(graphDef); + } + + public void testHistoryTracking() { + GenNode nodeA = getGenNodeA(); + assertNotNull(nodeA); + GenNode nodeB = getGenNodeB(); + assertNotNull(nodeB); + final GenChildNode childA = (GenChildNode) nodeA.getChildNodes().get(0); + // dumb check, although makes me believe DGMT set attributes + // of the node that is actually a duplicate of top-level node + assertEquals(nodeA.getDomainMetaClass(), childA.getDomainMetaClass()); + assertEquals(nodeA.getDiagramRunTimeClass(), childA.getDiagramRunTimeClass()); + assertTrue(childA.getChildNodes().contains(childA)); + + final GenChildNode bFirstLevelChild = (GenChildNode) nodeA.getChildNodes().get(0); + final GenChildNode bSecondLevelChild = (GenChildNode) bFirstLevelChild.getChildNodes().get(0); + assertTrue(bSecondLevelChild.getChildNodes().contains(bFirstLevelChild)); + } + + private GenNode getGenNodeA() { + return findTopNode(getNodeDomainElement(0)); + } + + private GenNode getGenNodeB() { + return findTopNode(getNodeDomainElement(1)); + } + + private EClass getNodeDomainElement(int idx) { + return ((TopNodeReference) getMapping().getNodes().get(idx)).getOwnedChild().getDomainMetaElement(); + } + + private GenNode findTopNode(EClass eClass) { + for (Iterator it = transformationResult.getDiagram().getTopLevelNodes().iterator(); it.hasNext();) { + GenTopLevelNode next = (GenTopLevelNode) it.next(); + if (next.getDomainMetaClass().getEcoreClass() == eClass) { + return next; + } + } + return null; + } +} |