[Layers] Correct the saving mechanism of the layer resouce

Change-Id: I9766a74ce47fa8fbd1cc0451c2986393ab52db11
Signed-off-by: Quentin Le Menez <quentin.lemenez@cea.fr>
diff --git a/layers/plugins/org.eclipse.papyrus.infra.gmfdiag.layers.runtime/src/org/eclipse/papyrus/internal/infra/gmfdiag/layers/runtime/LayersStackAndApplicationLifeCycleEventNotifier.java b/layers/plugins/org.eclipse.papyrus.infra.gmfdiag.layers.runtime/src/org/eclipse/papyrus/internal/infra/gmfdiag/layers/runtime/LayersStackAndApplicationLifeCycleEventNotifier.java
index f75dac2..301d3ec 100755
--- a/layers/plugins/org.eclipse.papyrus.infra.gmfdiag.layers.runtime/src/org/eclipse/papyrus/internal/infra/gmfdiag/layers/runtime/LayersStackAndApplicationLifeCycleEventNotifier.java
+++ b/layers/plugins/org.eclipse.papyrus.infra.gmfdiag.layers.runtime/src/org/eclipse/papyrus/internal/infra/gmfdiag/layers/runtime/LayersStackAndApplicationLifeCycleEventNotifier.java
@@ -40,7 +40,7 @@
 	 * States used in the state machine.
 	 */
 	protected enum State {
-	NoApplication, ApplicationCreated, disposed
+		NoApplication, ApplicationCreated, disposed
 	};
 
 	protected State state;
@@ -72,7 +72,6 @@
 		@Override
 		public void layersModelRootAdded(Notification msg) {
 			if (state == State.NoApplication) {
-				layersModel.shouldSave(true);
 				transitionNoApplicationToApplicationCreatedState();
 			}
 		}
diff --git a/layers/plugins/org.eclipse.papyrus.infra.gmfdiag.layers.runtime/src/org/eclipse/papyrus/internal/infra/gmfdiag/layers/runtime/model/LayersModelEventRootNotifier.java b/layers/plugins/org.eclipse.papyrus.infra.gmfdiag.layers.runtime/src/org/eclipse/papyrus/internal/infra/gmfdiag/layers/runtime/model/LayersModelEventRootNotifier.java
index 3a1618b..cc51f18 100755
--- a/layers/plugins/org.eclipse.papyrus.infra.gmfdiag.layers.runtime/src/org/eclipse/papyrus/internal/infra/gmfdiag/layers/runtime/model/LayersModelEventRootNotifier.java
+++ b/layers/plugins/org.eclipse.papyrus.infra.gmfdiag.layers.runtime/src/org/eclipse/papyrus/internal/infra/gmfdiag/layers/runtime/model/LayersModelEventRootNotifier.java
@@ -37,7 +37,7 @@
 	/**
 	 * List of listener to notify.
 	 */
-	protected List<ILayersModelRootEventListener> listeners = new ArrayList<ILayersModelRootEventListener>();
+	protected List<ILayersModelRootEventListener> listeners = new ArrayList<>();
 
 	protected Adapter modelListener = new AdapterImpl() {
 
@@ -59,6 +59,7 @@
 				// LayerOperator::layers || LayersStack::layers
 				// check the event type.
 				switch (notification.getEventType()) {
+
 				case Notification.SET:
 
 					break;
diff --git a/layers/plugins/org.eclipse.papyrus.infra.gmfdiag.layers.runtime/src/org/eclipse/papyrus/internal/infra/gmfdiag/layers/runtime/model/LayersModelResource.java b/layers/plugins/org.eclipse.papyrus.infra.gmfdiag.layers.runtime/src/org/eclipse/papyrus/internal/infra/gmfdiag/layers/runtime/model/LayersModelResource.java
index 5e89711..4d19497 100755
--- a/layers/plugins/org.eclipse.papyrus.infra.gmfdiag.layers.runtime/src/org/eclipse/papyrus/internal/infra/gmfdiag/layers/runtime/model/LayersModelResource.java
+++ b/layers/plugins/org.eclipse.papyrus.infra.gmfdiag.layers.runtime/src/org/eclipse/papyrus/internal/infra/gmfdiag/layers/runtime/model/LayersModelResource.java
@@ -11,10 +11,20 @@
 package org.eclipse.papyrus.internal.infra.gmfdiag.layers.runtime.model;
 
 import java.io.IOException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
 
+import org.eclipse.emf.common.command.Command;
 import org.eclipse.emf.common.util.URI;
 import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.impl.BasicEObjectImpl;
 import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.edit.command.RemoveCommand;
+import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
+import org.eclipse.emf.edit.domain.EditingDomain;
+import org.eclipse.osgi.util.NLS;
 import org.eclipse.papyrus.infra.core.resource.AbstractModelWithSharedResource;
 import org.eclipse.papyrus.infra.core.resource.IModel;
 import org.eclipse.papyrus.infra.core.resource.ModelSet;
@@ -22,6 +32,7 @@
 import org.eclipse.papyrus.internal.infra.gmfdiag.layers.model.layers.LayersStackApplication;
 import org.eclipse.papyrus.internal.infra.gmfdiag.layers.runtime.Activator;
 import org.eclipse.papyrus.internal.infra.gmfdiag.layers.runtime.LayersStackAndApplicationLifeCycleEventNotifier;
+import org.eclipse.papyrus.internal.infra.gmfdiag.layers.runtime.resource.utils.DanglingCrossReferencer;
 
 
 /**
@@ -44,10 +55,11 @@
 	 */
 	public static final String MODEL_ID = "org.eclipse.papyrus.layers.resource.LayersModel"; //$NON-NLS-1$
 
+	/**
+	 * The LifeCycleEventNotifier of this model
+	 */
 	private LayersStackAndApplicationLifeCycleEventNotifier layersStackAndApplicationLifeCycleEventNotifier = null;
 
-	boolean isDirty = false;
-
 
 	/**
 	 * Constructor.
@@ -127,8 +139,8 @@
 	 * 
 	 * @param isDirty
 	 */
-	public void shouldSave(boolean isDirty) {
-		this.isDirty = isDirty;
+	public boolean shouldSave() {
+		return this.resource.isModified();
 	}
 
 	/**
@@ -139,12 +151,34 @@
 	@Override
 	public void saveModel() throws IOException {
 
-		if (isDirty) {
+		if (shouldSave()) {
 			final ModelSet set = getModelManager();
 
 			for (Resource resource : getResources()) {
 				if (set.shouldSave(resource)) {
 					try {
+						DanglingCrossReferencer danglingReferencer = new DanglingCrossReferencer(resource);
+
+						Map<EObject, Collection<EStructuralFeature.Setting>> danglingReferences = danglingReferencer.findDanglingCrossReferences();
+
+						if (danglingReferences.size() > 0) {
+							for (Map.Entry<EObject, Collection<EStructuralFeature.Setting>> danglingReferenceEntry : danglingReferences
+									.entrySet()) {
+								BasicEObjectImpl danglingReference = (BasicEObjectImpl) danglingReferenceEntry.getKey();
+								for (EStructuralFeature.Setting setting : danglingReferenceEntry.getValue()) {
+									EObject objectWithDanglingRefs = setting.getEObject();
+
+									// CheckDanglingReferences
+									EditingDomain domain = AdapterFactoryEditingDomain.getEditingDomainFor(objectWithDanglingRefs);
+									Command addThePart = RemoveCommand.create(domain, objectWithDanglingRefs,
+											setting.getEStructuralFeature(), Collections.singleton(danglingReference));
+									domain.getCommandStack().execute(addThePart);
+
+									// Activator.log.warn("There are dangling references in your model,you should think about cleaning it");//$NON-NLS-1$
+								}
+							}
+						}
+
 						resource.save(null);
 					} catch (IOException ex) {
 						// If an exception occurs, we should not prevent other resources from being saved.
diff --git a/layers/plugins/org.eclipse.papyrus.infra.gmfdiag.layers.runtime/src/org/eclipse/papyrus/internal/infra/gmfdiag/layers/runtime/resource/utils/DanglingCrossReferencer.java b/layers/plugins/org.eclipse.papyrus.infra.gmfdiag.layers.runtime/src/org/eclipse/papyrus/internal/infra/gmfdiag/layers/runtime/resource/utils/DanglingCrossReferencer.java
new file mode 100755
index 0000000..dd3c765
--- /dev/null
+++ b/layers/plugins/org.eclipse.papyrus.infra.gmfdiag.layers.runtime/src/org/eclipse/papyrus/internal/infra/gmfdiag/layers/runtime/resource/utils/DanglingCrossReferencer.java
@@ -0,0 +1,45 @@
+/*****************************************************************************
+ * Copyright (c) 2018 CEA LIST and others.
+ * 
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *   CEA LIST - Initial API and implementation
+ *   
+ *****************************************************************************/
+
+package org.eclipse.papyrus.internal.infra.gmfdiag.layers.runtime.resource.utils;
+
+import java.util.Collection;
+import java.util.Map;
+
+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.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+
+/**
+ * @author QL238289
+ *
+ */
+public class DanglingCrossReferencer extends EcoreUtil.CrossReferencer {
+	public DanglingCrossReferencer(Resource resource) {
+		super(resource);
+	}
+
+	@Override
+	protected boolean crossReference(EObject eObject, EReference eReference, EObject crossReferencedEObject) {
+		return crossReferencedEObject.eResource() == null && !crossReferencedEObject.eIsProxy() && !eReference.isTransient();
+	}
+
+	public Map<EObject, Collection<EStructuralFeature.Setting>> findDanglingCrossReferences() {
+		crossReference();
+		done();
+		return this;
+	}
+}