### Eclipse Workspace Patch 1.0 #P org.eclipse.gmf.codegen.reconciler Index: src/org/eclipse/gmf/codegen/reconciler/ReconcilerConfig.java =================================================================== RCS file: src/org/eclipse/gmf/codegen/reconciler/ReconcilerConfig.java diff -N src/org/eclipse/gmf/codegen/reconciler/ReconcilerConfig.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/gmf/codegen/reconciler/ReconcilerConfig.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,20 @@ +/* + * 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: + * Michael Golubev (Borland) - initial API and implementation + */ + +package org.eclipse.gmf.codegen.reconciler; + +import org.eclipse.emf.ecore.EClass; + +public interface ReconcilerConfig { + Matcher getMatcher(EClass eClass); + DecisionMaker[] getDecisionMakers(EClass eClass); +} Index: build.properties =================================================================== RCS file: build.properties diff -N build.properties --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ build.properties 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . Index: src/org/eclipse/gmf/codegen/reconciler/StringPatternDecisionMaker.java =================================================================== RCS file: src/org/eclipse/gmf/codegen/reconciler/StringPatternDecisionMaker.java diff -N src/org/eclipse/gmf/codegen/reconciler/StringPatternDecisionMaker.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/gmf/codegen/reconciler/StringPatternDecisionMaker.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,48 @@ +/* + * 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: + * Michael Golubev (Borland) - initial API and implementation + */ + +package org.eclipse.gmf.codegen.reconciler; + +import java.util.regex.Pattern; + +import org.eclipse.emf.ecore.EAttribute; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EcorePackage; + +public class StringPatternDecisionMaker extends DecisionMaker { + private Pattern myPattern; + + public StringPatternDecisionMaker(String valuePattern, EAttribute attribute){ + this(Pattern.compile(valuePattern), attribute); + } + + public StringPatternDecisionMaker(Pattern valuePattern, EAttribute attribute){ + super(attribute); + if (attribute.getEAttributeType() != EcorePackage.eINSTANCE.getEString()){ + throw new IllegalArgumentException("Expected string attribute"); + } + if (attribute.getUpperBound() != 1){ + throw new IllegalArgumentException("Expected multiplicity [0..1] or [1]"); + } + myPattern = valuePattern; + } + + public Decision makeDecision(EObject current, EObject old) { + String oldValue = (String)old.eGet(getFeature()); + if (oldValue != null && !myPattern.matcher(oldValue).matches()){ + return Decision.PRESERVE_OLD; + } else { + return Decision.ACCEPT_NEW; + } + } + +} Index: src/org/eclipse/gmf/codegen/reconciler/AttributeMatcher.java =================================================================== RCS file: src/org/eclipse/gmf/codegen/reconciler/AttributeMatcher.java diff -N src/org/eclipse/gmf/codegen/reconciler/AttributeMatcher.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/gmf/codegen/reconciler/AttributeMatcher.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,62 @@ +/* + * 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: + * Michael Golubev (Borland) - initial API and implementation + */ + +package org.eclipse.gmf.codegen.reconciler; + +import java.text.MessageFormat; + +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EStructuralFeature; + +public class AttributeMatcher implements Matcher { + private final String myFeatureName; + private EClass myCachedFeatureOwner; + private EStructuralFeature myCachedFeature; + + public AttributeMatcher(String featureName){ + myFeatureName = featureName; + } + + public AttributeMatcher(EStructuralFeature feature){ + this(feature.getName()); + } + + public boolean match(EObject current, EObject old) { + assertCompatible(current, old); + EStructuralFeature feature = findFeature(current.eClass()); + return safeEquals(current.eGet(feature), old.eGet(feature)); + } + + private void assertCompatible(EObject current, EObject old){ + if (!current.eClass().equals(old.eClass())){ + throw new IllegalStateException(MessageFormat.format("Objects not compatible: {0}, {1}", new Object[] {current, old})); + } + } + + private EStructuralFeature findFeature(EClass eClass){ + if (!eClass.equals(myCachedFeatureOwner)){ + EStructuralFeature result = eClass.getEStructuralFeature(myFeatureName); + if (result == null){ + throw new IllegalStateException(MessageFormat.format("Unknown feature {0} in EClass {1}", new Object[] {myFeatureName, eClass})); + } + myCachedFeatureOwner = eClass; + myCachedFeature = result; + } + return myCachedFeature; + } + + private boolean safeEquals(Object first, Object second){ + return first == null ? second == null : first.equals(second); + } + +} Index: src/org/eclipse/gmf/codegen/reconciler/ReconcilerConfigBase.java =================================================================== RCS file: src/org/eclipse/gmf/codegen/reconciler/ReconcilerConfigBase.java diff -N src/org/eclipse/gmf/codegen/reconciler/ReconcilerConfigBase.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/gmf/codegen/reconciler/ReconcilerConfigBase.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,112 @@ +/* + * 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: + * Michael Golubev (Borland) - initial API and implementation + */ + +package org.eclipse.gmf.codegen.reconciler; + +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.emf.ecore.EAttribute; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EReference; + +public class ReconcilerConfigBase implements ReconcilerConfig { + private static final EClassRecord EMPTY_RECORD = new EClassRecord(); + private final HashMap myEClass2Record; + + public ReconcilerConfigBase(){ + myEClass2Record = new HashMap(); + } + + public final Matcher getMatcher(EClass eClass) { + return getRecord(eClass, false).getMatcher(); + } + + public final DecisionMaker[] getDecisionMakers(EClass eClass) { + return getRecord(eClass, false).getDecisionMakers(); + } + + protected final void setMatcher(EClass eClass, Matcher matcher){ + getRecord(eClass, true).setMatcher(matcher); + } + + protected final void addDecisionMaker(EClass eClass, DecisionMaker decisionMaker){ + getRecord(eClass, true).addDecisionMaker(decisionMaker); + } + + protected final void setMatcher(EClass eClass, EAttribute attribute){ + checkStructuralFeature(eClass, attribute); + Matcher matcher = new AttributeMatcher(attribute); + setMatcher(eClass, matcher); + } + + protected final void setMatcher(EClass eClass, EReference reference){ + if (eClass.getEPackage().equals(reference.eClass().getEPackage())){ + //XXX: use lazyly resolved matcher??? + setMatcher(eClass, new AttributeMatcher(reference)); + } else { + setMatcher(eClass, new AttributeMatcher(reference)); + } + } + + private EClassRecord getRecord(EClass eClass, boolean force){ + EClassRecord result = (EClassRecord) myEClass2Record.get(eClass); + if (result == null){ + if (force){ + result = new EClassRecord(); + myEClass2Record.put(eClass, result); + } else { + result = EMPTY_RECORD; + } + } + return result; + } + + private void checkStructuralFeature(EClass expectedClass, EAttribute feature) { + if (expectedClass.getEStructuralFeature(feature.getFeatureID()) != feature){ + throw new IllegalArgumentException(MessageFormat.format("Alien feature {0} for EClass {1}", new Object[] {feature, expectedClass})); + } + } + + private static class EClassRecord { + private Matcher myMatcher = Matcher.FALSE; + private final List myDecisionMakers = new LinkedList(); + private DecisionMaker[] myMakersArray; + + public void addDecisionMaker(DecisionMaker maker){ + myDecisionMakers.add(maker); + makersSetChanged(); + } + + public DecisionMaker[] getDecisionMakers(){ + if (myMakersArray == null){ + myMakersArray = (DecisionMaker[]) myDecisionMakers.toArray(new DecisionMaker[myDecisionMakers.size()]); + } + return myMakersArray; + } + + public void setMatcher(Matcher matcher) { + myMatcher = matcher; + } + + public Matcher getMatcher() { + return myMatcher; + } + + private void makersSetChanged(){ + myMakersArray = null; + } + } + +} Index: .project =================================================================== RCS file: .project diff -N .project --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ .project 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,28 @@ + + + org.eclipse.gmf.codegen.reconciler + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + Index: META-INF/MANIFEST.MF =================================================================== RCS file: META-INF/MANIFEST.MF diff -N META-INF/MANIFEST.MF --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ META-INF/MANIFEST.MF 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,11 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.gmf.codegen.reconciler +Bundle-Version: 1.0.0.version +Bundle-Vendor: %providerName +Bundle-Localization: plugin +Require-Bundle: org.eclipse.emf.ecore, + org.eclipse.gmf.codegen +Export-Package: org.eclipse.gmf.codegen.reconciler, + org.eclipse.gmf.internal.codegen.reconciler Index: src/org/eclipse/gmf/codegen/reconciler/DefaultDecisionMaker.java =================================================================== RCS file: src/org/eclipse/gmf/codegen/reconciler/DefaultDecisionMaker.java diff -N src/org/eclipse/gmf/codegen/reconciler/DefaultDecisionMaker.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/gmf/codegen/reconciler/DefaultDecisionMaker.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,28 @@ +/* + * 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: + * Michael Golubev (Borland) - initial API and implementation + */ + +package org.eclipse.gmf.codegen.reconciler; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EStructuralFeature; + +public class DefaultDecisionMaker extends DecisionMaker { + public DefaultDecisionMaker(EStructuralFeature feature){ + super(feature); + } + + public Decision makeDecision(EObject current, EObject old) { + assert current.eClass().equals(old.eClass()); + return (!current.eIsSet(getFeature()) && old.eIsSet(getFeature())) ? Decision.PRESERVE_OLD : Decision.ACCEPT_NEW; + } + +} Index: src/org/eclipse/gmf/codegen/reconciler/Matcher.java =================================================================== RCS file: src/org/eclipse/gmf/codegen/reconciler/Matcher.java diff -N src/org/eclipse/gmf/codegen/reconciler/Matcher.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/gmf/codegen/reconciler/Matcher.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,68 @@ +/* + * 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: + * Michael Golubev (Borland) - initial API and implementation + */ + +package org.eclipse.gmf.codegen.reconciler; + +import java.util.Collection; + +import org.eclipse.emf.ecore.EObject; + +public interface Matcher { + public boolean match(EObject current, EObject old); + + public static final Matcher FALSE = new Matcher() { + public boolean match(EObject current, EObject old) { + return false; + } + }; + + public static class OR implements Matcher { + private final Matcher[] myMatchers; + + public OR(Matcher[] matchers){ + myMatchers = matchers; + } + + public OR(Collection matchers){ + this((Matcher[])matchers.toArray(new Matcher[matchers.size()])); + } + + public boolean match(EObject current, EObject old) { + boolean result = false; + for (int i = 0; !result && i < myMatchers.length; i++){ + result = myMatchers[i].match(current, old); + } + return result; + } + } + + public static class AND implements Matcher { + private final Matcher[] myMatchers; + + public AND(Matcher[] matchers){ + myMatchers = matchers; + } + + public AND(Collection matchers){ + this((Matcher[])matchers.toArray(new Matcher[matchers.size()])); + } + + public boolean match(EObject current, EObject old) { + boolean result = true; + for (int i = 0; result && i < myMatchers.length; i++){ + result = myMatchers[i].match(current, old); + } + return result; + } + } + +} Index: src/org/eclipse/gmf/codegen/reconciler/Reconciler.java =================================================================== RCS file: src/org/eclipse/gmf/codegen/reconciler/Reconciler.java diff -N src/org/eclipse/gmf/codegen/reconciler/Reconciler.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/gmf/codegen/reconciler/Reconciler.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,80 @@ +/* + * 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: + * Michael Golubev (Borland) - initial API and implementation + */ + +package org.eclipse.gmf.codegen.reconciler; + +import java.util.Collection; +import java.util.Iterator; + +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; + +public class Reconciler { + private final ReconcilerConfig myConfig; + + public Reconciler(ReconcilerConfig config){ + myConfig = config; + } + + protected void handleNotMatchedCurrent(EObject current){ + //FIXME ??? Is it user escape -- check history ??? + //FIXME How to handle not macthed old ??? + } + + public void reconcileResource(Resource current, Resource old){ + reconcileContents(current.getContents(), old.getContents()); + } + + public void reconcileTree(EObject currentRoot, EObject oldRoot){ + reconcileVertex(currentRoot, oldRoot); + reconcileContents(currentRoot.eContents(), oldRoot.eContents()); + } + + private void reconcileVertex(EObject current, EObject old){ + assert current.eClass().equals(old.eClass()); + DecisionMaker[] decisionMakers = myConfig.getDecisionMakers(current.eClass()); + for (int i = 0; i < decisionMakers.length; i++){ + DecisionMaker next = decisionMakers[i]; + Decision decision = next.makeDecision(current, old); + decision.apply(current, old, next.getFeature()); + } + } + + private void reconcileContents(Collection allCurrents, Collection allOlds){ + for (Iterator currentContents = allCurrents.iterator(); currentContents.hasNext();){ + EObject nextCurrent = (EObject) currentContents.next(); + EObject nextOld = findMatched(nextCurrent, allOlds); + if (nextOld == null){ + handleNotMatchedCurrent(nextCurrent); + } else { + reconcileTree(nextCurrent, nextOld); + } + } + } + + private EObject findMatched(EObject current, Collection allOld){ + EClass eClass = current.eClass(); + Matcher matcher = myConfig.getMatcher(eClass); + EObject result = null; + if (matcher != Matcher.FALSE){ + for (Iterator all = allOld.iterator(); result == null && all.hasNext();){ + EObject next = (EObject)all.next(); + if (eClass.equals(eClass) && matcher.match(current, next)){ + result = next; + } + } + } + return result; + } + +} Index: plugin.properties =================================================================== RCS file: plugin.properties diff -N plugin.properties --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ plugin.properties 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,20 @@ +# +# +# +# $Id$ + +# ==================================================================== +# To code developer: +# Do NOT change the properties between this line and the +# "%%% END OF TRANSLATED PROPERTIES %%%" line. +# Make a new property name, append to the end of the file and change +# the code to use the new property. +# ==================================================================== + +# ==================================================================== +# %%% END OF TRANSLATED PROPERTIES %%% +# ==================================================================== + +pluginName = GMFGen Reconciler Plugin +providerName = Eclipse.org + Index: src/org/eclipse/gmf/codegen/reconciler/DecisionMaker.java =================================================================== RCS file: src/org/eclipse/gmf/codegen/reconciler/DecisionMaker.java diff -N src/org/eclipse/gmf/codegen/reconciler/DecisionMaker.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/gmf/codegen/reconciler/DecisionMaker.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,51 @@ +/* + * 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: + * Michael Golubev (Borland) - initial API and implementation + */ + +package org.eclipse.gmf.codegen.reconciler; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EStructuralFeature; + +public abstract class DecisionMaker { + private final EStructuralFeature myFeature; + + public abstract Decision makeDecision(EObject current, EObject old); + + public DecisionMaker(EStructuralFeature feature){ + myFeature = feature; + } + + public final EStructuralFeature getFeature(){ + return myFeature; + } + + public static class ALWAYS_OLD extends DecisionMaker { + public ALWAYS_OLD(EStructuralFeature feature){ + super(feature); + } + + public Decision makeDecision(EObject current, EObject old) { + return Decision.PRESERVE_OLD; + } + } + + public static class ALWAYS_NEW extends DecisionMaker { + public ALWAYS_NEW(EStructuralFeature feature){ + super(feature); + } + + public Decision makeDecision(EObject current, EObject old) { + return Decision.ACCEPT_NEW; + } + } + +} Index: src/org/eclipse/gmf/codegen/reconciler/Decision.java =================================================================== RCS file: src/org/eclipse/gmf/codegen/reconciler/Decision.java diff -N src/org/eclipse/gmf/codegen/reconciler/Decision.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/gmf/codegen/reconciler/Decision.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,33 @@ +/* + * 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: + * Michael Golubev (Borland) - initial API and implementation + */ + +package org.eclipse.gmf.codegen.reconciler; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EStructuralFeature; + +public interface Decision { + public void apply(EObject current, EObject old, EStructuralFeature feature); + + public static final Decision PRESERVE_OLD = new Decision(){ + public void apply(EObject current, EObject old, EStructuralFeature feature) { + Object oldValue = old.eGet(feature, true); + current.eSet(feature, oldValue); + } + }; + + public static final Decision ACCEPT_NEW = new Decision(){ + public void apply(EObject current, EObject old, EStructuralFeature feature) { + //do nothing + } + }; +} Index: src/org/eclipse/gmf/internal/codegen/reconciler/GMFGenConfig.java =================================================================== RCS file: src/org/eclipse/gmf/internal/codegen/reconciler/GMFGenConfig.java diff -N src/org/eclipse/gmf/internal/codegen/reconciler/GMFGenConfig.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/gmf/internal/codegen/reconciler/GMFGenConfig.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,49 @@ +/* + * 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: + * Michael Golubev (Borland) - initial API and implementation + */ + +package org.eclipse.gmf.internal.codegen.reconciler; + +import org.eclipse.emf.ecore.EAttribute; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.gmf.codegen.gmfgen.GMFGenPackage; +import org.eclipse.gmf.codegen.reconciler.DefaultDecisionMaker; +import org.eclipse.gmf.codegen.reconciler.Matcher; +import org.eclipse.gmf.codegen.reconciler.ReconcilerConfigBase; + +public class GMFGenConfig extends ReconcilerConfigBase { + private static final GMFGenPackage GMFGEN = GMFGenPackage.eINSTANCE; + + public GMFGenConfig(){ + setMatcher(GMFGEN.getGenEditorGenerator(), ALWAYS_MATCH); + 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 + addDecisionMaker(eClass, new DefaultDecisionMaker(feature)); + } + + private static final Matcher ALWAYS_MATCH = new Matcher(){ + public boolean match(EObject current, EObject old) { + return current.eClass().equals(old.eClass()); + } + }; + +} Index: .classpath =================================================================== RCS file: .classpath diff -N .classpath --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ .classpath 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,7 @@ + + + + + + + #P org.eclipse.gmf.codegen.ui Index: src/org/eclipse/gmf/internal/codegen/popup/actions/TransformToGenModel.java =================================================================== RCS file: /cvsroot/technology/org.eclipse.gmf/plugins/org.eclipse.gmf.codegen.ui/src/org/eclipse/gmf/internal/codegen/popup/actions/TransformToGenModel.java,v retrieving revision 1.15 diff -u -r1.15 TransformToGenModel.java --- src/org/eclipse/gmf/internal/codegen/popup/actions/TransformToGenModel.java 15 Feb 2006 14:04:08 -0000 1.15 +++ src/org/eclipse/gmf/internal/codegen/popup/actions/TransformToGenModel.java 10 Mar 2006 18:59:52 -0000 @@ -15,6 +15,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.Map; import org.eclipse.core.resources.IFile; @@ -45,8 +46,10 @@ import org.eclipse.gmf.bridge.genmodel.GenModelAccess; import org.eclipse.gmf.bridge.genmodel.SpecificDiagramRunTimeModelHelper; import org.eclipse.gmf.codegen.gmfgen.GenEditorGenerator; +import org.eclipse.gmf.codegen.reconciler.Reconciler; import org.eclipse.gmf.internal.bridge.naming.gen.GenModelNamingMediatorImpl; import org.eclipse.gmf.internal.codegen.CodeGenUIPlugin; +import org.eclipse.gmf.internal.codegen.reconciler.GMFGenConfig; import org.eclipse.gmf.mappings.Mapping; import org.eclipse.jface.action.IAction; import org.eclipse.jface.dialogs.ErrorDialog; @@ -131,13 +134,19 @@ } protected IStatus run(IProgressMonitor monitor) { - monitor.beginTask(getName(), 3); + monitor.beginTask(getName(), 4); try { GenEditorGenerator genEditor = transform(mapping); monitor.worked(1); if (monitor.isCanceled()) { return Status.CANCEL_STATUS; } + + reconcile(genEditor); + monitor.worked(1); + if (monitor.isCanceled()) { + return Status.CANCEL_STATUS; + } save(genEditor); monitor.worked(1); @@ -172,6 +181,28 @@ dgmmRes.getContents().add(genBurdern); dgmmRes.save(getSaveOptions()); } + + private void reconcile(GenEditorGenerator genBurdern) { + GenEditorGenerator old = null; + Resource resource = null; + try { + resource = resSet.getResource(getGenModelURI(), true); + List contents = resource.getContents(); + if (!contents.isEmpty() && contents.get(0) instanceof GenEditorGenerator){ + old = (GenEditorGenerator)contents.get(0); + } + } catch (RuntimeException e){ + old = null; + } finally { + if (resource != null){ + resource.unload(); + } + } + + if (old != null){ + new Reconciler(new GMFGenConfig()).reconcileTree(genBurdern, old); + } + } }.schedule(); } Index: META-INF/MANIFEST.MF =================================================================== RCS file: /cvsroot/technology/org.eclipse.gmf/plugins/org.eclipse.gmf.codegen.ui/META-INF/MANIFEST.MF,v retrieving revision 1.14 diff -u -r1.14 MANIFEST.MF --- META-INF/MANIFEST.MF 1 Mar 2006 14:20:27 -0000 1.14 +++ META-INF/MANIFEST.MF 10 Mar 2006 18:59:52 -0000 @@ -9,7 +9,8 @@ org.eclipse.core.runtime, org.eclipse.core.resources, org.eclipse.gmf.bridge, - org.eclipse.gmf.codegen.edit + org.eclipse.gmf.codegen.edit, + org.eclipse.gmf.codegen.reconciler Eclipse-LazyStart: true Bundle-Vendor: %providerName Export-Package: org.eclipse.gmf.internal.codegen.popup.actions;x-friends:="org.eclipse.gmf.bridge.ui.dashboard" #P org.eclipse.gmf.codegen.reconciler.test.taipan Index: build.properties =================================================================== RCS file: build.properties diff -N build.properties --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ build.properties 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . Index: .classpath =================================================================== RCS file: .classpath diff -N .classpath --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ .classpath 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,7 @@ + + + + + + + Index: META-INF/MANIFEST.MF =================================================================== RCS file: META-INF/MANIFEST.MF diff -N META-INF/MANIFEST.MF --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ META-INF/MANIFEST.MF 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,14 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Reconciler Tests Plugin +Bundle-SymbolicName: org.eclipse.gmf.codegen.reconciler.test.taipan +Bundle-Version: 1.0.0.version +Bundle-Vendor: Eclipse.org +Bundle-Localization: plugin +Require-Bundle: org.eclipse.gmf.codegen, + org.eclipse.gmf.codegen.reconciler, + org.eclipse.gmf.examples.taipan, + org.junit, + org.eclipse.osgi, + org.eclipse.core.runtime, + org.eclipse.gmf.bridge Index: src/org/eclipse/gmf/codegen/reconciler/test/ReconcileTaipanTest.java =================================================================== RCS file: src/org/eclipse/gmf/codegen/reconciler/test/ReconcileTaipanTest.java diff -N src/org/eclipse/gmf/codegen/reconciler/test/ReconcileTaipanTest.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/gmf/codegen/reconciler/test/ReconcileTaipanTest.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,96 @@ +/* + * 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: + * Michael Golubev (Borland) - initial API and implementation + */ + +package org.eclipse.gmf.codegen.reconciler.test; + +import java.io.IOException; + +import junit.framework.TestCase; + +import org.eclipse.gmf.codegen.gmfgen.GenEditorGenerator; +import org.eclipse.gmf.codegen.gmfgen.GenPlugin; +import org.eclipse.gmf.codegen.reconciler.Reconciler; +import org.eclipse.gmf.internal.codegen.reconciler.GMFGenConfig; + +public class ReconcileTaipanTest extends TestCase { + public void testLoadGMFGen() throws Exception { + GenEditorGenerator original = loadTaipanGMFGen(); + assertNotNull(original); + GenEditorGenerator copy = loadTaipanGMFGen(); + 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 { + GenPlugin old = loadTaipanGMFGen().getPlugin(); + GenPlugin current = loadTaipanGMFGen().getPlugin(); + + assertNotNull(old.getProvider()); + assertNotNull(old.getVersion()); + + final String NEW_PROVIDER = "NewProviderValue"; + final String NEW_VERSION = "NewVersionValue"; + + old.setProvider(NEW_PROVIDER); + old.setVersion(NEW_VERSION); + + getReconciler().reconcileTree(current, old); + + assertEquals(NEW_PROVIDER, current.getProvider()); + assertEquals(NEW_VERSION, current.getVersion()); + } + + public void testReconcileGenEditorGenerator() throws Exception { + GenEditorGenerator old = loadTaipanGMFGen(); + GenEditorGenerator current = loadTaipanGMFGen(); + + old.setCopyrightText("AAA"); + old.setPackageNamePrefix("BBB"); + old.setDiagramFileExtension("CCC"); + + boolean sameFile = !old.isSameFileForDiagramAndModel(); + old.setSameFileForDiagramAndModel(sameFile); + + //we do not reconcile this now + old.setTemplateDirectory("DDD"); + assertEquals("DDD", old.getTemplateDirectory()); + + getReconciler().reconcileTree(current, old); + + assertEquals("AAA", current.getCopyrightText()); + assertEquals("BBB", current.getPackageNamePrefix()); + assertEquals("CCC", current.getDiagramFileExtension()); + assertEquals(sameFile, current.isSameFileForDiagramAndModel()); + + assertEquals("DDD", old.getTemplateDirectory()); + assertFalse("DDD".equals(current.getTemplateDirectory())); + } + + private Reconciler getReconciler(){ + return new Reconciler(new GMFGenConfig()); + } + + private GenEditorGenerator loadTaipanGMFGen() throws IOException{ + return new TaipanSuite().createTaipanEditorGenerator(); + } +} Index: .project =================================================================== RCS file: .project diff -N .project --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ .project 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,28 @@ + + + org.eclipse.gmf.codegen.reconciler.test.taipan + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + Index: src/org/eclipse/gmf/codegen/reconciler/test/TaipanSuite.java =================================================================== RCS file: src/org/eclipse/gmf/codegen/reconciler/test/TaipanSuite.java diff -N src/org/eclipse/gmf/codegen/reconciler/test/TaipanSuite.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/gmf/codegen/reconciler/test/TaipanSuite.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,99 @@ +/* + * 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: + * Michael Golubev (Borland) - initial API and implementation + */ + +package org.eclipse.gmf.codegen.reconciler.test; + +import java.io.IOException; +import java.net.URL; +import java.util.HashSet; +import java.util.Iterator; + +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.Platform; +import org.eclipse.emf.codegen.ecore.genmodel.GenModel; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.gmf.bridge.genmodel.BasicDiagramRunTimeModelHelper; +import org.eclipse.gmf.bridge.genmodel.BasicGenModelAccess; +import org.eclipse.gmf.bridge.genmodel.DiagramGenModelTransformer; +import org.eclipse.gmf.bridge.genmodel.DiagramRunTimeModelHelper; +import org.eclipse.gmf.codegen.gmfgen.GenEditorGenerator; +import org.eclipse.gmf.internal.bridge.naming.gen.GenModelNamingMediatorImpl; +import org.eclipse.gmf.mappings.Mapping; +import org.osgi.framework.Bundle; + +public class TaipanSuite { + private static final String TAIPAN = "org.eclipse.gmf.examples.taipan"; + + private final Bundle myBundle; + private final ResourceSet myResourceSet; + + public TaipanSuite(){ + myResourceSet = new ResourceSetImpl(); + myBundle = Platform.getBundle(TAIPAN); + if (myBundle == null){ + throw new IllegalStateException(); + } + } + + public GenEditorGenerator createTaipanEditorGenerator() throws IOException{ + Mapping mapping = (Mapping) loadResource("/models/taipan.gmfmap").getContents().get(0); + BasicGenModelAccess gma = getGenModelAccess(mapping); + gma.initDefault(); + gma.load(myResourceSet); + GenModel domainGenModel = gma.model(); + DiagramRunTimeModelHelper drtHelper = new BasicDiagramRunTimeModelHelper(); + DiagramGenModelTransformer transformer = new DiagramGenModelTransformer(drtHelper, new GenModelNamingMediatorImpl()); + if (domainGenModel != null) { + transformer.setEMFGenModel(domainGenModel); + } + transformer.transform(mapping); + GenEditorGenerator result = transformer.getResult(); + return result; + } + + public Resource loadResource(String relativePath) throws IOException{ + URL resolvedUrl = FileLocator.resolve(myBundle.getEntry(relativePath)); + URI uri = URI.createURI(resolvedUrl.toString()); + return myResourceSet.getResource(uri, true); + } + + public BasicGenModelAccess getGenModelAccess(Mapping mapping) { + HashSet packages = new HashSet(); + for (Iterator it = EcoreUtil.ExternalCrossReferencer.find(mapping).keySet().iterator(); it.hasNext();) { + Object next = it.next(); + if (next instanceof EClass) { + packages.add(((EClass) next).getEPackage()); + } + } + for (Iterator it = packages.iterator(); it.hasNext();) { + EPackage next = (EPackage) it.next(); + if (next.getESuperPackage() != null && EcoreUtil.isAncestor(packages, next.getESuperPackage())) { + it.remove(); + } + } + if (packages.isEmpty()) { + throw new IllegalStateException("Mapping without domain model"); + } + if (packages.size() != 1) { + throw new IllegalStateException("Too many packages"); + } + EPackage theOnly = (EPackage) packages.iterator().next(); + return new BasicGenModelAccess(theOnly); + } + +}