diff --git a/org.fortiss.tooling.base/src/org/fortiss/tooling/base/migration/.ratings b/org.fortiss.tooling.base/src/org/fortiss/tooling/base/migration/.ratings
index 5633daf969db8251bbf77fd7418a1c19bf30868a..9d0d7f8df1b322b3005d555d7552e4aa62d05156 100644
--- a/org.fortiss.tooling.base/src/org/fortiss/tooling/base/migration/.ratings
+++ b/org.fortiss.tooling.base/src/org/fortiss/tooling/base/migration/.ratings
@@ -1,3 +1,3 @@
-AddMissingAnnotationsMigrationProvider.java a3f2b3cbcd39f85e15bc998650f899f55d9f563e GREEN
-RemoveDuplicatedAnnotationsMigrationProvider.java f1bdb4733d5b9c6003a2b7fee59b89240a0a3b61 GREEN
-RemoveOutdatedAnnotationInstanceMigrationProvider.java 29c29f2bb7515cad1de45a30ffc185001b47a016 GREEN
+AddMissingAnnotationsMigrationProvider.java ebc5b9348b61ffb23493942949ecccf1c1fa2ae1 GREEN
+RemoveDuplicatedAnnotationsMigrationProvider.java 6920909f8f211b9c5b5990644b5abcd8c4abaa3a GREEN
+RemoveOutdatedAnnotationInstanceMigrationProvider.java 245530d6026f9ff29ffc577983d9de03ae5e75e5 GREEN
diff --git a/org.fortiss.tooling.base/src/org/fortiss/tooling/base/migration/AddMissingAnnotationsMigrationProvider.java b/org.fortiss.tooling.base/src/org/fortiss/tooling/base/migration/AddMissingAnnotationsMigrationProvider.java
index a3f2b3cbcd39f85e15bc998650f899f55d9f563e..ebc5b9348b61ffb23493942949ecccf1c1fa2ae1 100644
--- a/org.fortiss.tooling.base/src/org/fortiss/tooling/base/migration/AddMissingAnnotationsMigrationProvider.java
+++ b/org.fortiss.tooling.base/src/org/fortiss/tooling/base/migration/AddMissingAnnotationsMigrationProvider.java
@@ -15,6 +15,7 @@
 +--------------------------------------------------------------------------*/
 package org.fortiss.tooling.base.migration;
 
+import static java.util.Collections.emptyMap;
 import static org.fortiss.tooling.base.utils.AnnotationUtils.instantiateAnnotationsRecursive;
 
 import java.util.ArrayList;
@@ -49,9 +50,11 @@ public class AddMissingAnnotationsMigrationProvider implements IMigrationProvide
 
 	/** {@inheritDoc} */
 	@Override
-	public void migrate(ITopLevelElement modelElement, Map<EObject, AnyType> unknownFeatures) {
+	public Map<EObject, AnyType> migrate(ITopLevelElement modelElement,
+			Map<EObject, AnyType> unknownFeatures) {
 		EObject rootElement = modelElement.getRootModelElement();
 		instantiateAnnotationsRecursive(rootElement);
 		migratedProjects.add(modelElement);
+		return emptyMap();
 	}
 }
diff --git a/org.fortiss.tooling.base/src/org/fortiss/tooling/base/migration/RemoveDuplicatedAnnotationsMigrationProvider.java b/org.fortiss.tooling.base/src/org/fortiss/tooling/base/migration/RemoveDuplicatedAnnotationsMigrationProvider.java
index f1bdb4733d5b9c6003a2b7fee59b89240a0a3b61..6920909f8f211b9c5b5990644b5abcd8c4abaa3a 100644
--- a/org.fortiss.tooling.base/src/org/fortiss/tooling/base/migration/RemoveDuplicatedAnnotationsMigrationProvider.java
+++ b/org.fortiss.tooling.base/src/org/fortiss/tooling/base/migration/RemoveDuplicatedAnnotationsMigrationProvider.java
@@ -15,6 +15,7 @@
 +--------------------------------------------------------------------------*/
 package org.fortiss.tooling.base.migration;
 
+import static java.util.Collections.emptyMap;
 import static org.fortiss.tooling.kernel.utils.EcoreUtils.getChildrenWithType;
 import static org.fortiss.tooling.kernel.utils.EcoreUtils.pickInstanceOf;
 import static org.fortiss.tooling.kernel.utils.LoggingUtils.error;
@@ -87,7 +88,8 @@ public class RemoveDuplicatedAnnotationsMigrationProvider implements IMigrationP
 
 	/** {@inheritDoc} */
 	@Override
-	public void migrate(ITopLevelElement topLevelElement, Map<EObject, AnyType> unknownFeatures) {
+	public Map<EObject, AnyType> migrate(ITopLevelElement topLevelElement,
+			Map<EObject, AnyType> unknownFeatures) {
 
 		doInternal(topLevelElement, true);
 
@@ -95,5 +97,6 @@ public class RemoveDuplicatedAnnotationsMigrationProvider implements IMigrationP
 		error(ToolingBaseActivator.getDefault(),
 				"Duplicate annotations have been removed from \"" + uri.lastSegment() +
 						"\". Please report this incident since it indicates an internal problem.");
+		return emptyMap();
 	}
 }
diff --git a/org.fortiss.tooling.base/src/org/fortiss/tooling/base/migration/RemoveOutdatedAnnotationInstanceMigrationProvider.java b/org.fortiss.tooling.base/src/org/fortiss/tooling/base/migration/RemoveOutdatedAnnotationInstanceMigrationProvider.java
index 29c29f2bb7515cad1de45a30ffc185001b47a016..245530d6026f9ff29ffc577983d9de03ae5e75e5 100644
--- a/org.fortiss.tooling.base/src/org/fortiss/tooling/base/migration/RemoveOutdatedAnnotationInstanceMigrationProvider.java
+++ b/org.fortiss.tooling.base/src/org/fortiss/tooling/base/migration/RemoveOutdatedAnnotationInstanceMigrationProvider.java
@@ -15,6 +15,7 @@
 +--------------------------------------------------------------------------*/
 package org.fortiss.tooling.base.migration;
 
+import static java.util.Collections.emptyMap;
 import static org.eclipse.emf.ecore.util.EcoreUtil.delete;
 import static org.fortiss.tooling.common.util.LambdaUtils.isAssignableFromAny;
 import static org.fortiss.tooling.kernel.utils.EcoreUtils.getChildrenWithType;
@@ -67,12 +68,14 @@ public abstract class RemoveOutdatedAnnotationInstanceMigrationProvider<T extend
 
 	/** {@inheritDoc} */
 	@Override
-	public void migrate(ITopLevelElement modelElement, Map<EObject, AnyType> unknownFeatures) {
+	public Map<EObject, AnyType> migrate(ITopLevelElement modelElement,
+			Map<EObject, AnyType> unknownFeatures) {
 		EObject rootModelElement = modelElement.getRootModelElement();
 		for(T annotation : getChildrenWithType(rootModelElement, annotationType)) {
 			if(!isAssignableFromAny(modelElementTypes, annotation.getSpecificationOf())) {
 				delete(annotation);
 			}
 		}
+		return emptyMap();
 	}
 }
diff --git a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/.ratings b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/.ratings
index 0a98fb5c57e6ec70b3853c8145ec72ebe32eb99e..b2f23c1f28fd6be6f4cd785dfbd17d06d59c5604 100644
--- a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/.ratings
+++ b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/.ratings
@@ -6,7 +6,7 @@ IEclipseResourceStorageLocationProvider.java 0ab7f304d52a9d86f01f66e308e9a7ca420
 IElementCompositor.java 5b0ab1732f71b3f8467e0276c844f0dd549e191f GREEN
 ILibraryElementHandler.java 00ef5b25c63b8570006e6f6748aed0da1f33a5f1 GREEN
 ILogMessageHandler.java 9ab53e836a095ef00fd84ecc0375167edf593b46 GREEN
-IMigrationProvider.java fdb1078dfca10a82a18f79b862d7b8644e80e14e GREEN
+IMigrationProvider.java 241bfd8594dfb86ce0f89dc95b43662f52d9e450 GREEN
 IPrototypeProvider.java d5e3dbae19b5654caf28b81da6b1609d3c12be12 GREEN
 IStorageProvider.java d9b14cdd254d0c956dc5715c1c4d4d955a705dd5 GREEN
 ITransformationProvider.java a4ee2ea08720bb2fce29806062eb01499bb5071e GREEN
diff --git a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/IMigrationProvider.java b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/IMigrationProvider.java
index fdb1078dfca10a82a18f79b862d7b8644e80e14e..241bfd8594dfb86ce0f89dc95b43662f52d9e450 100644
--- a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/IMigrationProvider.java
+++ b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/IMigrationProvider.java
@@ -45,12 +45,12 @@ public interface IMigrationProvider extends IObjectAware<ITopLevelElement> {
 	/**
 	 * Applies the provider to the given element.
 	 * 
-	 * The parameter "unknownFeatures" returns a map indicating the features that are not recognized
+	 * The parameter "unknownFeatures" indicates 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 a 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!
+	 * @return all unknown features that have successfully been migrated.
 	 */
-	void migrate(ITopLevelElement modelElement, Map<EObject, AnyType> unknownFeatures);
+	Map<EObject, AnyType> migrate(ITopLevelElement modelElement,
+			Map<EObject, AnyType> unknownFeatures);
 }
diff --git a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/base/RemoveDeprecatedArtifactsMigrationProviderBase.java b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/base/RemoveDeprecatedArtifactsMigrationProviderBase.java
deleted file mode 100644
index 4a1b676223b7ec53259a26d1a671b11ff2f911e2..0000000000000000000000000000000000000000
--- a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/base/RemoveDeprecatedArtifactsMigrationProviderBase.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*-------------------------------------------------------------------------+
-| Copyright 2018 fortiss GmbH                                              |
-|                                                                          |
-| Licensed under the Apache License, Version 2.0 (the "License");          |
-| you may not use this file except in compliance with the License.         |
-| You may obtain a copy of the License at                                  |
-|                                                                          |
-|    http://www.apache.org/licenses/LICENSE-2.0                            |
-|                                                                          |
-| Unless required by applicable law or agreed to in writing, software      |
-| distributed under the License is distributed on an "AS IS" BASIS,        |
-| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
-| See the License for the specific language governing permissions and      |
-| limitations under the License.                                           |
-+--------------------------------------------------------------------------*/
-package org.fortiss.tooling.kernel.extension.base;
-
-import static org.conqat.lib.commons.reflect.ReflectionUtils.isInstanceOfAny;
-import static org.eclipse.emf.ecore.util.EcoreUtil.delete;
-import static org.fortiss.tooling.common.util.LambdaUtils.asStream;
-
-import java.util.Collection;
-import java.util.Map;
-import java.util.Optional;
-import java.util.stream.Stream;
-
-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.model.INamedCommentedElement;
-
-/**
- * Remove artificats related to deprecated use case model.
- * 
- * @author barner
- */
-public abstract class RemoveDeprecatedArtifactsMigrationProviderBase implements IMigrationProvider { // NO_UCD
-	// Migrators are retired after a release, but this base class should be available when needed.
-	// See https://af3-developer.fortiss.org/projects/autofocus3/wiki/Model_Migration
-
-	/** Returns the {@link Collection} of deprecated artifact types to be removed from the model. */
-	protected abstract Collection<Class<? extends EObject>> getDeprecatedArtifacts();
-
-	/**
-	 * Returns the {@link Collection} of deprecated root artifact types (possibly empty subset of
-	 * {@link #getDeprecatedArtifacts()}) for which a comment is added to the migrated model that
-	 * deprecated artifacts have been removed.
-	 */
-	protected abstract Collection<Class<? extends EObject>> getDeprecatedRootArtifacts();
-
-	/** Returns the {@link Stream} of deprecated model elements to be removed. */
-	private Stream<EObject> getDeprecatedModelElements(ITopLevelElement modelElement) {
-		Stream<EObject> root = asStream(modelElement.getRootModelElement().eAllContents());
-		Collection<Class<? extends EObject>> deprArtifacts = getDeprecatedArtifacts();
-		return root.filter(
-				e -> isInstanceOfAny(e, deprArtifacts.toArray(new Class[deprArtifacts.size()])));
-	}
-
-	/** {@inheritDoc} */
-
-	@Override
-	public boolean needMigration(ITopLevelElement modelElement,
-			Map<EObject, AnyType> unknownFeatures) {
-
-		return getDeprecatedModelElements(modelElement).findAny().isPresent();
-	}
-
-	/** {@inheritDoc} */
-	@Override
-	public void migrate(ITopLevelElement modelElement, Map<EObject, AnyType> unknownFeatures) {
-		EObject object;
-		do {
-			object = null;
-			Stream<EObject> deprecatedModelElements = getDeprecatedModelElements(modelElement);
-			Optional<EObject> anyObject = deprecatedModelElements.findAny();
-			if(anyObject.isPresent()) {
-				object = anyObject.get();
-				if(object.eContainer() instanceof INamedCommentedElement) {
-					INamedCommentedElement parent = (INamedCommentedElement)object.eContainer();
-					if(parent.getComment() == null || parent.getComment().isEmpty()) {
-						for(Class<? extends EObject> rootType : getDeprecatedRootArtifacts()) {
-							if(rootType.isAssignableFrom(object.getClass())) {
-								parent.setComment(rootType.getSimpleName() +
-										" models are no longer supported. This sub-model has been removed automatically!");
-								break;
-							}
-						}
-					}
-				}
-				delete(object);
-			}
-		} while(object != null);
-	}
-}
diff --git a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/internal/.ratings b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/internal/.ratings
index e6e117aec42749c55a27ff79b3607f3b914272f7..2f69b2046501b5917850e19477bc500f81ea116c 100644
--- a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/internal/.ratings
+++ b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/internal/.ratings
@@ -7,7 +7,7 @@ ElementCompositorService.java 98c5d27e09881e60aa4f87c1ac0c7787cdec9f7c GREEN
 LibraryPrototypeProvider.java b77eddbdca78f561ffb1233e98817be361c690ae GREEN
 LibraryService.java d22671ba820466062852c15873698adf28960d94 GREEN
 LoggingService.java da784259f7b456b54bf75c41ec268f64919ce78d GREEN
-MigrationService.java 632c13563a3d69681e2a608023fcdadbe5340c4b GREEN
+MigrationService.java 2f800eac9793aa736089a802bbfc2c4c1c09770d GREEN
 PersistencyService.java 103eef642c038ef63fa49b743d803aaa3fea2724 GREEN
 PrototypeService.java 18c3db05ab11f189a9711bf241c3c7f35c954a9e GREEN
 ToolingKernelInternal.java d624a5f6b237ce993e150e2b8d1b4390e3fc8f7a GREEN
diff --git a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/internal/MigrationService.java b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/internal/MigrationService.java
index 632c13563a3d69681e2a608023fcdadbe5340c4b..2f800eac9793aa736089a802bbfc2c4c1c09770d 100644
--- a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/internal/MigrationService.java
+++ b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/internal/MigrationService.java
@@ -16,18 +16,21 @@
 package org.fortiss.tooling.kernel.internal;
 
 import static java.util.Collections.emptyList;
+import static java.util.stream.Collectors.joining;
+import static java.util.stream.Collectors.toSet;
 import static org.fortiss.tooling.kernel.utils.EcoreUtils.getFirstChildWithType;
 import static org.fortiss.tooling.kernel.utils.LoggingUtils.error;
+import static org.fortiss.tooling.kernel.utils.LoggingUtils.warning;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.stream.Stream;
 
 import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.emf.common.util.BasicEList;
 import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.util.FeatureMap;
 import org.eclipse.emf.ecore.xml.type.AnyType;
 import org.fortiss.tooling.kernel.ToolingKernelActivator;
 import org.fortiss.tooling.kernel.extension.IMigrationProvider;
@@ -97,19 +100,6 @@ public class MigrationService extends ObjectAwareServiceBase<IMigrationProvider>
 		return false;
 	}
 
-	/** Extracts the list of feature names from a map of features. */
-	private 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;
-	}
-
 	/** {@inheritDoc} */
 	@Override
 	public void migrate(final ITopLevelElement input, final Map<EObject, AnyType> unknownFeatures) {
@@ -117,17 +107,12 @@ public class MigrationService extends ObjectAwareServiceBase<IMigrationProvider>
 
 			@Override
 			public void run() {
+				Map<EObject, AnyType> migratedFeatures = new HashMap<EObject, AnyType>();
 				for(IMigrationProvider provider : getProviders(input)) {
 					if(provider.needMigration(input, unknownFeatures)) {
-						provider.migrate(input, unknownFeatures);
+						migratedFeatures.putAll(provider.migrate(input, unknownFeatures));
 					}
 				}
-				if(!unknownFeatures.isEmpty()) {
-					error(ToolingKernelActivator.getDefault(),
-							input.getSaveableName() + " contains one or more unknown feature(s): " +
-									featuresToStrings(unknownFeatures));
-				}
-
 				for(IMigrationProvider provider : getProviders(input)) {
 					if(provider.needMigration(input, unknownFeatures)) {
 						error(ToolingKernelActivator.getDefault(),
@@ -136,6 +121,19 @@ public class MigrationService extends ObjectAwareServiceBase<IMigrationProvider>
 										"already performed. Please fix the migrator (or model).");
 					}
 				}
+				unknownFeatures.entrySet().removeAll(migratedFeatures.entrySet());
+				if(!unknownFeatures.isEmpty()) {
+					Stream<AnyType> anyTypes = unknownFeatures.values().stream()
+							.map(v -> v.getMixed()).flatMap(f -> f.stream()).map(e -> e.getValue())
+							.filter(AnyType.class::isInstance).map(AnyType.class::cast);
+					String removedTypes = anyTypes.map(a -> a.eClass().getName()).collect(toSet())
+							.stream().collect(joining(", "));
+					warning(ToolingKernelActivator.getDefault(), input.getSaveableName() +
+							" contains one or more feature(s) of the following unkown types that will be deleted: " +
+							removedTypes + ".");
+
+					unknownFeatures.clear();
+				}
 			}
 		});
 
diff --git a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/internal/storage/eclipse/.ratings b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/internal/storage/eclipse/.ratings
index 4a4edee0b9b29c4f7e79c5026854886346e3d02a..605b741d853bf1e95bbf06c68ab9a477dea3beb5 100644
--- a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/internal/storage/eclipse/.ratings
+++ b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/internal/storage/eclipse/.ratings
@@ -1,5 +1,5 @@
 AutoUndoCommandStack.java fc326adf66c6cea2354884cdc240da5f2f82689a GREEN
 EMFTransactionalCommand.java ba4b5bead9768b6ce6c955b9238cd96cb722533c GREEN
 EclipseResourceStorageService.java e29e32272286921c5e43963253902b3ba54490c7 GREEN
-ModelContext.java 55de5f19c5d625f935fb8136ff72d80b3a54ff19 GREEN
+ModelContext.java db1735834c85e7b508266f56463d011f2b72af0e GREEN
 NonDirtyingEMFTransactionalCommand.java d288ebe35d22442c603496b0c917fb99a8febeea GREEN
diff --git a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/internal/storage/eclipse/ModelContext.java b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/internal/storage/eclipse/ModelContext.java
index 55de5f19c5d625f935fb8136ff72d80b3a54ff19..db1735834c85e7b508266f56463d011f2b72af0e 100644
--- a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/internal/storage/eclipse/ModelContext.java
+++ b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/internal/storage/eclipse/ModelContext.java
@@ -330,7 +330,9 @@ class ModelContext implements ITopLevelElement, CommandStackListener {
 
 		// Step 3..n: Save resources not managed by kernel
 		for(Resource currentResource : rset.getResources()) {
-			if(currentResource != resource && !editingDomain.isReadOnly(currentResource)) {
+			if(currentResource != resource && !editingDomain.isReadOnly(currentResource) &&
+					!currentResource.getContents().isEmpty()) {
+				// do not save resources which are not contained (by a FileProject)
 				try {
 					currentResource.save(saveOptions);
 				} catch(IOException e) {
diff --git a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/utils/.ratings b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/utils/.ratings
index d85861e2edafbeb32da7cbcff68cc64ad45f8ba9..a14d336f35b4b272093a2fc62dcf8c95d8cadab7 100644
--- a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/utils/.ratings
+++ b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/utils/.ratings
@@ -10,6 +10,6 @@ JavaUtils.java 65cdadfb9137a240ad59992eacf53a15b7f20804 GREEN
 KernelModelElementUtils.java fded09befe7e543fc04ea5184ffc1c8a309d7a66 GREEN
 LoggingUtils.java 0e0aa5d466d80ea29cfc7e91178b23a5cdd4ddf7 GREEN
 PrototypesUtils.java ec75bed75cfc5103f1f38e3a29df86f729428775 GREEN
-ResourceUtils.java 698c7db34acb4f1a258a1953e6afcca9823763a8 GREEN
+ResourceUtils.java e31eda3fdbedd2e44c85d471f717b14f92a3c663 GREEN
 TransformationUtils.java 552d3a9d56d34450be781af828efe0b8aa5d359e GREEN
 UniqueIDUtils.java 665955b1790c1bd1c2087e23114da920bfec2265 GREEN
diff --git a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/utils/ResourceUtils.java b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/utils/ResourceUtils.java
index 698c7db34acb4f1a258a1953e6afcca9823763a8..e31eda3fdbedd2e44c85d471f717b14f92a3c663 100644
--- a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/utils/ResourceUtils.java
+++ b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/utils/ResourceUtils.java
@@ -51,6 +51,11 @@ import org.eclipse.emf.ecore.resource.ResourceSet;
 import org.eclipse.emf.ecore.resource.impl.ResourceFactoryImpl;
 import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
 import org.eclipse.emf.ecore.xmi.PackageNotFoundException;
+import org.eclipse.emf.ecore.xmi.XMLHelper;
+import org.eclipse.emf.ecore.xmi.XMLLoad;
+import org.eclipse.emf.ecore.xmi.XMLResource;
+import org.eclipse.emf.ecore.xmi.impl.SAXXMIHandler;
+import org.eclipse.emf.ecore.xmi.impl.XMILoadImpl;
 import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;
 import org.eclipse.emf.ecore.xmi.impl.XMLResourceFactoryImpl;
 import org.eclipse.emf.ecore.xml.type.AnyType;
@@ -58,6 +63,7 @@ import org.fortiss.tooling.kernel.ToolingKernelActivator;
 import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
 import org.fortiss.tooling.kernel.model.IIdLabeled;
 import org.fortiss.tooling.kernel.service.IPersistencyService;
+import org.xml.sax.helpers.DefaultHandler;
 
 /**
  * Utility class for dealing with EMF {@link Resource}s.
@@ -77,12 +83,79 @@ public final class ResourceUtils {
 	 */
 	public static class KernelResourceFactory extends ResourceFactoryImpl {
 
+		/**
+		 * XMIHandler that cleans up dangling references when loading models with unknown types
+		 * instead of throwing an exception.
+		 */
+		private final class DanglingReferencesCleanupXMIHandler extends SAXXMIHandler {
+			/** Constructor. */
+			private DanglingReferencesCleanupXMIHandler(XMLResource xmiResource, XMLHelper helper,
+					Map<?, ?> options) {
+				super(xmiResource, helper, options);
+			}
+
+			/** {@inheritDoc} */
+			@Override
+			protected void handleForwardReferences(boolean isEndDocument) {
+				List<SingleReference> toRemoveFwdSingleRefs = new ArrayList<>();
+				for(SingleReference ref : forwardSingleReferences) {
+					EObject obj;
+					try {
+						obj = xmlResource.getEObject((String)ref.getValue());
+					} catch(RuntimeException exception) {
+						obj = null;
+					}
+					if(obj == null || obj instanceof AnyType) {
+						warnRefWithUnknownType((AnyType)obj, ref.getLineNumber(),
+								ref.getColumnNumber());
+						toRemoveFwdSingleRefs.add(ref);
+					}
+				}
+				forwardSingleReferences.removeAll(toRemoveFwdSingleRefs);
+
+				List<ManyReference> toRemoveFwdManyRefs = new ArrayList<>();
+				for(ManyReference ref : forwardManyReferences) {
+					Object[] values = ref.getValues();
+
+					for(String id : (String[])values) {
+
+						EObject obj;
+						try {
+							obj = xmlResource.getEObject(id);
+						} catch(RuntimeException exception) {
+							obj = null;
+						}
+						if(obj == null || obj instanceof AnyType) {
+							warnRefWithUnknownType((AnyType)obj, ref.getLineNumber(),
+									ref.getColumnNumber());
+							toRemoveFwdManyRefs.add(ref);
+							break;
+						}
+					}
+				}
+				forwardManyReferences.removeAll(toRemoveFwdManyRefs);
+
+				super.handleForwardReferences(isEndDocument);
+			}
+
+			/** Issues a warning for a given {@link AnyType}d object. */
+			private void warnRefWithUnknownType(AnyType obj, int line, int col) {
+				String message = "Removing reference to element with unknown type" +
+						(obj != null ? " \"" + obj.eClass().getName() + "\"" : "") + " in line " +
+						line + ", column " + col + ".";
+
+				// Static inline not possible: name clash with XMLHandler::warning()
+				LoggingUtils.warning(ToolingKernelActivator.getDefault(), message);
+			}
+		}
+
 		/**
 		 * {@link XMIResourceImpl} used to persist models managed by the tooling kernel.
 		 * 
 		 * @author barner
 		 */
 		private final class KernelXMIResource extends XMIResourceImpl {
+
 			/** Constructs a new {@link KernelXMIResource}. */
 			private KernelXMIResource(URI uri) {
 				super(uri);
@@ -99,7 +172,7 @@ public final class ResourceUtils {
 			public String getID(EObject eObject) {
 				String id = super.getID(eObject);
 				if(id == null && eObject instanceof IIdLabeled) {
-					id = new Integer(((IIdLabeled)eObject).getId()).toString();
+					id = String.valueOf(((IIdLabeled)eObject).getId());
 					setID(eObject, id);
 				}
 				return id;
@@ -140,6 +213,18 @@ public final class ResourceUtils {
 				}
 				return eObjectToExtensionMap;
 			}
+
+			/** {@inheritDoc} */
+			@Override
+			protected XMLLoad createXMLLoad() {
+				return new XMILoadImpl(createXMLHelper()) {
+					/** {@inheritDoc} */
+					@Override
+					protected DefaultHandler makeDefaultHandler() {
+						return new DanglingReferencesCleanupXMIHandler(resource, helper, options);
+					}
+				};
+			}
 		}
 
 		/** {@inheritDoc} */
@@ -196,13 +281,13 @@ public final class ResourceUtils {
 
 	/**
 	 * <p>
-	 * Determines the {@link ITopLevelElement} which shares the same {@link ResourceSet} as the a
-	 * {@link Resource} with the specified {@link URI}. If no such {@link Resource} has been loaded,
-	 * {@code null} is returned.
+	 * Determines the {@link ITopLevelElement} which shares the same {@link ResourceSet} as the
+	 * a {@link Resource} with the specified {@link URI}. If no such {@link Resource} has been
+	 * loaded, {@code null} is returned.
 	 * </p>
 	 * <p>
-	 * This is useful to determine to which model managed by the Kernel a given (external) model is
-	 * linked.
+	 * This is useful to determine to which model managed by the Kernel a given (external) model
+	 * is linked.
 	 * </p>
 	 * 
 	 * @param uri
@@ -226,8 +311,8 @@ public final class ResourceUtils {
 	}
 
 	/**
-	 * Obtains a model of a given type from a {@code resourceSet}, or {@code null} if it could not
-	 * be found.
+	 * Obtains a model of a given type from a {@code resourceSet}, or {@code null} if it could
+	 * not be found.
 	 * 
 	 * @param resourceSet
 	 *            {@link ResourceSet} from which model of given type should be determined
@@ -251,25 +336,30 @@ public final class ResourceUtils {
 	}
 
 	/**
-	 * Obtains a model of a given type from a {@code resourceSet}, and creates the model if it does
-	 * not exist yet (and adds it to the given {@code resourceSet}). Returns {@code null} if the
-	 * model could not be created.
+	 * Obtains a model of a given type from a {@code resourceSet}, and creates the model if it
+	 * does not exist yet (and adds it to the given {@code resourceSet}). Returns {@code null} if
+	 * the model could not be created.
 	 * 
 	 * @param resourceSet
 	 *            {@link ResourceSet} from which model of given type should be determined
 	 * @param clazz
 	 *            Type of model to be returned.
 	 * @param factory
-	 *            {@link EFactory} to create root model element in case the model does not exist in
+	 *            {@link EFactory} to create root model element in case the model does not exist
+	 *            in
 	 *            the {@code resourceSet} yet.
 	 * @param fileExtension
-	 *            File extension to be used in case a new resource has to be created and added to
-	 *            the given given {@code resourceSet}. In case this parameter is {@code null}, this
+	 *            File extension to be used in case a new resource has to be created and added
+	 *            to
+	 *            the given given {@code resourceSet}. In case this parameter is {@code null},
+	 *            this
 	 *            method effectively behaves like {@link #getModel(ResourceSet, Class)}.
 	 * @param referenceClazz
-	 *            Type of root model element whose {@link Resource} {@link URI} should be used to
+	 *            Type of root model element whose {@link Resource} {@link URI} should be used
+	 *            to
 	 *            derive the base name in case a new {@link Resource} has to be created. In case
-	 *            this parameter is {@code null}, the {@link URI} of the first {@link Resource} in
+	 *            this parameter is {@code null}, the {@link URI} of the first {@link Resource}
+	 *            in
 	 *            the given {@link ResourceSet} is used.
 	 * 
 	 * @return Model of a given type, or {@code null} if it could not be created.
@@ -368,12 +458,14 @@ public final class ResourceUtils {
 	 *            {@link Resource} for which {@link URI}s of directly or indirectly referencing
 	 *            resources should be determined.
 	 * @param includeSelf
-	 *            Flag if the {@link URI} of the given {@code resource} should be contained in the
+	 *            Flag if the {@link URI} of the given {@code resource} should be contained in
+	 *            the
 	 *            result.
 	 * @param progressMonitor
 	 *            {@link IProgressMonitor} (may be {@code null}). Loading all resources in a
 	 *            directory may be a long-running operation.
-	 * @return {@link URI}s of directly or indirectly referencing resources, possibly including the
+	 * @return {@link URI}s of directly or indirectly referencing resources, possibly including
+	 *         the
 	 *         {@link URI} of the given {@code resource} itself (see {@code includeSelf}).
 	 */
 	public static Collection<URI> getReferencingResourceURIs(Resource resource, boolean includeSelf,