/* * Copyright (c) 2005, 2008 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 java.lang.reflect.Method; import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import org.junit.Assert; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.commands.operations.OperationHistoryFactory; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Status; import org.eclipse.emf.codegen.ecore.genmodel.GenClass; import org.eclipse.emf.codegen.ecore.genmodel.GenFeature; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.emf.workspace.AbstractEMFOperation; import org.eclipse.gmf.codegen.gmfgen.FeatureLinkModelFacet; import org.eclipse.gmf.codegen.gmfgen.GenCompartment; import org.eclipse.gmf.codegen.gmfgen.GenNode; import org.eclipse.gmf.codegen.gmfgen.TypeLinkModelFacet; import org.eclipse.gmf.runtime.diagram.core.DiagramEditingDomainFactory; import org.eclipse.gmf.runtime.notation.Bounds; import org.eclipse.gmf.runtime.notation.Diagram; import org.eclipse.gmf.runtime.notation.Edge; import org.eclipse.gmf.runtime.notation.Node; import org.eclipse.gmf.runtime.notation.NotationFactory; import org.osgi.framework.Bundle; /** * TODO DomainModelInstanceSource to separate instantiation from diagram creation and * to facilitate testing of domain model instance - not to miss containments and other * potential problems in DomainModelSource * Simple implementation that creates simple diagram with few elements * @author artem */ public class RTSetup implements RTSource { private static int ourURISuffix = 1; protected Diagram myCanvas; private Node myNodeA; private Node myNodeB; private Edge myLinkByClass; private Edge myLinkByRef; private Node myNodeACompartment; private Node myNodeBCompartment; protected EObject myDiagramElement; public RTSetup() { } public final RTSetup init(Bundle b, DiaGenSource genSource) { return init(b, genSource, null); } public final RTSetup init(Bundle b, DiaGenSource genSource, TransactionalEditingDomain domain) { return init(new CoolDomainInstanceProducer(b), genSource, domain); } public final RTSetup init(DiaGenSource genSource) { return init(genSource, null); } public final RTSetup init(DiaGenSource genSource, TransactionalEditingDomain domain) { return init(new NaiveDomainInstanceProducer(), genSource, domain); } private RTSetup init(DomainInstanceProducer producer, DiaGenSource genSource, TransactionalEditingDomain domain) { initDiagramFileContents(producer, genSource); saveDiagramFile(domain, genSource.getGenDiagram().getEditingDomainID()); return this; } /** * @return <code>this</code> for convenience */ protected void initDiagramFileContents(DomainInstanceProducer instanceProducer, DiaGenSource genSource) { myCanvas = NotationFactory.eINSTANCE.createDiagram(); myDiagramElement = instanceProducer.createInstance(genSource.getGenDiagram().getDomainDiagramElement()); myCanvas.setElement(myDiagramElement); myCanvas.setType(genSource.getGenDiagram().getEditorGen().getModelID()); myNodeA = setupNotationNode(genSource.getNodeA(), instanceProducer); List compartments = setupNotationCompartments(myNodeA, genSource.getNodeA()); if (compartments.size() > 0) { myNodeACompartment = (Node) compartments.get(0); } myNodeB = setupNotationNode(genSource.getNodeB(), instanceProducer); compartments = setupNotationCompartments(myNodeB, genSource.getNodeB()); if (compartments.size() > 0) { myNodeBCompartment = (Node) compartments.get(0); } myLinkByClass = NotationFactory.eINSTANCE.createEdge(); myCanvas.getPersistedEdges().add(myLinkByClass); //myNode.setVisualID(genSource.getGenNode().getVisualID()); TypeLinkModelFacet byClassFacet = (TypeLinkModelFacet) genSource.getLinkC().getModelFacet(); EObject linkElement = instanceProducer.createInstance(byClassFacet.getMetaClass()); instanceProducer.setFeatureValue(myNodeA.getElement(), linkElement, byClassFacet.getContainmentMetaFeature()); instanceProducer.setFeatureValue(linkElement, myNodeB.getElement(), byClassFacet.getTargetMetaFeature()); myLinkByClass.setElement(linkElement); myLinkByClass.setType(String.valueOf(genSource.getLinkC().getVisualID())); myLinkByClass.setSource(myNodeA); myLinkByClass.setTarget(myNodeB); setBendpoints(myLinkByClass); FeatureLinkModelFacet byRefFacet = (FeatureLinkModelFacet) genSource.getLinkD().getModelFacet(); Assert.assertNotNull(byRefFacet); EStructuralFeature metaFeature = byRefFacet.getMetaFeature().getEcoreFeature(); //The direction of the link is unspecified, could be from A to B or vice versa myLinkByRef = NotationFactory.eINSTANCE.createEdge(); if (myNodeA.getElement().eClass().getEStructuralFeature(metaFeature.getName()) != null) { instanceProducer.setFeatureValue(myNodeA.getElement(), myNodeB.getElement(), byRefFacet.getMetaFeature()); myLinkByRef.setSource(myNodeA); myLinkByRef.setTarget(myNodeB); } else if (myNodeB.getElement().eClass().getEStructuralFeature(metaFeature.getName()) != null) { instanceProducer.setFeatureValue(myNodeB.getElement(), myNodeA.getElement(), byRefFacet.getMetaFeature()); myLinkByRef.setSource(myNodeB); myLinkByRef.setTarget(myNodeA); } myCanvas.getPersistedEdges().add(myLinkByRef); myLinkByRef.setType(String.valueOf(genSource.getLinkD().getVisualID())); myLinkByRef.setElement(null); setBendpoints(myLinkByRef); /* Object nc = diagramElement.eGet(genSource.getGenNode().getContainmentMetaFeature().getEcoreFeature()); assert nc instanceof EList; ((EList) nc).add(nodeElement); Object lc = nodeElement.eGet(genSource.getGenLink().getContainmentMetaFeature().getEcoreFeature()); if (lc instanceof EList) { ((EList) lc).add(linkElement); } else { nodeElement.eSet(genSource.getGenLink().getContainmentMetaFeature().getEcoreFeature(), linkElement); } */ } private void setBendpoints(Edge edge){ edge.setBendpoints(NotationFactory.eINSTANCE.createRelativeBendpoints()); } private Node setupNotationNode(GenNode genNode, DomainInstanceProducer instanceProducer){ Node result = NotationFactory.eINSTANCE.createNode(); myCanvas.getPersistedChildren().add(result); EObject nodeElement = instanceProducer.createInstance(genNode.getDomainMetaClass()); instanceProducer.setFeatureValue(myDiagramElement, nodeElement, genNode.getModelFacet().getContainmentMetaFeature()); result.setElement(nodeElement); result.setType(String.valueOf(genNode.getVisualID())); result.getStyles().add(NotationFactory.eINSTANCE.createShapeStyle()); Bounds b = NotationFactory.eINSTANCE.createBounds(); b.setWidth(0); b.setHeight(0); result.setLayoutConstraint(b); return result; } private List<Node> setupNotationCompartments(Node notationParent, GenNode genParent){ LinkedList<Node> compartments = new LinkedList<Node>(); for (GenCompartment nextCompartment : genParent.getCompartments()) { Node notationCompartment = NotationFactory.eINSTANCE.createNode(); notationCompartment.setType(String.valueOf(nextCompartment.getVisualID())); notationParent.getTransientChildren().add(notationCompartment); Assert.assertTrue(notationParent.getChildren().contains(notationCompartment)); compartments.add(notationCompartment); } return compartments; } private void saveDiagramFile(TransactionalEditingDomain ted, String editingDomainId){ if (ted == null) { ted = DiagramEditingDomainFactory.getInstance().createEditingDomain(); ted.setID(editingDomainId); ((AdapterFactoryEditingDomain) ted).setResourceToReadOnlyMap(new HashMap<Resource, Boolean>() { @Override public Boolean get(Object key) { if (key instanceof Resource && "uri".equals(((Resource) key).getURI().scheme())) { return Boolean.FALSE; } return super.get(key); } }); } ResourceSet rs = ted.getResourceSet(); URI uri = URI.createURI("uri://fake/z" + ourURISuffix++); //$NON-NLS-1$ Resource r = rs.getResource(uri, false); if (r == null) { r = rs.createResource(uri); } final Resource diagramFile = r; AbstractEMFOperation operation = new AbstractEMFOperation(ted, "") { //$NON-NLS-1$ protected IStatus doExecute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { diagramFile.getContents().clear(); diagramFile.getContents().add(getCanvas()); diagramFile.getContents().add(getDiagramElement()); return Status.OK_STATUS; }; }; try { OperationHistoryFactory.getOperationHistory().execute(operation, new NullProgressMonitor(), null); } catch (ExecutionException e) { e.printStackTrace(); Assert.fail("Failed to set diagram resource contents"); //$NON-NLS-1$ } } public final Diagram getCanvas() { return myCanvas; } public final Node getNodeA() { return myNodeA; } public final Node getNodeB() { return myNodeB; } public Node getNodeACompartment() { Assert.assertNotNull("No compartment for Node A in this genmodel", myNodeACompartment); return myNodeACompartment; } public Node getNodeBCompartment() { Assert.assertNotNull("No compartment for Node B in this genmodel", myNodeBCompartment); return myNodeBCompartment; } public Edge getLinkByClass() { return myLinkByClass; } public Edge getLinkByRef() { return myLinkByRef; } protected EObject getDiagramElement(){ return myDiagramElement; } protected interface DomainInstanceProducer { EObject createInstance(GenClass genClass); void setFeatureValue(EObject src, EObject value, GenFeature genFeature); } private static class NaiveDomainInstanceProducer implements DomainInstanceProducer { public EObject createInstance(GenClass genClass) { return createInstance(genClass.getEcoreClass()); } public void setFeatureValue(EObject src, EObject value, GenFeature genFeature) { EStructuralFeature feature = genFeature.getEcoreFeature(); if (genFeature.isListType()) { @SuppressWarnings("unchecked") Collection<EObject> result = (Collection<EObject>) src.eGet(feature); result.add(value); } else { src.eSet(feature, value); } } public EObject createInstance(EClass eClass) { return eClass.getEPackage().getEFactoryInstance().create(eClass); } } private static class CoolDomainInstanceProducer implements DomainInstanceProducer { private final Bundle bundle; public EObject createInstance(GenClass genClass) { try { Class<?> factoryClass = getFactoryClass(genClass); Method m = factoryClass.getMethod("create" + genClass.getName(), new Class[0]); return (EObject) m.invoke(getInstance(factoryClass), new Object[0]); } catch (Exception ex) { Assert.fail(ex.getClass().getSimpleName() + ":" + ex.getMessage()); } Assert.fail(); return null; } public void setFeatureValue(EObject src, EObject value, GenFeature genFeature) { try { Class<?> packageClass = getPackageClass(genFeature); Method featureAccessor = packageClass.getMethod("get" + genFeature.getFeatureAccessorName(), new Class[0]); EStructuralFeature feature = (EStructuralFeature) featureAccessor.invoke(getInstance(packageClass), new Object[0]); if (genFeature.isListType()) { @SuppressWarnings("unchecked") Collection<EObject> result = (Collection<EObject>) src.eGet(feature); result.add(value); } else { src.eSet(feature, value); } } catch (Exception ex) { Assert.fail(ex.getClass().getSimpleName() + ":" + ex.getMessage()); } } private Class<?> getFactoryClass(GenClass genClass) throws ClassNotFoundException { return bundle.loadClass(genClass.getGenPackage().getQualifiedFactoryInterfaceName()); } private Object getInstance(Class<?> interfaceClass) throws NoSuchFieldException, IllegalAccessException { return interfaceClass.getField("eINSTANCE").get(null); } private Class<?> getPackageClass(GenFeature genFeature) throws ClassNotFoundException { return bundle.loadClass(genFeature.getGenPackage().getQualifiedPackageInterfaceName()); } public CoolDomainInstanceProducer(Bundle b) { bundle = b; } } }