Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoratikhomirov2007-05-18 16:39:13 -0400
committeratikhomirov2007-05-18 16:39:13 -0400
commit1d73ed034b480a094fe271beee418cc5b7f250e8 (patch)
treeaebb28a14fc1484dfc9d1a1285077b78c75ab40d
parent730ba8ff77835ba8c1549cd0e4ee8bb8fe9be9e3 (diff)
downloadorg.eclipse.gmf-tooling-1d73ed034b480a094fe271beee418cc5b7f250e8.tar.gz
org.eclipse.gmf-tooling-1d73ed034b480a094fe271beee418cc5b7f250e8.tar.xz
org.eclipse.gmf-tooling-1d73ed034b480a094fe271beee418cc5b7f250e8.zip
[187811] akarjakina - Migration support refactored
-rw-r--r--plugins/org.eclipse.gmf.common/META-INF/MANIFEST.MF4
-rw-r--r--plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/CompatibleToolResourceFactory.java58
-rw-r--r--plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/FeatureKey.java72
-rw-r--r--plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/MigrationConfig.java259
-rw-r--r--plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/MigrationHelper.java197
-rw-r--r--plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/MigrationHelperDelegate.java34
-rw-r--r--plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/MigrationResource.java355
-rw-r--r--plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/MigrationUtil.java91
-rw-r--r--plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/ModelLoadHelper.java4
9 files changed, 310 insertions, 764 deletions
diff --git a/plugins/org.eclipse.gmf.common/META-INF/MANIFEST.MF b/plugins/org.eclipse.gmf.common/META-INF/MANIFEST.MF
index 16c77ac74..92affaaac 100644
--- a/plugins/org.eclipse.gmf.common/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.gmf.common/META-INF/MANIFEST.MF
@@ -7,7 +7,7 @@ Bundle-Localization: plugin
Export-Package: org.eclipse.gmf.common,
org.eclipse.gmf.common.codegen,
org.eclipse.gmf.internal.codegen.dispatch;x-friends:="org.eclipse.gmf.codegen,org.eclipse.gmf.graphdef.codegen,org.eclipse.gmf.codegen.lite",
- org.eclipse.gmf.internal.common;x-friends:="org.eclipse.gmf.codegen.edit,org.eclipse.gmf.graphdef.edit,org.eclipse.gmf.map.edit,org.eclipse.gmf.tooldef.edit,org.eclipse.gmf.bridge.trace,org.eclipse.gmf.bridge.ui,org.eclipse.gmf.bridge,org.eclipse.gmf.tests,org.eclipse.gmf.bridge.ui.dashboard,org.eclipse.gmf.codegen.ui,org.eclipse.gmf.codegen.lite.ui",
+ org.eclipse.gmf.internal.common;x-friends:="org.eclipse.gmf.codegen.edit,org.eclipse.gmf.graphdef.edit,org.eclipse.gmf.map.edit,org.eclipse.gmf.tooldef.edit,org.eclipse.gmf.bridge.trace,org.eclipse.gmf.bridge.ui,org.eclipse.gmf.bridge,org.eclipse.gmf.tests,org.eclipse.gmf.bridge.ui.dashboard,org.eclipse.gmf.codegen.ui,org.eclipse.gmf.codegen.lite.ui,org.eclipse.gmf.codegen,org.eclipse.gmf.map",
org.eclipse.gmf.internal.common.codegen;x-friends:="org.eclipse.gmf.codegen,org.eclipse.gmf.graphdef.codegen,org.eclipse.gmf.bridge,org.eclipse.gmf.codegen.lite,org.eclipse.gmf.tests,org.eclipse.gmf.codegen.ui,org.eclipse.gmf.codegen.lite.ui,org.eclipse.gmf.tests.lite,org.eclipse.gmf.graphdef.codegen.ui",
org.eclipse.gmf.internal.common.migrate;x-friends:="org.eclipse.gmf.codegen.ui,org.eclipse.gmf.tests,org.eclipse.gmf.codegen,org.eclipse.gmf.map,org.eclipse.gmf.bridge.ui",
org.eclipse.gmf.internal.common.reconcile;x-friends:="org.eclipse.gmf.tests,org.eclipse.gmf.codegen,org.eclipse.gmf.bridge.ui",
@@ -16,7 +16,7 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.3.0,4.0.0)",
org.eclipse.emf.common.ui;bundle-version="[2.3.0,3.0.0)",
org.eclipse.emf.codegen;bundle-version="[2.3.0,3.0.0)",
org.eclipse.emf.codegen.ecore;bundle-version="[2.3.0,3.0.0)",
- org.eclipse.emf.ecore.xmi;bundle-version="[2.3.0,3.0.0)",
+ org.eclipse.emf.ecore.xmi;bundle-version="[2.3.0,3.0.0)";visibility:=reexport,
org.eclipse.core.resources;bundle-version="[3.3.0,4.0.0)";visibility:=reexport,
org.eclipse.ui.ide;bundle-version="[3.3.0,4.0.0)",
org.eclipse.ui.forms;bundle-version="[3.3.0,4.0.0)",
diff --git a/plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/CompatibleToolResourceFactory.java b/plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/CompatibleToolResourceFactory.java
deleted file mode 100644
index a67fd1f4b..000000000
--- a/plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/CompatibleToolResourceFactory.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2005 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: Radek Dvorak (Borland) - initial API and implementation
- */
-package org.eclipse.gmf.internal.common.migrate;
-
-import org.eclipse.emf.common.util.URI;
-import org.eclipse.emf.ecore.resource.Resource;
-import org.eclipse.gmf.internal.common.ToolingResourceFactory;
-
-
-/**
- * Backward compatible tooling resource factory, creates resource supporting loading of serialized
- * contents of incompatible historical versions of tooling models.
- * <p>
- * The resources from this factory handle backward compatibility as follows:<p>
- * If old model version is recognized and resource is loaded with errors,
- * the loaded resource records a diagnostic indicating old version as possible impact for
- * loading and proposes to run migration.<br>
- * No load-time migration is performed automatically and migration + overwriting the original
- * model resource is an explicit step to be done by the user.<br>
- * <b>Note</b>: Backward incompatibilities may cause throwing runtime exceptions during load operation which
- * is the feature of EMF.
- * <p>
- * For performing in-memory migration at load-time use {@link CompatibleToolResourceFactory.MigrateOnLoad } factory.
- */
-public class CompatibleToolResourceFactory extends ToolingResourceFactory {
-
- /**
- * This variant of factory produce resources which ensures that old version contents
- * is loaded correctly. In case, an obsolete contents is loaded, in-memory migration
- * at load-time is performed and loaded resource reports diagnostic 'migration required'.
- */
- public static class MigrateOnLoad extends ToolingResourceFactory {
-
- public MigrateOnLoad() {
- super();
- }
-
- public Resource createResource(URI uri) {
- return MigrationResource.createCheckAndMigrateOnLoadResource(uri);
- }
- }
-
- public CompatibleToolResourceFactory() {
- super();
- }
-
- public Resource createResource(URI uri) {
- return MigrationResource.createCheckedResource(uri);
- }
-}
diff --git a/plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/FeatureKey.java b/plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/FeatureKey.java
deleted file mode 100644
index 6c80a9c9a..000000000
--- a/plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/FeatureKey.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/**
- * Copyright (c) 2006 Eclipse.org
- *
- * 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: dvorak - initial API and implementation
- */
-package org.eclipse.gmf.internal.common.migrate;
-
-import org.eclipse.emf.ecore.EClass;
-import org.eclipse.emf.ecore.EStructuralFeature;
-
-/**
- * Key class uniquely identifying a structural feature.
- * <p>
- * Motivation: avoid use of object identity based equals(..) for EStructuralFeature.
- */
-public class FeatureKey {
-
- private String namespaceURI;
- private String className;
- private String featureName;
-
- /**
- * Creates uninitialized feature key.
- * <p>
- * Note: It's safe to use {@link #equals(Object)}, {@link #hashCode()} on the created
- * instance. A particular feature can be assigned repeatedly in order to support key
- * instance reuse.
- *
- * @see #setFeature(EStructuralFeature)
- */
- public FeatureKey() {
- }
-
- public static FeatureKey create(EStructuralFeature feature) {
- FeatureKey pair = new FeatureKey();
- pair.setFeature(feature);
- return pair;
- }
-
- public void setFeature(EStructuralFeature feature) {
- EClass eClass = feature.getEContainingClass();
- this.className = (eClass != null) ? eClass.getName() : null;
- this.namespaceURI = (eClass != null && eClass.getEPackage() != null) ? eClass.getEPackage().getNsURI() : null;
- this.featureName = feature.getName();
- }
-
- @Override
- public boolean equals(Object that) {
- FeatureKey another = (FeatureKey) that;
- return (className != null ? className.equals(another.className) : another.className == null) &&
- (featureName != null ? featureName.equals(another.featureName) : another.featureName == null) &&
- (namespaceURI != null ? namespaceURI.equals(another.namespaceURI) : another.namespaceURI == null);
- }
-
- @Override
- public int hashCode() {
- return (className == null ? 0 : className.hashCode()) ^ (featureName == null ? 0 : featureName.hashCode()) ^ (namespaceURI == null ? 0 : namespaceURI.hashCode());
- }
-
- @Override
- public String toString() {
- StringBuffer buf = new StringBuffer();
- buf.append('[').append(namespaceURI).append(']').append(':');
- buf.append(className).append(':').append(featureName);
- return buf.toString();
- }
-} \ No newline at end of file
diff --git a/plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/MigrationConfig.java b/plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/MigrationConfig.java
deleted file mode 100644
index f696e1dce..000000000
--- a/plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/MigrationConfig.java
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Copyright (c) 2006, 2007 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: Radek Dvorak (Borland) - initial API and implementation
- */
-package org.eclipse.gmf.internal.common.migrate;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Set;
-
-import org.eclipse.emf.ecore.EClass;
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.EReference;
-import org.eclipse.emf.ecore.EStructuralFeature;
-import org.eclipse.emf.ecore.resource.Resource;
-import org.eclipse.gmf.internal.common.migrate.MigrationResource.MigrationHandler;
-
-/**
- * This class holds information used for upgrading existing model instance created with
- * older versions of its meta-model.<p>
- * Use {@linkplain MigrationConfig.Registry#INSTANCE} for individual migration config registration.<p>
- * <li>
- * It is assumed that there is only the current (latest) version of the metamodel available in
- * its binary form.</li>
- * <li>
- * Changes described by the config are to be applied to previous versions at loading time,
- * resulting in model instance based on the latest meta-model version.</li>
- */
-public class MigrationConfig {
-
- /**
- * Global registry of GMF meta-models migration configs
- */
- public interface Registry {
- /**
- * Retrieves migration config for the given model file
- *
- * @param extension model filename extension
- * @return migration config or <code>null</code> if no config is registered for
- * this extension
- */
- MigrationConfig getConfig(String extension);
- /**
- * Registers the given descriptor with this registry. If a descriptor for the
- * same file extension already exists, the latter one overrides it.
- *
- * @param descriptor migration config descriptor
- */
- void register(Descriptor descriptor);
-
- /**
- * Global registry instance
- */
- Registry INSTANCE = new RegistryImpl();
- }
-
- /**
- * A wrapper of MigrationConfig for use with {@link MigrationConfig.Registry}.</p>
- * The main purpose of this interface is to enable on demand migration config creation.
- */
- public interface Descriptor {
- /**
- * Get file extension of models for which this descriptor is applicable
- * @return extension string
- */
- String getExtension();
- /**
- * Gets config associated with this descriptor.
- * @return non-null config object
- */
- MigrationConfig getConfig();
- }
-
- // instance fields
- private final String metamodelURI;
- private Set<String> backwardSupportedURIs = Collections.emptySet();
- private final LinkedHashMap<FeatureKey, EClass> addedERefTypes = new LinkedHashMap<FeatureKey, EClass>();
- private final Map<String, Set<EClass>> deletedAttributes = new HashMap<String, Set<EClass>>();
-
-
- /**
- * Constructs migration config for the given metamodel.
- *
- * @param metamodelNsURI namespace URI of the metamodel, migration of which is
- * to be described by this config.
- *
- * @param backwardSupportedURIs set of namespace URIs of previous migratable versions
- */
- public MigrationConfig(String metamodelNsURI, String[] backwardSupportedURIs) {
- if(metamodelNsURI == null) {
- throw new IllegalArgumentException("null metamodel"); //$NON-NLS-1$
- }
- this.metamodelURI = metamodelNsURI;
- for (int i = 0; i < backwardSupportedURIs.length; i++) {
- addBackwardSupportedNsURIs(backwardSupportedURIs[i]);
- }
- }
-
- /**
- * Gets the metamodel namespace URI representing its current version
- * @return the uri string
- */
- public String getMetamodelNsURI() {
- return metamodelURI;
- }
-
- /**
- * Gets namespace URIs of previous metamodel versions which are migratable to its latest state.
- * @return set of URI strings
- */
- public Set<String> backwardSupportedNsURIs() {
- return Collections.unmodifiableSet(backwardSupportedURIs);
- }
-
- /**
- * Avoid "Feature 'name' not found" exception while loading resources with objects holding deleted attributes.
- *
- * <p>Though we could use XMLResource.OPTION_RECORD_UNKNOWN_FEATURE, it seems to have next drawbacks:
- * <ul>
- * <li>it's all-or-nothing approach
- * <li>attributes and values loaded this way will be preserved on save
- * </ul>
- */
- public void registerDeletedAttribute(EClass attributeOwner, String attrName) {
- assert attributeOwner != null && attrName != null;
- Set<EClass> known = deletedAttributes.get(attrName);
- if (known == null) {
- known = new HashSet<EClass>();
- deletedAttributes.put(attrName, known);
- }
- known.add(attributeOwner);
- }
-
- /**
- * Counterpart to {@link #registerDeletedAttribute(EClass, String)} that answers whether
- * this migration config knows attribute with the name passed as an argument as deleted.
- */
- public boolean shouldIgnoreAttribute(EObject object, String attrName) {
- Set<EClass> known = deletedAttributes.get(attrName);
- if (known == null) {
- return false;
- }
- final EClass objClass = object.eClass();
- for (EClass c : known) {
- if (c.isSuperTypeOf(objClass)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Adds reference type narrowing migration patch.<p>
- * Ensures correct type narrowing of previosly saved referenced objects in case of missing
- * xsi/xmi:type info in existing serialized contents.
- * <p>
- * @param reference the current version of migrated EReference in the metamodel.
- * The newly introduced type must be conformant with the old reference type.
- * @param oldReferenceType EClass representing the reference type used in the previous version.
- * It must be a concrete class which is instantiated for old version referenced objects.
- *
- * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=154712
- */
- public void addNarrowReferenceType(EReference reference, EClass oldReferenceType) {
- if(reference == null || oldReferenceType == null) {
- throw new IllegalArgumentException("Null reference or old reference type"); //$NON-NLS-1$
- }
- if(!reference.getEReferenceType().isSuperTypeOf(oldReferenceType) ||
- oldReferenceType.isAbstract() || oldReferenceType.isInterface()) {
- throw new IllegalArgumentException("Non-compliant reference types"); //$NON-NLS-1$
- }
- if(reference.getEReferenceType() == oldReferenceType) {
- throw new IllegalArgumentException("Identical reference types"); //$NON-NLS-1$
- }
- if(addedERefTypes.containsKey(reference)) {
- throw new IllegalArgumentException("Reference already has a migration entry"); //$NON-NLS-1$
- }
- addedERefTypes.put(FeatureKey.create(reference), oldReferenceType);
- }
-
- @Override
- public String toString() {
- return getClass().getSimpleName() + " : " + getMetamodelNsURI();//$NON-NLS-1$
- }
-
- EClass getAddedTypeInfo(FeatureKey reference) {
- return addedERefTypes.get(reference);
- }
-
- private void addBackwardSupportedNsURIs(String nsURI) {
- if(nsURI == null || nsURI.equals(metamodelURI)) {
- throw new IllegalArgumentException();
- }
-
- if(backwardSupportedURIs.isEmpty()) {
- backwardSupportedURIs = new HashSet<String>();
- }
- backwardSupportedURIs.add(nsURI);
- }
-
- protected void handleResourceLoaded(Resource resource, Map<EObject, Map<String, String>> ignoredAttributes) {
- // override
- }
-
- protected boolean handleCreateObject(MigrationHandler handler, EObject peekObject, EStructuralFeature feature) {
- // override
- return false;
- }
-
- protected boolean handleFeature(MigrationHandler handler, String prefix, String name) {
- // override
- return false;
- }
-
- protected boolean setAttribValue(MigrationHandler handler, EObject peekObject, String name, String value) {
- // override
- return false;
- }
-
- /**
- * Migration config registry implementaion.
- */
- private static class RegistryImpl extends HashMap<String, Object> implements Registry {
-
- RegistryImpl() {
- }
-
- public MigrationConfig getConfig(String ext) {
- Object regEntry = get(ext);
- if(regEntry instanceof MigrationConfig) {
- return (MigrationConfig)regEntry;
- }
- else if(regEntry instanceof Descriptor) {
- Descriptor descriptor = (Descriptor)regEntry;
- MigrationConfig migrationConfig = descriptor.getConfig();
- this.put(ext, migrationConfig);
- return migrationConfig;
- }
- return null;
- }
-
- public void register(Descriptor descriptor) {
- if(descriptor == null || descriptor.getExtension() == null) {
- throw new IllegalArgumentException("null extension or descriptor"); //$NON-NLS-1$
- }
- put(descriptor.getExtension(), descriptor);
- }
- }
-
-}
diff --git a/plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/MigrationHelper.java b/plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/MigrationHelper.java
new file mode 100644
index 000000000..69a0f8045
--- /dev/null
+++ b/plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/MigrationHelper.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2007 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: Borland - initial API and implementation
+ */
+package org.eclipse.gmf.internal.common.migrate;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EFactory;
+import org.eclipse.emf.ecore.EObject;
+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.impl.EReferenceImpl;
+import org.eclipse.emf.ecore.xmi.XMLResource;
+import org.eclipse.emf.ecore.xmi.impl.XMIHelperImpl;
+
+public class MigrationHelper extends XMIHelperImpl {
+ private final MigrationHelperDelegate myDelegate;
+ private EStructuralFeature mySavedFeature;
+ private EReferenceImpl myFakeFeatureWithNarrowType;
+
+ public MigrationHelper(XMLResource resource, MigrationHelperDelegate delegate) {
+ super(resource);
+ assert delegate != null;
+ myDelegate = delegate;
+ }
+
+ public static class MigrationHelperDelegateImpl implements MigrationHelperDelegate {
+
+ public MigrationHelperDelegateImpl() {
+ super();
+ }
+
+ private static EStructuralFeature ourDeletedAttribute = EcoreFactory.eINSTANCE.createEAttribute();
+ static {
+ ourDeletedAttribute.setName("attributeIsDeleted"); //$NON-NLS-1$
+ ourDeletedAttribute.setEType(EcorePackage.eINSTANCE.getEString());
+ }
+
+ private Map<EClassifier, Collection<String>> myDeletedAttributes = new HashMap<EClassifier, Collection<String>>();
+ private Map<EReference, EClass> myNarrowReferenceTypes = new HashMap<EReference, EClass>();
+ private Map<EClass, Map<String, EStructuralFeature>> myRenamedAttributes = new HashMap<EClass, Map<String, EStructuralFeature>>();
+ private Map<String, EClassifier> myRenamedTypes = new HashMap<String, EClassifier>();
+
+ public void registerDeletedAttributes(EClassifier classifier, String... deletedAttrNames) {
+ assert !myDeletedAttributes.containsKey(classifier);
+ myDeletedAttributes.put(classifier, Arrays.asList(deletedAttrNames));
+ }
+
+ public void registerNarrowReferenceType(EReference reference, EClass concreteType) {
+ myNarrowReferenceTypes.put(reference, concreteType);
+ }
+
+ public void registerRenamedAttributes(EClass eClass, Map<String, EStructuralFeature> renamedAttributes) {
+ myRenamedAttributes.put(eClass, renamedAttributes);
+ }
+
+ public void registerRenamedType(String oldTypeName, EClassifier newType) {
+ myRenamedTypes.put(oldTypeName, newType);
+ }
+
+ public void registerRenamedAttribute(EClass eClass, String oldName, EStructuralFeature newStructuralFeature) {
+ Map<String, EStructuralFeature> renamedAttributes = myRenamedAttributes.get(eClass);
+ if (renamedAttributes == null) {
+ renamedAttributes = new HashMap<String, EStructuralFeature>();
+ }
+ renamedAttributes.put(oldName, newStructuralFeature);
+ registerRenamedAttributes(eClass, renamedAttributes);
+ }
+
+ public boolean isAttributeDeleted(EClass clazz, String name) {
+ Collection<String> deletedAttributes = myDeletedAttributes.get(clazz);
+ boolean result = deletedAttributes != null && deletedAttributes.contains(name);
+ for (Iterator<EClass> it=clazz.getEAllSuperTypes().iterator(); !result && it.hasNext();) {
+ EClass nextParent = it.next();
+ result = isAttributeDeleted(nextParent, name);
+ }
+ return result;
+ }
+
+ public EClass getNarrowReferenceType(EStructuralFeature feature) {
+ return myNarrowReferenceTypes.get(feature);
+ }
+
+ public EStructuralFeature getRenamedFeatureFor(EClass clazz, String name) {
+ Map<String, EStructuralFeature> renamings = myRenamedAttributes.get(clazz);
+ EStructuralFeature result = renamings != null ? renamings.get(name) : null;
+ for (Iterator<EClass> it=clazz.getEAllSuperTypes().iterator(); result == null && it.hasNext();) {
+ EClass nextParent = it.next();
+ result = getRenamedFeatureFor(nextParent, name);
+ }
+ return result;
+ }
+
+ public EClassifier getRenamedType(String typeName) {
+ return myRenamedTypes.get(typeName);
+ }
+
+ public EClass getStructuralFeatureType(EStructuralFeature feature) {
+ return getNarrowReferenceType(feature);
+ }
+
+ public boolean setValue(EObject object, EStructuralFeature feature, Object value, int position) {
+ return ourDeletedAttribute.equals(feature);
+ }
+
+ public EStructuralFeature getFeature(EClass eClass, String namespaceURI, String name, boolean isElement) {
+ EStructuralFeature result = null;
+ EStructuralFeature rename = null;
+ if (isAttributeDeleted(eClass, name)) {
+ result = ourDeletedAttribute;
+ } else if ((rename = getRenamedFeatureFor(eClass, name)) != null) {
+ result = rename;
+ }
+ return result;
+ }
+
+ public EClassifier getType(EFactory factory, String typeName) {
+ EClassifier result = null;
+ EClassifier type = getRenamedType(typeName);
+ if (type != null) {
+ result = type;
+ }
+ return result;
+ }
+
+ public EObject createObject(EFactory factory, EClassifier type) {
+ return null;
+ }
+
+ public void postProcess() {
+ }
+
+ public void processObject(EObject result) {
+ }
+ }
+
+ public EObject createObject(EFactory factory, EClassifier type) {
+ EObject result = myDelegate.createObject(factory, type);
+ if (result == null) {
+ result = super.createObject(factory, type);
+ }
+ myDelegate.processObject(result);
+ return result;
+ }
+
+ public void setValue(EObject object, EStructuralFeature feature, Object value, int position) {
+ if (feature != null && feature.equals(myFakeFeatureWithNarrowType)) {
+ feature = mySavedFeature;
+ }
+ if (!myDelegate.setValue(object, feature, value, position)) {
+ super.setValue(object, feature, value, position);
+ }
+ }
+
+ public EStructuralFeature getFeature(EClass eClass, String namespaceURI, String name, boolean isElement) {
+ EStructuralFeature result = myDelegate.getFeature(eClass, namespaceURI, name, isElement);
+ if (result == null) {
+ result = super.getFeature(eClass, namespaceURI, name);
+ }
+ EClass narrow = myDelegate.getStructuralFeatureType(result);
+ if (narrow != null) {
+ mySavedFeature = result;
+ myFakeFeatureWithNarrowType = new EReferenceImpl() {};
+ myFakeFeatureWithNarrowType.setName(result.getName());
+ myFakeFeatureWithNarrowType.setEType(narrow);
+ return myFakeFeatureWithNarrowType;
+ }
+ return result;
+ }
+
+ public EClassifier getType(EFactory factory, String typeName) {
+ EClassifier result = myDelegate.getType(factory, typeName);
+ if (result == null) {
+ result = super.getType(factory, typeName);
+ }
+ return result;
+ }
+
+ public void popContext() {
+ myDelegate.postProcess();
+ }
+}
diff --git a/plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/MigrationHelperDelegate.java b/plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/MigrationHelperDelegate.java
new file mode 100644
index 000000000..4c63f0b38
--- /dev/null
+++ b/plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/MigrationHelperDelegate.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2007 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: Borland - initial API and implementation
+ */
+package org.eclipse.gmf.internal.common.migrate;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EFactory;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+
+public interface MigrationHelperDelegate {
+
+ public boolean setValue(EObject object, EStructuralFeature feature, Object value, int position);
+
+ public EStructuralFeature getFeature(EClass eClass, String namespaceURI, String name, boolean isElement);
+
+ public EClassifier getType(EFactory factory, String typeName);
+
+ public EClass getStructuralFeatureType(EStructuralFeature feature);
+
+ public EObject createObject(EFactory factory, EClassifier type);
+
+ public void postProcess();
+
+ public void processObject(EObject result);
+}
diff --git a/plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/MigrationResource.java b/plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/MigrationResource.java
index 67adbb2e6..5f494b1fa 100644
--- a/plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/MigrationResource.java
+++ b/plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/MigrationResource.java
@@ -6,21 +6,18 @@
* accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
- * Contributors: Radek Dvorak (Borland) - initial API and implementation
+ * Contributors:
+ * Borland - initial API and implementation
*/
package org.eclipse.gmf.internal.common.migrate;
import java.io.IOException;
import java.io.InputStream;
-import java.util.HashMap;
+import java.util.Collection;
import java.util.Map;
import org.eclipse.emf.common.util.URI;
-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.resource.Resource;
import org.eclipse.emf.ecore.xmi.XMLHelper;
import org.eclipse.emf.ecore.xmi.XMLLoad;
@@ -29,318 +26,116 @@ import org.eclipse.emf.ecore.xmi.impl.XMILoadImpl;
import org.eclipse.gmf.internal.common.ToolingResourceFactory.ToolResource;
import org.xml.sax.helpers.DefaultHandler;
-/**
- * This resource implementation is intended to handle loading of old (incompatible) versions
- * of tooling models.
- * <p>
- * This class makes use of {@link MigrationConfig.Registry#INSTANCE} end performs load-time migration
- * in case that there is a migration config registered for the resource to load.
- *
- * @see MigrationConfig
- */
-public class MigrationResource extends ToolResource {
-
- protected boolean oldVersionDetected;
- protected boolean migrationApplied;
- private Map<EObject, Map<String, String>> ignoredAttributes;
- private MigrationConfig config;
-
- MigrationResource(URI uri) {
- super(uri);
- }
+public abstract class MigrationResource extends ToolResource {
- /*
- * Create XMLLoad which handles old model migration at load-time
- * @see org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl#createXMLLoad()
- */
- protected XMLLoad createXMLLoad() {
- return new XMILoadImpl(createXMLHelper()) {
+ private boolean isOldVersionDetected;
- protected DefaultHandler makeDefaultHandler() {
- return new MigrationHandler(MigrationResource.this, helper, options);
- }
- };
- }
-
- protected final void doUnload() {
- try {
- super.doUnload();
- } finally {
- this.oldVersionDetected = false;
- this.migrationApplied = false;
- }
+ protected MigrationResource(URI uri) {
+ super(uri);
}
+ @Override
public final void doLoad(InputStream inputStream, Map<?,?> options) throws IOException {
try {
- ignoredAttributes = new HashMap<EObject, Map<String, String>>();
+ isOldVersionDetected = false;
super.doLoad(inputStream, options);
- handlePostLoad(null);
+ handlePostLoadSuccess();
} catch (IOException e) {
- handlePostLoad(e);
+ handlePostLoadException(e);
throw e;
} catch (RuntimeException e) {
- handlePostLoad(e);
+ handlePostLoadException(e);
throw e;
- } finally {
- ignoredAttributes = null;
- config = null;
}
}
- /**
- * Called back if nsURI of old version is recognized during resource load.
- */
- protected void handleOldVersionDetected() {
- this.oldVersionDetected = true;
- }
-
- /**
- * Called back at load-time in case an incompatible model construct required migration.
- */
- protected void handleMigrationPatchApplied() {
- this.migrationApplied = true;
- }
-
- /**
- * Called back after resource load finished.
- * @param exception the exception thrown during {@link #doLoad(InputStream, Map)} or
- * <code>null</code> in case of load success.
- */
- protected void handlePostLoad(Exception exception) {
- if (exception == null && config != null) {
- config.handleResourceLoaded(this, ignoredAttributes);
- }
- }
+ @Override
+ protected XMLLoad createXMLLoad() {
+ return new XMILoadImpl(createXMLHelper()) {
- /**
- * Creates resource which checks for and reports incompatible model version
- * in case that resource load fails.
- *
- * @param uri the resource uri
- *
- * @return resource object in unloaded state
- */
- static Resource createCheckedResource(URI uri) {
- return new MigrationResource(uri) {
-
- protected XMLLoad createXMLLoad() {
- final MigrationResource res = this;
- return new XMILoadImpl(createXMLHelper()) {
- protected DefaultHandler makeDefaultHandler() {
- return new BCKWDCompatibleHandler(res, helper, options);
+ @Override
+ protected DefaultHandler makeDefaultHandler() {
+ return new SAXXMIHandler(resource, helper, options) {
+ @Override
+ protected EPackage getPackageForURI(String uriString) {
+ // FIXME move the check to delegate
+ if (!getMetamodelNsURI().equals(uriString) && getBackwardSupportedURIs().contains(uriString)) {
+ handleOldVersionDetected();
+ return super.getPackageForURI(getMetamodelNsURI());
+ }
+ return super.getPackageForURI(uriString);
}
};
}
-
- protected void handlePostLoad(Exception exception) {
- super.handlePostLoad(exception);
- // if old model version is loaded, check if any problems during resource load have occured
- // if yes, report an old version load attempt
- // otherwise, the resource happens to have no incompatible contents
- if(oldVersionDetected && exception != null || !getErrors().isEmpty() || !getWarnings().isEmpty()) {
- Diagnostic diagnostic = MigrationUtil.createMessageDiagnostic(this, Messages.oldModelVersionLoadErrorMigrationMayBeRequired);
- getErrors().add(0, diagnostic);
- }
- }
};
}
-
- /**
- * Creates resource which performs only in-memory migration of old model versions at load-time
- * and reports migration diagnostic.
- *
- * @param uri the resource uri
- * @return resource object in unloaded state
- */
- static Resource createCheckAndMigrateOnLoadResource(URI uri) {
- return new MigrationResource(uri) {
- protected void handlePostLoad(Exception exception) {
- super.handlePostLoad(exception);
- if(this.oldVersionDetected && migrationApplied) {
- Diagnostic diagnostic = MigrationUtil.createMessageDiagnostic(this, Messages.oldModelVersionLoadedMigrationRequired);
- getWarnings().add(0, diagnostic);
- }
- }
- };
- }
- /**
- * Handles detection of loaded model nsURI and checks if an old model version is to be loaded.
- */
- private static class BCKWDCompatibleHandler extends SAXXMIHandler {
- MigrationConfig config;
- protected boolean fixmePotentiallyCompatibilityIssues;
+ private void handleOldVersionDetected() {
+ isOldVersionDetected = true;
+ }
- BCKWDCompatibleHandler(MigrationResource xmiResource, XMLHelper helper, Map<?, ?> options) {
- super(xmiResource, helper, options);
+ protected void handlePostLoadSuccess() {
+ if (isOldVersionDetected) {
+ Diagnostic diagnostic = MigrationResource.createMessageDiagnostic(this, Messages.oldModelVersionLoadedMigrationRequired);
+ getWarnings().add(0, diagnostic);
}
+ }
- /*
- * Detects if and old version of model is to be loaded
- */
- @Override
- protected EPackage getPackageForURI(String uriString) {
- if(config == null) {
- // Remark: ensure that GMF meta-models generated packages are initialized before accessing
- // MigrationConfig.Registry, as a migrated package initialization code performs the migration config
- // registration.
- // TODO - better to use extension point for migration config registry
- EPackage.Registry.INSTANCE.getEPackage(uriString);
-
- String ext = xmlResource.getURI().fileExtension();
- config = (ext != null) ? MigrationConfig.Registry.INSTANCE.getConfig(ext) : null;
- resource().config = config;
- }
-
- if(config != null) {
- if(!config.getMetamodelNsURI().equals(uriString) &&
- config.backwardSupportedNsURIs().contains(uriString)) {
- resource().handleOldVersionDetected();
-
- return super.getPackageForURI(config.getMetamodelNsURI());
- }
- if (config.getMetamodelNsURI().equals(uriString)) {
- // assume new version always needs migration, at least between milestones
- // FIXME better detection algorithm
- // FIXME delete this code after genmodel freeze in 2.0
- fixmePotentiallyCompatibilityIssues = true;
- }
- }
+ protected void handlePostLoadException(Exception e) {
+ Diagnostic diagnostic = MigrationResource.createMessageDiagnostic(this, Messages.oldModelVersionLoadErrorMigrationMayBeRequired);
+ getErrors().add(0, diagnostic);
+ }
- return super.getPackageForURI(uriString);
- }
+ @Override
+ protected XMLHelper createXMLHelper() {
+ MigrationHelperDelegate delegate = createDelegate();
+ assert delegate != null;
+ return new MigrationHelper(this, delegate);
+ }
+
+ protected abstract Collection<String> getBackwardSupportedURIs();
+ protected abstract MigrationHelperDelegate createDelegate();
+ protected abstract String getMetamodelNsURI();
- @Override
- protected void handleUnknownFeature(String prefix, String name, boolean isElement, EObject peekObject, String value) {
- if (fixmePotentiallyCompatibilityIssues) {
- if (config.shouldIgnoreAttribute(peekObject, name)) {
- resource().handleOldVersionDetected();
- }
- }
- super.handleUnknownFeature(prefix, name, isElement, peekObject, value);
- }
-
- MigrationResource resource() {
- assert xmlResource instanceof MigrationResource;
- return (MigrationResource)xmlResource;
- }
- };
/**
- * Handler performing migration changes at load-time
+ * Creates resource diagnostic wrapping the given message.
+ * @param resource the resource associated with the created diagnostic
+ * @param message non-<code>null</code> message text to be wrapped as diagnostic
+ *
+ * @return diagnostic object
*/
- public static class MigrationHandler extends BCKWDCompatibleHandler {
-
- private FeatureKey processedFeatureKey;
-
- MigrationHandler(MigrationResource resource, XMLHelper helper, Map<?, ?> options) {
- super(resource, helper, options);
- this.processedFeatureKey = new FeatureKey();
- }
-
- @Override
- protected void setAttribValue(EObject object, String name, String value) {
- if ((isMigrationEnabled() || fixmePotentiallyCompatibilityIssues)) {
- if (config.setAttribValue(this, object, name, value)) {
- notifyMigrationApplied();
- return;
- }
- if (config.shouldIgnoreAttribute(object, name)) {
- Map<EObject, Map<String, String>> ignoredAttributes = resource().ignoredAttributes;
- if (ignoredAttributes != null) {
- Map<String, String> attrs = ignoredAttributes.get(object);
- if (attrs == null) {
- attrs = new HashMap<String, String>();
- ignoredAttributes.put(object, attrs);
- }
- attrs.put(name, value);
- }
- notifyMigrationApplied(); // notify we had to migrate
- return; // do not try to set value
- }
- }
- super.setAttribValue(object, name, value);
- }
+ private static Diagnostic createMessageDiagnostic(Resource resource, final String message) {
+ final String location = resource.getURI() == null ? null : resource.getURI().toString();
+ return new Diagnostic(message, location);
+ }
- @Override
- protected void createObject(EObject peekObject, EStructuralFeature feature) {
- if(isMigrationEnabled()) {
- if (config.handleCreateObject(this, peekObject, feature)) {
- notifyMigrationApplied();
- return;
- }
- processedFeatureKey.setFeature(feature);
- if(getXSIType() == null && feature instanceof EReference) {
- // adding xsi/xmi:type
- // @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=154712
- EClass oldDefaultRefType = (config != null) ? config.getAddedTypeInfo(processedFeatureKey) : null;
-
- if(oldDefaultRefType != null) {
- String typeQName = helper.getQName(oldDefaultRefType);
- super.createObjectFromTypeName(peekObject, typeQName, feature);
- // notify resource that a migration was neccessary
- notifyMigrationApplied();
- return;
- }
- }
- } // end of migration
- super.createObject(peekObject, feature);
- }
+ /**
+ * Just a marker for diagnostic notification messages
+ */
+ public static class Diagnostic implements Resource.Diagnostic {
+ private final String myMessage;
+ private final String myLocation;
- @Override
- protected void handleFeature(String prefix, String name) {
- if (isMigrationEnabled()) {
- if (config.handleFeature(this, prefix, name)) {
- notifyMigrationApplied();
- return;
- }
- }
- super.handleFeature(prefix, name);
- }
-
- /**
- * Make public for access from config.
- */
- public EObject createObjectFromTypeNameHook(EObject peekObject, String typeQName, EStructuralFeature feature) {
- return super.createObjectFromTypeName(peekObject, typeQName, feature);
+ Diagnostic(String message, String location) {
+ myMessage = message;
+ myLocation = location;
}
- /**
- * Make public for access from config.
- */
- public void handleFeatureHook(String prefix, String name) {
- super.handleFeature(prefix, name);
- }
+ public String getMessage() {
+ return myMessage;
+ }
- /**
- * Make public for access from config.
- */
- public String getXSIType() {
- return super.getXSIType();
+ public String getLocation() {
+ return myLocation;
}
- /**
- * Make public for access from config.
- */
- public EObject peekEObject() {
- return objects.peekEObject();
+ public int getColumn() {
+ return 0;
}
- private boolean isMigrationEnabled() {
- return config != null && resource().oldVersionDetected;
- }
-
- /**
- * To be called if a migration patch had to be applied to load model successfully.
- * <p>
- * Note: It's important in order to detect whether an old model version which
- * was loaded contained incompatible constructs. No diagnostics are produced
- * for old version models with compatible contents.
- */
- private void notifyMigrationApplied() {
- resource().handleMigrationPatchApplied();
+ public int getLine() {
+ return 0;
}
}
-
}
diff --git a/plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/MigrationUtil.java b/plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/MigrationUtil.java
deleted file mode 100644
index e1e40c790..000000000
--- a/plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/MigrationUtil.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2005 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: Radek Dvorak (Borland) - initial API and implementation
- */
-package org.eclipse.gmf.internal.common.migrate;
-
-import org.eclipse.emf.common.util.URI;
-import org.eclipse.emf.ecore.resource.Resource;
-import org.eclipse.emf.ecore.resource.Resource.Factory;
-import org.eclipse.emf.ecore.resource.impl.ResourceFactoryRegistryImpl;
-import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
-import org.eclipse.gmf.internal.common.ToolingResourceFactory;
-
-/**
- * Utility class providing model migration related functionality.
- */
-public class MigrationUtil {
-
- private MigrationUtil() {
- }
-
- /**
- * Creates and loads the given resource and forces migration to be performed at load-time.<p>
- * <code>Note:</code>No runtime exception is thrown, all detected problems are recorded
- * as {@link Resource.Diagnostic}.
- *
- * @param modelResourceURI the resource uri containing the model to migrate
- *
- * @return model-load-helper encapsulating the resource and its in-memory migrated contents.
- */
- public static ModelLoadHelper migrateModel(URI modelResourceURI) {
- if(modelResourceURI == null) {
- throw new IllegalArgumentException("null resource uri"); //$NON-NLS-1$
- }
- ResourceSetImpl rset = new ResourceSetImpl();
- rset.setResourceFactoryRegistry(new ResourceFactoryRegistryImpl() {
- public Factory getFactory(URI uri) {
- return new ToolingResourceFactory() {
- public Resource createResource(URI uri) {
- return new MigrationResource(uri);
- }
- };
- }
- });
-
- ModelLoadHelper loadHelper = new ModelLoadHelper(rset, modelResourceURI);
- return loadHelper;
- }
-
- /**
- * Creates resource diagnostic wrapping the given message.
- * @param resource the resource associated with the created diagnostic
- * @param message non-<code>null</code> message text to be wrapped as diagnostic
- *
- * @return diagnostic object
- */
- public static MigrationDiagnostic createMessageDiagnostic(Resource resource, final String message) {
- final String location = resource.getURI() == null ? null : resource.getURI().toString();
- return new MigrationDiagnostic() {
-
- public String getMessage() {
- return message;
- }
-
- public String getLocation() {
- return location;
- }
-
- public int getColumn() {
- return 0;
- }
-
- public int getLine() {
- return 0;
- }
- };
- }
-
- /**
- * Just a marker interface for diagnostic notification messages
- */
- public interface MigrationDiagnostic extends Resource.Diagnostic {
- }
-}
-
diff --git a/plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/ModelLoadHelper.java b/plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/ModelLoadHelper.java
index c39ade4e1..096236c2b 100644
--- a/plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/ModelLoadHelper.java
+++ b/plugins/org.eclipse.gmf.common/src/org/eclipse/gmf/internal/common/migrate/ModelLoadHelper.java
@@ -1,5 +1,5 @@
-/**
- * Copyright (c) 2006 Eclipse.org
+/*
+ * 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

Back to the top