| package org.eclipse.gmf.tooling.tests.xtend.rt; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.UnsupportedEncodingException; |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.ArrayList; |
| import java.util.Calendar; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.core.commands.operations.IUndoableOperation; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.emf.codegen.ecore.Generator; |
| import org.eclipse.emf.codegen.util.CodeGenUtil.EclipseUtil; |
| import org.eclipse.emf.common.util.URI; |
| 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.EStructuralFeature; |
| import org.eclipse.emf.ecore.EcoreFactory; |
| import org.eclipse.emf.ecore.EcorePackage; |
| import org.eclipse.emf.ecore.resource.impl.ResourceImpl; |
| import org.eclipse.gef.EditPart; |
| import org.eclipse.gef.commands.Command; |
| import org.eclipse.gef.commands.CompoundCommand; |
| import org.eclipse.gmf.codegen.gmfgen.ElementType; |
| import org.eclipse.gmf.codegen.gmfgen.GenDiagram; |
| import org.eclipse.gmf.codegen.gmfgen.GenNode; |
| import org.eclipse.gmf.codegen.gmfgen.GenTopLevelNode; |
| import org.eclipse.gmf.codegen.gmfgen.MetamodelType; |
| import org.eclipse.gmf.codegen.gmfgen.SpecializationType; |
| import org.eclipse.gmf.codegen.util.GMFGeneratorModule; |
| import org.eclipse.gmf.codegen.xtend.ui.handlers.Xtend2Emitter; |
| import org.eclipse.gmf.common.UnexpectedBehaviourException; |
| import org.eclipse.gmf.internal.common.codegen.TextEmitter; |
| import org.eclipse.gmf.mappings.Constraint; |
| import org.eclipse.gmf.mappings.FeatureSeqInitializer; |
| import org.eclipse.gmf.mappings.FeatureValueSpec; |
| import org.eclipse.gmf.mappings.GMFMapFactory; |
| import org.eclipse.gmf.mappings.Language; |
| import org.eclipse.gmf.mappings.NodeMapping; |
| import org.eclipse.gmf.runtime.common.core.command.ICompositeCommand; |
| import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy; |
| import org.eclipse.gmf.runtime.diagram.ui.requests.EditCommandRequestWrapper; |
| import org.eclipse.gmf.runtime.emf.type.core.requests.SetRequest; |
| import org.eclipse.gmf.runtime.notation.Diagram; |
| import org.eclipse.gmf.runtime.notation.Node; |
| import org.eclipse.gmf.tests.Utils; |
| import org.eclipse.gmf.tests.rt.EditHelpersTest; |
| import org.eclipse.gmf.tests.setup.DiaDefSource; |
| import org.eclipse.gmf.tests.setup.DomainModelSource; |
| import org.eclipse.gmf.tests.setup.GenProjectSetup; |
| import org.eclipse.gmf.tests.setup.GeneratedDiagramPlugin; |
| import org.eclipse.gmf.tests.setup.GeneratorConfiguration; |
| import org.eclipse.gmf.tests.setup.MapDefSource; |
| import org.eclipse.gmf.tests.setup.MapSetup; |
| import org.eclipse.gmf.tests.setup.SessionSetup; |
| import org.eclipse.gmf.tests.setup.ToolDefSource; |
| import org.eclipse.gmf.tooling.tests.xtend.setup.RuntimeBasedGeneratorConfigurationXtend; |
| import org.osgi.framework.BundleException; |
| |
| import com.google.inject.Guice; |
| import com.google.inject.Injector; |
| import com.google.inject.Module; |
| |
| import edithelpers.edithelper; |
| import edithelpers.manifest; |
| import edithelpers.plugin; |
| |
| public class EditHelpersTestXtend extends EditHelpersTest { |
| |
| private static final String BEFORE_PREFIX = "before"; |
| |
| private static final String AFTER_PREFIX = "after"; |
| |
| private static final String MARKER_COMMAND_LABEL = "MarkerCommand"; |
| |
| private final static Injector injector = Guice.createInjector(new Module[]{new GMFGeneratorModule(null)});; |
| |
| public EditHelpersTestXtend(String name) { |
| super(name, new RuntimeBasedGeneratorConfigurationXtend()); |
| } |
| |
| public void testSingleEditHelperAdviceNode() { |
| assertTrue(getSetup().getGenModel().getNodeA().getElementType() instanceof MetamodelType); |
| Command command = getSetNewTopLeveNodeNameCommand(getSetup().getGenModel().getNodeA(), getSetup().getDomainModel().getNodeA().getNameAttr().getName()); |
| Collection<IUndoableOperation> allMarkerCommands = getAllMarkerCommands(command); |
| Collection<IUndoableOperation> beforeCommands = getBeforeCommands(allMarkerCommands); |
| Collection<IUndoableOperation> afterCommands = getAfterCommands(allMarkerCommands); |
| // One before and one after command should be associated with this |
| // element type |
| assertTrue(beforeCommands.size() == 1); |
| assertTrue(getEditHelperVisualID(beforeCommands.iterator().next()) == getSetup().getGenModel().getNodeA().getVisualID()); |
| assertTrue(afterCommands.size() == 1); |
| assertTrue(getEditHelperVisualID(afterCommands.iterator().next()) == getSetup().getGenModel().getNodeA().getVisualID()); |
| } |
| |
| public void testTwoEditHelperAdvicesNode() { |
| assertTrue(getSetup().getGenModel().getNodeB().getElementType() instanceof SpecializationType); |
| Command command = getSetNewTopLeveNodeNameCommand(getSetup().getGenModel().getNodeB(), getSetup().getDomainModel().getNodeB().getNameAttr().getName()); |
| Collection<IUndoableOperation> allMarkerCommands = getAllMarkerCommands(command); |
| Collection<IUndoableOperation> beforeCommands = getBeforeCommands(allMarkerCommands); |
| Collection<IUndoableOperation> afterCommands = getAfterCommands(allMarkerCommands); |
| // Two before and two after commands should be associated with this |
| // element type |
| assertTrue(beforeCommands.size() == 2); |
| assertTrue(hasCommand(beforeCommands, getSetup().getGenModel().getNodeA().getVisualID())); |
| assertTrue(hasCommand(beforeCommands, getSetup().getGenModel().getNodeB().getVisualID())); |
| |
| assertTrue(afterCommands.size() == 2); |
| assertTrue(hasCommand(afterCommands, getSetup().getGenModel().getNodeA().getVisualID())); |
| assertTrue(hasCommand(afterCommands, getSetup().getGenModel().getNodeB().getVisualID())); |
| } |
| |
| @Override |
| protected Diagram createDiagramView(EObject domainElement, GeneratedDiagramPlugin genPlugin) { |
| return RuntimeBasedGeneratorConfigurationXtend.createDiagram(domainElement, genPlugin); |
| } |
| |
| private boolean hasCommand(Collection<IUndoableOperation> beforeCommands, int visualID) { |
| for (IUndoableOperation operation : beforeCommands) { |
| if (getEditHelperVisualID(operation) == visualID) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| private Command getSetNewTopLeveNodeNameCommand(GenNode genNode, String nameAttribute) { |
| Node node = createNode(genNode, getDiagram()); |
| assertNotNull(node); |
| EditPart nodeEditPart = getViewerConfiguration().findEditPart(node); |
| assertNotNull(nodeEditPart); |
| EObject nodeElement = node.getElement(); |
| SetRequest setReq = new SetRequest(nodeElement, nodeElement.eClass().getEStructuralFeature(nameAttribute), "newName"); |
| Command command = nodeEditPart.getCommand(new EditCommandRequestWrapper(setReq)); |
| assertNotNull(command); |
| assertTrue(command.canExecute()); |
| return command; |
| } |
| |
| private Collection<IUndoableOperation> getAllMarkerCommands(Command command) { |
| if (command instanceof CompoundCommand) { |
| Collection<IUndoableOperation> result = new ArrayList<IUndoableOperation>(); |
| for (Object object : ((CompoundCommand) command).getCommands()) { |
| result.addAll(getAllMarkerCommands((Command) object)); |
| } |
| return result; |
| } |
| if (command instanceof ICommandProxy) { |
| ICommandProxy commandProxy = (ICommandProxy) command; |
| return getAllMarkerCommands(commandProxy.getICommand()); |
| } |
| return Collections.emptyList(); |
| } |
| |
| private Collection<IUndoableOperation> getAllMarkerCommands(IUndoableOperation operation) { |
| if (operation instanceof ICompositeCommand) { |
| ICompositeCommand compositeCommand = (ICompositeCommand) operation; |
| Collection<IUndoableOperation> result = new ArrayList<IUndoableOperation>(); |
| for (Iterator<?> it = compositeCommand.iterator(); it.hasNext();) { |
| result.addAll(getAllMarkerCommands((IUndoableOperation) it.next())); |
| } |
| return result; |
| } |
| if (isMarkerCommand(operation)) { |
| return Collections.singletonList(operation); |
| } |
| return Collections.emptyList(); |
| } |
| |
| private boolean isMarkerCommand(IUndoableOperation operation) { |
| String label = operation.getLabel(); |
| return label != null && label.indexOf(MARKER_COMMAND_LABEL) > -1; |
| } |
| |
| private Collection<IUndoableOperation> getBeforeCommands(Collection<IUndoableOperation> markerCommands) { |
| Collection<IUndoableOperation> result = new ArrayList<IUndoableOperation>(); |
| for (IUndoableOperation command : markerCommands) { |
| if (isBeforeMarkerCommand(command)) { |
| result.add(command); |
| } |
| } |
| return result; |
| } |
| |
| private Collection<IUndoableOperation> getAfterCommands(Collection<IUndoableOperation> markerCommands) { |
| Collection<IUndoableOperation> result = new ArrayList<IUndoableOperation>(); |
| for (IUndoableOperation command : markerCommands) { |
| if (isAfterMarkerCommand(command)) { |
| result.add(command); |
| } |
| } |
| return result; |
| } |
| |
| private boolean isBeforeMarkerCommand(IUndoableOperation operation) { |
| assertTrue("Should be marker operation", isMarkerCommand(operation)); |
| String label = operation.getLabel(); |
| return BEFORE_PREFIX.equals(label.substring(0, label.indexOf(MARKER_COMMAND_LABEL))); |
| } |
| |
| private boolean isAfterMarkerCommand(IUndoableOperation operation) { |
| assertTrue("Should be marker operation", isMarkerCommand(operation)); |
| String label = operation.getLabel(); |
| return AFTER_PREFIX.equals(label.substring(0, label.indexOf(MARKER_COMMAND_LABEL))); |
| } |
| |
| private int getEditHelperVisualID(IUndoableOperation operation) { |
| assertTrue("Should be marker operation", isMarkerCommand(operation)); |
| String label = operation.getLabel(); |
| return Integer.valueOf(label.substring(label.indexOf(MARKER_COMMAND_LABEL) + MARKER_COMMAND_LABEL.length())); |
| } |
| |
| public static final class EditHelpersSessionSetup extends SessionSetup { |
| |
| public EditHelpersSessionSetup() { |
| super(new RuntimeBasedGeneratorConfigurationXtend()); |
| } |
| |
| @Override |
| protected DomainModelSource createDomainModel() { |
| return new EditHelpersModelSource(); |
| } |
| |
| @Override |
| protected GenProjectSetup createGenProject(GeneratorConfiguration generatorConfiguration) throws BundleException { |
| return new EditHelpersProjectSetup(generatorConfiguration).init(getGenModel()); |
| } |
| |
| @Override |
| public MapDefSource createMapModel() { |
| return new EditHelpersMapSetup().init(getGraphDefModel(), getDomainModel(), getToolDefModel()); |
| } |
| } |
| |
| private static final class EditHelpersMapSetup extends MapSetup { |
| |
| @Override |
| public MapSetup init(DiaDefSource ddSource, DomainModelSource domainSource, ToolDefSource toolDef) { |
| super.init(ddSource, domainSource, toolDef); |
| addConstraint(getNodeA(), "nodeName2.oclIsUndefined()"); |
| addNameInitializer(getNodeA(), domainSource.getNodeA().getNameAttr(), "'name'"); |
| addConstraint(getNodeB(), "nodeName1.oclIsUndefined()"); |
| addNameInitializer(getNodeB(), domainSource.getNodeB().getNameAttr(), "'name'"); |
| return this; |
| } |
| |
| private void addConstraint(NodeMapping node, String body) { |
| node.setDomainSpecialization(GMFMapFactory.eINSTANCE.createConstraint()); |
| node.getDomainSpecialization().setLanguage(Language.OCL_LITERAL); |
| node.getDomainSpecialization().setBody(body); |
| } |
| |
| private void addNameInitializer(NodeMapping node, EStructuralFeature feature, String value) { |
| FeatureSeqInitializer root = GMFMapFactory.eINSTANCE.createFeatureSeqInitializer(); |
| node.setDomainInitializer(root); |
| FeatureValueSpec nameSpecification = GMFMapFactory.eINSTANCE.createFeatureValueSpec(); |
| root.getInitializers().add(nameSpecification); |
| nameSpecification.setFeature(feature); |
| Constraint valueExpr = GMFMapFactory.eINSTANCE.createConstraint(); |
| nameSpecification.setValue(valueExpr); |
| valueExpr.setBody(value); |
| valueExpr.setLanguage(Language.OCL_LITERAL); |
| } |
| |
| } |
| |
| private static final class EditHelpersProjectSetup extends GenProjectSetup { |
| |
| private String myBundleName; |
| |
| |
| |
| private EditHelpersProjectSetup(GeneratorConfiguration generatorFactory) { |
| super(generatorFactory); |
| } |
| |
| @Override |
| protected void generateDiagramPrerequisites(GenDiagram d) throws Exception { |
| super.generateDiagramPrerequisites(d); |
| generateEditHelpersProject(d); |
| } |
| |
| private void generateEditHelpersProject(GenDiagram d) { |
| myBundleName = Utils.createUniquePluginID() + ".edithelpers"; |
| IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(myBundleName); |
| final Path srcPath = new Path('/' + project.getName() + "/src"); //$NON-NLS-1$ |
| final int style = Generator.EMF_PLUGIN_PROJECT_STYLE; |
| final List<?> pluginVariables = null; |
| Generator.createEMFProject(srcPath, null, Collections.<IProject> emptyList(), new NullProgressMonitor(), style, pluginVariables); |
| createManifestMF(); |
| for (GenTopLevelNode node : d.getTopLevelNodes()) { |
| createEditHelper(node); |
| } |
| createPluginXML(d); |
| projectsToInit.add(myBundleName); |
| } |
| |
| public void createManifestMF() { |
| Xtend2Emitter emiter = new Xtend2Emitter(injector, manifest.class, "main"); |
| doGenerateFile(emiter, new Path("/" + myBundleName + "/META-INF/MANIFEST.MF"), myBundleName); |
| } |
| |
| public void createEditHelper(GenTopLevelNode node) { |
| ElementType elementType = node.getElementType(); |
| if (elementType == null) { |
| return ; |
| } |
| String className; |
| if (elementType instanceof MetamodelType) { |
| className = ((MetamodelType) elementType).getEditHelperClassName() + "ExternalAdvice"; |
| } else if (elementType instanceof SpecializationType) { |
| String adviceClassName = ((SpecializationType) elementType).getEditHelperAdviceClassName(); |
| if (adviceClassName == null || adviceClassName.trim().length() ==0) { |
| // advice class name is usually empty, as we do not generate anything reasonable inside them, |
| // hence, need to identify SpecializationType differently |
| adviceClassName = node.getUniqueIdentifier(); |
| } |
| className = adviceClassName + "ExternalAdvice"; |
| } else { |
| return; |
| } |
| Xtend2Emitter emiter = new Xtend2Emitter(injector, edithelper.class, "main"); |
| doGenerateFile(emiter, new Path("/" + myBundleName + "/src/" + className + ".java"), elementType); |
| } |
| |
| public void createPluginXML(GenDiagram d) { |
| Xtend2Emitter emiter = new Xtend2Emitter(injector, plugin.class, "main"); |
| doGenerateFile(emiter, new Path("/" + myBundleName + "/plugin.xml"), d); |
| } |
| |
| private void doGenerateFile(TextEmitter emitter, IPath filePath, Object... param) { |
| try { |
| IPath containerPath = filePath.removeLastSegments(1); |
| EclipseUtil.findOrCreateContainer(containerPath, false, (IPath) null, new NullProgressMonitor()); |
| String genText = emitter.generate(new NullProgressMonitor(), param); |
| IFile f = ResourcesPlugin.getWorkspace().getRoot().getFile(filePath); |
| f.create(new ByteArrayInputStream(genText.getBytes(f.getCharset())), true, new NullProgressMonitor()); |
| } catch (InvocationTargetException ex) { |
| fail(ex.getMessage()); |
| } catch (UnexpectedBehaviourException ex) { |
| fail(ex.getMessage()); |
| } catch (CoreException ex) { |
| fail(ex.getMessage()); |
| } catch (UnsupportedEncodingException ex) { |
| fail(ex.getMessage()); |
| } catch (InterruptedException ex) { |
| fail(ex.getMessage()); |
| } |
| } |
| } |
| |
| private static final class EditHelpersModelSource implements DomainModelSource { |
| |
| private EClass myDiagramElement; |
| |
| private EPackage myPackage; |
| |
| private NodeData myNode1; |
| |
| private LinkData myClassLink; |
| |
| private NodeData myNode2; |
| |
| private EReference myRefLink; |
| { |
| myPackage = EcoreFactory.eINSTANCE.createEPackage(); |
| myPackage.setName("eh"); |
| myPackage.setNsPrefix("sampleEH"); |
| Calendar c = Calendar.getInstance(); |
| myPackage.setNsURI("uri://eclipse/gmf/tests/sample/eh/" + c.get(Calendar.HOUR_OF_DAY) + '/' + c.get(Calendar.MINUTE) + '/'); |
| |
| myDiagramElement = EcoreFactory.eINSTANCE.createEClass(); |
| myDiagramElement.setName("DiagramElement"); |
| myPackage.getEClassifiers().add(myDiagramElement); |
| |
| EClass node = EcoreFactory.eINSTANCE.createEClass(); |
| node.setName("Node"); |
| myPackage.getEClassifiers().add(node); |
| EAttribute node1Name = EcoreFactory.eINSTANCE.createEAttribute(); |
| node1Name.setName("nodeName1"); |
| node1Name.setEType(EcorePackage.eINSTANCE.getEString()); |
| node.getEStructuralFeatures().add(node1Name); |
| EAttribute node2Name = EcoreFactory.eINSTANCE.createEAttribute(); |
| node2Name.setName("nodeName2"); |
| node2Name.setEType(EcorePackage.eINSTANCE.getEString()); |
| node.getEStructuralFeatures().add(node2Name); |
| |
| EReference nodeContainment = EcoreFactory.eINSTANCE.createEReference(); |
| nodeContainment.setName("nodeContainment"); |
| nodeContainment.setContainment(true); |
| nodeContainment.setUpperBound(-1); |
| nodeContainment.setEType(node); |
| myDiagramElement.getEStructuralFeatures().add(nodeContainment); |
| |
| EClass classLink = EcoreFactory.eINSTANCE.createEClass(); |
| classLink.setName("Link"); |
| myPackage.getEClassifiers().add(classLink); |
| |
| EReference linkContainment = EcoreFactory.eINSTANCE.createEReference(); |
| linkContainment.setName("linkContainment"); |
| linkContainment.setEType(classLink); |
| linkContainment.setUpperBound(-1); |
| linkContainment.setContainment(true); |
| node.getEStructuralFeatures().add(linkContainment); |
| |
| EReference linkTarget = EcoreFactory.eINSTANCE.createEReference(); |
| linkTarget.setName("target"); |
| linkTarget.setEType(node); |
| linkTarget.setUpperBound(1); |
| classLink.getEStructuralFeatures().add(linkTarget); |
| |
| myRefLink = EcoreFactory.eINSTANCE.createEReference(); |
| myRefLink.setName("refLink"); |
| myRefLink.setEType(node); |
| myRefLink.setUpperBound(-1); |
| node.getEStructuralFeatures().add(myRefLink); |
| |
| new ResourceImpl(URI.createURI("uri://org.eclipse.gmf.eh/tests/DomainModelSetup")).getContents().add(myPackage); |
| |
| myNode1 = new NodeData(node, node1Name, nodeContainment); |
| myNode2 = new NodeData(node, node2Name, nodeContainment); |
| myClassLink = new LinkData(classLink, linkTarget, linkContainment); |
| } |
| |
| public EClass getDiagramElement() { |
| return myDiagramElement; |
| } |
| |
| public LinkData getLinkAsClass() { |
| return myClassLink; |
| } |
| |
| public EReference getLinkAsRef() { |
| return myRefLink; |
| } |
| |
| public EPackage getModel() { |
| return myPackage; |
| } |
| |
| public NodeData getNodeA() { |
| return myNode1; |
| } |
| |
| public NodeData getNodeB() { |
| return myNode2; |
| } |
| } |
| |
| } |