/* * Copyright (c) 2006, 2010 Borland Software Corporation and others * * 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: * Michael Golubev (Borland) - initial API and implementation */ package org.eclipse.gmf.tests.gen; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.LinkedList; import org.junit.Assert; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.EcorePackage; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.gmf.codegen.gmfgen.*; import org.eclipse.gmf.internal.codegen.util.GMFGenConfig; import org.eclipse.gmf.internal.common.reconcile.DefaultDecision; import org.eclipse.gmf.internal.common.reconcile.Reconciler; import org.eclipse.gmf.internal.common.reconcile.ReconcilerConfigBase; import org.eclipse.gmf.tests.ConfiguredTestCase; import org.eclipse.gmf.tests.setup.DiaGenSource; public class CodegenReconcileTest extends ConfiguredTestCase { public CodegenReconcileTest(String name) { super(name); } protected final GenEditorGenerator getOriginal() { return getSetup().getGenModel().getGenDiagram().getEditorGen(); } protected final GenEditorGenerator createCopy() { return EcoreUtil.copy(getOriginal()); } public void testLoadGMFGen() throws Exception { GenEditorGenerator original = getOriginal(); assertNotNull(original); GenEditorGenerator copy = createCopy(); assertNotNull(copy); assertFalse(original == copy); assertFalse(original.equals(copy)); assertEquals(original.getCopyrightText(), copy.getCopyrightText()); assertEquals(original.isSameFileForDiagramAndModel(), copy.isSameFileForDiagramAndModel()); assertEquals(original.getPackageNamePrefix(), copy.getPackageNamePrefix()); final String NEW_VALUE = "New Value"; copy.setCopyrightText(NEW_VALUE); assertEquals(copy.getCopyrightText(), NEW_VALUE); assertFalse(copy.getCopyrightText().equals(original.getCopyrightText())); } public void testReconcileDeepElementWithAlwaysMatcher() throws Exception { class GenPluginChange extends Assert implements UserChange { private final String NEW_PROVIDER = "NewProviderValue"; private final String NEW_VERSION = "NewVersionValue"; private final String NEW_ID = "NewPluginID"; private final String NEW_ACTIVATOR = "NewActivator"; private final String NEW_NAME = "NewName With Space"; private boolean myExpectedPrintingEnabled; public void applyChanges(GenEditorGenerator old) { GenPlugin genPlugin = old.getPlugin(); assertNotNull(genPlugin.getProvider()); assertNotNull(genPlugin.getVersion()); assertNotNull(genPlugin.getID()); assertNotNull(genPlugin.getActivatorClassName()); assertNotNull(genPlugin.getName()); assertFalse(genPlugin.isPrintingEnabled()); myExpectedPrintingEnabled = !genPlugin.isPrintingEnabled(); genPlugin.setProvider(NEW_PROVIDER); genPlugin.setVersion(NEW_VERSION); genPlugin.setID(NEW_ID); genPlugin.setActivatorClassName(NEW_ACTIVATOR); genPlugin.setPrintingEnabled(myExpectedPrintingEnabled); genPlugin.setName(NEW_NAME); } public void assertChangesPreserved(GenEditorGenerator current) { GenPlugin genPlugin = current.getPlugin(); assertEquals(NEW_PROVIDER, genPlugin.getProvider()); assertEquals(NEW_VERSION, genPlugin.getVersion()); assertEquals(NEW_ID, genPlugin.getID()); assertEquals(NEW_ACTIVATOR, genPlugin.getActivatorClassName()); assertEquals(myExpectedPrintingEnabled, genPlugin.isPrintingEnabled()); assertEquals(NEW_NAME, genPlugin.getName()); } public ReconcilerConfigBase getReconcilerConfig() { return new GMFGenConfig(); } } checkUserChange(new GenPluginChange()); } public void testReconcileCompartmentIsListLayout(){ class CompartmentChange extends Assert implements UserChange { private int myCompartmentsTotalCount; private final EStructuralFeature myGenCompartmentFeature; private final Boolean myExpectedValue; public CompartmentChange(EStructuralFeature genCompartmentFeature, boolean expectedValue){ assertEquals(EcorePackage.eINSTANCE.getEBoolean(), genCompartmentFeature.getEType()); myGenCompartmentFeature = genCompartmentFeature; myExpectedValue = Boolean.valueOf(expectedValue); } public final void applyChanges(GenEditorGenerator old) { GenDiagram diagram = old.getDiagram(); assertFalse("Precondition, we need some nodes", diagram.getChildNodes().isEmpty()); assertFalse("Precondition, we need some nodes", diagram.getTopLevelNodes().isEmpty()); myCompartmentsTotalCount = 0; for (GenNode next : diagram.getAllNodes()){ for (GenCompartment nextCompartment : next.getCompartments()){ myCompartmentsTotalCount++; nextCompartment.eSet(myGenCompartmentFeature, myExpectedValue); } } assertTrue(myCompartmentsTotalCount > 0); } public final void assertChangesPreserved(GenEditorGenerator current) { GenDiagram diagram = current.getDiagram(); assertFalse(diagram.getChildNodes().isEmpty()); assertFalse(diagram.getTopLevelNodes().isEmpty()); int actualCompartmentsTotalCount = 0; for (GenNode next : diagram.getAllNodes()){ for (GenCompartment nextCompartment : next.getCompartments()){ actualCompartmentsTotalCount++; Boolean actualValue = (Boolean)nextCompartment.eGet(myGenCompartmentFeature); assertEquals(getChangeDescription(), myExpectedValue, actualValue); } } assertEquals(myCompartmentsTotalCount, actualCompartmentsTotalCount); } public ReconcilerConfigBase getReconcilerConfig() { return new GMFGenConfig(); } private String getChangeDescription() { return "CompartmentChange: " + myGenCompartmentFeature.getName() + ":" + myExpectedValue; } } DiaGenSource diaGenSource = getSetup().getGenModel(); assertFalse(diaGenSource.getNodeA().getCompartments().isEmpty()); assertFalse(diaGenSource.getNodeB().getCompartments().isEmpty()); final GMFGenPackage GMFGEN = GMFGenPackage.eINSTANCE; // checkUserChange(new CompartmentChange(GMFGEN.getGenCompartment_CanCollapse(), true)); // checkUserChange(new CompartmentChange(GMFGEN.getGenCompartment_CanCollapse(), false)); checkUserChange(new CompartmentChange(GMFGEN.getGenCompartment_HideIfEmpty(), true)); checkUserChange(new CompartmentChange(GMFGEN.getGenCompartment_HideIfEmpty(), false)); // checkUserChange(new CompartmentChange(GMFGEN.getGenCompartment_NeedsTitle(), true)); // checkUserChange(new CompartmentChange(GMFGEN.getGenCompartment_NeedsTitle(), false)); // checkUserChange(new CompartmentChange(GMFGEN.getGenCompartment_ListLayout(), true)); checkUserChange(new CompartmentChange(GMFGEN.getGenCompartment_ListLayout(), false)); } public void testReconcileGenNodes() throws Exception { class ListLayoutChange extends Assert implements UserChange { private final String NEW_CANONICAL_EP = "MyCanonicalPolicy"; private final String NEW_GRAPHICAL_EP = "MyGraphicalPolicy"; private final String BAD_CANONICAL_EP = "MyCanonicalEditPolicy"; //changed but still follows "(.*)CanonicalEditPolicy" pattern private final String BAD_GRAPHICAL_EP = "MyGraphicalNodeEditPolicy"; //changed but still follows "(.*)GraphicalNodeEditPolicy" pattern public void applyChanges(GenEditorGenerator old) { EList<GenTopLevelNode> oldNodes = old.getDiagram().getTopLevelNodes(); assertTrue(oldNodes.size() > 1); GenNode nodeA = oldNodes.get(0); GenNode nodeB = oldNodes.get(1); nodeA.setCanonicalEditPolicyClassName(NEW_CANONICAL_EP); nodeA.setGraphicalNodeEditPolicyClassName(NEW_GRAPHICAL_EP); nodeB.setCanonicalEditPolicyClassName(BAD_CANONICAL_EP); nodeB.setGraphicalNodeEditPolicyClassName(BAD_GRAPHICAL_EP); } public void assertChangesPreserved(GenEditorGenerator current) { EList<GenTopLevelNode> currentNodes = current.getDiagram().getTopLevelNodes(); assertTrue(currentNodes.size() > 1); GenNode nodeA = currentNodes.get(0); GenNode nodeB = currentNodes.get(1); assertEquals(NEW_CANONICAL_EP, nodeA.getCanonicalEditPolicyClassName()); assertEquals(NEW_GRAPHICAL_EP, nodeA.getGraphicalNodeEditPolicyClassName()); assertEquals(BAD_CANONICAL_EP, nodeB.getCanonicalEditPolicyClassName()); assertEquals(BAD_GRAPHICAL_EP, nodeB.getGraphicalNodeEditPolicyClassName()); } public ReconcilerConfigBase getReconcilerConfig() { return new GMFGenConfig(); } } checkUserChange(new ListLayoutChange()); } public void testReconcileGenDiagram(){ final class DiagramChange extends SingleChange { public DiagramChange(EAttribute attribute, String valueToSet) { super(attribute, valueToSet); } public DiagramChange(EAttribute attribute, boolean valueToSet) { super(attribute, valueToSet); } protected EObject findChangeSubject(GenEditorGenerator root) { return root.getDiagram(); } } GMFGenPackage GMF = GMFGenPackage.eINSTANCE; checkUserChange(new DiagramChange(GMF.getGenDiagram_Synchronized(), true)); checkUserChange(new DiagramChange(GMF.getGenDiagram_Synchronized(), false)); checkUserChange(new DiagramChange(GMF.getEditorCandies_CreationWizardIconPath(), null)); checkUserChange(new DiagramChange(GMF.getEditorCandies_CreationWizardIconPath(), "")); checkUserChange(new DiagramChange(GMF.getEditorCandies_CreationWizardIconPath(), "\\..\\a\\B\\c")); checkUserChange(new DiagramChange(GMF.getEditorCandies_CreationWizardIconPath(), "http://localhost:8080/")); checkUserChange(new DiagramChange(GMF.getEditorCandies_CreationWizardCategoryID(), null)); checkUserChange(new DiagramChange(GMF.getEditorCandies_CreationWizardCategoryID(), "")); checkUserChange(new DiagramChange(GMF.getEditorCandies_CreationWizardCategoryID(), " ")); checkUserChange(new DiagramChange(GMF.getEditorCandies_CreationWizardCategoryID(), "org.eclipse.ui.Examples")); //actual default value checkUserChange(new DiagramChange(GMF.getEditorCandies_CreationWizardCategoryID(), "com.myCompany.TheBestCategory")); } public void testReconcileGenDiagram_Shortcuts(){ final String[] PROVIDED_FOR = {"ModelA", "ModelB", "ModelC"}; final String[] CONTAINS_TO = {"txt", "mdm", "taipan"}; final String[] EMPTY = new String[0]; class ShortcutChange extends Assert implements UserChange { private final String[] myProvidedFor; private final String[] myContainsTo; public ShortcutChange(String[] providedFor, String[] containsTo){ myProvidedFor = providedFor; myContainsTo = containsTo; } public void applyChanges(GenEditorGenerator old) { GenDiagram diagram = old.getDiagram(); assertNotNull(diagram); diagram.getShortcutsProvidedFor().addAll(Arrays.asList(myProvidedFor)); diagram.getContainsShortcutsTo().addAll(Arrays.asList(myContainsTo)); assertEquals(Arrays.asList(myProvidedFor), diagram.getShortcutsProvidedFor()); assertEquals(Arrays.asList(myContainsTo), diagram.getContainsShortcutsTo()); } public void assertChangesPreserved(GenEditorGenerator current) { GenDiagram diagram = current.getDiagram(); assertEquals(Arrays.asList(myProvidedFor), diagram.getShortcutsProvidedFor()); assertEquals(Arrays.asList(myContainsTo), diagram.getContainsShortcutsTo()); } public ReconcilerConfigBase getReconcilerConfig() { return new GMFGenConfig(); } } ShortcutChange someChange = new ShortcutChange(PROVIDED_FOR, CONTAINS_TO); ShortcutChange emptyChange = new ShortcutChange(EMPTY, EMPTY); checkUserChange(someChange); checkUserChange(emptyChange); } public void testReconcileGenEditorGenerator_LimitedConfig() throws Exception { class UserChangeImpl extends Assert implements UserChange { private boolean mySameFile; private final boolean myExpectingCopyrightPreserved; public UserChangeImpl(boolean reconcileCopyright){ myExpectingCopyrightPreserved = reconcileCopyright; } public void applyChanges(GenEditorGenerator old){ old.setCopyrightText("AAA"); old.setPackageNamePrefix("BBB"); old.setDiagramFileExtension("CCC"); mySameFile = !old.isSameFileForDiagramAndModel(); old.setSameFileForDiagramAndModel(mySameFile); // we do not reconcile this with limited config old.setTemplateDirectory("DDD"); assertEquals("DDD", old.getTemplateDirectory()); } public void assertChangesPreserved(GenEditorGenerator current){ if (myExpectingCopyrightPreserved){ assertEquals("AAA", current.getCopyrightText()); } else { assertFalse("AAA".equals(current.getCopyrightText())); } assertEquals("BBB", current.getPackageNamePrefix()); assertEquals("CCC", current.getDiagramFileExtension()); assertEquals(mySameFile, current.isSameFileForDiagramAndModel()); //not expected to be reconciled -- limited config assertFalse("DDD".equals(current.getTemplateDirectory())); } public ReconcilerConfigBase getReconcilerConfig(){ return new LimitedGMFGenConfig(myExpectingCopyrightPreserved); } } checkUserChange(new UserChangeImpl(false)); checkUserChange(new UserChangeImpl(true)); } public void testReconcileGenEditorGenerator(){ class GenEditorGeneratorChange extends SingleChange { public GenEditorGeneratorChange(EAttribute attribute, boolean expectedValue) { super(attribute, expectedValue); } public GenEditorGeneratorChange(EAttribute attribute, Object expectedValue) { super(attribute, expectedValue); } protected final EObject findChangeSubject(GenEditorGenerator root) { return root; } } class TemplateDirectoryChange extends GenEditorGeneratorChange { public TemplateDirectoryChange(String value){ super(GMFGenPackage.eINSTANCE.getGenEditorGenerator_TemplateDirectory(), value); } } class DynamicTemplatesChange extends GenEditorGeneratorChange { public DynamicTemplatesChange(boolean value) { super(GMFGenPackage.eINSTANCE.getGenEditorGenerator_DynamicTemplates(), value); } } class ModelIdChange extends GenEditorGeneratorChange { public ModelIdChange(String value){ super(GMFGenPackage.eINSTANCE.getGenEditorGenerator_ModelID(), value); } } checkUserChange(new DynamicTemplatesChange(true)); checkUserChange(new DynamicTemplatesChange(false)); checkUserChange(new TemplateDirectoryChange(null)); checkUserChange(new TemplateDirectoryChange("")); checkUserChange(new TemplateDirectoryChange("\\a\\b\\c")); checkUserChange(new TemplateDirectoryChange("c:/my-folder/my templates with space/")); checkUserChange(new ModelIdChange("ABC")); checkUserChange(new ModelIdChange("ABC ")); checkUserChange(new ModelIdChange("")); checkUserChange(new ModelIdChange(" ")); checkUserChange(new ModelIdChange(null)); checkUserChange(new GenEditorGeneratorChange(GMFGenPackage.eINSTANCE.getGenEditorGenerator_DomainFileExtension(), "xxx")); checkUserChange(new UserChange() { public void applyChanges(GenEditorGenerator old) { assertNotNull(old.getNavigator()); old.setNavigator(null); } public void assertChangesPreserved(GenEditorGenerator current) { assertNull(current.getNavigator()); } public ReconcilerConfigBase getReconcilerConfig() { return new GMFGenConfig(); } }); } public void testReconcileGenEditorView(){ final class EditorChange extends SingleChange { public EditorChange(EAttribute attribute, String valueToSet) { super(attribute, valueToSet); } protected EObject findChangeSubject(GenEditorGenerator root) { return root.getEditor(); } } GMFGenPackage GMF = GMFGenPackage.eINSTANCE; checkUserChange(new EditorChange(GMF.getGenEditorView_IconPath(), null)); checkUserChange(new EditorChange(GMF.getGenEditorView_IconPath(), "")); checkUserChange(new EditorChange(GMF.getGenEditorView_IconPath(), "//a//b//c")); checkUserChange(new EditorChange(GMF.getGenEditorView_IconPath(), "c:\\myIconsFolder")); checkUserChange(new EditorChange(GMF.getGenEditorView_ClassName(), null)); checkUserChange(new EditorChange(GMF.getGenEditorView_ClassName(), "")); checkUserChange(new EditorChange(GMF.getGenEditorView_ClassName(), "MyClass")); checkUserChange(new EditorChange(GMF.getGenEditorView_ClassName(), "org.eclipse.MyClass")); checkUserChange(new EditorChange(GMF.getGenEditorView_ID(), null)); checkUserChange(new EditorChange(GMF.getGenEditorView_ID(), "")); checkUserChange(new EditorChange(GMF.getGenEditorView_ID(), "my.editor.id")); } public void testReconcileViewmapAttributes(){ abstract class AbstractAttributesChange implements UserChange { private int myAffectedViewmapsCount; protected abstract Attributes findAttributes(Viewmap viewmap); protected abstract Attributes createUserAttributes(); protected abstract void assertChanges(Attributes attributes); public final void applyChanges(GenEditorGenerator old) { myAffectedViewmapsCount = 0; for (GenNode next : old.getDiagram().getAllNodes()){ Viewmap nextViewmap = next.getViewmap(); if (nextViewmap == null){ continue; } Attributes attributes = findAttributes(nextViewmap); assertNull("Reconciler is intended to work with attributes that are created only by user", attributes); attributes = createUserAttributes(); nextViewmap.getAttributes().add(attributes); myAffectedViewmapsCount++; } assertTrue(myAffectedViewmapsCount > 0); } public final void assertChangesPreserved(GenEditorGenerator current) { int checkedViewmapsCount = 0; for (GenNode next : current.getDiagram().getAllNodes()){ Viewmap nextViewmap = next.getViewmap(); if (nextViewmap == null){ continue; } Attributes attributes = findAttributes(nextViewmap); assertNotNull(attributes); assertChanges(attributes); checkedViewmapsCount++; } assertEquals(myAffectedViewmapsCount, checkedViewmapsCount); } public final ReconcilerConfigBase getReconcilerConfig() { return new GMFGenConfig(); } } class DefaultSizeChange extends AbstractAttributesChange { private static final int HEIGHT = 23; private static final int WIDTH = 32; protected void assertChanges(Attributes attributes) { DefaultSizeAttributes defaultSize = (DefaultSizeAttributes)attributes; assertEquals(HEIGHT, defaultSize.getHeight()); assertEquals(WIDTH, defaultSize.getWidth()); } protected Attributes createUserAttributes() { DefaultSizeAttributes defaultSize = GMFGenFactory.eINSTANCE.createDefaultSizeAttributes(); defaultSize.setHeight(HEIGHT); defaultSize.setWidth(WIDTH); return defaultSize; } protected Attributes findAttributes(Viewmap viewmap) { return viewmap.find(DefaultSizeAttributes.class); } } checkUserChange(new DefaultSizeChange()); } public void testReconcileMetamodelType(){ abstract class ElementTypeChange implements UserChange { protected abstract void applyChange(ElementType elementType); protected abstract void assertChange(ElementType elementType); protected Collection<GenContainerBase> collectSubjects(GenEditorGenerator editorGenerator){ LinkedList<GenContainerBase> allWithType = new LinkedList<GenContainerBase>(); GenDiagram diagram = editorGenerator.getDiagram(); allWithType.add(diagram); allWithType.addAll(diagram.getAllChildContainers()); //XXX: we do not know how to match links yet //allWithType.addAll(diagram.getLinks()); return allWithType; } public final void applyChanges(GenEditorGenerator old) { for (GenCommonBase next : collectSubjects(old)) { ElementType nextElementType = next.getElementType(); if (nextElementType == null){ continue; } applyChange(nextElementType); } } public final void assertChangesPreserved(GenEditorGenerator current) { for (GenCommonBase next : collectSubjects(current)) { ElementType nextElementType = next.getElementType(); if (nextElementType == null){ continue; } assertChange(nextElementType); } } public final ReconcilerConfigBase getReconcilerConfig() { return new GMFGenConfig(); } protected String toString(ElementType elementType) { return String.valueOf(elementType)/* + " for :" + String.valueOf(elementType.getDiagramElement())*/; } } class DisplayNameChange extends ElementTypeChange { private final String myValue; public DisplayNameChange(String value){ myValue = value; } protected void applyChange(ElementType elementType) { elementType.setDisplayName(myValue); } protected void assertChange(ElementType elementType) { assertEquals(toString(elementType), myValue, elementType.getDisplayName()); } } class DefinedExternallyChange extends ElementTypeChange { private boolean myValue; public DefinedExternallyChange(boolean value){ myValue = value; } protected void applyChange(ElementType elementType) { elementType.setDefinedExternally(myValue); } protected void assertChange(ElementType elementType) { assertEquals(toString(elementType), myValue, elementType.isDefinedExternally()); } } checkUserChange(new DisplayNameChange("ABCD")); //XXX: does not work: checkUserChange(new DisplayNameChange("")); checkUserChange(new DefinedExternallyChange(true)); checkUserChange(new DefinedExternallyChange(false)); } public void testGenNavigator() { class DomainNavigatorRemovingChange implements UserChange { public void applyChanges(GenEditorGenerator old) { assertNotNull(old.getNavigator()); old.getNavigator().setGenerateDomainModelNavigator(false); } public void assertChangesPreserved(GenEditorGenerator current) { assertFalse(current.getNavigator().isGenerateDomainModelNavigator()); } public ReconcilerConfigBase getReconcilerConfig() { return new GMFGenConfig(); } } checkUserChange(new DomainNavigatorRemovingChange()); class NavigatorChange extends SingleChange { public NavigatorChange(EAttribute attribute, String valueToSet) { super(attribute, valueToSet); } protected EObject findChangeSubject(GenEditorGenerator root) { assertNotNull(root.getNavigator()); return root.getNavigator(); } } GMFGenPackage gmfGenPackage = GMFGenPackage.eINSTANCE; checkUserChange(new NavigatorChange(gmfGenPackage.getGenDomainModelNavigator_DomainContentExtensionID(), "customId")); checkUserChange(new NavigatorChange(gmfGenPackage.getGenDomainModelNavigator_DomainContentExtensionName(), "customName")); checkUserChange(new NavigatorChange(gmfGenPackage.getGenDomainModelNavigator_DomainContentExtensionPriority(), "customPriorityName")); checkUserChange(new NavigatorChange(gmfGenPackage.getGenDomainModelNavigator_DomainContentProviderClassName(), "CustomContentProvider")); checkUserChange(new NavigatorChange(gmfGenPackage.getGenDomainModelNavigator_DomainLabelProviderClassName(), "CustomLabelProvider")); checkUserChange(new NavigatorChange(gmfGenPackage.getGenDomainModelNavigator_DomainModelElementTesterClassName(), "CustomModelElementTester")); checkUserChange(new NavigatorChange(gmfGenPackage.getGenDomainModelNavigator_DomainNavigatorItemClassName(), "CustomNavigatorItem")); checkUserChange(new NavigatorChange(gmfGenPackage.getGenNavigator_ContentExtensionID(), "customID")); checkUserChange(new NavigatorChange(gmfGenPackage.getGenNavigator_ContentExtensionName(), "customName")); checkUserChange(new NavigatorChange(gmfGenPackage.getGenNavigator_ContentExtensionPriority(), "customPriority")); checkUserChange(new NavigatorChange(gmfGenPackage.getGenNavigator_LinkHelperExtensionID(), "customID")); checkUserChange(new NavigatorChange(gmfGenPackage.getGenNavigator_SorterExtensionID(), "customID")); checkUserChange(new NavigatorChange(gmfGenPackage.getGenNavigator_ActionProviderID(), "customID")); checkUserChange(new NavigatorChange(gmfGenPackage.getGenNavigator_ContentProviderClassName(), "CustomContentProvider")); checkUserChange(new NavigatorChange(gmfGenPackage.getGenNavigator_LabelProviderClassName(), "CustomLabelProvider")); checkUserChange(new NavigatorChange(gmfGenPackage.getGenNavigator_LinkHelperClassName(), "CustomLinkHelper")); checkUserChange(new NavigatorChange(gmfGenPackage.getGenNavigator_SorterClassName(), "CustomSorter")); checkUserChange(new NavigatorChange(gmfGenPackage.getGenNavigator_ActionProviderClassName(), "CustomActionProvider")); checkUserChange(new NavigatorChange(gmfGenPackage.getGenNavigator_AbstractNavigatorItemClassName(), "CustomAbstractNavigator")); checkUserChange(new NavigatorChange(gmfGenPackage.getGenNavigator_NavigatorGroupClassName(), "CustomNavigatorGroup")); checkUserChange(new NavigatorChange(gmfGenPackage.getGenNavigator_NavigatorItemClassName(), "CustomItemClass")); checkUserChange(new NavigatorChange(gmfGenPackage.getGenNavigator_UriInputTesterClassName(), "CustomURITester")); checkUserChange(new NavigatorChange(gmfGenPackage.getGenNavigator_PackageName(), "customPackage")); } public void testGenJavaExpressionPovider() { GenEditorGenerator editorGen = createCopy(); editorGen.setExpressionProviders(GMFGenFactory.eINSTANCE.createGenExpressionProviderContainer()); editorGen.getExpressionProviders().getProviders().add(GMFGenFactory.eINSTANCE.createGenJavaExpressionProvider()); class GenJavaExpressionProviderChange extends SingleChange { public GenJavaExpressionProviderChange(EAttribute attribute, boolean valueToSet) { super(attribute, valueToSet); } protected EObject findChangeSubject(GenEditorGenerator root) { assertNotNull(root.getExpressionProviders()); for (GenExpressionProviderBase expressionProvider : root.getExpressionProviders().getProviders()) { if (expressionProvider instanceof GenJavaExpressionProvider) { return expressionProvider; } } fail("No GenJavaExpression provider found."); return null; } } checkUserChange(new GenJavaExpressionProviderChange(GMFGenPackage.eINSTANCE.getGenJavaExpressionProvider_InjectExpressionBody(), true), editorGen, EcoreUtil.copy(editorGen)); } public void testGenParsers() { getOriginal().getLabelParsers().setProviderPriority(null); // reset to default value, as previous // tests may alter it to another value, and as long as preserveIfSet/DefaultDecision // doesn't keep old value if there's new value which is eIsSet() == true, need to make sure // this tests starts with a clean state ("new" model passed to reconciler has default value) class GenParsersChange extends SingleChange { public GenParsersChange(EAttribute attr, Object value) { super(attr, value); } @Override protected EObject findChangeSubject(GenEditorGenerator genEditor) { return genEditor.getLabelParsers(); } } GMFGenPackage ePack = GMFGenPackage.eINSTANCE; checkUserChange(new GenParsersChange(ePack.getGenParsers_ClassName(), "ClassNaaaame")); checkUserChange(new GenParsersChange(ePack.getGenParsers_PackageName(), "org.ssaammppllee")); checkUserChange(new GenParsersChange(ePack.getGenParsers_ProviderPriority(), ProviderPriority.HIGH_LITERAL)); assertEquals("Sanity", Boolean.FALSE, ePack.getGenParsers_ExtensibleViaService().getDefaultValue()); checkUserChange(new GenParsersChange(ePack.getGenParsers_ExtensibleViaService(), true)); } public void testCustomParser_CopyWithCrossRef() { UserChange userChange = new UserChange() { private CustomParser myParser; public void applyChanges(GenEditorGenerator old) { myParser = GMFGenFactory.eINSTANCE.createCustomParser(); myParser.setQualifiedName("some.unique.name"); GenNodeLabel labelWithFeatureFacet = null; L1: for (GenNode n : old.getDiagram().getAllNodes()) { for (GenNodeLabel l : n.getLabels()) { if (l.getModelFacet() instanceof FeatureLabelModelFacet) { labelWithFeatureFacet = l; break L1; } } } assertNotNull("sanity: need at least one label with FeatureLabelModelFacet", labelWithFeatureFacet); myParser.getUses().add(labelWithFeatureFacet.getModelFacet()); old.getLabelParsers().getImplementations().add(myParser); } public void assertChangesPreserved(GenEditorGenerator current) { CustomParser found = null; for (GenParserImplementation pi : current.getLabelParsers().getImplementations()) { if (pi instanceof CustomParser && myParser.getQualifiedName().equals(((CustomParser) pi).getQualifiedName())) { found = (CustomParser) pi; break; } } assertNotNull(found); assertFalse(found.getUses().isEmpty()); LabelModelFacet lmf = found.getUses().get(0); assertTrue(lmf instanceof FeatureLabelModelFacet); } public ReconcilerConfigBase getReconcilerConfig() { return new GMFGenConfig(); } }; checkUserChange(userChange); } public void testGenContextMenu() { GenEditorGenerator old = createCopy(); GenEditorGenerator current = createCopy(); // make clean initial state current.getContextMenus().clear(); old.getContextMenus().clear(); // GenContextMenu menu1 = GMFGenFactory.eINSTANCE.createGenContextMenu(); GenContextMenu menu2 = GMFGenFactory.eINSTANCE.createGenContextMenu(); old.getContextMenus().add(menu1); old.getContextMenus().add(menu2); menu1.setID("menu1"); menu1.getContext().add(old.getDiagram()); menu1.getItems().add(GMFGenFactory.eINSTANCE.createGenSeparator()); menu2.setID("menu2"); // use couple of top nodes as a context menu2.getContext().add(old.getDiagram().getTopLevelNodes().get(0)); menu2.getContext().add(old.getDiagram().getTopLevelNodes().get(1)); // few items GenCustomAction ca = GMFGenFactory.eINSTANCE.createGenCustomAction(); GenCommandAction cmda = GMFGenFactory.eINSTANCE.createGenCommandAction(); GenSeparator sep = GMFGenFactory.eINSTANCE.createGenSeparator(); GenGroupMarker gm = GMFGenFactory.eINSTANCE.createGenGroupMarker(); ca.setQualifiedClassName("sample.action1"); cmda.setCommandIdentifier("cmd.ident"); sep.setGroupName("sepa"); gm.setGroupName("group.gm"); menu2.getItems().add(ca); menu2.getItems().add(sep); menu2.getItems().add(cmda); menu2.getItems().add(gm); GenContextMenu menu1_new = GMFGenFactory.eINSTANCE.createGenContextMenu(); GenContextMenu menu3 = GMFGenFactory.eINSTANCE.createGenContextMenu(); current.getContextMenus().add(menu1_new); current.getContextMenus().add(menu3); // same as menu1, diagram as context, separator as a sole item menu1_new.getContext().add(current.getDiagram()); menu1_new.getItems().add(GMFGenFactory.eINSTANCE.createGenSeparator()); // non-matching context menu3.getContext().add(current.getDiagram().getLinks().get(0)); // new Reconciler(new GMFGenConfig()).reconcileTree(current, old); // assertEquals(3, current.getContextMenus().size()); assertTrue(menu1_new == current.getContextMenus().get(0)); assertTrue(menu3 == current.getContextMenus().get(1)); GenContextMenu menu2_new = current.getContextMenus().get(2); assertEquals(menu2.getContext().size(), menu2_new.getContext().size()); assertEquals(menu2.getID(), menu2_new.getID()); assertEquals(menu2.getItems().size(), menu2_new.getItems().size()); // check contexts are the same HashSet<Integer> diagramElements = new HashSet<Integer>(); for (GenCommonBase de : menu2.getContext()) { diagramElements.add(de.getVisualID()); } assertEquals(menu2_new.getContext().size(), diagramElements.size()); for (GenCommonBase de : menu2_new.getContext()) { diagramElements.remove(de.getVisualID()); } assertTrue(diagramElements.isEmpty()); } private void checkUserChange(UserChange userChange){ checkUserChange(userChange, createCopy(), createCopy()); } private void checkUserChange(UserChange userChange, GenEditorGenerator old, GenEditorGenerator current) { userChange.applyChanges(old); new Reconciler(userChange.getReconcilerConfig()).reconcileTree(current, old); userChange.assertChangesPreserved(current); } private static interface UserChange { public void applyChanges(GenEditorGenerator old); public void assertChangesPreserved(GenEditorGenerator current); public ReconcilerConfigBase getReconcilerConfig(); } private static class LimitedGMFGenConfig extends ReconcilerConfigBase { public LimitedGMFGenConfig(boolean reconcileCopyright){ final GMFGenPackage GMFGEN = GMFGenPackage.eINSTANCE; setMatcher(GMFGEN.getGenEditorGenerator(), ALWAYS_MATCH); if (reconcileCopyright){ preserveIfSet(GMFGEN.getGenEditorGenerator(), GMFGEN.getGenEditorGenerator_CopyrightText()); } preserveIfSet(GMFGEN.getGenEditorGenerator(), GMFGEN.getGenEditorGenerator_PackageNamePrefix()); preserveIfSet(GMFGEN.getGenEditorGenerator(), GMFGEN.getGenEditorGenerator_DiagramFileExtension()); preserveIfSet(GMFGEN.getGenEditorGenerator(), GMFGEN.getGenEditorGenerator_SameFileForDiagramAndModel()); setMatcher(GMFGEN.getGenPlugin(), ALWAYS_MATCH); //exactly one feature for ALWAYS_MATCH GenEditorGenerator preserveIfSet(GMFGEN.getGenPlugin(), GMFGEN.getGenPlugin_Provider()); preserveIfSet(GMFGEN.getGenPlugin(), GMFGEN.getGenPlugin_Version()); } private void preserveIfSet(EClass eClass, EAttribute feature){ //FIXME: only attributes for now, allow references addDecision(eClass, new DefaultDecision(feature)); } } private abstract static class SingleChange implements UserChange { private final EAttribute myAttribute; private final Object myValueToSet; private Object myExpectedValue; public SingleChange(EAttribute attribute, boolean valueToSet){ this(attribute, Boolean.valueOf(valueToSet)); } public SingleChange(EAttribute attribute, Object valueToSet){ myAttribute = attribute; myValueToSet = valueToSet; } protected abstract EObject findChangeSubject(GenEditorGenerator root); public void applyChanges(GenEditorGenerator old) { EObject subject = findChangeSubject(old); assertNotNull(subject); subject.eSet(myAttribute, myValueToSet); myExpectedValue = subject.eGet(myAttribute); } public void assertChangesPreserved(GenEditorGenerator current) { EObject subject = findChangeSubject(current); assertNotNull(subject); assertEquals(myExpectedValue, subject.eGet(myAttribute)); } public ReconcilerConfigBase getReconcilerConfig() { return new GMFGenConfig(); } } }