Skip to content
Snippets Groups Projects
Commit a776c0b1 authored by Vincent Aravantinos's avatar Vincent Aravantinos
Browse files

Implemented issue 1943

refs 1943
parent 7c4605fd
No related branches found
No related tags found
No related merge requests found
Showing
with 122 additions and 26 deletions
......@@ -19,6 +19,10 @@ package org.fortiss.tooling.base.migration;
import static org.fortiss.tooling.kernel.utils.UniqueIDUtils.hasMissingIDs;
import java.util.Map;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.xml.type.AnyType;
import org.fortiss.tooling.kernel.extension.IMigrationProvider;
import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
import org.fortiss.tooling.kernel.utils.UniqueIDUtils;
......@@ -28,13 +32,14 @@ import org.fortiss.tooling.kernel.utils.UniqueIDUtils;
* @author Shaka
* @author $Author: hoelzl $
* @version $Rev: 18709 $
* @ConQAT.Rating RED Hash:
* @ConQAT.Rating YELLOW Hash: DB938B8077EEAFB9455F8A83BF92CD86
*/
public class IDMigrationProvider implements IMigrationProvider {
/** {@inheritDoc} */
@Override
public boolean needMigration(ITopLevelElement modelElement) {
public boolean needMigration(ITopLevelElement modelElement,
Map<EObject, AnyType> unknownFeatures) {
// if the id of model element is 0
if(modelElement != null && modelElement.getRootModelElement() != null &&
hasMissingIDs(modelElement.getRootModelElement())) {
......@@ -45,7 +50,7 @@ public class IDMigrationProvider implements IMigrationProvider {
/** {@inheritDoc} */
@Override
public void migrate(ITopLevelElement modelElement) {
public void migrate(ITopLevelElement modelElement, Map<EObject, AnyType> unknownFeatures) {
UniqueIDUtils.fixMissingIDs(modelElement);
}
......
......@@ -17,6 +17,10 @@ $Id$
+--------------------------------------------------------------------------*/
package org.fortiss.tooling.kernel.extension;
import java.util.Map;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.xml.type.AnyType;
import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
import org.fortiss.tooling.kernel.service.IMigrationService;
import org.fortiss.tooling.kernel.service.base.IObjectAware;
......@@ -29,16 +33,31 @@ import org.fortiss.tooling.kernel.service.base.IObjectAware;
* @author mou
* @author $Author$
* @version $Rev$
* @ConQAT.Rating GREEN Hash: 644590FDA54780140699CE0595DCC8B2
* @ConQAT.Rating YELLOW Hash: 27DD99D2F4AB22CA803D51E3D356AB93
*/
public interface IMigrationProvider extends IObjectAware<ITopLevelElement> {
/**
* Determines whether migration provider is needed for the given
* model element.
*
* The parameter "unknownFeatures" returns a map indicating the features that are not recognized
* in the model.
* This can be useful to detect features coming from old models and can be then translated to
* the new model by the migrator.
*/
boolean needMigration(ITopLevelElement modelElement);
boolean needMigration(ITopLevelElement modelElement, Map<EObject, AnyType> unknownFeatures);
/** Applies the provider to the given element. */
void migrate(ITopLevelElement modelElement);
/**
* Applies the provider to the given element.
*
* The parameter "unknownFeatures" returns a map indicating the features that are not recognized
* in the model.
* This can be useful to detect features coming from old models and can be then translated to
* the new model by the migrator.
*
* The migrator should remove from unknownFeatures the features that it dealt with.
* If one forgets to do so, the migrator will run into an infinite loop!
*/
void migrate(ITopLevelElement modelElement, Map<EObject, AnyType> unknownFeatures);
}
......@@ -17,7 +17,13 @@ $Id$
+--------------------------------------------------------------------------*/
package org.fortiss.tooling.kernel.internal;
import static org.fortiss.tooling.kernel.utils.MigrationUtils.featuresToStrings;
import java.util.Map;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.xml.type.AnyType;
import org.fortiss.tooling.kernel.ToolingKernelActivator;
import org.fortiss.tooling.kernel.extension.IMigrationProvider;
import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
......@@ -31,7 +37,7 @@ import org.fortiss.tooling.kernel.utils.LoggingUtils;
* @author mou
* @author $Author$
* @version $Rev$
* @ConQAT.Rating GREEN Hash: 84ED0C27EA5D8E9F603E63E935263B3B
* @ConQAT.Rating YELLOW Hash: D41B3F3BD99B6BC9ECA3F6B4B795A807
*/
public class MigrationService extends ObjectAwareServiceBase<IMigrationProvider> implements
IMigrationService {
......@@ -48,21 +54,25 @@ public class MigrationService extends ObjectAwareServiceBase<IMigrationProvider>
/** {@inheritDoc} */
@Override
public boolean needMigration(ITopLevelElement input) {
return getProvider(input) != null;
public boolean needMigration(ITopLevelElement input, Map<EObject, AnyType> unknownFeatures) {
return(getProvider(input, unknownFeatures) != null);
}
/** {@inheritDoc} */
@Override
public void migrate(final ITopLevelElement input) {
public void migrate(final ITopLevelElement input, final Map<EObject, AnyType> unknownFeatures) {
input.runAsCommand(new Runnable() {
@Override
public void run() {
IMigrationProvider provider;
while(null != (provider = getProvider(input))) {
provider.migrate(input);
while(null != (provider = getProvider(input, unknownFeatures))) {
provider.migrate(input, unknownFeatures);
}
if(unknownFeatures.size() >= 1)
throw new RuntimeException(input.getSaveableName() +
" contains one or more unknown feature(s): " +
featuresToStrings(unknownFeatures));
}
});
......@@ -80,9 +90,10 @@ public class MigrationService extends ObjectAwareServiceBase<IMigrationProvider>
}
/** get the suitable provider for the input */
private IMigrationProvider getProvider(ITopLevelElement input) {
private IMigrationProvider getProvider(ITopLevelElement input,
Map<EObject, AnyType> unknownFeatures) {
for(IMigrationProvider provider : getAllHandlers()) {
if(provider.needMigration(input)) {
if(provider.needMigration(input, unknownFeatures)) {
return provider;
}
}
......
......@@ -65,7 +65,7 @@ import org.osgi.framework.Bundle;
* @author hoelzl
* @author $Author$
* @version $Rev$
* @ConQAT.Rating GREEN Hash: C5A912CC95063A2054B6DB8630092D59
* @ConQAT.Rating YELLOW Hash: 92AA964C5B5676011D12861C0412C980
*/
public class EclipseResourceStorageProvider implements IEclipseResourceStorageService,
IResourceChangeListener, IResourceDeltaVisitor, IStorageProvider {
......@@ -220,7 +220,6 @@ public class EclipseResourceStorageProvider implements IEclipseResourceStorageSe
ModelContext mc = new ModelContext(file);
loadedContexts.put(file, mc);
rootElementContexts.put(mc.getRootModelElement(), mc);
postLoadContext(mc);
} catch(Exception ioex) {
String msg = "Exception while loading model file: " + file.getName();
......@@ -231,8 +230,8 @@ public class EclipseResourceStorageProvider implements IEclipseResourceStorageSe
/** Post-actions after loading a model context */
private void postLoadContext(ModelContext mc) {
if(IMigrationService.INSTANCE.needMigration(mc)) {
IMigrationService.INSTANCE.migrate(mc);
if(IMigrationService.INSTANCE.needMigration(mc, mc.getUnknownFeatures())) {
IMigrationService.INSTANCE.migrate(mc, mc.getUnknownFeatures());
}
}
......
......@@ -25,9 +25,11 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.EventObject;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
......@@ -40,6 +42,8 @@ import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.xmi.XMIResource;
import org.eclipse.emf.ecore.xml.type.AnyType;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.fortiss.tooling.kernel.ToolingKernelActivator;
import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
......@@ -54,7 +58,7 @@ import org.fortiss.tooling.kernel.utils.UniqueIDUtils;
* @author hummel
* @author $Author$
* @version $Rev$
* @ConQAT.Rating GREEN Hash: 88E97F37C63D306BDBFFB77CC88BB853
* @ConQAT.Rating YELLOW Hash: A7B00E66E3893E14F4097D435147ACFC
*/
class ModelContext implements ITopLevelElement, CommandStackListener {
......@@ -82,6 +86,13 @@ class ModelContext implements ITopLevelElement, CommandStackListener {
/** The maximal ID used in this model (used to generate new IDs). */
private int maxId = -1;
/**
* The map containing the unknown features. Can be non-empty, in which case the migrators have
* to deal with it.
* Only if they don't the model context is buggy.
*/
private Map<EObject, AnyType> unknownFeatures;
/** Constructor. */
/* package */ModelContext(IFile file) throws IOException {
this.file = file;
......@@ -93,6 +104,9 @@ class ModelContext implements ITopLevelElement, CommandStackListener {
getResourceSet().createResource(
URI.createPlatformResourceURI(file.getFullPath().toString(), true));
resource.load(buildOptionsMap());
unknownFeatures =
resource instanceof XMIResource ? ((XMIResource)resource)
.getEObjectToExtensionMap() : new HashMap<EObject, AnyType>();
transactionalCommandStack = new AutoUndoCommandStack(editingDomain);
transactionalCommandStack.addCommandStackListener(this);
......@@ -355,4 +369,9 @@ class ModelContext implements ITopLevelElement, CommandStackListener {
public ResourceSet getResourceSet() {
return rset;
}
/** Returns unknownFeatures. */
public Map<EObject, AnyType> getUnknownFeatures() {
return unknownFeatures;
}
}
......@@ -17,6 +17,10 @@ $Id$
+--------------------------------------------------------------------------*/
package org.fortiss.tooling.kernel.service;
import java.util.Map;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.xml.type.AnyType;
import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
import org.fortiss.tooling.kernel.internal.MigrationService;
......@@ -26,7 +30,7 @@ import org.fortiss.tooling.kernel.internal.MigrationService;
* @author mou
* @author $Author$
* @version $Rev$
* @ConQAT.Rating GREEN Hash: 479B525CFD483D015D1EFD646969F24B
* @ConQAT.Rating YELLOW Hash: 9275EB22F8F3218FC5A0BA636584B46F
*/
public interface IMigrationService {
......@@ -34,8 +38,8 @@ public interface IMigrationService {
public static final IMigrationService INSTANCE = new MigrationService();
/** Checks whether the migration is needed. */
public boolean needMigration(ITopLevelElement input);
public boolean needMigration(ITopLevelElement input, Map<EObject, AnyType> unknownFeatures);
/** Performs the migration for the given input. */
public void migrate(ITopLevelElement input);
public void migrate(ITopLevelElement input, Map<EObject, AnyType> unknownFeatures);
}
......@@ -21,13 +21,16 @@ import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.conqat.lib.commons.collections.Pair;
import org.eclipse.core.resources.IFile;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
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.xmi.XMIResource;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.ecore.xml.type.AnyType;
import org.fortiss.tooling.kernel.ToolingKernelActivator;
/**
......@@ -66,6 +69,7 @@ public final class EMFResourceUtils {
public static Map<String, Object> buildOptionsMap() {
Map<String, Object> options = new HashMap<String, Object>();
options.put(XMLResource.OPTION_ENCODING, "UTF-8");
options.put(XMLResource.OPTION_RECORD_UNKNOWN_FEATURE, true);
options.put(Resource.OPTION_ZIP, false);
return options;
}
......@@ -78,17 +82,33 @@ public final class EMFResourceUtils {
* the resource URI
* @return the root {@link EObject}
*/
public static EObject loadModelFromFile(URI uri) {
public static Pair<EObject, Map<EObject, AnyType>>
loadModelFromFileWithUnknownFeatures(URI uri) {
try {
ResourceSet rset = new ResourceSetImpl();
Resource r;
r = rset.createResource(uri);
r.load(EMFResourceUtils.buildOptionsMap());
return r.getContents().get(0);
Map<EObject, AnyType> unknownFeatures =
r instanceof XMIResource ? ((XMIResource)r).getEObjectToExtensionMap()
: new HashMap<EObject, AnyType>();
return new Pair<EObject, Map<EObject, AnyType>>(r.getContents().get(0), unknownFeatures);
} catch(IOException ex) {
LoggingUtils.error(ToolingKernelActivator.getDefault(), "Failed to load model from " +
uri.toString(), ex);
}
return null;
}
/**
* Loads the root model element from the given URI. Logs errors to the
* console and returns <code>null</code>.
*
* @param uri
* the resource URI
* @return the root {@link EObject}
*/
public static EObject loadModelFromFile(URI uri) {
return loadModelFromFileWithUnknownFeatures(uri).getFirst();
}
}
......@@ -19,9 +19,15 @@ package org.fortiss.tooling.kernel.utils;
import static org.fortiss.tooling.kernel.utils.EcoreUtils.getChildrenWithType;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.util.FeatureMap;
import org.eclipse.emf.ecore.xml.type.AnyType;
/**
* Utility methods for the migrators.
......@@ -29,7 +35,7 @@ import org.eclipse.emf.ecore.util.EcoreUtil;
* @author SVoss
* @author $Author$
* @version $Rev$
* @ConQAT.Rating GREEN Hash: C59C0D2AC819F4A8595D75F556B8E050
* @ConQAT.Rating YELLOW Hash: FFB94099E84BD8C3E5B44CE007CF6EDE
*/
public class MigrationUtils {
......@@ -49,4 +55,17 @@ public class MigrationUtils {
EcoreUtil.delete(obj);
}
}
/** Extract the list of feature names from a map of features. */
public static List<String> featuresToStrings(Map<EObject, AnyType> features) {
List<String> res = new BasicEList<String>();
for(AnyType featuresPerKey : features.values()) {
FeatureMap actualFeatures = featuresPerKey.getMixed();
actualFeatures.addAll(featuresPerKey.getAnyAttribute());
for(FeatureMap.Entry feature : actualFeatures) {
res.add(feature.getEStructuralFeature().getName());
}
}
return res;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment