Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian W. Damus2014-07-25 19:19:58 +0000
committerGerrit Code Review @ Eclipse.org2014-07-25 19:19:58 +0000
commit43af1aa06fba01ee95ad7b72f07cabf80321bce2 (patch)
tree244572e62a28ef2180c216b7a9bb445816614cda
parentd558c050796a7e06772835b0b5bb6a936166b0bb (diff)
parentdfde88b139d345b628415dda0769aa87dd7733c6 (diff)
downloadorg.eclipse.papyrus-43af1aa06fba01ee95ad7b72f07cabf80321bce2.tar.gz
org.eclipse.papyrus-43af1aa06fba01ee95ad7b72f07cabf80321bce2.tar.xz
org.eclipse.papyrus-43af1aa06fba01ee95ad7b72f07cabf80321bce2.zip
Merge "437217: [Editors] In-place reloading of model resources in the editors https://bugs.eclipse.org/bugs/show_bug.cgi?id=437217"
-rw-r--r--plugins/editor/org.eclipse.papyrus.editor/META-INF/MANIFEST.MF3
-rw-r--r--plugins/editor/org.eclipse.papyrus.editor/src/org/eclipse/papyrus/editor/PapyrusPaletteSynchronizer.java57
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/editor/AbstractMultiPageSashEditor.java47
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/SashWindowsContainer.java12
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/META-INF/MANIFEST.MF3
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/contentoutline/NestedEditorDelegatedOutlinePage.java152
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/CoreMultiDiagramEditor.java178
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/IReloadableEditor.java106
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/MultiDiagramEditorSelectionContext.java218
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/CompositeReloadContext.java86
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/DelegatingReloadContext.java74
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/EMFSelectionContext.java52
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/EMFTreeViewerContext.java52
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/EditorReloadAdapter.java36
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/EditorReloadEvent.java189
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/IDisposableReloadContext.java23
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/IEditorReloadListener.java44
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/IInternalEMFSelectionContext.java106
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/IReloadContextProvider.java38
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/SelectionContext.java81
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/TreeViewerContext.java62
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/services/ResourceUpdateService.java80
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/plugin.xml7
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/DiagramReloadContextProvider.java149
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/PaletteViewerReloadContextProvider.java117
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/SynchronizableGmfDiagramEditor.java162
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/adapter/DiagramOutlineAdapterFactory.java39
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/adapter/DiagramOutlineReloadContextProvider.java135
-rw-r--r--plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.outline/src/org/eclipse/papyrus/infra/gmfdiag/outline/DiagramOutline.java56
-rw-r--r--plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/META-INF/MANIFEST.MF3
-rw-r--r--plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/src/org/eclipse/papyrus/infra/nattable/common/editor/AbstractEMFNattableEditor.java6
-rw-r--r--plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/src/org/eclipse/papyrus/infra/nattable/common/editor/NattableReloadContextProvider.java90
-rw-r--r--plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/util/LocalMemento.java284
-rw-r--r--plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/util/UIUtil.java11
-rw-r--r--plugins/views/modelexplorer/org.eclipse.papyrus.views.modelexplorer/src/org/eclipse/papyrus/views/modelexplorer/ModelExplorerTreeViewerContext.java141
-rw-r--r--plugins/views/modelexplorer/org.eclipse.papyrus.views.modelexplorer/src/org/eclipse/papyrus/views/modelexplorer/ModelExplorerView.java173
-rw-r--r--plugins/views/validation/org.eclipse.papyrus.views.validation/src/org/eclipse/papyrus/views/validation/internal/providers/ProblemsContentProvider.java95
-rw-r--r--tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/META-INF/MANIFEST.MF3
-rw-r--r--tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/banking.di12
-rw-r--r--tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/banking.notation91
-rw-r--r--tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/banking.uml46
-rw-r--r--tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/employment.di18
-rw-r--r--tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/employment.notation415
-rw-r--r--tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/employment.uml44
-rw-r--r--tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/library.di12
-rw-r--r--tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/library.notation72
-rw-r--r--tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/library.uml35
-rw-r--r--tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/org.eclipse.papyrus.editor.integration.tests.launch86
-rw-r--r--tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/src/org/eclipse/papyrus/editor/integration/tests/AllTests.java8
-rw-r--r--tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/src/org/eclipse/papyrus/editor/integration/tests/tests/EditorReloadTest.java530
-rw-r--r--tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/META-INF/MANIFEST.MF8
-rw-r--r--tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/matchers/DiagramMatchers.java104
-rw-r--r--tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/Duck.java2
-rw-r--r--tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/AbstractModelFixture.java46
-rw-r--r--tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/JavaResource.java4
-rw-r--r--tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PapyrusEditorFixture.java507
-rw-r--r--tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PluginResource.java4
-rw-r--r--tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/ShowView.java74
58 files changed, 4940 insertions, 348 deletions
diff --git a/plugins/editor/org.eclipse.papyrus.editor/META-INF/MANIFEST.MF b/plugins/editor/org.eclipse.papyrus.editor/META-INF/MANIFEST.MF
index 4995983e4c5..7e0bbf7ac34 100644
--- a/plugins/editor/org.eclipse.papyrus.editor/META-INF/MANIFEST.MF
+++ b/plugins/editor/org.eclipse.papyrus.editor/META-INF/MANIFEST.MF
@@ -6,7 +6,8 @@ Require-Bundle: org.eclipse.papyrus.infra.core;bundle-version="1.0.0",
org.eclipse.gmf.runtime.diagram.ui;bundle-version="1.5.0",
org.eclipse.papyrus.infra.core.sasheditor;bundle-version="1.0.0",
org.eclipse.ui.ide;bundle-version="3.8.0",
- org.eclipse.papyrus.infra.core.log;bundle-version="1.0.0"
+ org.eclipse.papyrus.infra.core.log;bundle-version="1.0.0",
+ com.google.guava;bundle-version="11.0.0"
Bundle-Vendor: %providerName
Bundle-ActivationPolicy: lazy
Bundle-Version: 1.0.0.qualifier
diff --git a/plugins/editor/org.eclipse.papyrus.editor/src/org/eclipse/papyrus/editor/PapyrusPaletteSynchronizer.java b/plugins/editor/org.eclipse.papyrus.editor/src/org/eclipse/papyrus/editor/PapyrusPaletteSynchronizer.java
index ad19bc2d895..f655bfc175a 100644
--- a/plugins/editor/org.eclipse.papyrus.editor/src/org/eclipse/papyrus/editor/PapyrusPaletteSynchronizer.java
+++ b/plugins/editor/org.eclipse.papyrus.editor/src/org/eclipse/papyrus/editor/PapyrusPaletteSynchronizer.java
@@ -1,3 +1,16 @@
+/*****************************************************************************
+ * Copyright (c) 2014 Montages AG, CEA, 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:
+ * Montages AG - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 437217
+ *
+ *****************************************************************************/
package org.eclipse.papyrus.editor;
import org.eclipse.gef.ui.views.palette.PaletteView;
@@ -20,27 +33,15 @@ import org.eclipse.ui.IWorkbenchPage;
public PapyrusPaletteSynchronizer(PapyrusMultiDiagramEditor multiEditor) {
myMultiDiagramEditor = multiEditor;
+
+ // Handle the initial page selection
+ synchronizePaletteView(multiEditor.getISashWindowsContainer().getActiveSashWindowsPage());
}
- /*
- * (non-Javadoc)
- *
- * @see
- * org.eclipse.papyrus.infra.core.sasheditor.internal.ActivePageTracker.IActiveEditorChangedListener
- * #activeEditorChanged(org.eclipse.papyrus.infra.core.sasheditor.internal.PagePart,
- * org.eclipse.papyrus.infra.core.sasheditor.internal.PagePart)
- */
public void activeEditorChanged(PagePart oldEditor, PagePart newEditor) {
synchronizePaletteView(newEditor);
}
- /*
- * (non-Javadoc)
- *
- * @see
- * org.eclipse.papyrus.infra.core.sasheditor.editor.IPageChangedListener#pageChanged(org.eclipse
- * .papyrus.infra.core.sasheditor.editor.IPage)
- */
public void pageChanged(IPage newPage) {
synchronizePaletteView(newPage);
}
@@ -50,21 +51,21 @@ import org.eclipse.ui.IWorkbenchPage;
* inner page
*
* @param activePage
- * inner page to synchronize palette view with
+ * inner page to synchronize palette view with
*/
private void synchronizePaletteView(IPage activePage) {
PaletteView paletteView = findPaletteView();
- if (paletteView == null) {
+ if(paletteView == null) {
return;
}
// IEditorPage is not granted, it may be, e.g ErrorComponentPart
- IEditorPart activePart = activePage instanceof IEditorPage ? ((IEditorPage) activePage).getIEditorPart() : null;
- if (activePart == myLastActivePart) {
+ IEditorPart activePart = activePage instanceof IEditorPage ? ((IEditorPage)activePage).getIEditorPart() : null;
+ if(activePart == myLastActivePart) {
return;
}
-
- if (activePart == null) {
+
+ if(activePart == null) {
paletteView.partClosed(myLastActivePart);
} else {
// multi-editor may be activated outside of this code
@@ -80,15 +81,15 @@ import org.eclipse.ui.IWorkbenchPage;
* Called when host editor is disposed, cleans up
*/
public void dispose() {
- if (myLastActivePart == null) {
- // nothing to do
- return;
- }
PaletteView paletteView = findPaletteView();
- if (paletteView == null) {
+ if(paletteView == null) {
return;
}
- paletteView.partClosed(myLastActivePart);
+ if(myLastActivePart != null) {
+ paletteView.partClosed(myLastActivePart);
+ } else {
+ paletteView.partClosed(myMultiDiagramEditor);
+ }
}
/**
@@ -98,7 +99,7 @@ import org.eclipse.ui.IWorkbenchPage;
*/
private PaletteView findPaletteView() {
IWorkbenchPage samePage = myMultiDiagramEditor.getSite().getPage();
- return (PaletteView) samePage.findView(PaletteView.ID);
+ return (PaletteView)samePage.findView(PaletteView.ID);
}
}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/editor/AbstractMultiPageSashEditor.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/editor/AbstractMultiPageSashEditor.java
index 69e50222664..c33a59e41df 100644
--- a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/editor/AbstractMultiPageSashEditor.java
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/editor/AbstractMultiPageSashEditor.java
@@ -9,6 +9,7 @@
* Contributors:
* Cedric Dumoulin Cedric.dumoulin@lifl.fr - Initial API and implementation
* Christian W. Damus (CEA) - bug 431953 (pre-requisite refactoring of ModelSet service start-up)
+ * Christian W. Damus (CEA) - bug 437217
*
*****************************************************************************/
package org.eclipse.papyrus.infra.core.sasheditor.editor;
@@ -33,6 +34,9 @@ import org.eclipse.ui.part.EditorPart;
*/
public abstract class AbstractMultiPageSashEditor extends EditorPart implements IMultiPageEditorPart, IMultiEditorManager {
+ /** The parent composite of my sash container. */
+ private Composite parentComposite;
+
/** The pageProvider */
private ISashWindowsContentProvider pageProvider;
@@ -116,7 +120,6 @@ public abstract class AbstractMultiPageSashEditor extends EditorPart implements
public void init(IEditorSite site, IEditorInput input) throws PartInitException {
setSite(site);
setInput(input);
- site.setSelectionProvider(new MultiPageSelectionProvider(this));
}
/**
@@ -124,15 +127,10 @@ public abstract class AbstractMultiPageSashEditor extends EditorPart implements
*/
@Override
public void createPartControl(Composite parent) {
-
- // Create and intialize sash windows
- sashContainer = new SashWindowsContainer(this);
- sashContainer.setContentProvider(getContentProvider());
- sashContainer.createPartControl(parent);
-
- // Add double click menu
- tabMouseEventListener = new TabMouseEventListener(sashContainer, getSite());
-
+ parentComposite = parent;
+
+ getSite().setSelectionProvider(new MultiPageSelectionProvider(this));
+
activate();
}
@@ -143,6 +141,14 @@ public abstract class AbstractMultiPageSashEditor extends EditorPart implements
*/
protected void activate() {
+ // Create and initialize sash windows
+ sashContainer = new SashWindowsContainer(this);
+ sashContainer.setContentProvider(getContentProvider());
+ sashContainer.createPartControl(parentComposite);
+
+ // Add double click menu
+ tabMouseEventListener = new TabMouseEventListener(sashContainer, getSite());
+
tabsSynchronizer = new SashTabDecorationSynchronizer(sashContainer);
}
@@ -160,6 +166,16 @@ public abstract class AbstractMultiPageSashEditor extends EditorPart implements
}
tabsSynchronizer.dispose();
tabsSynchronizer = null;
+
+ if(tabMouseEventListener != null) {
+ tabMouseEventListener.dispose(sashContainer);
+ tabMouseEventListener = null;
+ }
+
+ if(sashContainer != null) {
+ sashContainer.dispose();
+ }
+ pageProvider = null;
}
/**
@@ -171,18 +187,9 @@ public abstract class AbstractMultiPageSashEditor extends EditorPart implements
@Override
public void dispose() {
deactivate();
-
- if(tabMouseEventListener != null) {
- tabMouseEventListener.dispose(sashContainer);
- tabMouseEventListener = null;
- }
-
+
//The selection provider keeps a reference to "this". It is not disposed.
getSite().setSelectionProvider(null);
- if(sashContainer != null) {
- sashContainer.dispose();
- }
- pageProvider = null;
super.dispose();
}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/SashWindowsContainer.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/SashWindowsContainer.java
index 35c7316ff8e..926883e994d 100644
--- a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/SashWindowsContainer.java
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/SashWindowsContainer.java
@@ -1,6 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2009 CEA LIST & LIFL
- *
+ * Copyright (c) 2009, 2014 LIFL, 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
@@ -9,6 +8,7 @@
*
* Contributors:
* Cedric Dumoulin Cedric.dumoulin@lifl.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 437217
*
*****************************************************************************/
package org.eclipse.papyrus.infra.core.sasheditor.internal;
@@ -284,7 +284,13 @@ public class SashWindowsContainer implements ISashWindowsContainer {
// End disposing children's SWT controls.
// It is possible to recall the dispose() method on a Widget, even if we are called by the dispose event.
// Recalling the dispose method will continue disposing SWT children's.
- container.dispose();
+
+ // DO NOT dispose the container composite, as we did not create it!
+ if(container != null) {
+ for(Control next : container.getChildren()) {
+ next.dispose();
+ }
+ }
// dispose part children
if(rootPart!=null) {
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/META-INF/MANIFEST.MF b/plugins/infra/core/org.eclipse.papyrus.infra.core/META-INF/MANIFEST.MF
index 72fe68e603a..b60b29d15a7 100644
--- a/plugins/infra/core/org.eclipse.papyrus.infra.core/META-INF/MANIFEST.MF
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/META-INF/MANIFEST.MF
@@ -1,8 +1,9 @@
Manifest-Version: 1.0
Export-Package: org.eclipse.papyrus.infra.core,
- org.eclipse.papyrus.infra.core.clipboard,
+ org.eclipse.papyrus.infra.core.clipboard,
org.eclipse.papyrus.infra.core.contentoutline,
org.eclipse.papyrus.infra.core.editor,
+ org.eclipse.papyrus.infra.core.editor.reload,
org.eclipse.papyrus.infra.core.editorsfactory,
org.eclipse.papyrus.infra.core.extension,
org.eclipse.papyrus.infra.core.extension.commands,
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/contentoutline/NestedEditorDelegatedOutlinePage.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/contentoutline/NestedEditorDelegatedOutlinePage.java
index 491760a70d4..3e75bfbff41 100644
--- a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/contentoutline/NestedEditorDelegatedOutlinePage.java
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/contentoutline/NestedEditorDelegatedOutlinePage.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2013 CEA LIST.
+ * Copyright (c) 2013, 2014 CEA LIST and other.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,6 +8,7 @@
*
* Contributors:
* Remi Schnekenburger (CEA LIST) - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 437217
*
*****************************************************************************/
package org.eclipse.papyrus.infra.core.contentoutline;
@@ -17,6 +18,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -24,15 +26,25 @@ import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.PlatformObject;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.papyrus.infra.core.Activator;
import org.eclipse.papyrus.infra.core.editor.IMultiDiagramEditor;
+import org.eclipse.papyrus.infra.core.editor.IReloadableEditor;
+import org.eclipse.papyrus.infra.core.editor.reload.EditorReloadEvent;
+import org.eclipse.papyrus.infra.core.editor.reload.IEditorReloadListener;
+import org.eclipse.papyrus.infra.core.editor.reload.IReloadContextProvider;
+import org.eclipse.papyrus.infra.core.resource.ModelSet;
import org.eclipse.papyrus.infra.core.sasheditor.editor.IEditorPage;
import org.eclipse.papyrus.infra.core.sasheditor.editor.IPage;
import org.eclipse.papyrus.infra.core.sasheditor.editor.IPageLifeCycleEventsListener;
import org.eclipse.papyrus.infra.core.sasheditor.editor.ISashWindowsContainer;
+import org.eclipse.papyrus.infra.core.services.ServiceException;
+import org.eclipse.papyrus.infra.core.utils.AdapterUtils;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
@@ -50,10 +62,15 @@ import org.eclipse.ui.part.PageBook;
import org.eclipse.ui.part.PageSite;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
+import com.google.common.collect.Lists;
+
/**
* Page for Papyrus outline when active nested editor is a GMF editor
*/
-public class NestedEditorDelegatedOutlinePage extends Page implements IPapyrusContentOutlinePage, IPageLifeCycleEventsListener {
+public class NestedEditorDelegatedOutlinePage extends Page implements IPapyrusContentOutlinePage, IPageLifeCycleEventsListener, IEditorReloadListener {
+
+ /** The editor for which I am a slave. */
+ private IMultiDiagramEditor multiEditor;
/** Sash window container to listen for page changes inside the same editor */
private ISashWindowsContainer sashWindowsContainer;
@@ -82,7 +99,16 @@ public class NestedEditorDelegatedOutlinePage extends Page implements IPapyrusCo
* {@inheritDoc}
*/
public void init(IMultiDiagramEditor multiEditor) {
+ this.multiEditor = multiEditor;
+
+ internalInit(multiEditor);
+
+ IReloadableEditor.Adapter.getAdapter(multiEditor).addEditorReloadListener(this);
+ }
+
+ private void internalInit(IMultiDiagramEditor multiEditor) {
sashWindowsContainer = (ISashWindowsContainer)multiEditor.getAdapter(ISashWindowsContainer.class);
+ sashWindowsContainer.addPageLifeCycleListener(this);
}
/**
@@ -103,6 +129,19 @@ public class NestedEditorDelegatedOutlinePage extends Page implements IPapyrusCo
*/
@Override
public void dispose() {
+ if(multiEditor != null) {
+ IReloadableEditor.Adapter.getAdapter(multiEditor).removeEditorReloadListener(this);
+ }
+
+ internalDispose();
+
+ multiEditor = null;
+
+ // Run super.
+ super.dispose();
+ }
+
+ private void internalDispose() {
// Deref all of the pages.
activeRec = null;
if(defaultPageRec != null) {
@@ -122,9 +161,6 @@ public class NestedEditorDelegatedOutlinePage extends Page implements IPapyrusCo
// remove listener and all refs to editor
sashWindowsContainer.removePageLifeCycleListener(this);
-
- // Run super.
- super.dispose();
}
/**
@@ -182,10 +218,12 @@ public class NestedEditorDelegatedOutlinePage extends Page implements IPapyrusCo
*/
@Override
public void createControl(Composite parent) {
- sashWindowsContainer.addPageLifeCycleListener(this);
-
sashEditorPageBook = new PageBook(parent, SWT.BORDER);
+ createContents();
+ }
+
+ protected void createContents() {
// Create the default page rec.
IContentOutlinePage defaultPage = createDefaultPage(sashEditorPageBook);
defaultPageRec = new OutlinePageRec(null, defaultPage);
@@ -274,11 +312,8 @@ public class NestedEditorDelegatedOutlinePage extends Page implements IPapyrusCo
*/
public void pageActivated(IPage page) {
// Activator.log.debug("Activated");
- // Create a page for the part.
- OutlinePageRec rec = getOutlinePageRec(page);
- if(rec == null) {
- rec = createPage(page);
- }
+ // Create a page for the partm, if necessary.
+ OutlinePageRec rec = getOutlinePageRec(page, true);
// Show the page, if it was successfully created
if(rec != null) {
@@ -309,6 +344,21 @@ public class NestedEditorDelegatedOutlinePage extends Page implements IPapyrusCo
//throw new UnsupportedOperationException("pageAboutToBeClosed not implemented " + page);
}
+ @Override
+ public void editorAboutToReload(EditorReloadEvent event) {
+ event.putContext(new OutlineContext());
+
+ internalDispose();
+ }
+
+ @Override
+ public void editorReloaded(EditorReloadEvent event) {
+ internalInit(event.getEditor());
+ createContents();
+
+ ((OutlineContext)event.getContext()).restore();
+ }
+
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// MAINLY INSPIRED FROM PAGE BOOK VIEW
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -537,6 +587,14 @@ public class NestedEditorDelegatedOutlinePage extends Page implements IPapyrusCo
return mapIPapyrusPageToOutlineRec.get(papyrusPage);
}
+ OutlinePageRec getOutlinePageRec(IPage papyrusPage, boolean create) {
+ OutlinePageRec result = getOutlinePageRec(papyrusPage);
+ if(result == null) {
+ result = createPage(papyrusPage);
+ }
+ return result;
+ }
+
/**
* Returns the page record for the given page of this view.
*
@@ -572,14 +630,15 @@ public class NestedEditorDelegatedOutlinePage extends Page implements IPapyrusCo
control.dispose();
}
- // free the page
- doDestroyPage(rec.papyrusPage, rec);
-
+ // Do this before destroying the page, otherwise we won't be able to retrieve the page site (it will be null)
IPageSite site = rec.getPageSite();
if(site instanceof PageSite) { // test null pointer and PageSite
((SubActionBars)((PageSite)site).getActionBars()).deactivate();
((SubActionBars)((PageSite)site).getActionBars()).dispose();
}
+
+ // Free the page
+ doDestroyPage(rec.papyrusPage, rec);
}
/*
@@ -952,4 +1011,67 @@ public class NestedEditorDelegatedOutlinePage extends Page implements IPapyrusCo
}
}
+
+ private class OutlineContext {
+
+ private List<PageContext> pages = Lists.newArrayListWithCapacity(mapIPapyrusPageToOutlineRec.size());
+
+ OutlineContext() {
+ for(OutlinePageRec next : mapIPapyrusPageToOutlineRec.values()) {
+ pages.add(new PageContext(next));
+ }
+ }
+
+ public void restore() {
+ for(PageContext next : pages) {
+ next.restore();
+ }
+ }
+
+ //
+ // Nested types
+ //
+
+ private class PageContext {
+
+ final URI diagramToken;
+
+ final Object context;
+
+ PageContext(OutlinePageRec outlinePage) {
+ Object diagram = outlinePage.papyrusPage.getRawModel();
+ diagramToken = (diagram instanceof EObject) ? EcoreUtil.getURI((EObject)diagram) : null;
+
+ // Can only sensibly manage restoring the state of the page if we can find it again
+ if(diagramToken == null) {
+ context = null;
+ } else {
+ IReloadContextProvider provider = AdapterUtils.adapt(outlinePage.contentOutlinePage, IReloadContextProvider.class, null);
+ context = (provider == null) ? null : provider.createReloadContext();
+ }
+ }
+
+ void restore() {
+ if(diagramToken != null) {
+ try {
+ ModelSet modelSet = multiEditor.getServicesRegistry().getService(ModelSet.class);
+
+ Object diagram = modelSet.getEObject(diagramToken, true);
+ if(diagram != null) {
+ IPage page = sashWindowsContainer.lookupModelPage(diagram);
+ if(page != null) {
+ OutlinePageRec outlinePage = getOutlinePageRec(page, true);
+ if((outlinePage != null) && (context != null)) {
+ // Restore it. We know it adapts if it provided the reload state in the first place
+ AdapterUtils.adapt(outlinePage.contentOutlinePage, IReloadContextProvider.class, null).restore(context);
+ }
+ }
+ }
+ } catch (ServiceException e) {
+ Activator.log.error(e);
+ }
+ }
+ }
+ }
+ }
}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/CoreMultiDiagramEditor.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/CoreMultiDiagramEditor.java
index 70800f02d49..50644e87186 100644
--- a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/CoreMultiDiagramEditor.java
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/CoreMultiDiagramEditor.java
@@ -12,6 +12,7 @@
* Christian W. Damus (CEA) - manage models by URI, not IFile (CDO)
* Christian W. Damus (CEA) - bug 410346
* Christian W. Damus (CEA) - bug 431953 (pre-requisite refactoring of ModelSet service start-up)
+ * Christian W. Damus (CEA) - bug 437217
*
*****************************************************************************/
@@ -22,10 +23,14 @@ import static org.eclipse.papyrus.infra.core.Activator.log;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
import org.eclipse.core.commands.operations.IUndoContext;
import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.ui.URIEditorInput;
import org.eclipse.emf.common.util.URI;
@@ -41,10 +46,13 @@ import org.eclipse.gef.ui.actions.ActionRegistry;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.papyrus.infra.core.Activator;
import org.eclipse.papyrus.infra.core.contentoutline.ContentOutlineRegistry;
+import org.eclipse.papyrus.infra.core.editor.reload.EditorReloadEvent;
+import org.eclipse.papyrus.infra.core.editor.reload.IEditorReloadListener;
import org.eclipse.papyrus.infra.core.lifecycleevents.DoSaveEvent;
import org.eclipse.papyrus.infra.core.lifecycleevents.IEditorInputChangedListener;
import org.eclipse.papyrus.infra.core.lifecycleevents.ISaveAndDirtyService;
@@ -86,11 +94,15 @@ import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IGotoMarker;
import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.ui.progress.IWorkbenchSiteProgressService;
+import org.eclipse.ui.statushandlers.StatusManager;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
import org.eclipse.ui.views.properties.IPropertySheetPage;
import org.eclipse.ui.views.properties.tabbed.ITabbedPropertySheetPageContributor;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
+import com.google.common.collect.ImmutableList;
+
/**
* Multi diagram editor allowing to plug various kind of editors. Editors are
* registered with the help of the Eclipse extension mechanism. This
@@ -194,7 +206,7 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen
}
}
- protected EditorInputChangedListener editorInputChangedListener = new EditorInputChangedListener(this);
+ protected EditorInputChangedListener editorInputChangedListener;
private TransactionalEditingDomain transactionalEditingDomain;
@@ -222,7 +234,7 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen
/**
* A listener on model change events.
*/
- private ContentChangedListener contentChangedListener = new ContentChangedListener();
+ private ContentChangedListener contentChangedListener;
/**
* Undo context used to have the same undo context in all Papyrus related
@@ -233,6 +245,22 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen
private IUndoContext undoContext;
/**
+ * Editor reload listeners.
+ */
+ private CopyOnWriteArrayList<IEditorReloadListener> reloadListeners = new CopyOnWriteArrayList<IEditorReloadListener>();
+
+ /**
+ * Whether a re-load is currently pending (awaiting next activation of the editor).
+ */
+ private boolean reloadPending;
+
+ public CoreMultiDiagramEditor() {
+ super();
+
+ addSelfReloadListener();
+ }
+
+ /**
* Get the contentOutlineRegistry. Create it if needed.
*
* @return the contentOutlineRegistry
@@ -431,6 +459,10 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen
return getSite().getSelectionProvider().getSelection();
}
+ if(adapter == IReloadableEditor.class) {
+ return createReloadAdapter();
+ }
+
return super.getAdapter(adapter);
}
@@ -445,8 +477,7 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen
// Set editor name
setPartName(input.getName());
- loadModelAndServices();
- loadNestedEditors();
+ initContents();
}
@Override
@@ -610,6 +641,7 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen
// Listen on input changed from the ISaveAndDirtyService
+ editorInputChangedListener = new EditorInputChangedListener(this);
saveAndDirtyService.addInputChangedListener(editorInputChangedListener);
getLifecycleManager().firePostInit(this);
}
@@ -642,6 +674,9 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen
setContentProvider(contentProvider);
// Listen on contentProvider changes
+ if(contentChangedListener == null) {
+ contentChangedListener = new ContentChangedListener();
+ }
sashModelMngr.getSashModelContentChangedProvider().addListener(contentChangedListener);
IEditorInput input = getEditorInput();
@@ -680,8 +715,8 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen
*/
@Override
protected void activate() {
- // TODO Auto-generated method stub
super.activate();
+
initFolderTabMenus();
try {
@@ -739,17 +774,77 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen
*/
@Override
public void dispose() {
+ for(IPropertySheetPage propertiesPage : this.propertiesPages) {
+ propertiesPage.dispose();
+ }
+ propertiesPages.clear();
+
+ super.dispose();
+ }
+
+ private IReloadableEditor createReloadAdapter() {
+ return new IReloadableEditor() {
+
+ @Override
+ public void reloadEditor(boolean save) throws CoreException {
+ reloadPending = true;
+
+ if(save) {
+ try {
+ ((IWorkbenchSiteProgressService)getSite().getService(IWorkbenchSiteProgressService.class)).busyCursorWhile(new IRunnableWithProgress() {
+
+ @Override
+ public void run(IProgressMonitor monitor) {
+ doSave(monitor);
+ }
+ });
+ } catch (Exception e) {
+ throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Save before re-load failed.", e)); //$NON-NLS-1$
+ }
+ }
+
+ // If I am already active, then re-load now
+ IWorkbenchPage page = getSite().getPage();
+ if(page.getActiveEditor() == CoreMultiDiagramEditor.this) {
+ doReload();
+ }
+ }
+
+ @Override
+ public void addEditorReloadListener(IEditorReloadListener listener) {
+ reloadListeners.addIfAbsent(listener);
+ }
+
+ @Override
+ public void removeEditorReloadListener(IEditorReloadListener listener) {
+ reloadListeners.remove(listener);
+ }
+ };
+ }
+
+ private void addSelfReloadListener() {
+ createReloadAdapter().addEditorReloadListener(new IEditorReloadListener() {
+
+ @Override
+ public void editorAboutToReload(EditorReloadEvent event) {
+ event.putContext(new MultiDiagramEditorSelectionContext(event.getEditor()));
+ }
+
+ @Override
+ public void editorReloaded(EditorReloadEvent event) {
+ ((MultiDiagramEditorSelectionContext)event.getContext()).restore(event.getEditor());
+ }
+ });
+ }
+
+ @Override
+ protected void deactivate() {
getLifecycleManager().fireBeforeClose(this);
if(sashModelMngr != null) {
sashModelMngr.getSashModelContentChangedProvider().removeListener(contentChangedListener);
}
- // Avoid memory leak
- // This call is done from the ServicesRegistry when it is disposed.
- // Don't need to do it there.
- // if(resourceSet != null) {
- // resourceSet.unload();
- // }
+ super.deactivate();
// dispose available service
if(servicesRegistry != null) {
@@ -781,13 +876,66 @@ public class CoreMultiDiagramEditor extends AbstractMultiPageSashEditor implemen
undoContext = null;
saveAndDirtyService = null;
sashModelMngr = null;
+ }
- for(IPropertySheetPage propertiesPage : this.propertiesPages) {
- propertiesPage.dispose();
+ void initContents() throws PartInitException {
+ loadModelAndServices();
+ loadNestedEditors();
+ }
+
+ @Override
+ public void setFocus() {
+ super.setFocus();
+
+ if(isReloadPending()) {
+ doReload();
+ }
+ }
+
+ boolean isReloadPending() {
+ return reloadPending;
+ }
+
+ private void doReload() {
+ reloadPending = false;
+
+ final IWorkbenchPage page = getSite().getPage();
+ final IWorkbenchPart activePart = page.getActivePart();
+ final IEditorPart activeEditor = page.getActiveEditor();
+
+ final Iterable<? extends IEditorReloadListener> listeners = ImmutableList.copyOf(reloadListeners);
+ final EditorReloadEvent event = new EditorReloadEvent(CoreMultiDiagramEditor.this);
+
+ try {
+ event.dispatchEditorAboutToReload(listeners);
+
+ deactivate();
+
+ initContents();
+
+ activate();
+
+ // My self-listener will be first, to ensure that the pages are all restored before dependents run
+ event.dispatchEditorReloaded(listeners);
+ } catch (CoreException e) {
+ // Failed to properly unload/load in place, so just close
+ page.closeEditor(CoreMultiDiagramEditor.this, false);
+
+ StatusManager.getManager().handle(e.getStatus(), StatusManager.LOG | StatusManager.SHOW);
+ } finally {
+ event.dispose();
+
+ // Ensure that the editor previously active is active again (if it still exists)
+ if((activeEditor != null) && page.isPartVisible(activeEditor)) {
+ page.activate(activeEditor);
+ }
+
+ // Ensure that the part previously active is active again (if it still exists and is not the active editor)
+ if((activePart != null) && (activePart != activeEditor) && page.isPartVisible(activePart)) {
+ page.activate(activePart);
+ }
}
- propertiesPages.clear();
- super.dispose();
}
/**
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/IReloadableEditor.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/IReloadableEditor.java
new file mode 100644
index 00000000000..be3a7c7aca4
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/IReloadableEditor.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2014 CEA 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:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.infra.core.editor;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.papyrus.infra.core.Activator;
+import org.eclipse.papyrus.infra.core.editor.reload.IEditorReloadListener;
+import org.eclipse.papyrus.infra.core.utils.AdapterUtils;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.ide.IDE;
+
+
+/**
+ * An {@linkplain IAdaptable adapter protocol} for editors that know how to internally
+ * reload themselves without disturbing the workbench window's perspective layout.
+ */
+public interface IReloadableEditor {
+
+ /**
+ * Reloads me in-place in the perspective layout.
+ *
+ * @param save
+ * whether to save before re-loading
+ *
+ * @throws CoreException
+ * on any failure to unload, reload, or whatever
+ */
+ void reloadEditor(boolean save) throws CoreException;
+
+ void addEditorReloadListener(IEditorReloadListener listener);
+
+ void removeEditorReloadListener(IEditorReloadListener listener);
+
+ /**
+ * A convenience adapter for editors that don't actually know how to reload themselves in place.
+ * It simply closes the editor and then opens it again on the original input.
+ */
+ class Adapter implements IReloadableEditor {
+
+ private final IEditorPart editor;
+
+ public Adapter(IEditorPart editor) {
+ super();
+
+ this.editor = editor;
+ }
+
+ public static IReloadableEditor getAdapter(IMultiDiagramEditor editor) {
+ return AdapterUtils.adapt(editor, IReloadableEditor.class, new Adapter(editor));
+ }
+
+ public void reloadEditor(boolean save) throws CoreException {
+ final IWorkbenchPage page = editor.getSite().getPage();
+ final IEditorInput currentInput = editor.getEditorInput();
+
+ final Display display = editor.getSite().getShell().getDisplay();
+
+ final String editorId = editor.getSite().getId();
+
+ if(save) {
+ editor.doSave(new NullProgressMonitor());
+ }
+
+ page.closeEditor(editor, save);
+
+ display.asyncExec(new Runnable() {
+
+ @Override
+ public void run() {
+ try {
+ IDE.openEditor(page, currentInput, editorId);
+ } catch (PartInitException ex) {
+ Activator.log.error(ex);
+ }
+ }
+ });
+
+ }
+
+ @Override
+ public void addEditorReloadListener(IEditorReloadListener listener) {
+ // Don't need to track these listeners because I never properly reload an editor
+ }
+
+ @Override
+ public void removeEditorReloadListener(IEditorReloadListener listener) {
+ // Don't need to track these listeners because I never properly reload an editor
+ }
+ }
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/MultiDiagramEditorSelectionContext.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/MultiDiagramEditorSelectionContext.java
new file mode 100644
index 00000000000..366b636e7c1
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/MultiDiagramEditorSelectionContext.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2014 CEA 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:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.infra.core.editor;
+
+import java.util.List;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.papyrus.infra.core.editor.reload.CompositeReloadContext;
+import org.eclipse.papyrus.infra.core.editor.reload.DelegatingReloadContext;
+import org.eclipse.papyrus.infra.core.editor.reload.EMFSelectionContext;
+import org.eclipse.papyrus.infra.core.editor.reload.EditorReloadEvent;
+import org.eclipse.papyrus.infra.core.sasheditor.editor.IComponentPage;
+import org.eclipse.papyrus.infra.core.sasheditor.editor.IEditorPage;
+import org.eclipse.papyrus.infra.core.sasheditor.editor.IPage;
+import org.eclipse.papyrus.infra.core.sasheditor.editor.IPageVisitor;
+import org.eclipse.papyrus.infra.core.sasheditor.editor.ISashWindowsContainer;
+import org.eclipse.papyrus.infra.core.utils.AdapterUtils;
+
+import com.google.common.collect.Lists;
+
+
+/**
+ * A {@linkplain EditorReloadEvent reload event} context that restores the selection of which editor page
+ * is active in an {@link IMultiDiagramEditor} that is reloaded and delegates to its pages to capture
+ * re-load context for each to restore whatever they need to restore (internal selections etc.).
+ */
+class MultiDiagramEditorSelectionContext extends CompositeReloadContext {
+
+ private ISashWindowsContainer sashContainer;
+
+ MultiDiagramEditorSelectionContext(IMultiDiagramEditor editor) {
+ super();
+
+ init(editor);
+
+ ActivePageSelectionProvider activePageSelectionProvider = new ActivePageSelectionProvider();
+ IPage active = sashContainer.getActiveSashWindowsPage();
+ DiagramPageContext activePage = null;
+
+ List<IPage> visible = getAllPages(sashContainer);
+
+ for(IPage page : visible) {
+ final DelegatingReloadContext delegator = (page instanceof IEditorPage) ? add(new DelegatingReloadContext(((IEditorPage)page).getIEditorPart())) : null;
+ DiagramPageContext context;
+
+ if(page == active) {
+ // This one will have the selection of the active page
+ context = new DiagramPageContext(activePageSelectionProvider, page, delegator);
+ activePage = context;
+ } else {
+ // We make sure always to restore the active page last
+ // so that its selection is certain to be set properly
+ context = new DiagramPageContext(EmptySelectionProvider.INSTANCE, page, delegator);
+ add(context);
+ }
+ }
+
+ if(activePage != null) {
+ // Restore this one last
+ add(activePage);
+ }
+ }
+
+ @Override
+ public void dispose() {
+ sashContainer = null;
+ super.dispose();
+ }
+
+ private List<IPage> getAllPages(ISashWindowsContainer container) {
+ final List<IPage> result = Lists.newArrayList();
+
+ container.visit(new IPageVisitor() {
+
+ @Override
+ public void accept(IEditorPage page) {
+ result.add(page);
+ }
+
+ @Override
+ public void accept(IComponentPage page) {
+ result.add(page);
+ }
+ });
+
+ return result;
+ }
+
+ private void init(IMultiDiagramEditor editor) {
+ sashContainer = AdapterUtils.adapt(editor, ISashWindowsContainer.class, null);
+ }
+
+ void restore(IMultiDiagramEditor editor) {
+ init(editor);
+
+ ISelectionProvider selectionProvider = new ActivePageSelectionProvider();
+ for(DiagramPageContext next : getReloadContexts(DiagramPageContext.class)) {
+ next.restore(selectionProvider);
+ }
+ }
+
+ //
+ // Nested types
+ //
+
+ private class DiagramPageContext extends EMFSelectionContext {
+
+ private URI pageRef;
+
+ private DelegatingReloadContext pageContext;
+
+ DiagramPageContext(ISelectionProvider structuredSelectionProvider, IPage page, DelegatingReloadContext pageContext) {
+ super(structuredSelectionProvider);
+
+ this.pageContext = pageContext;
+ this.pageRef = getToken(page.getRawModel());
+ }
+
+ @Override
+ public void restore(ISelectionProvider structuredSelectionProvider) {
+ IPage page = sashContainer.lookupModelPage(resolveToken(pageRef));
+
+ if((pageContext != null) && (page instanceof IEditorPage)) {
+ pageContext.restore(((IEditorPage)page).getIEditorPart());
+ }
+
+ super.restore(structuredSelectionProvider);
+ }
+
+ @Override
+ protected Object deresolveSelectableElement(Object selectableElement) {
+ return (selectableElement instanceof IPage) ? ((IPage)selectableElement).getRawModel() : super.deresolveSelectableElement(selectableElement);
+ }
+
+ @Override
+ protected Object resolveSelectableElement(Object deresolved) {
+ return sashContainer.lookupModelPage(deresolved);
+ }
+ }
+
+ private static class EmptySelectionProvider implements ISelectionProvider {
+
+ static final EmptySelectionProvider INSTANCE = new EmptySelectionProvider();
+
+ EmptySelectionProvider() {
+ super();
+ }
+
+ @Override
+ public ISelection getSelection() {
+ return StructuredSelection.EMPTY;
+ }
+
+ @Override
+ public void setSelection(ISelection selection) {
+ // Pass
+ }
+
+ @Override
+ public void addSelectionChangedListener(ISelectionChangedListener listener) {
+ // Not needed because the selection is always empty
+ }
+
+ @Override
+ public void removeSelectionChangedListener(ISelectionChangedListener listener) {
+ // Not needed because the selection is always empty
+ }
+
+ }
+
+ private class ActivePageSelectionProvider implements ISelectionProvider {
+
+ ActivePageSelectionProvider() {
+ super();
+ }
+
+ @Override
+ public ISelection getSelection() {
+ IPage active = sashContainer.getActiveSashWindowsPage();
+
+ return (active == null) ? StructuredSelection.EMPTY : new StructuredSelection(active);
+ }
+
+ @Override
+ public void setSelection(ISelection selection) {
+ if(!selection.isEmpty()) {
+ IPage page = (IPage)((IStructuredSelection)selection).getFirstElement();
+ sashContainer.selectPage(page);
+ }
+ }
+
+ @Override
+ public void addSelectionChangedListener(ISelectionChangedListener listener) {
+ // Not needed
+ }
+
+ @Override
+ public void removeSelectionChangedListener(ISelectionChangedListener listener) {
+ // Not needed
+ }
+
+ }
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/CompositeReloadContext.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/CompositeReloadContext.java
new file mode 100644
index 00000000000..57d99c9fd03
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/CompositeReloadContext.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2014 CEA 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:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.infra.core.editor.reload;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.papyrus.infra.core.utils.AdapterUtils;
+
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+
+/**
+ * An {@linkplain EditorReloadEvent#putContext(Object) editor reload context} that composes other reload contexts.
+ * This should be used whenever a {@linkplain IReloadContextProvider reload context provider} supplies multiple
+ * reload contexts, to ensure that they are properly initialized by the reload system.
+ */
+public class CompositeReloadContext implements IDisposableReloadContext, IAdaptable {
+
+ private final Collection<Object> reloadContexts;
+
+ public CompositeReloadContext() {
+ this(Collections.EMPTY_LIST);
+ }
+
+ public CompositeReloadContext(Iterable<?> reloadContexts) {
+ super();
+
+ this.reloadContexts = Lists.newArrayList(reloadContexts);
+ }
+
+ public <T> T add(T reloadContext) {
+ reloadContexts.add(reloadContext);
+ return reloadContext;
+ }
+
+ public Iterable<?> getReloadContexts() {
+ return Collections.unmodifiableCollection(reloadContexts);
+ }
+
+ public <T> Iterable<T> getReloadContexts(Class<T> type) {
+ return Iterables.filter(getReloadContexts(), type);
+ }
+
+ @Override
+ public void dispose() {
+ for(Object next : reloadContexts) {
+ if(next instanceof IDisposableReloadContext) {
+ ((IDisposableReloadContext)next).dispose();
+ }
+ }
+
+ reloadContexts.clear();
+ }
+
+ @Override
+ public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
+ return (adapter == IInternalEMFSelectionContext.class) ? getEMFContext() : null;
+ }
+
+ private IInternalEMFSelectionContext getEMFContext() {
+ IInternalEMFSelectionContext result = null;
+
+ for(Object next : reloadContexts) {
+ if(AdapterUtils.adapt(next, IInternalEMFSelectionContext.class, null) != null) {
+ // We need the adapter
+ result = new IInternalEMFSelectionContext.Composite(this);
+ break;
+ }
+ }
+
+ return result;
+ }
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/DelegatingReloadContext.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/DelegatingReloadContext.java
new file mode 100644
index 00000000000..405c7c9977d
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/DelegatingReloadContext.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2014 CEA 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:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.infra.core.editor.reload;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.papyrus.infra.core.utils.AdapterUtils;
+
+
+/**
+ * An {@linkplain EditorReloadEvent#putContext(Object) editor reload context} that delegates to another reload context.
+ * This should be used whenever a {@linkplain IReloadContextProvider reload context provider} is needed to get a reload
+ * context to delegate to.
+ */
+public class DelegatingReloadContext implements IDisposableReloadContext, IAdaptable {
+
+ private Object delegate;
+
+ public DelegatingReloadContext(Object reloadContextProvider) {
+ super();
+
+ IReloadContextProvider provider = AdapterUtils.adapt(reloadContextProvider, IReloadContextProvider.class, null);
+ if(provider != null) {
+ delegate = provider.createReloadContext();
+ }
+ }
+
+ @Override
+ public void dispose() {
+ if(delegate instanceof IDisposableReloadContext) {
+ ((IDisposableReloadContext)delegate).dispose();
+ }
+
+ delegate = null;
+ }
+
+ public Object getDelegate() {
+ return delegate;
+ }
+
+ public void restore(Object reloadContextProvider) {
+ if(delegate != null) {
+ IReloadContextProvider provider = AdapterUtils.adapt(reloadContextProvider, IReloadContextProvider.class, null);
+ if(provider != null) {
+ provider.restore(delegate);
+ }
+ }
+ }
+
+ @Override
+ public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
+ return (adapter == IInternalEMFSelectionContext.class) ? getEMFContext() : null;
+ }
+
+ private IInternalEMFSelectionContext getEMFContext() {
+ IInternalEMFSelectionContext result = null;
+
+ if((delegate != null) && (AdapterUtils.adapt(delegate, IInternalEMFSelectionContext.class, null) != null)) {
+ // We need the adapter
+ result = new IInternalEMFSelectionContext.Delegating(this);
+ }
+
+ return result;
+ }
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/EMFSelectionContext.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/EMFSelectionContext.java
new file mode 100644
index 00000000000..e625a97aad7
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/EMFSelectionContext.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014 CEA 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:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.infra.core.editor.reload;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.jface.viewers.ISelectionProvider;
+
+
+/**
+ * A convenient selection re-load context for UIs that present EMF-based content.
+ */
+public class EMFSelectionContext extends SelectionContext<ISelectionProvider, URI> implements IAdaptable {
+
+ private IInternalEMFSelectionContext emfContext;
+
+ public EMFSelectionContext(ISelectionProvider structuredSelectionProvider) {
+ super(structuredSelectionProvider);
+ }
+
+ @Override
+ public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
+ return (adapter == IInternalEMFSelectionContext.class) ? getEMFContext() : null;
+ }
+
+ final IInternalEMFSelectionContext getEMFContext() {
+ if(emfContext == null) {
+ emfContext = new IInternalEMFSelectionContext.Default();
+ }
+ return emfContext;
+ }
+
+ @Override
+ protected URI getToken(Object object) {
+ return getEMFContext().getToken(object);
+ }
+
+ @Override
+ protected Object resolveToken(URI token) {
+ return getEMFContext().resolveToken(token);
+ }
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/EMFTreeViewerContext.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/EMFTreeViewerContext.java
new file mode 100644
index 00000000000..91b01e98d15
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/EMFTreeViewerContext.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014 CEA 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:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.infra.core.editor.reload;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.jface.viewers.AbstractTreeViewer;
+
+/**
+ * A convenient context object for {@link IEditorReloadListener}s to store in an {@link EditorReloadEvent} to capture and restore
+ * the expansion and selection state of nodes in an EMF-based tree viewer.
+ */
+public class EMFTreeViewerContext extends TreeViewerContext<URI> implements IAdaptable {
+
+ private IInternalEMFSelectionContext emfContext;
+
+ public EMFTreeViewerContext(AbstractTreeViewer viewer) {
+ super(viewer);
+ }
+
+ @Override
+ public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
+ return (adapter == IInternalEMFSelectionContext.class) ? getEMFContext() : null;
+ }
+
+ final IInternalEMFSelectionContext getEMFContext() {
+ if(emfContext == null) {
+ emfContext = new IInternalEMFSelectionContext.Default();
+ }
+ return emfContext;
+ }
+
+ @Override
+ protected URI getToken(Object object) {
+ return getEMFContext().getToken(object);
+ }
+
+ @Override
+ protected Object resolveToken(URI token) {
+ return getEMFContext().resolveToken(token);
+ }
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/EditorReloadAdapter.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/EditorReloadAdapter.java
new file mode 100644
index 00000000000..64a8445081c
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/EditorReloadAdapter.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2014 CEA 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:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.infra.core.editor.reload;
+
+
+
+/**
+ * Convenience superclass for selective implementation of editor reload call-backs.
+ */
+public class EditorReloadAdapter implements IEditorReloadListener {
+
+ public EditorReloadAdapter() {
+ super();
+ }
+
+ @Override
+ public void editorAboutToReload(EditorReloadEvent event) {
+ // Pass
+ }
+
+ @Override
+ public void editorReloaded(EditorReloadEvent event) {
+ // Pass
+ }
+
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/EditorReloadEvent.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/EditorReloadEvent.java
new file mode 100644
index 00000000000..20416bc86d8
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/EditorReloadEvent.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2014 CEA 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:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.infra.core.editor.reload;
+
+import java.util.EventObject;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.papyrus.infra.core.Activator;
+import org.eclipse.papyrus.infra.core.editor.IMultiDiagramEditor;
+import org.eclipse.papyrus.infra.core.editor.IReloadableEditor;
+import org.eclipse.papyrus.infra.core.resource.ModelSet;
+import org.eclipse.papyrus.infra.core.services.ServiceException;
+import org.eclipse.papyrus.infra.core.utils.AdapterUtils;
+
+import com.google.common.base.Supplier;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
+
+
+/**
+ * The event object for notifications of each phase in the reloading of a {@linkplain IReloadableEditor reloadable editor}.
+ */
+public class EditorReloadEvent extends EventObject {
+
+ private static final long serialVersionUID = 1L;
+
+ public static final int ABOUT_TO_RELOAD = 1;
+
+ public static final int RELOADED = 2;
+
+ private int type;
+
+ private transient Map<IEditorReloadListener, Object> context;
+
+ private transient IEditorReloadListener currentListener;
+
+ public EditorReloadEvent(IMultiDiagramEditor editor) {
+ super(editor);
+ }
+
+ public final IMultiDiagramEditor getEditor() {
+ return (IMultiDiagramEditor)getSource();
+ }
+
+ public final int getEventType() {
+ return type;
+ }
+
+ /**
+ * Puts some opaque representation of contextual state for the caller to retrieve later when an editor is
+ * {@linkplain IEditorReloadListener#editorReloaded(EditorReloadEvent) reloaded}.
+ * The canonical example of this usage is storing state such as selection, expanded tree nodes, etc. to restore after re-building a UI that
+ * depends on the reloaded editor. After the editor re-load completes and all listeners are notified of that, then all context objects are
+ * released. Any that implement the {@link IDisposableReloadContext} interface are disposed according to that protocol. This is done even if it
+ * happens that the editor re-load procedure cannot complete normally and the editor is forced to close without notifying the post-reload
+ * listeners.
+ *
+ * @param object
+ * some state to stash for later retrieval following the re-loading of the editor
+ *
+ * @return the previous context object, if any (there normally wouldn't be as each listener that is invoked has its own context storage
+ *
+ * @throws IllegalStateException
+ * on any attempt to invoke this method except during an {@link IEditorReloadListener#editorAboutToReload(EditorReloadEvent)} call-back
+ */
+ public Object putContext(Object object) {
+ checkContext(ABOUT_TO_RELOAD);
+
+ IInternalEMFSelectionContext emfContext = AdapterUtils.adapt(object, IInternalEMFSelectionContext.class, null);
+ if(emfContext != null) {
+ initContext(emfContext);
+ }
+
+ return context.put(currentListener, object);
+ }
+
+ /**
+ * Retrieves an opaque representation of contextual state that was previously {@linkplain #putContext(Object) put} by the caller.
+ *
+ * @return the previously stashed object, or {@code null} if none
+ *
+ * @throws IllegalStateException
+ * on any attempt to invoke this method except during an {@link IEditorReloadListener#editorReloaded(EditorReloadEvent)} call-back
+ */
+ public Object getContext() {
+ checkContext(RELOADED);
+ return context.get(currentListener);
+ }
+
+ private void initContext(IInternalEMFSelectionContext context) {
+ Supplier<ResourceSet> resourceSetSupplier = new Supplier<ResourceSet>() {
+
+ @Override
+ public ResourceSet get() {
+ try {
+ return getEditor().getServicesRegistry().getService(ModelSet.class);
+ } catch (ServiceException e) {
+ Activator.log.error(e);
+ throw new IllegalStateException("Invalid service registry in editor"); //$NON-NLS-1$
+ }
+ }
+ };
+
+ context.setResourceSetSupplier(resourceSetSupplier);
+ }
+
+ protected final void checkContext(int phase) {
+ if(currentListener == null) {
+ throw new IllegalStateException("Not in an IEditorReloadListener call-back"); //$NON-NLS-1$
+ }
+
+ if(phase != this.type) {
+ throw new IllegalStateException(String.format("Not in '%s' listener call-back", (phase == ABOUT_TO_RELOAD) ? "editorAboutToReload" : "editorReloaded"));
+ }
+ }
+
+ public final void dispatchEditorAboutToReload(Iterable<? extends IEditorReloadListener> listeners) {
+ context = Maps.newHashMap();
+ type = ABOUT_TO_RELOAD;
+
+ for(Iterator<? extends IEditorReloadListener> iter = listeners.iterator(); iter.hasNext();) {
+ currentListener = iter.next();
+
+ try {
+ currentListener.editorAboutToReload(this);
+ } catch (Exception e) {
+ Activator.log.error("Uncaught exception in editor reload listener.", e); //$NON-NLS-1$
+ } finally {
+ currentListener = null;
+ }
+ }
+ }
+
+ public final void dispatchEditorReloaded(Iterable<? extends IEditorReloadListener> listeners) {
+ type = RELOADED;
+
+ for(Iterator<? extends IEditorReloadListener> iter = listeners.iterator(); iter.hasNext();) {
+ currentListener = iter.next();
+
+ try {
+ currentListener.editorReloaded(this);
+ } catch (Exception e) {
+ Activator.log.error("Uncaught exception in editor reload listener.", e); //$NON-NLS-1$
+ } finally {
+ currentListener = null;
+ }
+ }
+ }
+
+ public void dispose() {
+ if(context != null) {
+ Error error = null;
+
+ try {
+ for(IDisposableReloadContext next : Iterables.filter(context.values(), IDisposableReloadContext.class)) {
+ try {
+ next.dispose();
+ } catch (Exception e) {
+ Activator.log.error("Uncaught exception in editor reload context disposal.", e); //$NON-NLS-1$
+ } catch (Error e) {
+ if(error == null) {
+ error = e;
+ }
+ Activator.log.error("Uncaught exception in editor reload context disposal.", e); //$NON-NLS-1$
+ }
+ }
+ } finally {
+ context = null;
+ }
+
+ if(error != null) {
+ throw error;
+ }
+ }
+ }
+
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/IDisposableReloadContext.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/IDisposableReloadContext.java
new file mode 100644
index 00000000000..2e44d932fa6
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/IDisposableReloadContext.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2014 CEA 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:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.infra.core.editor.reload;
+
+/**
+ * Protocol implemented by {@link EditorReloadEvent} context objects that must be disposed when they are no longer needed.
+ *
+ * @see EditorReloadEvent#dispose()
+ */
+public interface IDisposableReloadContext {
+
+ void dispose();
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/IEditorReloadListener.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/IEditorReloadListener.java
new file mode 100644
index 00000000000..27387a89c7c
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/IEditorReloadListener.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014 CEA 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:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.infra.core.editor.reload;
+
+import java.util.EventListener;
+
+import org.eclipse.papyrus.infra.core.editor.IReloadableEditor;
+
+
+/**
+ * A protocol for notification of the phases of re-loading of an {@link IReloadableEditor}.
+ */
+public interface IEditorReloadListener extends EventListener {
+
+ /**
+ * Notifies that an editor is about to reload. Implementors may put stuff into the {@code event}'s {@link EditorReloadEvent#putContext(Object)
+ * context} to retrieve in an eventual {@linkplain #editorReloaded(EditorReloadEvent) }re-load} notification. The canonical example of this
+ * usage is storing state such as selection, expanded tree nodes, etc. to restore after re-building a UI that depends on the reloaded
+ * editor.
+ *
+ * @param event
+ * notification that an editor is going to re-load itself
+ */
+ void editorAboutToReload(EditorReloadEvent event);
+
+ /**
+ * Notifies that an editor has reloaded. Implementors may retrieve from the {@code event} any {@link EditorReloadEvent#getContext()
+ * context} that they put in {@linkplain #editorAboutToReload(EditorReloadEvent) before} the re-load.
+ *
+ * @param event
+ * notification that an editor has reloaded
+ */
+ void editorReloaded(EditorReloadEvent event);
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/IInternalEMFSelectionContext.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/IInternalEMFSelectionContext.java
new file mode 100644
index 00000000000..c0c031a0378
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/IInternalEMFSelectionContext.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2014 CEA 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:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.infra.core.editor.reload;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.papyrus.infra.core.utils.AdapterUtils;
+
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+
+
+/**
+ * An internal interface provided (usually as an {@linkplain IAdaptable#getAdapter(Class) adapter}) by EMF-based {@linkplain SelectionContext
+ * selection contexts}.
+ */
+interface IInternalEMFSelectionContext {
+
+ void setResourceSetSupplier(Supplier<? extends ResourceSet> resourceSetSupplier);
+
+ URI getToken(Object object);
+
+ Object resolveToken(URI token);
+
+ class Default implements IInternalEMFSelectionContext {
+
+ Supplier<? extends ResourceSet> resourceSetSupplier;
+
+ Default() {
+ super();
+ }
+
+ public void setResourceSetSupplier(Supplier<? extends ResourceSet> resourceSetSupplier) {
+ this.resourceSetSupplier = Suppliers.memoize(resourceSetSupplier);
+ }
+
+ public URI getToken(Object object) {
+ return (object instanceof EObject) ? EcoreUtil.getURI((EObject)object) : null;
+ }
+
+ public Object resolveToken(URI token) {
+ ResourceSet rset = (resourceSetSupplier == null) ? null : resourceSetSupplier.get();
+ return (rset == null) ? null : rset.getEObject(token, true);
+ }
+
+ }
+
+ class Composite extends Default {
+
+ private final CompositeReloadContext composite;
+
+ Composite(CompositeReloadContext composite) {
+ super();
+
+ this.composite = composite;
+ }
+
+ @Override
+ public void setResourceSetSupplier(Supplier<? extends ResourceSet> resourceSetSupplier) {
+ super.setResourceSetSupplier(resourceSetSupplier);
+
+ for(Object next : composite.getReloadContexts()) {
+ IInternalEMFSelectionContext emfContext = AdapterUtils.adapt(next, IInternalEMFSelectionContext.class, null);
+ if(emfContext != null) {
+ // Pass along the memoizer so that we can all share it
+ emfContext.setResourceSetSupplier(this.resourceSetSupplier);
+ }
+ }
+ }
+ }
+
+ class Delegating extends Default {
+
+ private final DelegatingReloadContext delegating;
+
+ Delegating(DelegatingReloadContext delegating) {
+ super();
+
+ this.delegating = delegating;
+ }
+
+ @Override
+ public void setResourceSetSupplier(Supplier<? extends ResourceSet> resourceSetSupplier) {
+ super.setResourceSetSupplier(resourceSetSupplier);
+
+ IInternalEMFSelectionContext emfContext = AdapterUtils.adapt(delegating.getDelegate(), IInternalEMFSelectionContext.class, null);
+ if(emfContext != null) {
+ // Pass along the memoizer so that we can all share it
+ emfContext.setResourceSetSupplier(this.resourceSetSupplier);
+ }
+ }
+ }
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/IReloadContextProvider.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/IReloadContextProvider.java
new file mode 100644
index 00000000000..281c629e023
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/IReloadContextProvider.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014 CEA 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:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.infra.core.editor.reload;
+
+
+/**
+ * An adapter protocol for objects that can provide {@code context}s to be included in the
+ * re-load state of dependent parts in an {@link EditorReloadEvent}, for the purpose of
+ * restoring the state of those objects after re-load has completed.
+ */
+public interface IReloadContextProvider {
+
+ /**
+ * Creates an opaque token from which the receiver can be {@linkplain #restore(Object) restored} after the editor has reloaded.
+ *
+ * @return an opaque editor re-load context, or {@code null} if none is needed on this occasion (for example because the receiver
+ * is in its default state)
+ */
+ Object createReloadContext();
+
+ /**
+ * Reloads the receiver's state from a token previously {@linkplain #createReloadContext() provided}.
+ *
+ * @param reloadContext
+ * the opaque re-load context token
+ */
+ void restore(Object reloadContext);
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/SelectionContext.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/SelectionContext.java
new file mode 100644
index 00000000000..cfe1e3be89a
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/SelectionContext.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2014 CEA 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:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.infra.core.editor.reload;
+
+import java.util.List;
+
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+
+import com.google.common.collect.Lists;
+
+/**
+ * A convenient context object for {@link IEditorReloadListener}s to store in an {@link EditorReloadEvent} to capture and restore
+ * the selection state a selection provider;
+ *
+ * @param <V>
+ * the type of selection provider
+ * @param <T>
+ * the type of token used to restore the selection state
+ */
+public abstract class SelectionContext<V extends ISelectionProvider, T> {
+
+ private List<T> selection = Lists.newArrayList();
+
+ public SelectionContext(V structuredSelectionProvider) {
+ for(Object next : ((IStructuredSelection)structuredSelectionProvider.getSelection()).toList()) {
+ T token = token(next);
+ if(token != null) {
+ selection.add(token);
+ }
+ }
+ }
+
+ public void restore(V structuredSelectionProvider) {
+ List<Object> select = Lists.newArrayListWithCapacity(selection.size());
+ for(T next : selection) {
+ Object resolved = resolve(next);
+ if(resolved != null) {
+ select.add(resolved);
+ }
+ }
+ setSelection(structuredSelectionProvider, select);
+ }
+
+ T token(Object selectableElement) {
+ Object deresolved = deresolveSelectableElement(selectableElement);
+ return (deresolved == null) ? null : getToken(deresolved);
+ }
+
+ protected Object deresolveSelectableElement(Object selectableElement) {
+ return selectableElement;
+ }
+
+ protected abstract T getToken(Object object);
+
+ Object resolve(T token) {
+ Object deresolved = resolveToken(token);
+ return (deresolved == null) ? null : resolveSelectableElement(deresolved);
+ }
+
+ protected Object resolveSelectableElement(Object deresolved) {
+ return deresolved;
+ }
+
+ protected abstract Object resolveToken(T token);
+
+ protected void setSelection(V structuredSelectionProvider, List<?> selection) {
+ structuredSelectionProvider.setSelection(new StructuredSelection(selection));
+ }
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/TreeViewerContext.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/TreeViewerContext.java
new file mode 100644
index 00000000000..2c2ec8520cf
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/editor/reload/TreeViewerContext.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2014 CEA 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:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.infra.core.editor.reload;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.eclipse.jface.viewers.AbstractTreeViewer;
+import org.eclipse.jface.viewers.StructuredSelection;
+
+import com.google.common.collect.Lists;
+
+/**
+ * A convenient context object for {@link IEditorReloadListener}s to store in an {@link EditorReloadEvent} to capture and restore
+ * the expansion and selection state of nodes in a tree viewer.
+ */
+public abstract class TreeViewerContext<T> extends SelectionContext<AbstractTreeViewer, T> {
+
+ private List<T> expandedNodes = Lists.newArrayList();
+
+ public TreeViewerContext(AbstractTreeViewer viewer) {
+ super(viewer);
+
+ for(Object next : viewer.getExpandedElements()) {
+ T token = token(next);
+ if(token != null) {
+ expandedNodes.add(token);
+ }
+ }
+ }
+
+ public void restore(AbstractTreeViewer viewer) {
+ List<Object> expand = Lists.newArrayListWithCapacity(expandedNodes.size());
+ for(T next : expandedNodes) {
+ Object resolved = resolve(next);
+ if(resolved != null) {
+ expand.add(resolved);
+ }
+ }
+ setExpandedElements(viewer, expand);
+
+ super.restore(viewer);
+ }
+
+ protected void setSelection(AbstractTreeViewer viewer, List<?> selection) {
+ viewer.setSelection(new StructuredSelection(selection), true);
+ }
+
+ protected void setExpandedElements(AbstractTreeViewer viewer, Collection<?> toExpand) {
+ viewer.setExpandedElements(toExpand.toArray());
+ }
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/services/ResourceUpdateService.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/services/ResourceUpdateService.java
index 3cf5783c524..74ac57d45c2 100644
--- a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/services/ResourceUpdateService.java
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/services/ResourceUpdateService.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2013 CEA LIST.
+ * Copyright (c) 2013, 2014 CEA LIST and others.
*
*
* All rights reserved. This program and the accompanying materials
@@ -9,12 +9,14 @@
*
* Contributors:
* Camille Letavernier (camille.letavernier@cea.fr) - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 437217
*
*****************************************************************************/
package org.eclipse.papyrus.infra.core.services;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.concurrent.ConcurrentMap;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
@@ -23,14 +25,21 @@ import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.osgi.util.NLS;
import org.eclipse.papyrus.infra.core.Activator;
import org.eclipse.papyrus.infra.core.editor.IMultiDiagramEditor;
+import org.eclipse.papyrus.infra.core.editor.IReloadableEditor;
import org.eclipse.papyrus.infra.core.lifecycleevents.DoSaveEvent;
import org.eclipse.papyrus.infra.core.lifecycleevents.ILifeCycleEventsProvider;
import org.eclipse.papyrus.infra.core.lifecycleevents.ISaveAndDirtyService;
@@ -38,12 +47,14 @@ import org.eclipse.papyrus.infra.core.lifecycleevents.ISaveEventListener;
import org.eclipse.papyrus.infra.core.resource.ModelSet;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
-import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
-import org.eclipse.ui.PartInitException;
-import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.IWorkbenchPartSite;
+import org.eclipse.ui.progress.IWorkbenchSiteProgressService;
+import org.eclipse.ui.progress.UIJob;
+
+import com.google.common.collect.Maps;
/**
* A Service to check workspace modifications on current resources
@@ -61,6 +72,8 @@ public class ResourceUpdateService implements IService, IPartListener {
protected boolean isSaving;
+ protected ConcurrentMap<IMultiDiagramEditor, Job> pendingEditorCloseJobs = Maps.newConcurrentMap();
+
/**
* Update isSaving flag asynchronously to avoid race conditions, see bug 411574
*/
@@ -129,38 +142,49 @@ public class ResourceUpdateService implements IService, IPartListener {
}
final IMultiDiagramEditor editor = registry.getService(IMultiDiagramEditor.class);
if(editor != null) {
- Runnable closeEditorRunnable = new Runnable() {
+ final IWorkbenchPartSite site = editor.getSite();
+ UIJob closeEditorJob = new UIJob(site.getShell().getDisplay(), NLS.bind("Reload editor {0}", editor.getTitle())) {
@Override
- public void run() {
- final IWorkbenchPage page = editor.getSite().getPage();
- final IEditorInput currentInput = editor.getEditorInput();
-
-
- final String editorId = editor.getSite().getId();
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+ // Remove the pending job
+ pendingEditorCloseJobs.remove(editor);
+
+ IStatus result = Status.OK_STATUS;
+ monitor = SubMonitor.convert(monitor, IProgressMonitor.UNKNOWN);
+
+ try {
+ if(reopen) {
+ try {
+ IReloadableEditor.Adapter.getAdapter(editor).reloadEditor(save);
+ } catch (CoreException e) {
+ result = e.getStatus();
+ }
+ } else {
+ // Just close it
- if(save) {
- editor.doSave(new NullProgressMonitor());
- }
- page.closeEditor(editor, save);
- if(reopen) {
- Display.getCurrent().asyncExec(new Runnable() {
-
- @Override
- public void run() {
- try {
- IDE.openEditor(page, currentInput, editorId);
- } catch (PartInitException ex) {
- Activator.log.error(ex);
- }
+ if(save) {
+ editor.doSave(new NullProgressMonitor());
}
- });
+
+ final IWorkbenchPage page = editor.getSite().getPage();
+ page.closeEditor(editor, save);
+ }
+ } finally {
+ monitor.done();
}
+
+ return result;
}
};
- //Async execution to avoid lock conflicts on the Workspace (Probably owned by this thread, and not the UI thread)
- editor.getSite().getShell().getDisplay().asyncExec(closeEditorRunnable);
+ // We are notified usually of at least three resources (*.di, *.notation, *.uml) that are unloaded, but
+ // there's no need to close and re-open the same editor three times
+ if(pendingEditorCloseJobs.putIfAbsent(editor, closeEditorJob) == null) {
+ //Async execution to avoid lock conflicts on the Workspace (Probably owned by this thread, and not the UI thread)
+ IWorkbenchSiteProgressService progressService = (IWorkbenchSiteProgressService)site.getService(IWorkbenchSiteProgressService.class);
+ progressService.schedule(closeEditorJob);
+ }
}
} catch (ServiceException ex) {
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/plugin.xml b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/plugin.xml
index ec5c2816412..d24fc3ff8eb 100644
--- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/plugin.xml
+++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/plugin.xml
@@ -133,6 +133,13 @@
type="org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider.IOpenable">
</adapter>
</factory>
+ <factory
+ adaptableType="org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditor$DiagramOutlinePage"
+ class="org.eclipse.papyrus.infra.gmfdiag.common.adapter.DiagramOutlineAdapterFactory">
+ <adapter
+ type="org.eclipse.papyrus.infra.core.editor.reload.IReloadContextProvider">
+ </adapter>
+ </factory>
</extension>
<!-- ElementType bindings for diagram duplication with paste command -->
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/DiagramReloadContextProvider.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/DiagramReloadContextProvider.java
new file mode 100644
index 00000000000..0250f075318
--- /dev/null
+++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/DiagramReloadContextProvider.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2014 CEA 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:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.infra.gmfdiag.common;
+
+import java.util.Collection;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.gef.EditDomain;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.ui.palette.PaletteViewer;
+import org.eclipse.gef.ui.views.palette.PalettePage;
+import org.eclipse.papyrus.infra.core.editor.reload.EMFSelectionContext;
+import org.eclipse.papyrus.infra.core.editor.reload.EditorReloadEvent;
+import org.eclipse.papyrus.infra.core.editor.reload.IDisposableReloadContext;
+import org.eclipse.papyrus.infra.core.editor.reload.IReloadContextProvider;
+import org.eclipse.papyrus.infra.core.utils.AdapterUtils;
+
+import com.google.common.collect.Iterables;
+
+
+/**
+ * An {@linkplain EditorReloadEvent editor reload} context provider for nested diagram editors, providing
+ * a reload context that captures and restores the edit-part selection (tracked by URI of the selected
+ * edit parts' notation views) and palette state (delegated to a {@link PaletteViewerReloadContextProvider}).
+ */
+class DiagramReloadContextProvider implements IReloadContextProvider {
+
+ private final SynchronizableGmfDiagramEditor editor;
+
+ public DiagramReloadContextProvider(SynchronizableGmfDiagramEditor editor) {
+ this.editor = editor;
+ }
+
+ @Override
+ public Object createReloadContext() {
+ return new DiagramSelectionContext(editor);
+ }
+
+ @Override
+ public void restore(Object reloadContext) {
+ ((DiagramSelectionContext)reloadContext).restore(editor);
+ }
+
+ //
+ // Nested types
+ //
+
+ private static class DiagramSelectionContext extends EMFSelectionContext implements IDisposableReloadContext {
+
+ private SynchronizableGmfDiagramEditor editor;
+
+ private Object embeddedPaletteContext;
+
+ private Object palettePageContext;
+
+ DiagramSelectionContext(SynchronizableGmfDiagramEditor editor) {
+ super(editor.getDiagramGraphicalViewer());
+
+ PaletteViewer embedded = getEmbeddedPalette(editor);
+ if(embedded != null) {
+ embeddedPaletteContext = PaletteViewerReloadContextProvider.getInstance(embedded).createReloadContext();
+ }
+
+ PalettePage page = Iterables.getFirst(editor.getPalettePages(), null);
+ if(page != null) {
+ // Get one context for all the pages (there should be only one Palette view!)
+ IReloadContextProvider pageProvider = AdapterUtils.adapt(page, IReloadContextProvider.class, null);
+ if(pageProvider != null) {
+ palettePageContext = pageProvider.createReloadContext();
+ }
+ }
+ }
+
+ @Override
+ public void dispose() {
+ editor = null;
+ embeddedPaletteContext = null;
+ palettePageContext = null;
+ }
+
+ void restore(SynchronizableGmfDiagramEditor editor) {
+ this.editor = editor;
+
+ restore(editor.getDiagramGraphicalViewer());
+
+ if(embeddedPaletteContext != null) {
+ PaletteViewer palette = getEmbeddedPalette(editor);
+ if(palette != null) {
+ PaletteViewerReloadContextProvider.getInstance(palette).restore(embeddedPaletteContext);
+ }
+ }
+
+ if(palettePageContext != null) {
+ Collection<? extends PalettePage> pages = editor.getPalettePages();
+ if(pages.isEmpty()) {
+ // Defer until the page is created (which we assume it eventually will be, since evidently it
+ // was there when we captured the reload context)
+ editor.setDeferredPalettePageReloadContext(palettePageContext);
+ } else {
+ for(PalettePage page : pages) {
+ IReloadContextProvider pageProvider = AdapterUtils.adapt(page, IReloadContextProvider.class, null);
+ if(pageProvider != null) {
+ pageProvider.restore(palettePageContext);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ protected Object deresolveSelectableElement(Object selectableElement) {
+ Object result = null;
+
+ if(selectableElement instanceof EditPart) {
+ Object model = ((EditPart)selectableElement).getModel();
+ if(model instanceof EObject) {
+ result = model;
+ }
+ }
+
+ return result;
+ }
+
+ @Override
+ protected Object resolveSelectableElement(Object deresolved) {
+ return editor.getDiagramGraphicalViewer().getEditPartRegistry().get(deresolved);
+ }
+
+ PaletteViewer getEmbeddedPalette(SynchronizableGmfDiagramEditor editor) {
+ PaletteViewer result = null;
+
+ if(editor.getDiagramEditDomain() instanceof EditDomain) {
+ result = ((EditDomain)editor.getDiagramEditDomain()).getPaletteViewer();
+ }
+
+ return result;
+ }
+ }
+}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/PaletteViewerReloadContextProvider.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/PaletteViewerReloadContextProvider.java
new file mode 100644
index 00000000000..630f4994d46
--- /dev/null
+++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/PaletteViewerReloadContextProvider.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2014 CEA 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:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.infra.gmfdiag.common;
+
+import java.util.List;
+
+import org.eclipse.gef.palette.PaletteContainer;
+import org.eclipse.gef.palette.PaletteEntry;
+import org.eclipse.gef.palette.PaletteStack;
+import org.eclipse.gef.ui.palette.PaletteViewer;
+import org.eclipse.papyrus.infra.core.editor.reload.EditorReloadEvent;
+import org.eclipse.papyrus.infra.core.editor.reload.IReloadContextProvider;
+import org.eclipse.papyrus.infra.core.utils.AdapterUtils;
+import org.eclipse.papyrus.infra.tools.util.UIUtil;
+import org.eclipse.ui.IMemento;
+
+
+/**
+ * An {@linkplain EditorReloadEvent editor reload} context provider for palette viewers, providing
+ * a reload context that captures and restores the expansion states of drawers and selection states
+ * of stacks and tools.
+ */
+class PaletteViewerReloadContextProvider implements IReloadContextProvider {
+
+ private static final String MEMENTO_ACTIVE_ENTRY = "activeEntry"; //$NON-NLS-1$
+
+ private PaletteViewer palette;
+
+ public PaletteViewerReloadContextProvider(PaletteViewer palette) {
+ super();
+
+ this.palette = palette;
+ }
+
+ public static IReloadContextProvider getInstance(PaletteViewer palette) {
+ IReloadContextProvider result = AdapterUtils.adapt(palette, IReloadContextProvider.class, null);
+
+ if(result == null) {
+ result = new PaletteViewerReloadContextProvider(palette);
+ }
+
+ return result;
+ }
+
+ @Override
+ public Object createReloadContext() {
+ IMemento result = UIUtil.createLocalMemento();
+ palette.saveState(result);
+ saveMoreState(palette.getPaletteRoot(), result);
+ return result;
+ }
+
+ @Override
+ public void restore(Object reloadContext) {
+ IMemento memento = (IMemento)reloadContext;
+ palette.restoreState(memento);
+ restoreMoreState(palette.getPaletteRoot(), memento);
+ }
+
+ /**
+ * The palette's own memento doesn't record which tool of a stack is the stack's active tool.
+ */
+ void saveMoreState(PaletteEntry entry, IMemento memento) {
+ if(entry instanceof PaletteStack) {
+ PaletteStack stack = (PaletteStack)entry;
+ memento.putInteger(MEMENTO_ACTIVE_ENTRY, stack.getChildren().indexOf(stack.getActiveEntry()));
+ }
+
+ if(entry instanceof PaletteContainer) {
+ PaletteContainer container = (PaletteContainer)entry;
+ List<?> children = container.getChildren();
+ IMemento[] mementos = memento.getChildren();
+
+ int max = Math.min(children.size(), mementos.length);
+ for(int i = 0; i < max; i++) {
+ saveMoreState((PaletteEntry)children.get(i), mementos[i]);
+ }
+ }
+ }
+
+ /**
+ * @see #saveMoreState(PaletteEntry, IMemento)
+ */
+ void restoreMoreState(PaletteEntry entry, IMemento memento) {
+ if(entry instanceof PaletteStack) {
+ PaletteStack stack = (PaletteStack)entry;
+ List<?> children = stack.getChildren();
+
+ int activeIndex = memento.getInteger(MEMENTO_ACTIVE_ENTRY);
+ if((activeIndex >= 0) && (activeIndex < children.size())) {
+ stack.setActiveEntry((PaletteEntry)children.get(activeIndex));
+ }
+ }
+
+ if(entry instanceof PaletteContainer) {
+ PaletteContainer container = (PaletteContainer)entry;
+ List<?> children = container.getChildren();
+ IMemento[] mementos = memento.getChildren();
+
+ int max = Math.min(children.size(), mementos.length);
+ for(int i = 0; i < max; i++) {
+ restoreMoreState((PaletteEntry)children.get(i), mementos[i]);
+ }
+ }
+ }
+
+}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/SynchronizableGmfDiagramEditor.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/SynchronizableGmfDiagramEditor.java
index f1a007ac59d..42aa9c6f1bb 100644
--- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/SynchronizableGmfDiagramEditor.java
+++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/SynchronizableGmfDiagramEditor.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2010 CEA LIST.
+ * Copyright (c) 2010, 2014 CEA LIST and others.
*
*
* All rights reserved. This program and the accompanying materials
@@ -9,6 +9,7 @@
*
* Contributors:
* Patrick Tessier (CEA LIST) Patrick.tessier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 437217
*
*****************************************************************************/
package org.eclipse.papyrus.infra.gmfdiag.common;
@@ -21,11 +22,14 @@ import java.util.Map;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.emf.transaction.RollbackException;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.DefaultEditDomain;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.commands.CommandStack;
+import org.eclipse.gef.ui.palette.PaletteViewer;
+import org.eclipse.gef.ui.views.palette.PalettePage;
import org.eclipse.gmf.runtime.common.core.command.CompositeCommand;
import org.eclipse.gmf.runtime.common.core.command.ICommand;
import org.eclipse.gmf.runtime.diagram.core.preferences.PreferencesHint;
@@ -41,6 +45,7 @@ import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.papyrus.commands.CheckedDiagramCommandStack;
+import org.eclipse.papyrus.infra.core.editor.reload.IReloadContextProvider;
import org.eclipse.papyrus.infra.gmfdiag.common.preferences.PreferencesConstantsHelper;
import org.eclipse.papyrus.infra.gmfdiag.common.reconciler.DiagramReconciler;
import org.eclipse.papyrus.infra.gmfdiag.common.reconciler.DiagramReconcilersReader;
@@ -50,9 +55,18 @@ import org.eclipse.papyrus.infra.gmfdiag.common.utils.GMFUnsafe;
import org.eclipse.papyrus.infra.tools.util.EclipseCommandUtils;
import org.eclipse.papyrus.infra.widgets.util.IRevealSemanticElement;
import org.eclipse.papyrus.infra.widgets.util.NavigationTarget;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.IActionBars;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.commands.ICommandService;
+import org.eclipse.ui.part.IPageSite;
+
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
/**
*
@@ -66,6 +80,10 @@ import org.eclipse.ui.commands.ICommandService;
//suppress the warning for WorkspaceViewerProperties
public class SynchronizableGmfDiagramEditor extends DiagramDocumentEditor implements IRevealSemanticElement, NavigationTarget {
+ private Collection<PalettePageWrapper> palettePages;
+
+ private Object palettePageState;
+
public SynchronizableGmfDiagramEditor(boolean hasFlyoutPalette) {
super(hasFlyoutPalette);
}
@@ -151,9 +169,48 @@ public class SynchronizableGmfDiagramEditor extends DiagramDocumentEditor implem
if(type == Diagram.class) {
return getDiagram();
}
+ if(type == IReloadContextProvider.class) {
+ return new DiagramReloadContextProvider(this);
+ }
+ if(type == PalettePage.class) {
+ if(palettePages == null) {
+ palettePages = Lists.newArrayListWithExpectedSize(1);
+ } else {
+ cleanUpPalettePages();
+ if(!palettePages.isEmpty()) {
+ // Make the new page look just like the last one (for continuity of the UI when the
+ // PapyrusPaletteSynchronizer causes a new page to be created)
+ Iterables.getLast(palettePages, null).saveState();
+ }
+ }
+ PalettePageWrapper result = new PalettePageWrapper((CustomPalettePage)super.getAdapter(type));
+ palettePages.add(result);
+ return result;
+ }
return super.getAdapter(type);
}
+ Collection<? extends PalettePage> getPalettePages() {
+ if(palettePages == null) {
+ return Collections.emptyList();
+ } else {
+ cleanUpPalettePages();
+ return Collections.unmodifiableCollection(palettePages);
+ }
+ }
+
+ void setDeferredPalettePageReloadContext(Object reloadContext) {
+ palettePageState = reloadContext;
+ }
+
+ private void cleanUpPalettePages() {
+ for(Iterator<PalettePageWrapper> iter = palettePages.iterator(); iter.hasNext();) {
+ if(iter.next().isDisposed()) {
+ iter.remove();
+ }
+ }
+ }
+
/**
* Configures my diagram edit domain with its command stack.
* This method has been completely overridden in order to use a proxy stack.
@@ -357,6 +414,109 @@ public class SynchronizableGmfDiagramEditor extends DiagramDocumentEditor implem
}
}
+ protected class PalettePageWrapper implements PalettePage, IAdaptable {
+
+ private final CustomPalettePage delegate;
+
+ private boolean disposed;
+
+ protected PalettePageWrapper(CustomPalettePage delegate) {
+ this.delegate = delegate;
+ }
+
+ public void createControl(Composite parent) {
+ Control existing = getControl();
+ if((existing != null) && !existing.isDisposed()) {
+ // Attempting to creating the page controls again? Bail
+ return;
+ }
+
+ delegate.createControl(parent);
+
+ delegate.getControl().addDisposeListener(new DisposeListener() {
+
+ @Override
+ public void widgetDisposed(DisposeEvent e) {
+ disposed = true;
+
+ SynchronizableGmfDiagramEditor.this.palettePages.remove(PalettePageWrapper.this);
+ }
+ });
+
+ if(palettePageState != null) {
+ // We're re-creating the palette page after having closed it, either for editor re-load
+ // or the PapyrusPaletteSynchronizer forcing a palette refresh. Reinitialize from the
+ // last saved state
+ PaletteViewerReloadContextProvider.getInstance(getPaletteViewer()).restore(palettePageState);
+ palettePageState = null;
+ }
+ }
+
+ public void dispose() {
+ // Save current state for potential re-opening later
+ saveState();
+ delegate.dispose();
+ }
+
+ public boolean isDisposed() {
+ return disposed;
+ }
+
+ void saveState() {
+ PaletteViewer palette = getPaletteViewer();
+ if(palette != null) {
+ palettePageState = PaletteViewerReloadContextProvider.getInstance(palette).createReloadContext();
+ }
+ }
+
+ public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
+ if(adapter == IReloadContextProvider.class) {
+ return new IReloadContextProvider() {
+
+ @Override
+ public Object createReloadContext() {
+ return (getPaletteViewer() != null) ? PaletteViewerReloadContextProvider.getInstance(getPaletteViewer()).createReloadContext() : null;
+ }
+
+ @Override
+ public void restore(Object reloadContext) {
+ if(getPaletteViewer() != null) {
+ PaletteViewerReloadContextProvider.getInstance(getPaletteViewer()).restore(reloadContext);
+ } else {
+ // We'll defer this until the page control is created
+ palettePageState = reloadContext;
+ }
+ }
+ };
+ }
+ return delegate.getAdapter(adapter);
+ }
+
+ public Control getControl() {
+ // CustomPalettePage will NPE if asked for the control before the PaletteViewer is created
+ return (delegate.getPaletteViewer() == null) ? null : delegate.getControl();
+ }
+
+ public void setFocus() {
+ delegate.setFocus();
+ }
+
+ public void setActionBars(IActionBars actionBars) {
+ delegate.setActionBars(actionBars);
+ }
+ public void init(IPageSite pageSite) {
+ delegate.init(pageSite);
+ }
+
+ public IPageSite getSite() {
+ return delegate.getSite();
+ }
+
+ public PaletteViewer getPaletteViewer() {
+ return delegate.getPaletteViewer();
+ }
+
+ }
}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/adapter/DiagramOutlineAdapterFactory.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/adapter/DiagramOutlineAdapterFactory.java
new file mode 100644
index 00000000000..acf4fde39ae
--- /dev/null
+++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/adapter/DiagramOutlineAdapterFactory.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2014 CEA 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:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.infra.gmfdiag.common.adapter;
+
+import org.eclipse.core.runtime.IAdapterFactory;
+import org.eclipse.papyrus.infra.core.editor.reload.IReloadContextProvider;
+
+/**
+ * An adapter factory for the outline page contributed by nested diagram editors.
+ */
+public class DiagramOutlineAdapterFactory implements IAdapterFactory {
+
+ private static final Class<?>[] ADAPTERS = { IReloadContextProvider.class };
+
+ @SuppressWarnings("rawtypes")
+ public Class[] getAdapterList() {
+ return ADAPTERS;
+ }
+
+ public Object getAdapter(Object adaptableObject, @SuppressWarnings("rawtypes") Class adapterType) {
+ if(adapterType == IReloadContextProvider.class) {
+ if(DiagramOutlineReloadContextProvider.isDiagramOutline(adaptableObject)) {
+ return new DiagramOutlineReloadContextProvider(adaptableObject);
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/adapter/DiagramOutlineReloadContextProvider.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/adapter/DiagramOutlineReloadContextProvider.java
new file mode 100644
index 00000000000..2e9d4f381c6
--- /dev/null
+++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/adapter/DiagramOutlineReloadContextProvider.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2014 CEA 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:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.infra.gmfdiag.common.adapter;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditor;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.papyrus.infra.core.editor.reload.IReloadContextProvider;
+import org.eclipse.papyrus.infra.gmfdiag.common.Activator;
+
+
+/**
+ * A {@linkplain IReloadContextProvider reload context provider} for nested diagram outline pages that records and restores the selection of
+ * which presentation mode (tree outline or thumbnail overview) is active for each outline page. This implementation uses reflection to access
+ * internals (non API) of the outline page. On any problem in initializing this reflective access, the adapter basically disables itself and
+ * never participates in editor re-load, so that the system continues normally but with reduced functionality.
+ */
+class DiagramOutlineReloadContextProvider implements IReloadContextProvider {
+
+ private static final int ID_OUTLINE = 0;
+
+ private static final int ID_OVERVIEW = 1;
+
+ private static final Class<?> diagramOutlinePage;
+
+ private static final Method showPage;
+
+ private static final Field showOutlineAction;
+
+ static {
+ Class<?> diagramOutlinePageClass = null;
+ Method showPageMethod = null;
+ Field showOutlineActionField = null;
+
+ for(Class<?> next : DiagramEditor.class.getDeclaredClasses()) {
+ if("DiagramOutlinePage".equals(next.getSimpleName())) { //$NON-NLS-1$
+ diagramOutlinePageClass = next;
+
+ try {
+ showPageMethod = diagramOutlinePageClass.getDeclaredMethod("showPage", int.class); //$NON-NLS-1$
+ showPageMethod.setAccessible(true);
+
+ showOutlineActionField = diagramOutlinePageClass.getDeclaredField("showOutlineAction"); //$NON-NLS-1$
+ showOutlineActionField.setAccessible(true);
+ } catch (Exception e) {
+ // Can't reflect? Then abandon all hope
+ Activator.log.error(e);
+ diagramOutlinePageClass = null;
+ }
+
+ break;
+ }
+ }
+
+ diagramOutlinePage = diagramOutlinePageClass;
+ showPage = showPageMethod;
+ showOutlineAction = showOutlineActionField;
+ }
+
+ private final Object diagramOutline;
+
+ public DiagramOutlineReloadContextProvider(Object diagramOutline) {
+ super();
+
+ this.diagramOutline = diagramOutline;
+ }
+
+ @Override
+ public Object createReloadContext() {
+ return new ReloadContext(diagramOutline);
+ }
+
+ @Override
+ public void restore(Object reloadContext) {
+ ((ReloadContext)reloadContext).restore(diagramOutline);
+ }
+
+ static boolean isDiagramOutline(Object o) {
+ // If we couldn't reflect on DiagramOutline class, then we will never detect a diagram outline
+ // instance, so we will never try to create an adapter, and all is safe. The only consequence
+ // will be that we don't get diagram outline state properly restored. That's fine
+ return (diagramOutlinePage != null) && diagramOutlinePage.isInstance(o);
+ }
+
+ //
+ // Nested types
+ //
+
+ private static class ReloadContext {
+
+ private final int pageID;
+
+ public ReloadContext(Object diagramOutline) {
+ super();
+
+ try {
+ this.pageID = ((IAction)showOutlineAction.get(diagramOutline)).isChecked() ? ID_OUTLINE : ID_OVERVIEW;
+ } catch (IllegalAccessException e) {
+ // We wouldn't be here if we couldn't make it accessible. Something is very wrong
+ throw new Error(e);
+ }
+ }
+
+ void restore(Object diagramOutline) {
+ try {
+ showPage.invoke(diagramOutline, pageID);
+ } catch (IllegalAccessException e) {
+ // We wouldn't be here if we couldn't make it accessible. Something is very wrong
+ throw new Error(e);
+ } catch (InvocationTargetException e) {
+ Throwable target = e.getTargetException();
+ if(target instanceof RuntimeException) {
+ throw (RuntimeException)target;
+ } else if(target instanceof Error) {
+ throw (Error)target;
+ } else {
+ Activator.log.error(target);
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.outline/src/org/eclipse/papyrus/infra/gmfdiag/outline/DiagramOutline.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.outline/src/org/eclipse/papyrus/infra/gmfdiag/outline/DiagramOutline.java
index a9b1798347c..dfe7cebb9b1 100644
--- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.outline/src/org/eclipse/papyrus/infra/gmfdiag/outline/DiagramOutline.java
+++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.outline/src/org/eclipse/papyrus/infra/gmfdiag/outline/DiagramOutline.java
@@ -1,5 +1,5 @@
/***********************************************************************
- * Copyright (c) 2008, 2009 Anyware Technologies, Obeo, CEA LIST
+ * Copyright (c) 2008, 2014 Anyware Technologies, Obeo, 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
@@ -10,10 +10,13 @@
* Anyware Technologies - initial API and implementation
* Obeo
* CEA LIST - synchronization between selection and outline content
+ * Christian W. Damus (CEA) - bug 437217
*
**********************************************************************/
package org.eclipse.papyrus.infra.gmfdiag.outline;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.GraphicalViewer;
@@ -31,6 +34,7 @@ import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.papyrus.infra.core.contentoutline.IPapyrusContentOutlinePage;
import org.eclipse.papyrus.infra.core.editor.BackboneException;
import org.eclipse.papyrus.infra.core.editor.IMultiDiagramEditor;
+import org.eclipse.papyrus.infra.core.editor.reload.IReloadContextProvider;
import org.eclipse.papyrus.infra.core.services.ServiceException;
import org.eclipse.papyrus.infra.gmfdiag.outline.internal.Activator;
import org.eclipse.papyrus.infra.gmfdiag.outline.internal.Messages;
@@ -56,7 +60,7 @@ import org.eclipse.ui.plugin.AbstractUIPlugin;
*/
//FIXME: The outline is broken in Eclipse 4.2. #createControl(Composite) is never called.
//See #refresh()
-public class DiagramOutline extends Page implements IPapyrusContentOutlinePage, ISelectionListener {
+public class DiagramOutline extends Page implements IPapyrusContentOutlinePage, ISelectionListener, IAdaptable {
private final class ShowAllAction extends Action {
@@ -451,4 +455,52 @@ public class DiagramOutline extends Page implements IPapyrusContentOutlinePage,
return showActionMode;
}
+
+ private void setShowActionMode(int showAction) {
+ switch(showAction) {
+ case SHOW_TREE:
+ showTreeItem.getAction().setChecked(true);
+ break;
+ case SHOW_OVERVIEW:
+ showOverviewItem.getAction().setChecked(true);
+ break;
+ case SHOW_BOTH:
+ showAllItem.getAction().setChecked(true);
+ break;
+ default:
+ throw new IllegalArgumentException("showAction"); //$NON-NLS-1$
+ }
+
+ performShowAction();
+ }
+
+ public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
+ if(adapter == IReloadContextProvider.class) {
+ return new IReloadContextProvider() {
+
+ public Object createReloadContext() {
+ return new ReloadContext(DiagramOutline.this);
+ }
+
+ public void restore(Object reloadContext) {
+ ((ReloadContext)reloadContext).restore(DiagramOutline.this);
+ }
+ };
+ }
+
+ return Platform.getAdapterManager().getAdapter(this, adapter);
+ }
+
+ private static class ReloadContext {
+
+ private final int showAction;
+
+ ReloadContext(DiagramOutline outline) {
+ this.showAction = outline.getShowActionMode();
+ }
+
+ void restore(DiagramOutline outline) {
+ outline.setShowActionMode(showAction);
+ }
+ }
}
diff --git a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/META-INF/MANIFEST.MF b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/META-INF/MANIFEST.MF
index f087767b49f..c47c1807a79 100644
--- a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/META-INF/MANIFEST.MF
+++ b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/META-INF/MANIFEST.MF
@@ -22,7 +22,8 @@ Require-Bundle: org.eclipse.ui,
org.eclipse.e4.core.contexts,
org.eclipse.core.expressions,
org.eclipse.emf.edit.ui,
- org.eclipse.papyrus.infra.viewpoints.policy;bundle-version="1.0.0"
+ org.eclipse.papyrus.infra.viewpoints.policy;bundle-version="1.0.0",
+ com.google.guava;bundle-version="11.0.0"
Bundle-Vendor: %Bundle-Vendor
Bundle-ActivationPolicy: lazy
Bundle-Version: 1.0.0.qualifier
diff --git a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/src/org/eclipse/papyrus/infra/nattable/common/editor/AbstractEMFNattableEditor.java b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/src/org/eclipse/papyrus/infra/nattable/common/editor/AbstractEMFNattableEditor.java
index 21a651b8585..f3d56f24321 100644
--- a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/src/org/eclipse/papyrus/infra/nattable/common/editor/AbstractEMFNattableEditor.java
+++ b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/src/org/eclipse/papyrus/infra/nattable/common/editor/AbstractEMFNattableEditor.java
@@ -11,6 +11,7 @@
* Cedric Dumoulin Cedric.dumoulin@lifl.fr - Initial API and implementation
* Vincent Lorenzo (CEA-LIST) vincent.lorenzo@cea.fr
* Christian W. Damus (CEA) - bug 430880
+ * Christian W. Damus (CEA) - bug 437217
*
*****************************************************************************/
package org.eclipse.papyrus.infra.nattable.common.editor;
@@ -30,6 +31,7 @@ import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.jface.preference.PreferenceStore;
import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.papyrus.infra.core.editor.reload.IReloadContextProvider;
import org.eclipse.papyrus.infra.core.services.ServiceException;
import org.eclipse.papyrus.infra.core.services.ServicesRegistry;
import org.eclipse.papyrus.infra.core.utils.ServiceUtils;
@@ -228,6 +230,10 @@ public abstract class AbstractEMFNattableEditor extends EditorPart {
return this.tableManager.getTable();
}
}
+
+ if(adapter == IReloadContextProvider.class) {
+ return new NattableReloadContextProvider(this);
+ }
return super.getAdapter(adapter);
}
diff --git a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/src/org/eclipse/papyrus/infra/nattable/common/editor/NattableReloadContextProvider.java b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/src/org/eclipse/papyrus/infra/nattable/common/editor/NattableReloadContextProvider.java
new file mode 100644
index 00000000000..a3123d9add2
--- /dev/null
+++ b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/src/org/eclipse/papyrus/infra/nattable/common/editor/NattableReloadContextProvider.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2014 CEA 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:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.infra.nattable.common.editor;
+
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.nebula.widgets.nattable.NatTable;
+import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
+import org.eclipse.nebula.widgets.nattable.selection.command.SelectColumnCommand;
+import org.eclipse.nebula.widgets.nattable.selection.command.SelectRowsCommand;
+import org.eclipse.papyrus.infra.core.editor.reload.EMFSelectionContext;
+import org.eclipse.papyrus.infra.core.editor.reload.IReloadContextProvider;
+import org.eclipse.papyrus.infra.core.utils.AdapterUtils;
+import org.eclipse.papyrus.infra.nattable.manager.table.INattableModelManager;
+
+
+/**
+ * A {@linkplain IReloadContextProvider reload context provider} for {@link NatTable} selection state.
+ */
+class NattableReloadContextProvider implements IReloadContextProvider {
+
+ private final AbstractEMFNattableEditor editor;
+
+ NattableReloadContextProvider(AbstractEMFNattableEditor editor) {
+ super();
+
+ this.editor = editor;
+ }
+
+ @Override
+ public Object createReloadContext() {
+ return new NatTableSelectionContext(getSelectionProvider(), getSelectionLayer());
+ }
+
+ @Override
+ public void restore(Object reloadContext) {
+ ((NatTableSelectionContext)reloadContext).restore(getSelectionProvider(), getSelectionLayer());
+ }
+
+ private ISelectionProvider getSelectionProvider() {
+ // The table editor registers its table-selection provider in its site
+ return editor.getSite().getSelectionProvider();
+ }
+
+ private SelectionLayer getSelectionLayer() {
+ INattableModelManager mgr = AdapterUtils.adapt(editor, INattableModelManager.class, null);
+ return mgr.getBodyLayerStack().getSelectionLayer();
+ }
+
+ //
+ // Nested types
+ //
+
+ private static class NatTableSelectionContext extends EMFSelectionContext {
+
+ private final int[] selectedRows;
+
+ private final int[] selectedColumns;
+
+ NatTableSelectionContext(ISelectionProvider structuredSelectionProvider, SelectionLayer selectionLayer) {
+ super(structuredSelectionProvider);
+
+ selectedRows = selectionLayer.getFullySelectedRowPositions();
+ selectedColumns = selectionLayer.getFullySelectedColumnPositions();
+ }
+
+ void restore(ISelectionProvider structuredSelectionProvider, SelectionLayer selectionLayer) {
+ selectionLayer.clear();
+ if(selectedColumns.length > 0) {
+ for(int i = 0; i < selectedColumns.length; i++) {
+ selectionLayer.doCommand(new SelectColumnCommand(selectionLayer, selectedColumns[i], Integer.MAX_VALUE, false, true));
+ }
+ }
+ if(selectedRows.length > 0) {
+ selectionLayer.doCommand(new SelectRowsCommand(selectionLayer, Integer.MAX_VALUE, selectedRows, false, true, selectedRows[selectedRows.length - 1]));
+ }
+
+ restore(structuredSelectionProvider);
+ }
+ }
+}
diff --git a/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/util/LocalMemento.java b/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/util/LocalMemento.java
new file mode 100644
index 00000000000..c456b15a49f
--- /dev/null
+++ b/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/util/LocalMemento.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2014 CEA 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:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.infra.tools.util;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.ui.IMemento;
+
+
+/**
+ * Invocation handler for the dynamic local memento implementation.
+ */
+class LocalMemento implements InvocationHandler {
+
+ private static final Class<?>[] INTERFACES = { IMemento.class };
+
+ private static final Map<Method, Method> delegates = createDelegates();
+
+ private final String type;
+
+ private final String id;
+
+ private final List<IMemento> children = new ArrayList<IMemento>();
+
+ private final Map<String, Object> attributes = new HashMap<String, Object>();
+
+ private String textData;
+
+ LocalMemento(String type, String id) {
+ super();
+
+ this.type = type;
+ this.id = id;
+ }
+
+ static IMemento createMemento(String type, String id) {
+ LocalMemento handler = new LocalMemento(type, id);
+ return (IMemento)Proxy.newProxyInstance(LocalMemento.class.getClassLoader(), INTERFACES, handler);
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ Object result = null;
+
+ Method implementation = delegates.get(method);
+ if(implementation == null) {
+ throw new UnsupportedOperationException("dynamic proxy handler does not understand " + method.getName()); //$NON-NLS-1$
+ } else {
+ result = implementation.invoke(this, args);
+ }
+
+ return result;
+ }
+
+ @API
+ String getType() {
+ return type;
+ }
+
+ @API
+ String getID() {
+ return id;
+ }
+
+ @API
+ IMemento createChild(String type) {
+ return createChild(type, null);
+ }
+
+ @API
+ IMemento createChild(String type, String id) {
+ IMemento result = createMemento(type, id);
+ children.add(result);
+ return result;
+ }
+
+ @API
+ IMemento getChild(String type) {
+ IMemento result = null;
+ for(IMemento next : children) {
+ if(type.equals(next.getType())) {
+ result = next;
+ break;
+ }
+ }
+ return result;
+ }
+
+ @API
+ IMemento[] getChildren() {
+ return children.toArray(new IMemento[children.size()]);
+ }
+
+ @API
+ IMemento[] getChildren(String type) {
+ List<IMemento> result = new ArrayList<IMemento>(children.size());
+ for(IMemento next : children) {
+ if(type.equals(next.getType())) {
+ result.add(next);
+ }
+ }
+ return result.toArray(new IMemento[result.size()]);
+ }
+
+ @API
+ Float getFloat(String key) {
+ return coerce(attributes.get(key), Float.class);
+ }
+
+ private <T> T coerce(Object value, Class<T> type) {
+ Object result;
+
+ if(value == null) {
+ result = value;
+ } else if(type.isInstance(value)) {
+ result = value;
+ } else if(Number.class.isAssignableFrom(type) && (value instanceof Number)) {
+ Number number = (Number)value;
+ if(type == Integer.class) {
+ result = number.intValue();
+ } else if(type == Float.class) {
+ result = number.floatValue();
+ } else {
+ throw new IllegalArgumentException("unsupported numeric type: " + type.getSimpleName()); //$NON-NLS-1$
+ }
+ } else if(Number.class.isAssignableFrom(type) && (value instanceof String)) {
+ String string = (String)value;
+ if(type == Integer.class) {
+ result = Integer.valueOf(string);
+ } else if(type == Float.class) {
+ result = Float.valueOf(string);
+ } else {
+ throw new IllegalArgumentException("unsupported numeric type: " + type.getSimpleName()); //$NON-NLS-1$
+ }
+ } else if(type == Boolean.class) {
+ // We know the value isn't a Boolean, otherwise we would have handled it already
+ if(value instanceof String) {
+ result = Boolean.valueOf((String)value);
+ } else {
+ throw new IllegalArgumentException("unsupported boolean conversion from type: " + ((value == null) ? "null" : value.getClass().getSimpleName())); //$NON-NLS-1$
+ }
+ } else if(type == String.class) {
+ result = String.valueOf(value);
+ } else {
+ throw new IllegalArgumentException("unsupported attribute type: " + type.getSimpleName()); //$NON-NLS-1$
+ }
+
+ return type.cast(result);
+ }
+
+ @API
+ Integer getInteger(String key) {
+ return coerce(attributes.get(key), Integer.class);
+ }
+
+ @API
+ String getString(String key) {
+ return coerce(attributes.get(key), String.class);
+ }
+
+ @API
+ Boolean getBoolean(String key) {
+ return coerce(attributes.get(key), Boolean.class);
+ }
+
+ @API
+ String getTextData() {
+ return textData;
+ }
+
+ @API
+ String[] getAttributeKeys() {
+ return attributes.keySet().toArray(new String[attributes.size()]);
+ }
+
+ @API
+ void putFloat(String key, float value) {
+ attributes.put(key, value);
+ }
+
+ @API
+ void putInteger(String key, int value) {
+ attributes.put(key, value);
+ }
+
+ @API
+ void putString(String key, String value) {
+ attributes.put(key, value);
+ }
+
+ @API
+ void putBoolean(String key, boolean value) {
+ attributes.put(key, value);
+ }
+
+ @API
+ void putTextData(String data) {
+ textData = data;
+ }
+
+ private boolean isLocalMemento(IMemento memento) {
+ return (memento != null) && Proxy.isProxyClass(memento.getClass()) && ((Proxy.getInvocationHandler(memento) instanceof LocalMemento));
+ }
+
+ @API
+ void putMemento(IMemento memento) {
+ if(!isLocalMemento(memento)) {
+ throw new IllegalArgumentException("memento is not a local memento"); //$NON-NLS-1$
+ }
+ children.add(memento);
+ }
+
+ @API(owner = Object.class)
+ public String toString() {
+ StringBuilder result = new StringBuilder();
+
+ append(result, 0);
+
+ return result.toString();
+ }
+
+ private void append(StringBuilder buf, int depth) {
+ // Indent
+ for(int i = 0; i < depth; i++) {
+ buf.append(" "); //$NON-NLS-1$
+ }
+
+ buf.append("LocalMemento(");//$NON-NLS-1$
+ buf.append(type);
+ if(id != null) {
+ buf.append('[').append(id).append(']');
+ }
+ buf.append(") ").append(attributes); //$NON-NLS-1$
+ buf.append('\n');
+
+ final int nextDepth = depth + 1;
+ for(IMemento next : children) {
+ ((LocalMemento)Proxy.getInvocationHandler(next)).append(buf, nextDepth);
+ }
+ }
+
+ private static Map<Method, Method> createDelegates() {
+ Map<Method, Method> result = new HashMap<Method, Method>();
+
+ for(Method implementation : LocalMemento.class.getDeclaredMethods()) {
+ if(implementation.isAnnotationPresent(API.class)) {
+ try {
+ Method api = implementation.getAnnotation(API.class).owner().getMethod(implementation.getName(), implementation.getParameterTypes());
+ result.put(api, implementation);
+ } catch (NoSuchMethodException e) {
+ throw new LinkageError("Incompatible IMemento API change: " + implementation.getName());
+ }
+ }
+ }
+
+ return result;
+ }
+
+ @Target(ElementType.METHOD)
+ @Retention(RetentionPolicy.RUNTIME)
+ private @interface API {
+
+ Class<?> owner() default IMemento.class;
+ }
+}
diff --git a/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/util/UIUtil.java b/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/util/UIUtil.java
index 051bb4dba11..10d4ea7054f 100644
--- a/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/util/UIUtil.java
+++ b/plugins/infra/org.eclipse.papyrus.infra.tools/src/org/eclipse/papyrus/infra/tools/util/UIUtil.java
@@ -27,6 +27,7 @@ import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IMemento;
/**
@@ -54,6 +55,16 @@ public class UIUtil {
return new UIExecutorService(display);
}
+ /**
+ * Creates a local memento that is not persistable and is not based on an XML document. This is useful for capturing the
+ * state of UI elements locally in cases where persistence of the memento is not required.
+ *
+ * @return the memento
+ */
+ public static IMemento createLocalMemento() {
+ return LocalMemento.createMemento("__anonymous__", null); //$NON-NLS-1$
+ }
+
//
// Nested types
//
diff --git a/plugins/views/modelexplorer/org.eclipse.papyrus.views.modelexplorer/src/org/eclipse/papyrus/views/modelexplorer/ModelExplorerTreeViewerContext.java b/plugins/views/modelexplorer/org.eclipse.papyrus.views.modelexplorer/src/org/eclipse/papyrus/views/modelexplorer/ModelExplorerTreeViewerContext.java
new file mode 100644
index 00000000000..e81398f494a
--- /dev/null
+++ b/plugins/views/modelexplorer/org.eclipse.papyrus.views.modelexplorer/src/org/eclipse/papyrus/views/modelexplorer/ModelExplorerTreeViewerContext.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2010, 2014 CEA 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
+ * Christian W. Damus (CEA) - adapted from ModelExplorerView::reveal(...) API
+ *
+ */
+package org.eclipse.papyrus.views.modelexplorer;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.jface.viewers.AbstractTreeViewer;
+import org.eclipse.papyrus.infra.core.editor.reload.EMFTreeViewerContext;
+import org.eclipse.papyrus.infra.core.resource.ModelSet;
+import org.eclipse.papyrus.infra.core.resource.additional.AdditionalResourcesModel;
+import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
+import org.eclipse.papyrus.views.modelexplorer.matching.IMatchingItem;
+import org.eclipse.papyrus.views.modelexplorer.matching.LinkItemMatchingItem;
+import org.eclipse.papyrus.views.modelexplorer.matching.ModelElementItemMatchingItem;
+import org.eclipse.papyrus.views.modelexplorer.matching.ReferencableMatchingItem;
+
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+
+/**
+ * A specialization of the editor re-load tree viewer context that knows how to expand and select nodes
+ * in the EMF Facet-based Model Explorer view.
+ */
+class ModelExplorerTreeViewerContext extends EMFTreeViewerContext {
+
+ public ModelExplorerTreeViewerContext(AbstractTreeViewer viewer) {
+ super(viewer);
+ }
+
+ public Object deresolveSelectableElement(Object selectableElement) {
+ return EMFHelper.getEObject(selectableElement);
+ }
+
+ public Object resolveSelectableElement(Object object) {
+ return new ModelElementItemMatchingItemWithElement((EObject)object);
+ }
+
+ @Override
+ protected void setExpandedElements(AbstractTreeViewer viewer, Collection<?> toExpand) {
+ // EMF Facet makes expanding tree elements very complicated
+ if(viewer.getContentProvider() != null) {
+ for(ModelElementItemMatchingItemWithElement next : Iterables.filter(toExpand, ModelElementItemMatchingItemWithElement.class)) {
+
+ // retrieve the ancestors to reveal them
+ // and allow the selection of the object
+ EObject currentEObject = next.element();
+ ArrayList<EObject> parents = new ArrayList<EObject>();
+ EObject tmp = currentEObject.eContainer();
+ while(tmp != null) {
+ parents.add(tmp);
+ tmp = tmp.eContainer();
+ }
+
+ Iterable<EObject> reverseParents = Lists.reverse(parents);
+
+ // reveal the resource if necessary
+ Resource r = null;
+ if(!parents.isEmpty()) {
+ r = parents.get(parents.size() - 1).eResource();
+ } else {
+ r = currentEObject.eResource();
+ }
+
+ if(r != null) {
+ final ResourceSet rs = r.getResourceSet();
+ final Resource resource = r;
+ if(rs instanceof ModelSet && AdditionalResourcesModel.isAdditionalResource((ModelSet)rs, r.getURI())) {
+ viewer.expandToLevel(new ReferencableMatchingItem(rs), 1);
+ viewer.expandToLevel(new ReferencableMatchingItem(resource), 1);
+ }
+ }
+
+ /*
+ * reveal the ancestors tree using expandToLevel on each of them
+ * in the good order. This is a lot faster than going through the whole tree
+ * using getChildren of the ContentProvider since our Viewer uses a Hashtable
+ * to keep track of the revealed elements.
+ *
+ * However we need to use a dedicated MatchingItem to do the matching,
+ * and a specific comparer in our viewer so than the equals of MatchingItem is
+ * used in priority.
+ *
+ * Please refer to MatchingItem for more infos.
+ */
+ EObject previousParent = null;
+ for(EObject parent : reverseParents) {
+ if(parent.eContainingFeature() != null && previousParent != null) {
+ viewer.expandToLevel(new LinkItemMatchingItem(previousParent, parent.eContainmentFeature()), 1);
+ }
+
+ final IMatchingItem itemToExpand = new ModelElementItemMatchingItem(parent);
+ viewer.expandToLevel(itemToExpand, 1);
+
+ previousParent = parent;
+ }
+
+ // expand a reference-link item, if necessary
+ final IMatchingItem linkItem = new LinkItemMatchingItem(currentEObject.eContainer(), currentEObject.eContainmentFeature());
+ viewer.expandToLevel(linkItem, 1);
+
+ // and the actual element
+ viewer.expandToLevel(next, 1);
+ }
+ }
+ }
+
+ //
+ // Nested types
+ //
+
+ static class ModelElementItemMatchingItemWithElement extends ModelElementItemMatchingItem {
+
+ private EObject element;
+
+ ModelElementItemMatchingItemWithElement(EObject element) {
+ super(element);
+
+ this.element = element;
+ }
+
+ EObject element() {
+ return element;
+ }
+ }
+}
diff --git a/plugins/views/modelexplorer/org.eclipse.papyrus.views.modelexplorer/src/org/eclipse/papyrus/views/modelexplorer/ModelExplorerView.java b/plugins/views/modelexplorer/org.eclipse.papyrus.views.modelexplorer/src/org/eclipse/papyrus/views/modelexplorer/ModelExplorerView.java
index 7f2a6262cf1..b7f71045b88 100644
--- a/plugins/views/modelexplorer/org.eclipse.papyrus.views.modelexplorer/src/org/eclipse/papyrus/views/modelexplorer/ModelExplorerView.java
+++ b/plugins/views/modelexplorer/org.eclipse.papyrus.views.modelexplorer/src/org/eclipse/papyrus/views/modelexplorer/ModelExplorerView.java
@@ -12,6 +12,7 @@
* Christian W. Damus (CEA) - post refreshes for transaction commit asynchronously (CDO)
* Christian W. Damus (CEA) - bug 429826
* Christian W. Damus (CEA) - bug 434635
+ * Christian W. Damus (CEA) - bug 437217
*
*****************************************************************************/
package org.eclipse.papyrus.views.modelexplorer;
@@ -53,6 +54,10 @@ import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerColumn;
import org.eclipse.jface.window.ToolTip;
import org.eclipse.papyrus.infra.core.editor.IMultiDiagramEditor;
+import org.eclipse.papyrus.infra.core.editor.IReloadableEditor;
+import org.eclipse.papyrus.infra.core.editor.reload.EditorReloadAdapter;
+import org.eclipse.papyrus.infra.core.editor.reload.EditorReloadEvent;
+import org.eclipse.papyrus.infra.core.editor.reload.TreeViewerContext;
import org.eclipse.papyrus.infra.core.lifecycleevents.IEditorInputChangedListener;
import org.eclipse.papyrus.infra.core.lifecycleevents.ISaveAndDirtyService;
import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler2;
@@ -127,7 +132,7 @@ import com.google.common.collect.Lists;
public class ModelExplorerView extends CommonNavigator implements IRevealSemanticElement, IEditingDomainProvider, IPageLifeCycleEventsListener {
private SharedModelExplorerState sharedState;
-
+
private SharedModelExplorerState.StateChangedListener sharedStateListener;
/**
@@ -138,16 +143,10 @@ public class ModelExplorerView extends CommonNavigator implements IRevealSemanti
public static final String LABEL_PROVIDER_SERVICE_CONTEXT = "org.eclipse.papyrus.views.modelexplorer.labelProvider.context";
/**
- * The associated EditorPart
- * The View is associated to the ServicesRegistry rather than to an editor.
- * */
- // private IMultiDiagramEditor editorPart;
-
- /**
* The {@link ServicesRegistry} associated to the Editor. This view is associated to the
* ServicesRegistry rather than to the EditorPart.
*/
- private final ServicesRegistry serviceRegistry;
+ private ServicesRegistry serviceRegistry;
/** The save aservice associated to the editor. */
private ISaveAndDirtyService saveAndDirtyService;
@@ -217,10 +216,37 @@ public class ModelExplorerView extends CommonNavigator implements IRevealSemanti
throw new IllegalArgumentException("A part should be provided.");
}
+ init(part);
+
+ IReloadableEditor.Adapter.getAdapter(part).addEditorReloadListener(new EditorReloadAdapter() {
+
+ @Override
+ public void editorAboutToReload(EditorReloadEvent event) {
+ // Stash expansion and selection state of the common viewer
+ event.putContext(new ModelExplorerTreeViewerContext(getCommonViewer()));
+
+ deactivate();
+ }
+
+ @Override
+ public void editorReloaded(EditorReloadEvent event) {
+ init(event.getEditor());
+
+ activate();
+
+ initCommonViewer(getCommonViewer());
+
+ // Restore expansion and selection state of the common viewer
+ ((TreeViewerContext<?>)event.getContext()).restore(getCommonViewer());
+ }
+ });
+ }
+
+ private void init(IMultiDiagramEditor editor) {
// Try to get the ServicesRegistry
- serviceRegistry = part.getServicesRegistry();
+ serviceRegistry = editor.getServicesRegistry();
if(serviceRegistry == null) {
- throw new IllegalArgumentException("The part should have a ServiceRegistry.");
+ throw new IllegalArgumentException("The editor should have a ServiceRegistry.");
}
// Get required services from ServicesRegistry
@@ -228,7 +254,7 @@ public class ModelExplorerView extends CommonNavigator implements IRevealSemanti
saveAndDirtyService = serviceRegistry.getService(ISaveAndDirtyService.class);
undoContext = serviceRegistry.getService(IUndoContext.class);
} catch (ServiceException e) {
- e.printStackTrace();
+ Activator.log.error(e);
}
}
@@ -341,6 +367,41 @@ public class ModelExplorerView extends CommonNavigator implements IRevealSemanti
@Override
protected CommonViewer createCommonViewerObject(Composite aParent) {
CommonViewer viewer = new CustomCommonViewer(getViewSite().getId(), aParent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
+
+ initCommonViewer(viewer);
+
+ viewer.getNavigatorContentService().getActivationService().addExtensionActivationListener(new IExtensionActivationListener() {
+
+ public void onExtensionActivation(String aViewerId, String[] theNavigatorExtensionIds, boolean isActive) {
+ sharedState.updateNavigatorContentExtensions(theNavigatorExtensionIds, isActive);
+ }
+ });
+
+ ColumnViewerToolTipSupport.enableFor(viewer, ToolTip.NO_RECREATE);
+
+ return viewer;
+ }
+
+ private void installEMFFacetTreePainter(Tree tree) {
+ // Install the EMFFacet Custom Tree Painter
+ //org.eclipse.papyrus.infra.emf.Activator.getDefault().getCustomizationManager().installCustomPainter(tree);
+
+ // The EMF Facet MeasureItem Listener is incompatible with the NavigatorDecoratingLabelProvider. Remove it.
+ // Symptoms: ModelElementItems with an EMF Facet Overlay have a small selection size
+ // Removal also fixes bug 400012: no scrollbar although tree is larger than visible area
+ Collection<Listener> listenersToRemove = new LinkedList<Listener>();
+ for(Listener listener : tree.getListeners(SWT.MeasureItem)) {
+ if(listener.getClass().getName().contains("org.eclipse.papyrus.emf.facet.infra.browser.uicore.internal.CustomTreePainter")) {
+ listenersToRemove.add(listener);
+ }
+ }
+
+ for(Listener listener : listenersToRemove) {
+ tree.removeListener(SWT.MeasureItem, listener);
+ }
+ }
+
+ private void initCommonViewer(CommonViewer viewer) {
// enable tool-tips
// workaround for bug 311827: the Common Viewer always uses NavigatorDecoratingLabelProvider
// as a wrapper for the LabelProvider provided by the application. The NavigatorDecoratingLabelProvider
@@ -375,36 +436,6 @@ public class ModelExplorerView extends CommonNavigator implements IRevealSemanti
}
}
contentService.dispose(); // No longer need this
-
- viewer.getNavigatorContentService().getActivationService().addExtensionActivationListener(new IExtensionActivationListener() {
-
- public void onExtensionActivation(String aViewerId, String[] theNavigatorExtensionIds, boolean isActive) {
- sharedState.updateNavigatorContentExtensions(theNavigatorExtensionIds, isActive);
- }
- });
-
- ColumnViewerToolTipSupport.enableFor(viewer, ToolTip.NO_RECREATE);
-
- return viewer;
- }
-
- private void installEMFFacetTreePainter(Tree tree) {
- // Install the EMFFacet Custom Tree Painter
- //org.eclipse.papyrus.infra.emf.Activator.getDefault().getCustomizationManager().installCustomPainter(tree);
-
- // The EMF Facet MeasureItem Listener is incompatible with the NavigatorDecoratingLabelProvider. Remove it.
- // Symptoms: ModelElementItems with an EMF Facet Overlay have a small selection size
- // Removal also fixes bug 400012: no scrollbar although tree is larger than visible area
- Collection<Listener> listenersToRemove = new LinkedList<Listener>();
- for(Listener listener : tree.getListeners(SWT.MeasureItem)) {
- if(listener.getClass().getName().contains("org.eclipse.papyrus.emf.facet.infra.browser.uicore.internal.CustomTreePainter")) {
- listenersToRemove.add(listener);
- }
- }
-
- for(Listener listener : listenersToRemove) {
- tree.removeListener(SWT.MeasureItem, listener);
- }
}
@Override
@@ -625,6 +656,19 @@ public class ModelExplorerView extends CommonNavigator implements IRevealSemanti
super.init(site, aMemento);
activate();
+
+ // Self-listen for property changes
+ addPropertyListener(new IPropertyListener() {
+
+ public void propertyChanged(Object source, int propId) {
+ switch(propId) {
+ case IS_LINKING_ENABLED_PROPERTY:
+ // Propagate to other instances
+ sharedState.setLinkingEnabled(isLinkingEnabled());
+ break;
+ }
+ }
+ });
}
/**
@@ -753,8 +797,6 @@ public class ModelExplorerView extends CommonNavigator implements IRevealSemanti
* Activate specified Part.
*/
private void activate() {
-
-
try {
this.editingDomain = ServiceUtils.getInstance().getTransactionalEditingDomain(serviceRegistry);
@@ -777,19 +819,6 @@ public class ModelExplorerView extends CommonNavigator implements IRevealSemanti
if(this.getCommonViewer() != null) {
syncRefresh();
}
-
- // Self-listen for property changes
- addPropertyListener(new IPropertyListener() {
-
- public void propertyChanged(Object source, int propId) {
- switch(propId) {
- case IS_LINKING_ENABLED_PROPERTY:
- // Propagate to other instances
- sharedState.setLinkingEnabled(isLinkingEnabled());
- break;
- }
- }
- });
}
/**
@@ -801,6 +830,15 @@ public class ModelExplorerView extends CommonNavigator implements IRevealSemanti
Activator.log.debug("deactivate ModelExplorerView"); //$NON-NLS-1$
}
+ try {
+ ISashWindowsContainer sashWindowsContainer = serviceRegistry.getService(ISashWindowsContainer.class);
+ if(sashWindowsContainer != null) {
+ sashWindowsContainer.removePageLifeCycleListener(this);
+ }
+ } catch (ServiceException ex) {
+ //Ignore
+ }
+
// Stop listening on change events
getSite().getPage().removeSelectionListener(pageSelectionListener);
// Stop Listening to isDirty flag
@@ -811,6 +849,11 @@ public class ModelExplorerView extends CommonNavigator implements IRevealSemanti
editingDomain = null;
}
+ saveAndDirtyService = null;
+ undoContext = null;
+ editingDomain = null;
+ editingDomain = null;
+ lastTrans = null;
}
/**
@@ -828,31 +871,19 @@ public class ModelExplorerView extends CommonNavigator implements IRevealSemanti
sharedState.removeListener(sharedStateListener);
}
- try {
- ISashWindowsContainer sashWindowsContainer = serviceRegistry.getService(ISashWindowsContainer.class);
- if(sashWindowsContainer != null) {
- sashWindowsContainer.removePageLifeCycleListener(this);
- }
- } catch (ServiceException ex) {
- //Ignore
+ if(getSite() != null) {
+ getSite().getPage().removeSelectionListener(pageSelectionListener);
}
deactivate();
- saveAndDirtyService = null;
- undoContext = null;
- editingDomain = null;
- pageSelectionListener = null;
- editingDomain = null;
- lastTrans = null;
-
for(IPropertySheetPage propertySheetPage : this.propertySheetPages) {
propertySheetPage.dispose();
}
propertySheetPages.clear();
-
+ pageSelectionListener = null;
super.dispose();
diff --git a/plugins/views/validation/org.eclipse.papyrus.views.validation/src/org/eclipse/papyrus/views/validation/internal/providers/ProblemsContentProvider.java b/plugins/views/validation/org.eclipse.papyrus.views.validation/src/org/eclipse/papyrus/views/validation/internal/providers/ProblemsContentProvider.java
index 23b5f5c347c..c47c5d83a33 100644
--- a/plugins/views/validation/org.eclipse.papyrus.views.validation/src/org/eclipse/papyrus/views/validation/internal/providers/ProblemsContentProvider.java
+++ b/plugins/views/validation/org.eclipse.papyrus.views.validation/src/org/eclipse/papyrus/views/validation/internal/providers/ProblemsContentProvider.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2013 CEA LIST.
+ * Copyright (c) 2013, 2014 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
@@ -8,6 +8,8 @@
*
* Contributors:
* CEA LIST - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 437217
+ *
*****************************************************************************/
package org.eclipse.papyrus.views.validation.internal.providers;
@@ -31,8 +33,7 @@ import com.google.common.collect.Iterables;
/**
* This is the ProblemsContentProvider type. Enjoy.
*/
-public class ProblemsContentProvider
- implements IStructuredContentProvider {
+public class ProblemsContentProvider implements IStructuredContentProvider {
private static final Object[] NONE = {};
@@ -53,31 +54,30 @@ public class ProblemsContentProvider
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
- this.viewer = (AbstractTableViewer) viewer;
+ this.viewer = (AbstractTableViewer)viewer;
- if (oldInput instanceof ValidationMarkersService) {
- ValidationMarkersService service = (ValidationMarkersService) oldInput;
+ if(oldInput instanceof ValidationMarkersService) {
+ ValidationMarkersService service = (ValidationMarkersService)oldInput;
unhookMarkers(service);
- unhookResourceSet(service.getModelSet()
- .getTransactionalEditingDomain());
+
+ // The old service may have been disposed if its editor was closed
+ if(service.getModelSet() != null) {
+ unhookResourceSet(service.getModelSet().getTransactionalEditingDomain());
+ }
+
this.service = null;
}
- if (newInput instanceof ValidationMarkersService) {
- ValidationMarkersService service = (ValidationMarkersService) newInput;
+ if(newInput instanceof ValidationMarkersService) {
+ ValidationMarkersService service = (ValidationMarkersService)newInput;
this.service = service;
hookMarkers(service);
- hookResourceSet(service.getModelSet()
- .getTransactionalEditingDomain());
+ hookResourceSet(service.getModelSet().getTransactionalEditingDomain());
}
}
public Object[] getElements(Object inputElement) {
- return (inputElement instanceof ValidationMarkersService)
- ? Iterables.toArray(
- ((ValidationMarkersService) inputElement).getMarkers(),
- IPapyrusMarker.class)
- : NONE;
+ return (inputElement instanceof ValidationMarkersService) ? Iterables.toArray(((ValidationMarkersService)inputElement).getMarkers(), IPapyrusMarker.class) : NONE;
}
protected void hookMarkers(ValidationMarkersService service) {
@@ -89,19 +89,18 @@ public class ProblemsContentProvider
}
private IValidationMarkerListener getValidationMarkerListener() {
- if (listener == null) {
+ if(listener == null) {
listener = new IValidationMarkerListener() {
- public void notifyMarkerChange(IPapyrusMarker marker,
- MarkerChangeKind kind) {
- if (viewer != null) {
- switch (kind) {
- case ADDED :
- viewer.add(marker);
- break;
- case REMOVED :
- viewer.remove(marker);
- break;
+ public void notifyMarkerChange(IPapyrusMarker marker, MarkerChangeKind kind) {
+ if(viewer != null) {
+ switch(kind) {
+ case ADDED:
+ viewer.add(marker);
+ break;
+ case REMOVED:
+ viewer.remove(marker);
+ break;
}
}
}
@@ -120,42 +119,36 @@ public class ProblemsContentProvider
}
private ResourceSetListener getResourceSetListener() {
- if (resourceSetListener == null) {
+ if(resourceSetListener == null) {
resourceSetListener = new DemultiplexingListener() {
@Override
- protected void handleNotification(
- TransactionalEditingDomain domain,
- Notification notification) {
+ protected void handleNotification(TransactionalEditingDomain domain, Notification notification) {
// handle containment changes of problem elements to update
// labels
Object feature = notification.getFeature();
- if ((feature instanceof EReference)
- && ((EReference) feature).isContainment()) {
-
- switch (notification.getEventType()) {
- case Notification.ADD :
- handleContainment((EObject) notification
- .getNewValue());
- break;
- case Notification.ADD_MANY :
- for (Object next : (Collection<?>) notification
- .getNewValue()) {
- handleContainment((EObject) next);
- }
- break;
- case Notification.SET :
- handleContainment((EObject) notification
- .getNewValue());
- break;
+ if((feature instanceof EReference) && ((EReference)feature).isContainment()) {
+
+ switch(notification.getEventType()) {
+ case Notification.ADD:
+ handleContainment((EObject)notification.getNewValue());
+ break;
+ case Notification.ADD_MANY:
+ for(Object next : (Collection<?>)notification.getNewValue()) {
+ handleContainment((EObject)next);
+ }
+ break;
+ case Notification.SET:
+ handleContainment((EObject)notification.getNewValue());
+ break;
}
}
}
private void handleContainment(EObject object) {
Object[] markers = service.getMarkers(object).toArray();
- if (markers.length > 0) {
+ if(markers.length > 0) {
viewer.update(markers, null);
}
}
diff --git a/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/META-INF/MANIFEST.MF b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/META-INF/MANIFEST.MF
index 8da92919d49..3f6472f23ea 100644
--- a/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/META-INF/MANIFEST.MF
+++ b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/META-INF/MANIFEST.MF
@@ -29,7 +29,8 @@ Require-Bundle: org.eclipse.ui,
org.eclipse.papyrus.infra.nattable.common;bundle-version="1.0.0",
org.eclipse.papyrus.infra.nattable;bundle-version="1.0.0",
org.eclipse.papyrus.uml.nattable.menu;bundle-version="1.0.0",
- org.eclipse.papyrus.uml.diagram.sequence;bundle-version="1.0.0"
+ org.eclipse.papyrus.uml.diagram.sequence;bundle-version="1.0.0",
+ org.eclipse.papyrus.infra.emf;bundle-version="1.0.0"
Export-Package: org.eclipse.papyrus.editor.integration.tests,
org.eclipse.papyrus.editor.integration.tests.tests
Bundle-Vendor: Eclipse Modeling Project
diff --git a/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/banking.di b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/banking.di
new file mode 100644
index 00000000000..db3312a6d7a
--- /dev/null
+++ b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/banking.di
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<di:SashWindowsMngr xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:di="http://www.eclipse.org/papyrus/0.7.0/sashdi">
+ <sashModel currentSelection="//@sashModel/@windows.0/@children.0">
+ <windows>
+ <children xsi:type="di:TabFolder">
+ <children>
+ <emfPageIdentifier href="banking.notation#_z6rXcPlAEeOEp7Wro2yWpw"/>
+ </children>
+ </children>
+ </windows>
+ </sashModel>
+</di:SashWindowsMngr>
diff --git a/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/banking.notation b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/banking.notation
new file mode 100644
index 00000000000..7a00061ce0e
--- /dev/null
+++ b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/banking.notation
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<notation:Diagram xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:notation="http://www.eclipse.org/gmf/runtime/1.0.2/notation" xmlns:style="http://www.eclipse.org/papyrus/infra/viewpoints/policy/style" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xmi:id="_z6rXcPlAEeOEp7Wro2yWpw" type="PapyrusUMLClassDiagram" name="classes" measurementUnit="Pixel">
+ <children xmi:type="notation:Shape" xmi:id="_5wKkIPlAEeOEp7Wro2yWpw" type="2008">
+ <children xmi:type="notation:DecorationNode" xmi:id="_5wKkIvlAEeOEp7Wro2yWpw" type="5029"/>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_5wKkI_lAEeOEp7Wro2yWpw" type="7017">
+ <children xmi:type="notation:Shape" xmi:id="_CClGQPlBEeOEp7Wro2yWpw" type="3012">
+ <element xmi:type="uml:Property" href="banking.uml#_CCiC8PlBEeOEp7Wro2yWpw"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_CClGQflBEeOEp7Wro2yWpw"/>
+ </children>
+ <styles xmi:type="notation:TitleStyle" xmi:id="_5wKkJPlAEeOEp7Wro2yWpw"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_5wKkJflAEeOEp7Wro2yWpw"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_5wKkJvlAEeOEp7Wro2yWpw"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_5wKkJ_lAEeOEp7Wro2yWpw"/>
+ </children>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_5wKkKPlAEeOEp7Wro2yWpw" type="7018">
+ <styles xmi:type="notation:TitleStyle" xmi:id="_5wKkKflAEeOEp7Wro2yWpw"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_5wKkKvlAEeOEp7Wro2yWpw"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_5wKkK_lAEeOEp7Wro2yWpw"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_5wKkLPlAEeOEp7Wro2yWpw"/>
+ </children>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_5wKkLflAEeOEp7Wro2yWpw" type="7019">
+ <styles xmi:type="notation:TitleStyle" xmi:id="_5wKkLvlAEeOEp7Wro2yWpw"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_5wKkL_lAEeOEp7Wro2yWpw"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_5wLLMPlAEeOEp7Wro2yWpw"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_5wLLMflAEeOEp7Wro2yWpw"/>
+ </children>
+ <element xmi:type="uml:Class" href="banking.uml#_5wJWAPlAEeOEp7Wro2yWpw"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_5wKkIflAEeOEp7Wro2yWpw" x="44" y="65"/>
+ </children>
+ <children xmi:type="notation:Shape" xmi:id="_YViK8PlBEeOEp7Wro2yWpw" type="2008">
+ <children xmi:type="notation:DecorationNode" xmi:id="_YViK8vlBEeOEp7Wro2yWpw" type="5029"/>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_YViK8_lBEeOEp7Wro2yWpw" type="7017">
+ <children xmi:type="notation:Shape" xmi:id="_amgIAPlBEeOEp7Wro2yWpw" type="3012">
+ <element xmi:type="uml:Property" href="banking.uml#_amdrwPlBEeOEp7Wro2yWpw"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_amgIAflBEeOEp7Wro2yWpw"/>
+ </children>
+ <children xmi:type="notation:Shape" xmi:id="_cxbHcPlBEeOEp7Wro2yWpw" type="3012">
+ <element xmi:type="uml:Property" href="banking.uml#_cxZ5UPlBEeOEp7Wro2yWpw"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_cxbHcflBEeOEp7Wro2yWpw"/>
+ </children>
+ <styles xmi:type="notation:TitleStyle" xmi:id="_YViK9PlBEeOEp7Wro2yWpw"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_YViK9flBEeOEp7Wro2yWpw"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_YViK9vlBEeOEp7Wro2yWpw"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_YViK9_lBEeOEp7Wro2yWpw"/>
+ </children>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_YViK-PlBEeOEp7Wro2yWpw" type="7018">
+ <styles xmi:type="notation:TitleStyle" xmi:id="_YViK-flBEeOEp7Wro2yWpw"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_YViK-vlBEeOEp7Wro2yWpw"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_YViK-_lBEeOEp7Wro2yWpw"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_YViK_PlBEeOEp7Wro2yWpw"/>
+ </children>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_YViyAPlBEeOEp7Wro2yWpw" type="7019">
+ <styles xmi:type="notation:TitleStyle" xmi:id="_YViyAflBEeOEp7Wro2yWpw"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_YViyAvlBEeOEp7Wro2yWpw"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_YViyA_lBEeOEp7Wro2yWpw"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_YViyBPlBEeOEp7Wro2yWpw"/>
+ </children>
+ <element xmi:type="uml:Class" href="banking.uml#_YVg80PlBEeOEp7Wro2yWpw"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_YViK8flBEeOEp7Wro2yWpw" x="305" y="61"/>
+ </children>
+ <styles xmi:type="notation:StringValueStyle" xmi:id="_z6rXcflAEeOEp7Wro2yWpw" name="diagram_compatibility_version" stringValue="1.0.0"/>
+ <styles xmi:type="notation:DiagramStyle" xmi:id="_z6rXcvlAEeOEp7Wro2yWpw"/>
+ <styles xmi:type="style:PapyrusViewStyle" xmi:id="_z6rXc_lAEeOEp7Wro2yWpw">
+ <owner xmi:type="uml:Model" href="banking.uml#_vtQUwPlAEeOEp7Wro2yWpw"/>
+ </styles>
+ <element xmi:type="uml:Model" href="banking.uml#_vtQUwPlAEeOEp7Wro2yWpw"/>
+ <edges xmi:type="notation:Connector" xmi:id="_kGAvYPlBEeOEp7Wro2yWpw" type="4001" source="_5wKkIPlAEeOEp7Wro2yWpw" target="_YViK8PlBEeOEp7Wro2yWpw">
+ <children xmi:type="notation:DecorationNode" xmi:id="_kGBWcPlBEeOEp7Wro2yWpw" type="6001">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_kGBWcflBEeOEp7Wro2yWpw" y="-20"/>
+ </children>
+ <children xmi:type="notation:DecorationNode" xmi:id="_kGBWcvlBEeOEp7Wro2yWpw" visible="false" type="6002">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_kGBWc_lBEeOEp7Wro2yWpw" y="20"/>
+ </children>
+ <children xmi:type="notation:DecorationNode" xmi:id="_kGBWdPlBEeOEp7Wro2yWpw" type="6003">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_kGBWdflBEeOEp7Wro2yWpw" x="10" y="-20"/>
+ </children>
+ <children xmi:type="notation:DecorationNode" xmi:id="_kGB9gPlBEeOEp7Wro2yWpw" type="6005">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_kGB9gflBEeOEp7Wro2yWpw" x="-11" y="20"/>
+ </children>
+ <children xmi:type="notation:DecorationNode" xmi:id="_kGB9gvlBEeOEp7Wro2yWpw" type="6033">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_kGB9g_lBEeOEp7Wro2yWpw" y="20"/>
+ </children>
+ <children xmi:type="notation:DecorationNode" xmi:id="_kGB9hPlBEeOEp7Wro2yWpw" type="6034">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_kGB9hflBEeOEp7Wro2yWpw" y="-20"/>
+ </children>
+ <styles xmi:type="notation:FontStyle" xmi:id="_kGAvYflBEeOEp7Wro2yWpw"/>
+ <element xmi:type="uml:Association" href="banking.uml#_kF-6MPlBEeOEp7Wro2yWpw"/>
+ <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_kGAvYvlBEeOEp7Wro2yWpw" points="[50, -8, -186, 0]$[211, -17, -25, -9]"/>
+ <targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_kGOKwPlBEeOEp7Wro2yWpw" id="(0.22522522522522523,0.4107142857142857)"/>
+ </edges>
+</notation:Diagram>
diff --git a/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/banking.uml b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/banking.uml
new file mode 100644
index 00000000000..ed2c9d13f1b
--- /dev/null
+++ b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/banking.uml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xmi:XMI xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ActionLanguage="http://www.omg.org/spec/ALF/20120827/ActionLanguage-Profile" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xsi:schemaLocation="http://www.omg.org/spec/ALF/20120827/ActionLanguage-Profile pathmap://PAPYRUS_ACTIONLANGUAGE_PROFILE/ActionLanguage-Profile.profile.uml#_sYse0YZLEeKyw49uR6nx3g">
+ <uml:Model xmi:id="_vtQUwPlAEeOEp7Wro2yWpw" name="banking">
+ <packageImport xmi:type="uml:PackageImport" xmi:id="_vtQUwflAEeOEp7Wro2yWpw">
+ <importedPackage xmi:type="uml:Model" href="pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#_0"/>
+ </packageImport>
+ <packagedElement xmi:type="uml:Class" xmi:id="_5wJWAPlAEeOEp7Wro2yWpw" name="Account">
+ <ownedAttribute xmi:type="uml:Property" xmi:id="_CCiC8PlBEeOEp7Wro2yWpw" name="id" visibility="public" isUnique="false">
+ <type xmi:type="uml:PrimitiveType" href="library.uml#_9VhhQPlAEeOEp7Wro2yWpw"/>
+ <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_X0ky8PlBEeOEp7Wro2yWpw" value="1"/>
+ <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_X0laAPlBEeOEp7Wro2yWpw" value="1"/>
+ </ownedAttribute>
+ <ownedAttribute xmi:type="uml:Property" xmi:id="_kF-TIPlBEeOEp7Wro2yWpw" name="signatory" type="_YVg80PlBEeOEp7Wro2yWpw" association="_kF-6MPlBEeOEp7Wro2yWpw">
+ <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_kF-TIflBEeOEp7Wro2yWpw"/>
+ <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_kF-TIvlBEeOEp7Wro2yWpw" value="*"/>
+ </ownedAttribute>
+ </packagedElement>
+ <packagedElement xmi:type="uml:Class" xmi:id="_YVg80PlBEeOEp7Wro2yWpw" name="Person">
+ <ownedAttribute xmi:type="uml:Property" xmi:id="_amdrwPlBEeOEp7Wro2yWpw" name="ssn" visibility="public" isUnique="false">
+ <type xmi:type="uml:DataType" href="library.uml#_AtaNAPJEEeOWJr1T78jdJA"/>
+ <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_cTywQPlBEeOEp7Wro2yWpw" value="1"/>
+ <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_cUEdEPlBEeOEp7Wro2yWpw" value="1"/>
+ </ownedAttribute>
+ <ownedAttribute xmi:type="uml:Property" xmi:id="_cxZ5UPlBEeOEp7Wro2yWpw" name="name" visibility="public" isUnique="false">
+ <type xmi:type="uml:DataType" href="library.uml#_vCcKoPJEEeOWJr1T78jdJA"/>
+ <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_jHClsPlBEeOEp7Wro2yWpw" value="1"/>
+ <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_jHLIkPlBEeOEp7Wro2yWpw" value="1"/>
+ </ownedAttribute>
+ </packagedElement>
+ <packagedElement xmi:type="uml:Association" xmi:id="_kF-6MPlBEeOEp7Wro2yWpw" name="A_account_person_1" memberEnd="_kF-6MflBEeOEp7Wro2yWpw _kF-TIPlBEeOEp7Wro2yWpw" navigableOwnedEnd="_kF-6MflBEeOEp7Wro2yWpw">
+ <ownedEnd xmi:type="uml:Property" xmi:id="_kF-6MflBEeOEp7Wro2yWpw" name="account" type="_5wJWAPlAEeOEp7Wro2yWpw" association="_kF-6MPlBEeOEp7Wro2yWpw">
+ <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_kF-6MvlBEeOEp7Wro2yWpw"/>
+ <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_kF-6M_lBEeOEp7Wro2yWpw" value="*"/>
+ </ownedEnd>
+ </packagedElement>
+ <profileApplication xmi:type="uml:ProfileApplication" xmi:id="_FFYv8PlBEeOEp7Wro2yWpw">
+ <eAnnotations xmi:type="ecore:EAnnotation" xmi:id="_FGT9APlBEeOEp7Wro2yWpw" source="http://www.eclipse.org/uml2/2.0.0/UML">
+ <references xmi:type="ecore:EPackage" href="pathmap://PAPYRUS_ACTIONLANGUAGE_PROFILE/ActionLanguage-Profile.profile.uml#_sYse0YZLEeKyw49uR6nx3g"/>
+ </eAnnotations>
+ <appliedProfile xmi:type="uml:Profile" href="pathmap://PAPYRUS_ACTIONLANGUAGE_PROFILE/ActionLanguage-Profile.profile.uml#ActionLanguage"/>
+ </profileApplication>
+ </uml:Model>
+ <ActionLanguage:TextualRepresentation xmi:id="_FJGyUPlBEeOEp7Wro2yWpw" language="org.eclipse.papyrus.uml.textedit.property.xtext.UmlProperty"/>
+ <ActionLanguage:TextualRepresentation xmi:id="_QzhLAPlBEeOEp7Wro2yWpw" language="org.eclipse.papyrus.uml.textedit.property.xtext.UmlProperty"/>
+ <ActionLanguage:TextualRepresentation xmi:id="_fuKlYPlBEeOEp7Wro2yWpw" language="org.eclipse.papyrus.uml.textedit.property.xtext.UmlProperty"/>
+</xmi:XMI>
diff --git a/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/employment.di b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/employment.di
new file mode 100644
index 00000000000..d94f1fa4ed4
--- /dev/null
+++ b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/employment.di
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<di:SashWindowsMngr xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:di="http://www.eclipse.org/papyrus/0.7.0/sashdi">
+ <sashModel currentSelection="//@sashModel/@windows.0/@children.0">
+ <windows>
+ <children xsi:type="di:TabFolder">
+ <children>
+ <emfPageIdentifier href="employment.notation#_6l9toPJDEeOWJr1T78jdJA"/>
+ </children>
+ <children>
+ <emfPageIdentifier href="employment.notation#_4hrxoPJXEeOWJr1T78jdJA"/>
+ </children>
+ <children>
+ <emfPageIdentifier href="employment.notation#_HvMBoPrfEeOjArr2x5XJOA"/>
+ </children>
+ </children>
+ </windows>
+ </sashModel>
+</di:SashWindowsMngr>
diff --git a/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/employment.notation b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/employment.notation
new file mode 100644
index 00000000000..ed846af8855
--- /dev/null
+++ b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/employment.notation
@@ -0,0 +1,415 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:configuration="http://www.eclipse.org/papyrus/infra/viewpoints/configuration" xmlns:css="http://www.eclipse.org/papyrus/infra/gmfdiag/css" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:nattable="http://www.eclipse.org/papyrus/nattable/model" xmlns:nattableaxis="http://www.eclipse.org/papyrus/nattable/model/table/nattableaxis" xmlns:nattableaxisconfiguration="http://www.eclipse.org/papyrus/nattable/model/table/nattableaxisconfiguration" xmlns:nattableaxisprovider="http://www.eclipse.org/papyrus/nattable/model/table/nattableaxisprovider" xmlns:nattableconfiguration="http://www.eclipse.org/papyrus/nattable/model/nattableconfiguration" xmlns:notation="http://www.eclipse.org/gmf/runtime/1.0.2/notation" xmlns:style="http://www.eclipse.org/papyrus/infra/viewpoints/policy/style" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xsi:schemaLocation="http://www.eclipse.org/papyrus/nattable/model/table/nattableaxis http://www.eclipse.org/papyrus/nattable/model#//nattableaxis http://www.eclipse.org/papyrus/nattable/model/table/nattableaxisconfiguration http://www.eclipse.org/papyrus/nattable/model#//nattableaxisconfiguration http://www.eclipse.org/papyrus/nattable/model/table/nattableaxisprovider http://www.eclipse.org/papyrus/nattable/model#//nattableaxisprovider http://www.eclipse.org/papyrus/nattable/model/nattableconfiguration http://www.eclipse.org/papyrus/nattable/model#//nattableconfiguration">
+ <notation:Diagram xmi:id="_6l9toPJDEeOWJr1T78jdJA" type="PapyrusUMLClassDiagram" name="classes" measurementUnit="Pixel">
+ <children xmi:type="notation:Shape" xmi:id="_YCT24PJEEeOWJr1T78jdJA" type="2008">
+ <children xmi:type="notation:DecorationNode" xmi:id="_YCT24vJEEeOWJr1T78jdJA" type="5029"/>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_YCUd8PJEEeOWJr1T78jdJA" type="7017">
+ <children xmi:type="notation:Shape" xmi:id="_mLpwIPJEEeOWJr1T78jdJA" type="3012">
+ <element xmi:type="uml:Property" href="employment.uml#_mLn68PJEEeOWJr1T78jdJA"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_mLpwIfJEEeOWJr1T78jdJA"/>
+ </children>
+ <children xmi:type="notation:Shape" xmi:id="_SDVpkPlAEeOEp7Wro2yWpw" type="3012">
+ <element xmi:type="uml:Property" href="employment.uml#_SDT0YPlAEeOEp7Wro2yWpw"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_SDVpkflAEeOEp7Wro2yWpw"/>
+ </children>
+ <styles xmi:type="notation:TitleStyle" xmi:id="_YCUd8fJEEeOWJr1T78jdJA"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_YCUd8vJEEeOWJr1T78jdJA"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_YCUd8_JEEeOWJr1T78jdJA"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_YCUd9PJEEeOWJr1T78jdJA"/>
+ </children>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_YCUd9fJEEeOWJr1T78jdJA" type="7018">
+ <styles xmi:type="notation:TitleStyle" xmi:id="_YCUd9vJEEeOWJr1T78jdJA"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_YCUd9_JEEeOWJr1T78jdJA"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_YCUd-PJEEeOWJr1T78jdJA"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_YCUd-fJEEeOWJr1T78jdJA"/>
+ </children>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_YCUd-vJEEeOWJr1T78jdJA" type="7019">
+ <styles xmi:type="notation:TitleStyle" xmi:id="_YCUd-_JEEeOWJr1T78jdJA"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_YCUd_PJEEeOWJr1T78jdJA"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_YCUd_fJEEeOWJr1T78jdJA"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_YCUd_vJEEeOWJr1T78jdJA"/>
+ </children>
+ <element xmi:type="uml:Class" href="employment.uml#_YCTP0PJEEeOWJr1T78jdJA"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_YCT24fJEEeOWJr1T78jdJA" x="348" y="71"/>
+ </children>
+ <children xmi:type="notation:Shape" xmi:id="__LIHkPMXEeOa2u9_4wMSZA" type="2008">
+ <children xmi:type="notation:DecorationNode" xmi:id="__LJVsPMXEeOa2u9_4wMSZA" type="5029"/>
+ <children xmi:type="notation:BasicCompartment" xmi:id="__LJVsfMXEeOa2u9_4wMSZA" type="7017">
+ <children xmi:type="notation:Shape" xmi:id="_M4Z1wPlAEeOEp7Wro2yWpw" type="3012">
+ <element xmi:type="uml:Property" href="employment.uml#_M1fEoPlAEeOEp7Wro2yWpw"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_M4Z1wflAEeOEp7Wro2yWpw"/>
+ </children>
+ <styles xmi:type="notation:TitleStyle" xmi:id="__LJVsvMXEeOa2u9_4wMSZA"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="__LJVs_MXEeOa2u9_4wMSZA"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="__LJVtPMXEeOa2u9_4wMSZA"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="__LJVtfMXEeOa2u9_4wMSZA"/>
+ </children>
+ <children xmi:type="notation:BasicCompartment" xmi:id="__LJVtvMXEeOa2u9_4wMSZA" type="7018">
+ <styles xmi:type="notation:TitleStyle" xmi:id="__LJVt_MXEeOa2u9_4wMSZA"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="__LJVuPMXEeOa2u9_4wMSZA"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="__LJVufMXEeOa2u9_4wMSZA"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="__LJVuvMXEeOa2u9_4wMSZA"/>
+ </children>
+ <children xmi:type="notation:BasicCompartment" xmi:id="__LJ8wPMXEeOa2u9_4wMSZA" type="7019">
+ <styles xmi:type="notation:TitleStyle" xmi:id="__LJ8wfMXEeOa2u9_4wMSZA"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="__LJ8wvMXEeOa2u9_4wMSZA"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="__LJ8w_MXEeOa2u9_4wMSZA"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="__LJ8xPMXEeOa2u9_4wMSZA"/>
+ </children>
+ <element xmi:type="uml:Class" href="employment.uml#__JZpQPMXEeOa2u9_4wMSZA"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="__LIHkfMXEeOa2u9_4wMSZA" x="50" y="70"/>
+ </children>
+ <styles xmi:type="notation:StringValueStyle" xmi:id="_6l9tofJDEeOWJr1T78jdJA" name="diagram_compatibility_version" stringValue="1.0.0"/>
+ <styles xmi:type="notation:DiagramStyle" xmi:id="_6l9tovJDEeOWJr1T78jdJA"/>
+ <styles xmi:type="style:PapyrusViewStyle" xmi:id="_6l9to_JDEeOWJr1T78jdJA">
+ <owner xmi:type="uml:Model" href="employment.uml#_6iAasPJDEeOWJr1T78jdJA"/>
+ </styles>
+ <element xmi:type="uml:Model" href="employment.uml#_6iAasPJDEeOWJr1T78jdJA"/>
+ <edges xmi:type="notation:Connector" xmi:id="_AsPVAPMYEeOa2u9_4wMSZA" type="4001" source="__LIHkPMXEeOa2u9_4wMSZA" target="_YCT24PJEEeOWJr1T78jdJA">
+ <children xmi:type="notation:DecorationNode" xmi:id="_AsP8EPMYEeOa2u9_4wMSZA" type="6001">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_AsP8EfMYEeOa2u9_4wMSZA" y="-20"/>
+ </children>
+ <children xmi:type="notation:DecorationNode" xmi:id="_AsP8EvMYEeOa2u9_4wMSZA" visible="false" type="6002">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_AsQjIPMYEeOa2u9_4wMSZA" y="20"/>
+ </children>
+ <children xmi:type="notation:DecorationNode" xmi:id="_AsQjIfMYEeOa2u9_4wMSZA" type="6003">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_AsQjIvMYEeOa2u9_4wMSZA" x="7" y="-15"/>
+ </children>
+ <children xmi:type="notation:DecorationNode" xmi:id="_AsRKMPMYEeOa2u9_4wMSZA" type="6005">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_AsRKMfMYEeOa2u9_4wMSZA" x="-7" y="20"/>
+ </children>
+ <children xmi:type="notation:DecorationNode" xmi:id="_AsRKMvMYEeOa2u9_4wMSZA" type="6033">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_AsRKM_MYEeOa2u9_4wMSZA" y="20"/>
+ </children>
+ <children xmi:type="notation:DecorationNode" xmi:id="_AsRxQPMYEeOa2u9_4wMSZA" type="6034">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_AsRxQfMYEeOa2u9_4wMSZA" y="-20"/>
+ </children>
+ <styles xmi:type="notation:FontStyle" xmi:id="_AsPVAfMYEeOa2u9_4wMSZA"/>
+ <element xmi:type="uml:Association" href="employment.uml#_AsIAQPMYEeOa2u9_4wMSZA"/>
+ <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_AsPVAvMYEeOa2u9_4wMSZA" points="[0, 0, -188, -63]$[188, 63, 0, 0]"/>
+ <sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_fYcuMPMZEeOa2u9_4wMSZA" id="(1.0,0.22)"/>
+ <targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_fYdVQPMZEeOa2u9_4wMSZA" id="(0.0,0.1875)"/>
+ </edges>
+ </notation:Diagram>
+ <notation:Diagram xmi:id="_4hrxoPJXEeOWJr1T78jdJA" type="PapyrusUMLActivityDiagram" name="ActivityDiagram" measurementUnit="Pixel">
+ <children xmi:type="notation:Shape" xmi:id="_4hrxofJXEeOWJr1T78jdJA" type="2001">
+ <children xmi:type="notation:DecorationNode" xmi:id="_4hrxovJXEeOWJr1T78jdJA" type="5001"/>
+ <children xmi:type="notation:DecorationNode" xmi:id="_4hrxpPJXEeOWJr1T78jdJA" type="7001">
+ <styles xmi:type="notation:SortingStyle" xmi:id="_4hrxpfJXEeOWJr1T78jdJA"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_4hrxpvJXEeOWJr1T78jdJA"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_4hrxp_JXEeOWJr1T78jdJA"/>
+ </children>
+ <children xmi:type="notation:DecorationNode" xmi:id="_4hrxqPJXEeOWJr1T78jdJA" type="7002">
+ <styles xmi:type="notation:SortingStyle" xmi:id="_4hrxqfJXEeOWJr1T78jdJA"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_4hrxqvJXEeOWJr1T78jdJA"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_4hrxq_JXEeOWJr1T78jdJA"/>
+ </children>
+ <children xmi:type="notation:DecorationNode" xmi:id="_4hrxrPJXEeOWJr1T78jdJA" type="7003">
+ <styles xmi:type="notation:SortingStyle" xmi:id="_4hrxrfJXEeOWJr1T78jdJA"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_4hrxrvJXEeOWJr1T78jdJA"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_4hrxr_JXEeOWJr1T78jdJA"/>
+ </children>
+ <children xmi:type="notation:DecorationNode" xmi:id="_4hrxsPJXEeOWJr1T78jdJA" type="7004">
+ <children xmi:type="notation:Shape" xmi:id="_6IPfwPJXEeOWJr1T78jdJA" type="3071">
+ <children xmi:type="notation:DecorationNode" xmi:id="_6IPfw_JXEeOWJr1T78jdJA" type="5121"/>
+ <children xmi:type="notation:DecorationNode" xmi:id="_6IQG0PJXEeOWJr1T78jdJA" type="7010">
+ <children xmi:type="notation:Shape" xmi:id="_DuvQoPlCEeOEp7Wro2yWpw" type="3007">
+ <children xmi:type="notation:DecorationNode" xmi:id="_DuvQo_lCEeOEp7Wro2yWpw" type="5003"/>
+ <styles xmi:type="notation:HintedDiagramLinkStyle" xmi:id="_DuvQoflCEeOEp7Wro2yWpw"/>
+ <element xmi:type="uml:OpaqueAction" href="employment.uml#_DupxEPlCEeOEp7Wro2yWpw"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_DuvQovlCEeOEp7Wro2yWpw" x="19" y="24" width="55" height="30"/>
+ </children>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_6IQG0fJXEeOWJr1T78jdJA"/>
+ </children>
+ <styles xmi:type="notation:HintedDiagramLinkStyle" xmi:id="_6IPfwfJXEeOWJr1T78jdJA"/>
+ <element xmi:type="uml:LoopNode" href="employment.uml#_6IKnQPJXEeOWJr1T78jdJA"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_6IPfwvJXEeOWJr1T78jdJA" x="146" y="59" width="109" height="70"/>
+ </children>
+ <children xmi:type="notation:Shape" xmi:id="_x7_nwPlBEeOEp7Wro2yWpw" type="3004">
+ <children xmi:type="notation:DecorationNode" xmi:id="_x8AO0PlBEeOEp7Wro2yWpw" type="5080">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_x8AO0flBEeOEp7Wro2yWpw" y="5"/>
+ </children>
+ <styles xmi:type="notation:HintedDiagramLinkStyle" xmi:id="_x7_nwflBEeOEp7Wro2yWpw"/>
+ <element xmi:type="uml:InitialNode" href="employment.uml#_x5npMPlBEeOEp7Wro2yWpw"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_x7_nwvlBEeOEp7Wro2yWpw" x="28" y="67"/>
+ </children>
+ <children xmi:type="notation:Shape" xmi:id="_2YAgEPlBEeOEp7Wro2yWpw" type="3006">
+ <children xmi:type="notation:DecorationNode" xmi:id="_2YBHIPlBEeOEp7Wro2yWpw" type="5082">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_2YBHIflBEeOEp7Wro2yWpw" y="5"/>
+ </children>
+ <styles xmi:type="notation:HintedDiagramLinkStyle" xmi:id="_2YAgEflBEeOEp7Wro2yWpw"/>
+ <element xmi:type="uml:FlowFinalNode" href="employment.uml#_2X-D0PlBEeOEp7Wro2yWpw"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_2YAgEvlBEeOEp7Wro2yWpw" x="350" y="80"/>
+ </children>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_4hrxsfJXEeOWJr1T78jdJA"/>
+ </children>
+ <element xmi:type="uml:Activity" href="employment.uml#_2W4uAPJXEeOWJr1T78jdJA"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_4hrxsvJXEeOWJr1T78jdJA"/>
+ </children>
+ <styles xmi:type="notation:StringValueStyle" xmi:id="_4hrxs_JXEeOWJr1T78jdJA" name="diagram_compatibility_version" stringValue="1.0.0"/>
+ <styles xmi:type="notation:DiagramStyle" xmi:id="_4hrxtPJXEeOWJr1T78jdJA"/>
+ <styles xmi:type="style:PapyrusViewStyle" xmi:id="_4hrxtfJXEeOWJr1T78jdJA">
+ <owner xmi:type="uml:Activity" href="employment.uml#_2W4uAPJXEeOWJr1T78jdJA"/>
+ </styles>
+ <element xmi:type="uml:Activity" href="employment.uml#_2W4uAPJXEeOWJr1T78jdJA"/>
+ <edges xmi:type="notation:Connector" xmi:id="_zIi6cPlBEeOEp7Wro2yWpw" type="4004" source="_x7_nwPlBEeOEp7Wro2yWpw" target="_6IPfwPJXEeOWJr1T78jdJA">
+ <children xmi:type="notation:DecorationNode" xmi:id="_zIi6c_lBEeOEp7Wro2yWpw" visible="false" type="6003">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_zIi6dPlBEeOEp7Wro2yWpw" y="20"/>
+ </children>
+ <children xmi:type="notation:DecorationNode" xmi:id="_zIjhgPlBEeOEp7Wro2yWpw" visible="false" type="6004">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_zIjhgflBEeOEp7Wro2yWpw" y="20"/>
+ </children>
+ <children xmi:type="notation:DecorationNode" xmi:id="_zIjhgvlBEeOEp7Wro2yWpw" visible="false" type="6009">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_zIjhg_lBEeOEp7Wro2yWpw" y="20"/>
+ </children>
+ <children xmi:type="notation:DecorationNode" xmi:id="_zIjhhPlBEeOEp7Wro2yWpw" visible="false" type="6011">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_zIjhhflBEeOEp7Wro2yWpw" y="-20"/>
+ </children>
+ <styles xmi:type="notation:FontStyle" xmi:id="_zIi6cflBEeOEp7Wro2yWpw"/>
+ <element xmi:type="uml:ControlFlow" href="employment.uml#_zIVfEPlBEeOEp7Wro2yWpw"/>
+ <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_zIi6cvlBEeOEp7Wro2yWpw" points="[10, 0, -114, 0]$[108, 7, -16, 7]"/>
+ <targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_zPwVsPlBEeOEp7Wro2yWpw" id="(0.0,0.5142857142857142)"/>
+ </edges>
+ <edges xmi:type="notation:Connector" xmi:id="_4S2cIPlBEeOEp7Wro2yWpw" type="4004" source="_6IPfwPJXEeOWJr1T78jdJA" target="_2YAgEPlBEeOEp7Wro2yWpw">
+ <children xmi:type="notation:DecorationNode" xmi:id="_4S2cI_lBEeOEp7Wro2yWpw" visible="false" type="6003">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_4S2cJPlBEeOEp7Wro2yWpw" y="20"/>
+ </children>
+ <children xmi:type="notation:DecorationNode" xmi:id="_4S2cJflBEeOEp7Wro2yWpw" visible="false" type="6004">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_4S3DMPlBEeOEp7Wro2yWpw" y="20"/>
+ </children>
+ <children xmi:type="notation:DecorationNode" xmi:id="_4S3DMflBEeOEp7Wro2yWpw" visible="false" type="6009">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_4S3DMvlBEeOEp7Wro2yWpw" y="20"/>
+ </children>
+ <children xmi:type="notation:DecorationNode" xmi:id="_4S3DM_lBEeOEp7Wro2yWpw" visible="false" type="6011">
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_4S3DNPlBEeOEp7Wro2yWpw" y="-20"/>
+ </children>
+ <styles xmi:type="notation:FontStyle" xmi:id="_4S2cIflBEeOEp7Wro2yWpw"/>
+ <element xmi:type="uml:ControlFlow" href="employment.uml#_4Sgd4PlBEeOEp7Wro2yWpw"/>
+ <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_4S2cIvlBEeOEp7Wro2yWpw" points="[18, -2, -131, -2]$[152, -10, 3, -10]"/>
+ <sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_4S-_APlBEeOEp7Wro2yWpw" id="(0.76,0.475)"/>
+ </edges>
+ </notation:Diagram>
+ <css:ModelStyleSheets xmi:id="_fBUnoPMZEeOa2u9_4wMSZA"/>
+ <nattable:Table xmi:id="_HvMBoPrfEeOjArr2x5XJOA" name="classes" currentRowAxisProvider="_HvMosfrfEeOjArr2x5XJOA" currentColumnAxisProvider="_HvMosPrfEeOjArr2x5XJOA">
+ <context xmi:type="uml:Model" href="employment.uml#_6iAasPJDEeOWJr1T78jdJA"/>
+ <owner xmi:type="uml:Model" href="employment.uml#_6iAasPJDEeOWJr1T78jdJA"/>
+ <prototype xmi:type="configuration:PapyrusSyncTable" href="platform:/plugin/org.eclipse.papyrus.infra.viewpoints.policy/builtin/default.configuration#_7wNb2NxhEeOqHvRyiN87hA"/>
+ <tableConfiguration xmi:type="nattableconfiguration:TableConfiguration" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#/"/>
+ <columnAxisProvidersHistory xmi:type="nattableaxisprovider:SlaveObjectAxisProvider" xmi:id="_HvMosPrfEeOjArr2x5XJOA" description="This axis provider provides available columns according to the rows of the table (features of the object displayed on the other axis)" name="UML Feature axis provider">
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kkPrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EAttribute" href="http://www.eclipse.org/uml2/5.0.0/UML#//NamedElement/visibility"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kkfrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Classifier/useCase"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kkvrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Classifier/substitution"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kk_rfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Classifier/general"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58klPrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Namespace/importedMember"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58klfrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//TemplateableElement/ownedTemplateSignature"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58klvrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Namespace/member"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kl_rfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//StructuredClassifier/part"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kmPrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Element/owner"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kmfrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Classifier/feature"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kmvrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EAttribute" href="http://www.eclipse.org/uml2/5.0.0/UML#//NamedElement/name"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58km_rfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Class/ownedOperation"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58knPrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//BehavioredClassifier/interfaceRealization"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58knfrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//TemplateableElement/templateBinding"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58knvrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Classifier/redefinedClassifier"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kn_rfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//StructuredClassifier/ownedConnector"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58koPrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//BehavioredClassifier/ownedBehavior"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kofrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Namespace/elementImport"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kovrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Classifier/attribute"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58ko_rfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Class/nestedClassifier"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kpPrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//RedefinableElement/redefinedElement"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kpfrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Class/extension"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kpvrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//NamedElement/nameExpression"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kp_rfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//ParameterableElement/owningTemplateParameter"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kqPrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//BehavioredClassifier/classifierBehavior"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kqfrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Namespace/ownedRule"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kqvrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Classifier/generalization"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kq_rfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EAttribute" href="http://www.eclipse.org/uml2/5.0.0/UML#//RedefinableElement/isLeaf"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58krPrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Classifier/collaborationUse"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58krfrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//EncapsulatedClassifier/ownedPort"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58krvrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//NamedElement/namespace"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kr_rfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//StructuredClassifier/role"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58ksPrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//ParameterableElement/templateParameter"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58ksfrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Class/superClass"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58ksvrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Namespace/ownedMember"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58ks_rfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Element/ownedComment"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58ktPrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EAttribute" href="http://www.eclipse.org/uml2/5.0.0/UML#//Class/isActive"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58ktfrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Classifier/powertypeExtent"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58ktvrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Element/ownedElement"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kt_rfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//NamedElement/clientDependency"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kuPrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Classifier/inheritedMember"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kufrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EAttribute" href="http://www.eclipse.org/uml2/5.0.0/UML#//NamedElement/qualifiedName"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kuvrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//RedefinableElement/redefinitionContext"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58ku_rfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Namespace/packageImport"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kvPrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EAttribute" href="http://www.eclipse.org/uml2/5.0.0/UML#//Classifier/isAbstract"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kvfrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EAttribute" href="http://www.eclipse.org/uml2/5.0.0/UML#//Classifier/isFinalSpecialization"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kvvrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Class/ownedReception"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kv_rfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//StructuredClassifier/ownedAttribute"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kwPrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Classifier/representation"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kwfrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Classifier/ownedUseCase"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kwvrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@columnHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="ecore:EReference" href="http://www.eclipse.org/uml2/5.0.0/UML#//Type/package"/>
+ </axis>
+ </columnAxisProvidersHistory>
+ <rowAxisProvidersHistory xmi:type="nattableaxisprovider:MasterObjectAxisProvider" xmi:id="_HvMosfrfEeOjArr2x5XJOA" description="This axis provider contains the object dropped by the user into the table" name="DroppedElementAxisProvider">
+ <axis xmi:type="nattableaxis:EObjectAxis" xmi:id="_I56vYPrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@rowHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="uml:Class" href="employment.uml#_YCTP0PJEEeOWJr1T78jdJA"/>
+ </axis>
+ <axis xmi:type="nattableaxis:EObjectAxis" xmi:id="_I57WcPrfEeOjArr2x5XJOA">
+ <manager xmi:type="nattableaxisconfiguration:AxisManagerRepresentation" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#//@rowHeaderAxisConfiguration/@axisManagers.0"/>
+ <element xmi:type="uml:Class" href="employment.uml#__JZpQPMXEeOa2u9_4wMSZA"/>
+ </axis>
+ </rowAxisProvidersHistory>
+ </nattable:Table>
+</xmi:XMI>
diff --git a/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/employment.uml b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/employment.uml
new file mode 100644
index 00000000000..4ff766e905a
--- /dev/null
+++ b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/employment.uml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<uml:Model xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xmi:id="_6iAasPJDEeOWJr1T78jdJA" name="employment">
+ <packageImport xmi:type="uml:PackageImport" xmi:id="_6iAasfJDEeOWJr1T78jdJA">
+ <importedPackage xmi:type="uml:Model" href="pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#_0"/>
+ </packageImport>
+ <packagedElement xmi:type="uml:Class" xmi:id="_YCTP0PJEEeOWJr1T78jdJA" name="Person">
+ <ownedAttribute xmi:type="uml:Property" xmi:id="_mLn68PJEEeOWJr1T78jdJA" name="ssn" visibility="public" isUnique="false">
+ <type xmi:type="uml:DataType" href="library.uml#_AtaNAPJEEeOWJr1T78jdJA"/>
+ <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_opwxUPJEEeOWJr1T78jdJA" value="1"/>
+ <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_op4tIPJEEeOWJr1T78jdJA" value="1"/>
+ </ownedAttribute>
+ <ownedAttribute xmi:type="uml:Property" xmi:id="_SDT0YPlAEeOEp7Wro2yWpw" name="name" visibility="public" isUnique="false">
+ <type xmi:type="uml:DataType" href="library.uml#_vCcKoPJEEeOWJr1T78jdJA"/>
+ <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_S4X0IPlAEeOEp7Wro2yWpw" value="1"/>
+ <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_S4izQPlAEeOEp7Wro2yWpw" value="1"/>
+ </ownedAttribute>
+ <ownedBehavior xmi:type="uml:Activity" xmi:id="_2W4uAPJXEeOWJr1T78jdJA" name="Activity" node="_6IKnQPJXEeOWJr1T78jdJA _x5npMPlBEeOEp7Wro2yWpw _2X-D0PlBEeOEp7Wro2yWpw" group="_6IKnQPJXEeOWJr1T78jdJA">
+ <edge xmi:type="uml:ControlFlow" xmi:id="_zIVfEPlBEeOEp7Wro2yWpw" name="ControlFlow" target="_6IKnQPJXEeOWJr1T78jdJA" source="_x5npMPlBEeOEp7Wro2yWpw"/>
+ <edge xmi:type="uml:ControlFlow" xmi:id="_4Sgd4PlBEeOEp7Wro2yWpw" name="ControlFlow1" target="_2X-D0PlBEeOEp7Wro2yWpw" source="_6IKnQPJXEeOWJr1T78jdJA"/>
+ <structuredNode xmi:type="uml:LoopNode" xmi:id="_6IKnQPJXEeOWJr1T78jdJA" name="work" incoming="_zIVfEPlBEeOEp7Wro2yWpw" outgoing="_4Sgd4PlBEeOEp7Wro2yWpw">
+ <node xmi:type="uml:OpaqueAction" xmi:id="_DupxEPlCEeOEp7Wro2yWpw" name="do work"/>
+ </structuredNode>
+ <node xmi:type="uml:InitialNode" xmi:id="_x5npMPlBEeOEp7Wro2yWpw" name="InitialNode" outgoing="_zIVfEPlBEeOEp7Wro2yWpw"/>
+ <node xmi:type="uml:FlowFinalNode" xmi:id="_2X-D0PlBEeOEp7Wro2yWpw" name="FlowFinalNode" incoming="_4Sgd4PlBEeOEp7Wro2yWpw"/>
+ </ownedBehavior>
+ </packagedElement>
+ <packagedElement xmi:type="uml:Class" xmi:id="__JZpQPMXEeOa2u9_4wMSZA" name="Company">
+ <ownedAttribute xmi:type="uml:Property" xmi:id="_AsHZMPMYEeOa2u9_4wMSZA" name="employee" type="_YCTP0PJEEeOWJr1T78jdJA" subsettedProperty="_mLn68PJEEeOWJr1T78jdJA" association="_AsIAQPMYEeOa2u9_4wMSZA">
+ <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_AsHZMfMYEeOa2u9_4wMSZA"/>
+ <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_AsHZMvMYEeOa2u9_4wMSZA" value="*"/>
+ </ownedAttribute>
+ <ownedAttribute xmi:type="uml:Property" xmi:id="_M1fEoPlAEeOEp7Wro2yWpw" name="name" visibility="public" isUnique="false">
+ <type xmi:type="uml:DataType" href="library.uml#_vCcKoPJEEeOWJr1T78jdJA"/>
+ <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_Q5IgQPlAEeOEp7Wro2yWpw" value="1"/>
+ <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_Q5YX4PlAEeOEp7Wro2yWpw" value="1"/>
+ </ownedAttribute>
+ </packagedElement>
+ <packagedElement xmi:type="uml:Association" xmi:id="_AsIAQPMYEeOa2u9_4wMSZA" name="A_company_person_1" memberEnd="_AsIAQfMYEeOa2u9_4wMSZA _AsHZMPMYEeOa2u9_4wMSZA">
+ <ownedEnd xmi:type="uml:Property" xmi:id="_AsIAQfMYEeOa2u9_4wMSZA" name="employer" visibility="public" type="__JZpQPMXEeOa2u9_4wMSZA" association="_AsIAQPMYEeOa2u9_4wMSZA">
+ <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_AsIAQvMYEeOa2u9_4wMSZA" value="1"/>
+ <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_AsIAQ_MYEeOa2u9_4wMSZA" value="1"/>
+ </ownedEnd>
+ </packagedElement>
+</uml:Model>
diff --git a/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/library.di b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/library.di
new file mode 100644
index 00000000000..42ec9bffb56
--- /dev/null
+++ b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/library.di
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<di:SashWindowsMngr xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:di="http://www.eclipse.org/papyrus/0.7.0/sashdi">
+ <sashModel currentSelection="//@sashModel/@windows.0/@children.0">
+ <windows>
+ <children xsi:type="di:TabFolder">
+ <children>
+ <emfPageIdentifier href="library.notation#__mWeUPJDEeOWJr1T78jdJA"/>
+ </children>
+ </children>
+ </windows>
+ </sashModel>
+</di:SashWindowsMngr>
diff --git a/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/library.notation b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/library.notation
new file mode 100644
index 00000000000..97b9536a1e0
--- /dev/null
+++ b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/library.notation
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<notation:Diagram xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:notation="http://www.eclipse.org/gmf/runtime/1.0.2/notation" xmlns:style="http://www.eclipse.org/papyrus/infra/viewpoints/policy/style" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xmi:id="__mWeUPJDEeOWJr1T78jdJA" type="PapyrusUMLClassDiagram" name="classes" measurementUnit="Pixel">
+ <children xmi:type="notation:Shape" xmi:id="_AuLpEPJEEeOWJr1T78jdJA" type="2010">
+ <children xmi:type="notation:DecorationNode" xmi:id="_AuMQIPJEEeOWJr1T78jdJA" type="5035"/>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_AuMQIfJEEeOWJr1T78jdJA" type="7020">
+ <children xmi:type="notation:Shape" xmi:id="_eT1fUPJEEeOWJr1T78jdJA" type="3018">
+ <element xmi:type="uml:Property" href="library.uml#_eThWQPJEEeOWJr1T78jdJA"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_eT1fUfJEEeOWJr1T78jdJA"/>
+ </children>
+ <styles xmi:type="notation:TitleStyle" xmi:id="_AuMQIvJEEeOWJr1T78jdJA"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_AuMQI_JEEeOWJr1T78jdJA"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_AuMQJPJEEeOWJr1T78jdJA"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_AuMQJfJEEeOWJr1T78jdJA"/>
+ </children>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_AuM3MPJEEeOWJr1T78jdJA" type="7021">
+ <styles xmi:type="notation:TitleStyle" xmi:id="_AuM3MfJEEeOWJr1T78jdJA"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_AuM3MvJEEeOWJr1T78jdJA"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_AuM3M_JEEeOWJr1T78jdJA"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_AuM3NPJEEeOWJr1T78jdJA"/>
+ </children>
+ <element xmi:type="uml:DataType" href="library.uml#_AtaNAPJEEeOWJr1T78jdJA"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_AuLpEfJEEeOWJr1T78jdJA" x="67" y="55"/>
+ </children>
+ <children xmi:type="notation:Shape" xmi:id="_vCdYwPJEEeOWJr1T78jdJA" type="2010">
+ <children xmi:type="notation:DecorationNode" xmi:id="_vCdYwvJEEeOWJr1T78jdJA" type="5035"/>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_vCdYw_JEEeOWJr1T78jdJA" type="7020">
+ <children xmi:type="notation:Shape" xmi:id="_W7AjIPlAEeOEp7Wro2yWpw" type="3018">
+ <element xmi:type="uml:Property" href="library.uml#_W65OYPlAEeOEp7Wro2yWpw"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_W7AjIflAEeOEp7Wro2yWpw"/>
+ </children>
+ <children xmi:type="notation:Shape" xmi:id="_YtLrYPlAEeOEp7Wro2yWpw" type="3018">
+ <element xmi:type="uml:Property" href="library.uml#_YtJ2MPlAEeOEp7Wro2yWpw"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_YtLrYflAEeOEp7Wro2yWpw"/>
+ </children>
+ <styles xmi:type="notation:TitleStyle" xmi:id="_vCdYxPJEEeOWJr1T78jdJA"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_vCdYxfJEEeOWJr1T78jdJA"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_vCdYxvJEEeOWJr1T78jdJA"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_vCdYx_JEEeOWJr1T78jdJA"/>
+ </children>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_vCdYyPJEEeOWJr1T78jdJA" type="7021">
+ <styles xmi:type="notation:TitleStyle" xmi:id="_vCdYyfJEEeOWJr1T78jdJA"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_vCdYyvJEEeOWJr1T78jdJA"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_vCdYy_JEEeOWJr1T78jdJA"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_vCdYzPJEEeOWJr1T78jdJA"/>
+ </children>
+ <element xmi:type="uml:DataType" href="library.uml#_vCcKoPJEEeOWJr1T78jdJA"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_vCdYwfJEEeOWJr1T78jdJA" x="276" y="54"/>
+ </children>
+ <children xmi:type="notation:Shape" xmi:id="_9VjWcPlAEeOEp7Wro2yWpw" type="2009">
+ <children xmi:type="notation:DecorationNode" xmi:id="_9VjWcvlAEeOEp7Wro2yWpw" type="5032"/>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_9VjWc_lAEeOEp7Wro2yWpw" type="7039">
+ <styles xmi:type="notation:TitleStyle" xmi:id="_9VjWdPlAEeOEp7Wro2yWpw"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_9VjWdflAEeOEp7Wro2yWpw"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_9VjWdvlAEeOEp7Wro2yWpw"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_9VjWd_lAEeOEp7Wro2yWpw"/>
+ </children>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_9VjWePlAEeOEp7Wro2yWpw" type="7040">
+ <styles xmi:type="notation:TitleStyle" xmi:id="_9VjWeflAEeOEp7Wro2yWpw"/>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_9VjWevlAEeOEp7Wro2yWpw"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_9VjWe_lAEeOEp7Wro2yWpw"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_9VjWfPlAEeOEp7Wro2yWpw"/>
+ </children>
+ <element xmi:type="uml:PrimitiveType" href="library.uml#_9VhhQPlAEeOEp7Wro2yWpw"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_9VjWcflAEeOEp7Wro2yWpw" x="498" y="55"/>
+ </children>
+ <styles xmi:type="notation:StringValueStyle" xmi:id="__mWeUfJDEeOWJr1T78jdJA" name="diagram_compatibility_version" stringValue="1.0.0"/>
+ <styles xmi:type="notation:DiagramStyle" xmi:id="__mWeUvJDEeOWJr1T78jdJA"/>
+ <styles xmi:type="style:PapyrusViewStyle" xmi:id="__mWeU_JDEeOWJr1T78jdJA">
+ <owner xmi:type="uml:Model" href="library.uml#__mBuMPJDEeOWJr1T78jdJA"/>
+ </styles>
+ <element xmi:type="uml:Model" href="library.uml#__mBuMPJDEeOWJr1T78jdJA"/>
+</notation:Diagram>
diff --git a/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/library.uml b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/library.uml
new file mode 100644
index 00000000000..3be4c8d6dc4
--- /dev/null
+++ b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/library.uml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xmi:XMI xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ActionLanguage="http://www.omg.org/spec/ALF/20120827/ActionLanguage-Profile" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xsi:schemaLocation="http://www.omg.org/spec/ALF/20120827/ActionLanguage-Profile pathmap://PAPYRUS_ACTIONLANGUAGE_PROFILE/ActionLanguage-Profile.profile.uml#_sYse0YZLEeKyw49uR6nx3g">
+ <uml:Model xmi:id="__mBuMPJDEeOWJr1T78jdJA" name="types">
+ <packageImport xmi:type="uml:PackageImport" xmi:id="__mBuMfJDEeOWJr1T78jdJA">
+ <importedPackage xmi:type="uml:Model" href="pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#_0"/>
+ </packageImport>
+ <packagedElement xmi:type="uml:DataType" xmi:id="_AtaNAPJEEeOWJr1T78jdJA" name="SSN">
+ <ownedAttribute xmi:type="uml:Property" xmi:id="_eThWQPJEEeOWJr1T78jdJA" name="ssn" visibility="public" isUnique="false">
+ <type xmi:type="uml:PrimitiveType" href="pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#String"/>
+ <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_gmTRMPJEEeOWJr1T78jdJA" value="1"/>
+ <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_gmcbIPJEEeOWJr1T78jdJA" value="1"/>
+ </ownedAttribute>
+ </packagedElement>
+ <packagedElement xmi:type="uml:DataType" xmi:id="_vCcKoPJEEeOWJr1T78jdJA" name="Name">
+ <ownedAttribute xmi:type="uml:Property" xmi:id="_W65OYPlAEeOEp7Wro2yWpw" name="lastName" visibility="public" isUnique="false">
+ <type xmi:type="uml:PrimitiveType" href="pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#String"/>
+ <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_YAKNUPlAEeOEp7Wro2yWpw" value="1"/>
+ <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_YAWakPlAEeOEp7Wro2yWpw" value="1"/>
+ </ownedAttribute>
+ <ownedAttribute xmi:type="uml:Property" xmi:id="_YtJ2MPlAEeOEp7Wro2yWpw" name="firstName" visibility="public" isUnique="false">
+ <type xmi:type="uml:PrimitiveType" href="pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#String"/>
+ <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_b6Vj4PlAEeOEp7Wro2yWpw" value="1"/>
+ <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_b6kNYPlAEeOEp7Wro2yWpw" value="1"/>
+ </ownedAttribute>
+ </packagedElement>
+ <packagedElement xmi:type="uml:PrimitiveType" xmi:id="_9VhhQPlAEeOEp7Wro2yWpw" name="Identifier"/>
+ <profileApplication xmi:type="uml:ProfileApplication" xmi:id="_ZdS5sPlAEeOEp7Wro2yWpw">
+ <eAnnotations xmi:type="ecore:EAnnotation" xmi:id="_ZeInMPlAEeOEp7Wro2yWpw" source="http://www.eclipse.org/uml2/2.0.0/UML">
+ <references xmi:type="ecore:EPackage" href="pathmap://PAPYRUS_ACTIONLANGUAGE_PROFILE/ActionLanguage-Profile.profile.uml#_sYse0YZLEeKyw49uR6nx3g"/>
+ </eAnnotations>
+ <appliedProfile xmi:type="uml:Profile" href="pathmap://PAPYRUS_ACTIONLANGUAGE_PROFILE/ActionLanguage-Profile.profile.uml#ActionLanguage"/>
+ </profileApplication>
+ </uml:Model>
+ <ActionLanguage:TextualRepresentation xmi:id="_ZeLDcPlAEeOEp7Wro2yWpw" language="org.eclipse.papyrus.uml.textedit.property.xtext.UmlProperty"/>
+</xmi:XMI>
diff --git a/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/org.eclipse.papyrus.editor.integration.tests.launch b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/org.eclipse.papyrus.editor.integration.tests.launch
index d3fbfd43b01..53fb6cee559 100644
--- a/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/org.eclipse.papyrus.editor.integration.tests.launch
+++ b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/org.eclipse.papyrus.editor.integration.tests.launch
@@ -1,43 +1,43 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<launchConfiguration type="org.eclipse.pde.ui.JunitLaunchConfig">
-<booleanAttribute key="append.args" value="true"/>
-<booleanAttribute key="askclear" value="false"/>
-<booleanAttribute key="automaticAdd" value="true"/>
-<booleanAttribute key="automaticValidate" value="false"/>
-<stringAttribute key="bootstrap" value=""/>
-<stringAttribute key="checked" value="[NONE]"/>
-<booleanAttribute key="clearConfig" value="true"/>
-<booleanAttribute key="clearws" value="true"/>
-<booleanAttribute key="clearwslog" value="false"/>
-<stringAttribute key="configLocation" value="${workspace_loc}/.metadata/.plugins/org.eclipse.pde.core/pde-junit"/>
-<booleanAttribute key="default" value="true"/>
-<booleanAttribute key="includeOptional" value="true"/>
-<stringAttribute key="location" value="${workspace_loc}/../junit-workspace-editor"/>
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
-<listEntry value="/org.eclipse.papyrus.editor.integration.tests/src/org/eclipse/papyrus/editor/integration/tests/AllTests.java"/>
-</listAttribute>
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
-<listEntry value="1"/>
-</listAttribute>
-<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/>
-<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
-<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
-<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
-<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/>
-<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
-<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.eclipse.papyrus.editor.integration.tests.AllTests"/>
-<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog"/>
-<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.papyrus.editor.integration.tests"/>
-<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
-<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dosgi.requiredJavaVersion=1.5 -Xms1024m -Xmx4086m -XX:MaxPermSize=1024M"/>
-<stringAttribute key="pde.version" value="3.3"/>
-<stringAttribute key="product" value="org.eclipse.sdk.ide"/>
-<booleanAttribute key="run_in_ui_thread" value="false"/>
-<booleanAttribute key="show_selected_only" value="false"/>
-<stringAttribute key="templateConfig" value="${target_home}\configuration\config.ini"/>
-<booleanAttribute key="tracing" value="false"/>
-<booleanAttribute key="useCustomFeatures" value="false"/>
-<booleanAttribute key="useDefaultConfig" value="true"/>
-<booleanAttribute key="useDefaultConfigArea" value="false"/>
-<booleanAttribute key="useProduct" value="true"/>
-</launchConfiguration>
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.pde.ui.JunitLaunchConfig">
+<booleanAttribute key="append.args" value="true"/>
+<booleanAttribute key="askclear" value="false"/>
+<booleanAttribute key="automaticAdd" value="true"/>
+<booleanAttribute key="automaticValidate" value="false"/>
+<stringAttribute key="bootstrap" value=""/>
+<stringAttribute key="checked" value="[NONE]"/>
+<booleanAttribute key="clearConfig" value="true"/>
+<booleanAttribute key="clearws" value="true"/>
+<booleanAttribute key="clearwslog" value="false"/>
+<stringAttribute key="configLocation" value="${workspace_loc}/.metadata/.plugins/org.eclipse.pde.core/pde-junit"/>
+<booleanAttribute key="default" value="true"/>
+<booleanAttribute key="includeOptional" value="true"/>
+<stringAttribute key="location" value="${workspace_loc}/../junit-workspace-editor"/>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+<listEntry value="/org.eclipse.papyrus.editor.integration.tests/src/org/eclipse/papyrus/editor/integration/tests/AllTests.java"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+<listEntry value="1"/>
+</listAttribute>
+<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/>
+<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
+<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
+<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
+<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/>
+<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.eclipse.papyrus.editor.integration.tests.AllTests"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.papyrus.editor.integration.tests"/>
+<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dosgi.requiredJavaVersion=1.5 -Xms1024m -Xmx4086m -XX:MaxPermSize=1024M"/>
+<stringAttribute key="pde.version" value="3.3"/>
+<stringAttribute key="product" value="org.eclipse.sdk.ide"/>
+<booleanAttribute key="run_in_ui_thread" value="true"/>
+<booleanAttribute key="show_selected_only" value="false"/>
+<stringAttribute key="templateConfig" value="${target_home}\configuration\config.ini"/>
+<booleanAttribute key="tracing" value="false"/>
+<booleanAttribute key="useCustomFeatures" value="false"/>
+<booleanAttribute key="useDefaultConfig" value="true"/>
+<booleanAttribute key="useDefaultConfigArea" value="false"/>
+<booleanAttribute key="useProduct" value="true"/>
+</launchConfiguration>
diff --git a/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/src/org/eclipse/papyrus/editor/integration/tests/AllTests.java b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/src/org/eclipse/papyrus/editor/integration/tests/AllTests.java
index a4023007aa9..761bd723d37 100644
--- a/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/src/org/eclipse/papyrus/editor/integration/tests/AllTests.java
+++ b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/src/org/eclipse/papyrus/editor/integration/tests/AllTests.java
@@ -10,12 +10,14 @@
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
* Christian W. Damus (CEA) - bug 422257
* Christian W. Damus (CEA) - bug 432813
+ * Christian W. Damus (CEA) - bug 437217
*
*****************************************************************************/
package org.eclipse.papyrus.editor.integration.tests;
import org.eclipse.papyrus.editor.integration.tests.tests.EditingScenariosMemoryLeakTest;
import org.eclipse.papyrus.editor.integration.tests.tests.EditorMemoryLeakTest;
+import org.eclipse.papyrus.editor.integration.tests.tests.EditorReloadTest;
import org.eclipse.papyrus.editor.integration.tests.tests.ModelSetTests;
import org.eclipse.papyrus.editor.integration.tests.tests.PageManagerTests;
import org.eclipse.papyrus.editor.integration.tests.tests.RecoveryTest;
@@ -26,12 +28,14 @@ import org.junit.runners.Suite.SuiteClasses;
/**
* The {@link EditorMemoryLeakTest} suite <b>must</b> run first, because some test case in one of the other suites
- * breaks the Outline view: it causes a pair of Overview/Outline actions from some diagram editor to linger in
+ * breaks the Outline view: it causes a pair of Overview/Outline actions from some diagram editor to linger in
* the outline view's toolbar even after the editor was closed, and these persistent actions cause leaks of
* models opened later.
*/
@RunWith(Suite.class)
-@SuiteClasses({ EditorMemoryLeakTest.class, EditingScenariosMemoryLeakTest.class, PageManagerTests.class, RecoveryTest.class, ModelSetTests.class })
+@SuiteClasses({ EditorMemoryLeakTest.class, EditingScenariosMemoryLeakTest.class, //
+PageManagerTests.class, RecoveryTest.class, ModelSetTests.class, //
+EditorReloadTest.class })
public class AllTests {
}
diff --git a/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/src/org/eclipse/papyrus/editor/integration/tests/tests/EditorReloadTest.java b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/src/org/eclipse/papyrus/editor/integration/tests/tests/EditorReloadTest.java
new file mode 100644
index 00000000000..315031ed396
--- /dev/null
+++ b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/src/org/eclipse/papyrus/editor/integration/tests/tests/EditorReloadTest.java
@@ -0,0 +1,530 @@
+/*
+ * Copyright (c) 2014 CEA 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:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.editor.integration.tests.tests;
+
+import static org.eclipse.papyrus.junit.matchers.DiagramMatchers.collapsedIn;
+import static org.eclipse.papyrus.junit.matchers.DiagramMatchers.editPartSelected;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.fail;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.edit.command.CommandParameter;
+import org.eclipse.emf.edit.command.SetCommand;
+import org.eclipse.emf.edit.domain.EditingDomain;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.palette.PaletteContainer;
+import org.eclipse.gef.palette.PaletteDrawer;
+import org.eclipse.gef.palette.PaletteEntry;
+import org.eclipse.gef.palette.PaletteStack;
+import org.eclipse.gef.palette.ToolEntry;
+import org.eclipse.gef.ui.palette.PaletteViewer;
+import org.eclipse.gef.ui.views.palette.PaletteView;
+import org.eclipse.jface.viewers.AbstractTreeViewer;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.papyrus.infra.core.editor.IMultiDiagramEditor;
+import org.eclipse.papyrus.infra.core.resource.ModelSet;
+import org.eclipse.papyrus.infra.core.services.IService;
+import org.eclipse.papyrus.infra.core.services.ServiceException;
+import org.eclipse.papyrus.infra.core.services.ServicesRegistry;
+import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
+import org.eclipse.papyrus.junit.utils.Duck;
+import org.eclipse.papyrus.junit.utils.classification.ExpensiveTest;
+import org.eclipse.papyrus.junit.utils.rules.PapyrusEditorFixture;
+import org.eclipse.papyrus.junit.utils.rules.PluginResource;
+import org.eclipse.papyrus.junit.utils.rules.ShowView;
+import org.eclipse.papyrus.junit.utils.rules.ShowView.Location;
+import org.eclipse.papyrus.junit.utils.tests.AbstractPapyrusTest;
+import org.eclipse.papyrus.views.modelexplorer.ModelExplorerPageBookView;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.navigator.CommonViewer;
+import org.eclipse.uml2.uml.NamedElement;
+import org.eclipse.uml2.uml.OpaqueAction;
+import org.eclipse.uml2.uml.Package;
+import org.eclipse.uml2.uml.Type;
+import org.eclipse.uml2.uml.UMLPackage;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+
+/**
+ * Test cases checking that various different scenarios in Papyrus editor re-loading for changes in resource dependencies.
+ *
+ * @see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=437217">bug 437217</a>
+ */
+@ExpensiveTest
+@PluginResource({ EditorReloadTest.EMPLOYMENT_MODEL, EditorReloadTest.BANKING_MODEL, EditorReloadTest.LIBRARY_MODEL })
+public class EditorReloadTest extends AbstractPapyrusTest {
+
+ static final String EMPLOYMENT_MODEL = "model/reload/employment.di";
+
+ static final String BANKING_MODEL = "model/reload/banking.di";
+
+ static final String LIBRARY_MODEL = "model/reload/library.di";
+
+ @Rule
+ public final PapyrusEditorFixture editorFixture = new PapyrusEditorFixture();
+
+ private IMultiDiagramEditor employmentEditor;
+
+ private IMultiDiagramEditor bankingEditor;
+
+ private IMultiDiagramEditor libraryEditor;
+
+ public EditorReloadTest() {
+ super();
+ }
+
+ /**
+ * Verify that dependent editors are not re-loaded immediately (this is deferred until they are activated).
+ */
+ @Test
+ public void testReloadIsDeferred() {
+ final ReloadAssertion reload = new ReloadAssertion(employmentEditor, bankingEditor);
+
+ pokeLibraryModel();
+ editorFixture.save(libraryEditor);
+
+ reload.assertNotReloaded();
+ }
+
+ /**
+ * Verify that re-loading two dependent editors doesn't mess up the perspective layout.
+ */
+ @Test
+ public void testPerspectiveLayoutUnperturbed() {
+ final ReloadAssertion reload = new ReloadAssertion(employmentEditor, bankingEditor);
+
+ pokeLibraryModel();
+ reload.save(libraryEditor);
+
+ // The ordering and separation of editor stacks is unchanged
+ assertThat(editorFixture.getPartStack(employmentEditor), is(Arrays.<IWorkbenchPart> asList(employmentEditor, libraryEditor)));
+ assertThat(editorFixture.getPartStack(bankingEditor), is(Arrays.<IWorkbenchPart> asList(bankingEditor)));
+ }
+
+ /**
+ * Verify that, after a <em>Save All</em> action that saves a non-active editor causing the active editor to re-load in place,
+ * the originally active editor is active once again.
+ */
+ @Test
+ public void testActiveEditorRestoredSaveAll() {
+ final ReloadAssertion reload = new ReloadAssertion(employmentEditor);
+
+ pokeLibraryModel();
+ editorFixture.activate(employmentEditor);
+ editorFixture.saveAll();
+
+ reload.assertReloaded(); // The editor is reloaded immediately because it is already active
+
+ assertThat(employmentEditor.getSite().getPage().getActiveEditor(), is((IEditorPart)employmentEditor));
+ }
+
+ /**
+ * Verify that the nested editor that was active is active again after the re-load.
+ */
+ @Test
+ public void testActiveDiagramRestored() {
+ final String diagramTitle = "ActivityDiagram";
+ final ReloadAssertion reload = new ReloadAssertion(employmentEditor);
+
+ editorFixture.activate(employmentEditor);
+ editorFixture.activateDiagram(employmentEditor, diagramTitle);
+
+ pokeLibraryModel();
+ reload.save(libraryEditor);
+
+ editorFixture.activate(employmentEditor);
+ assertThat(employmentEditor.getActiveEditor(), notNullValue());
+ assertThat(employmentEditor.getActiveEditor().getTitle(), is(diagramTitle));
+ }
+
+ /**
+ * Verify that edit-part selections in a diagram are restored after the re-load.
+ */
+ @Test
+ public void testEditPartSelectionRestored() {
+ final String diagramTitle = "ActivityDiagram";
+ final String nodeName = "do work";
+ final ReloadAssertion reload = new ReloadAssertion(employmentEditor);
+
+ EditPart activityNode = editorFixture.activateDiagram(employmentEditor, diagramTitle).findEditPart(nodeName, OpaqueAction.class);
+ editorFixture.select(activityNode);
+
+ pokeLibraryModel();
+ reload.save(libraryEditor);
+
+ activityNode = editorFixture.activateDiagram(employmentEditor, diagramTitle).findEditPart(nodeName, OpaqueAction.class);
+
+ assertThat(activityNode, notNullValue());
+ assertThat(activityNode, editPartSelected());
+ }
+
+ /**
+ * Verify that drawer, stack, and tool state in the palette is restored after editor re-load.
+ */
+ @Test
+ public void testPaletteStateRestored() {
+ doTestPaletteStateRestored();
+ }
+
+ /**
+ * Verify that drawer, stack, and tool state in the <em>Palette View</em> is restored after editor re-load.
+ */
+ @ShowView(PaletteView.ID)
+ @Test
+ public void testPaletteStateRestored_paletteView() {
+ doTestPaletteStateRestored();
+ }
+
+ void doTestPaletteStateRestored() {
+ final String diagramTitle = "ActivityDiagram";
+ final String drawerLabel = "Edges";
+ final String stackLabel = "ControlNodes";
+ final String stackEntryLabel = "Activity final";
+ final String activeToolLabel = "Comment";
+ final ReloadAssertion reload = new ReloadAssertion(employmentEditor);
+
+ PaletteViewer palette = editorFixture.activateDiagram(employmentEditor, diagramTitle).getPalette();
+
+ // Collapse the Edges drawer
+ PaletteDrawer edges = find(palette.getPaletteRoot(), drawerLabel, PaletteDrawer.class);
+ new Duck(palette.getEditPartRegistry().get(edges)).quack("setExpanded", false);
+
+ // Select the Activity Final Node in the control nodes stack
+ PaletteStack stack = find(palette.getPaletteRoot(), stackLabel, PaletteStack.class);
+ stack.setActiveEntry(find(stack, stackEntryLabel, ToolEntry.class));
+
+ // And make the Comment tool active
+ palette.setActiveTool(find(palette.getPaletteRoot(), activeToolLabel, ToolEntry.class));
+
+ editorFixture.flushDisplayEvents();
+
+ pokeLibraryModel();
+ reload.save(libraryEditor);
+
+ palette = editorFixture.activateDiagram(employmentEditor, diagramTitle).getPalette();
+
+ // Verify the Edges drawer
+ edges = find(palette.getPaletteRoot(), drawerLabel, PaletteDrawer.class);
+ assertThat(edges, collapsedIn(palette));
+
+ // Verify Activity Final Node selection in its stack
+ stack = find(palette.getPaletteRoot(), stackLabel, PaletteStack.class);
+ assertThat(stack.getActiveEntry().getLabel(), is(stackEntryLabel));
+
+ // Verify the active tool
+ assertThat(palette.getActiveTool().getLabel(), is(activeToolLabel));
+ }
+
+ @ShowView(value = ModelExplorerPageBookView.VIEW_ID, location = Location.LEFT)
+ @Test
+ public void testModelExplorerSelectionRestored() {
+ final ReloadAssertion reload = new ReloadAssertion(employmentEditor);
+
+ editorFixture.activate(employmentEditor);
+
+ CommonViewer explorer = editorFixture.getModelExplorerView().getCommonViewer();
+ Set<String> selectedLabels = ImmutableSet.of("employment::Company", "types::Name::firstName");
+ explorer.getTree().setSelection(getItems(explorer, selectedLabels));
+ Set<URI> selectedObjects = Sets.newHashSet();
+ for(Object next : ((IStructuredSelection)explorer.getSelection()).toList()) {
+ EObject object = EMFHelper.getEObject(next);
+ selectedObjects.add(EcoreUtil.getURI(object));
+ }
+
+ pokeLibraryModel();
+ reload.save(libraryEditor);
+
+ editorFixture.activate(employmentEditor);
+
+ explorer = editorFixture.getModelExplorerView().getCommonViewer();
+ Set<URI> selectedAgain = Sets.newHashSet();
+ for(Object next : ((IStructuredSelection)explorer.getSelection()).toList()) {
+ EObject object = EMFHelper.getEObject(next);
+ selectedAgain.add(EcoreUtil.getURI(object));
+ }
+ assertThat(selectedAgain, is(selectedObjects));
+ }
+
+ @ShowView(value = ModelExplorerPageBookView.VIEW_ID, location = Location.LEFT)
+ @Test
+ public void testModelExplorerExpansionRestored() {
+ final ReloadAssertion reload = new ReloadAssertion(employmentEditor);
+
+ editorFixture.activate(employmentEditor);
+
+ CommonViewer explorer = editorFixture.getModelExplorerView().getCommonViewer();
+ Set<String> expandedLabels = ImmutableSet.of("employment::A_company_person_1", "types::UML Primitive Types::PrimitiveTypes::Real");
+ for(TreeItem next : getItems(explorer, expandedLabels)) {
+ next.setExpanded(true);
+ }
+ Set<URI> expandedObjects = Sets.newHashSet();
+ for(Object next : explorer.getExpandedElements()) {
+ EObject object = EMFHelper.getEObject(next);
+ expandedObjects.add(EcoreUtil.getURI(object));
+ }
+
+ pokeLibraryModel();
+ reload.save(libraryEditor);
+
+ editorFixture.activate(employmentEditor);
+
+ explorer = editorFixture.getModelExplorerView().getCommonViewer();
+ Set<URI> expandedAgain = Sets.newHashSet();
+ for(Object next : explorer.getExpandedElements()) {
+ EObject object = EMFHelper.getEObject(next);
+ expandedAgain.add(EcoreUtil.getURI(object));
+ }
+ assertThat(expandedAgain, is(expandedObjects));
+ }
+
+ //
+ // Test framework
+ //
+
+ @Before
+ public void layOutWorkbenchPage() {
+ employmentEditor = editorFixture.getEditor(EMPLOYMENT_MODEL);
+ bankingEditor = editorFixture.getEditor(BANKING_MODEL);
+ libraryEditor = editorFixture.getEditor(LIBRARY_MODEL);
+
+ // Move the banking editor into its own part of the editor area
+ editorFixture.splitEditorArea(bankingEditor, false);
+ }
+
+ void pokeLibraryModel() {
+ // First, make sure that the library editor is active (user can't edit it, otherwise!)
+ editorFixture.activate(libraryEditor);
+
+ Package library = editorFixture.getModel(libraryEditor);
+ Type ssn = library.getOwnedType("SSN");
+ EditingDomain domain = editorFixture.getEditingDomain(libraryEditor);
+ domain.getCommandStack().execute(domain.createCommand(SetCommand.class, new CommandParameter(ssn, UMLPackage.Literals.NAMED_ELEMENT__NAME, "SocialSecurityNumber")));
+ }
+
+ <P extends PaletteEntry> P find(PaletteContainer container, String label, Class<P> type) {
+ P result = null;
+
+ for(P next : Iterables.filter(container.getChildren(), type)) {
+ if(label.equalsIgnoreCase(next.getLabel())) {
+ result = next;
+ break;
+ }
+ }
+
+ if(result == null) {
+ for(PaletteContainer next : Iterables.filter(container.getChildren(), PaletteContainer.class)) {
+ result = find(next, label, type);
+ if(result != null) {
+ break;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ Set<String> getLabels(Item... items) {
+ Set<String> result = Sets.newHashSet();
+
+ for(Item next : items) {
+ result.add(getLabel(next));
+ }
+
+ return result;
+ }
+
+ TreeItem[] getItems(AbstractTreeViewer tree, Collection<String> labels) {
+ List<TreeItem> result = Lists.newArrayListWithCapacity(labels.size());
+
+ for(String next : labels) {
+ Widget search = tree.getControl();
+ for(String part : Splitter.on(NamedElement.SEPARATOR).split(next)) {
+ search = findItem(tree, search, part);
+ }
+
+ if(search instanceof TreeItem) {
+ result.add((TreeItem)search);
+ }
+ }
+
+ return Iterables.toArray(result, TreeItem.class);
+ }
+
+ static final Pattern METACLASS_QUALIFIER = Pattern.compile("<.+>");
+
+ static final Pattern STEREOTYPE_QUALIFIER = Pattern.compile("«.+»");
+
+ static String getLabel(Item item) {
+ String result = item.getText();
+
+ if(result != null) {
+ result = METACLASS_QUALIFIER.matcher(result).replaceAll("");
+ result = STEREOTYPE_QUALIFIER.matcher(result).replaceAll("");
+ result = result.trim();
+ }
+
+ return result;
+ }
+
+ private Item findItem(AbstractTreeViewer tree, Widget parent, String label) {
+ Item result = null;
+
+ if(parent != null) {
+ if(parent instanceof TreeItem) {
+ tree.expandToLevel(parent.getData(), 1);
+ }
+
+ for(Item next : (Item[])new Duck(parent).quack("getItems")) {
+ if(label.equals(getLabel(next))) {
+ result = next;
+ break;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ private class ReloadAssertion {
+
+ private final Set<IMultiDiagramEditor> editors;
+
+ private final Set<IMultiDiagramEditor> unloaded = Sets.newHashSet();
+
+ ReloadAssertion(IMultiDiagramEditor... editor) {
+ this.editors = Sets.newHashSet(editor);
+
+ for(IMultiDiagramEditor next : editors) {
+ ServicesRegistry services = next.getServicesRegistry();
+
+ try {
+ services.add(Canary.class, 1, new Canary(next));
+ services.startServicesByClassKeys(Canary.class);
+ } catch (ServiceException e) {
+ e.printStackTrace();
+ fail("Failed to start Canary service: " + e.getLocalizedMessage());
+ }
+ }
+ }
+
+ /**
+ * Saves the specified editor, kicks the registered dependent editors by activating them, and asserts that they were re-loaded.
+ */
+ void save(IMultiDiagramEditor editor) {
+ editorFixture.save(editor);
+ kick();
+ assertReloaded();
+ }
+
+ void kick() {
+ if(!editors.isEmpty()) {
+ IWorkbenchPage page = Iterables.getFirst(editors, null).getSite().getPage();
+ IEditorPart active = page.getActiveEditor();
+
+ for(IEditorPart next : editors) {
+ // Activate this editor to trigger reload
+ page.activate(next);
+ }
+
+ if(active != null) {
+ // Restore the active editor
+ page.activate(active);
+ }
+
+ editorFixture.flushDisplayEvents();
+ }
+ }
+
+ void assertUnloaded() {
+ assertThat("Some editors were not unloaded", unloaded, is(editors));
+ }
+
+ void assertLoaded() {
+ for(IMultiDiagramEditor next : editors) {
+ try {
+ boolean loaded = next.getServicesRegistry().isStarted(ModelSet.class.getName());
+ assertThat("Editor not loaded: " + next.getTitle(), loaded, is(true));
+ } catch (ServiceException e) {
+ e.printStackTrace();
+ fail("Editor not loaded: " + next.getTitle());
+ }
+ }
+ }
+
+ void assertReloaded() {
+ assertUnloaded();
+ assertLoaded();
+ }
+
+ void assertNotUnloaded() {
+ assertThat("Some editors were unloaded", Sets.difference(editors, unloaded), is(editors));
+ }
+
+ void assertNotReloaded() {
+ assertNotUnloaded();
+ assertLoaded();
+ }
+
+ private class Canary implements IService {
+
+ private final IMultiDiagramEditor editor;
+
+ private ServicesRegistry services;
+
+ Canary(IMultiDiagramEditor editor) {
+ this.editor = editor;
+ }
+
+ public void init(ServicesRegistry servicesRegistry) throws ServiceException {
+ services = servicesRegistry;
+
+ // For symmetry only; this never actually has any effect
+ unloaded.remove(editor);
+ }
+
+ public void disposeService() throws ServiceException {
+ unloaded.add(editor);
+ services = null;
+ }
+
+ public void startService() throws ServiceException {
+ // Load everything in the resource set so that we are sure to know of the dependency on the library model
+ EcoreUtil.resolveAll(services.getService(ModelSet.class));
+ }
+ }
+
+ }
+}
diff --git a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/META-INF/MANIFEST.MF b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/META-INF/MANIFEST.MF
index ae8017b314c..58e9c06e0d5 100644
--- a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/META-INF/MANIFEST.MF
+++ b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/META-INF/MANIFEST.MF
@@ -18,8 +18,12 @@ Require-Bundle: org.eclipse.ui,
org.eclipse.papyrus.infra.tools;bundle-version="1.0.0",
org.eclipse.papyrus.infra.emf;bundle-version="1.0.0",
com.google.guava;bundle-version="11.0.0",
- org.eclipse.papyrus.infra.nattable.model;bundle-version="1.0.0"
-Export-Package: org.eclipse.papyrus.junit.utils,
+ org.eclipse.papyrus.infra.nattable.model;bundle-version="1.0.0",
+ org.eclipse.e4.ui.workbench;bundle-version="1.1.0",
+ org.eclipse.e4.ui.model.workbench;bundle-version="1.1.0",
+ org.eclipse.e4.core.contexts;bundle-version="1.3.0"
+Export-Package: org.eclipse.papyrus.junit.matchers,
+ org.eclipse.papyrus.junit.utils,
org.eclipse.papyrus.junit.utils.classification,
org.eclipse.papyrus.junit.utils.resources,
org.eclipse.papyrus.junit.utils.rules,
diff --git a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/matchers/DiagramMatchers.java b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/matchers/DiagramMatchers.java
new file mode 100644
index 00000000000..b78720e078a
--- /dev/null
+++ b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/matchers/DiagramMatchers.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2014 CEA 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:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.junit.matchers;
+
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.EditPartViewer;
+import org.eclipse.gef.palette.PaletteDrawer;
+import org.eclipse.gef.ui.palette.PaletteViewer;
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+
+
+/**
+ * Hamcrest matchers for assertions on GMF diagrams.
+ */
+public class DiagramMatchers {
+
+ private DiagramMatchers() {
+ super();
+ }
+
+ /**
+ * Match an edit part that is selected in its viewer.
+ */
+ public static Matcher<EditPart> editPartSelected() {
+ return EditPartSelected.INSTANCE;
+ }
+
+ /**
+ * Match a drawer that is expanded in the specified {@code viewer}.
+ */
+ public static Matcher<PaletteDrawer> expandedIn(PaletteViewer viewer) {
+ return new DrawerExpansion(viewer, true);
+ }
+
+ /**
+ * Match a drawer that is collapsed (closed) in the specified {@code viewer}.
+ */
+ public static Matcher<PaletteDrawer> collapsedIn(PaletteViewer viewer) {
+ return new DrawerExpansion(viewer, false);
+ }
+
+ //
+ // Nested types
+ //
+
+ static class EditPartSelected extends BaseMatcher<EditPart> {
+
+ private static final EditPartSelected INSTANCE = new EditPartSelected();
+
+ private EditPartSelected() {
+ super();
+ }
+
+ public void describeTo(Description description) {
+ description.appendText("edit-part is selected");
+ }
+
+ public boolean matches(Object item) {
+ return (item instanceof EditPart) && isSelected((EditPart)item);
+ }
+
+ boolean isSelected(EditPart editPart) {
+ EditPartViewer viewer = editPart.getViewer();
+ return (viewer != null) && viewer.getSelectedEditParts().contains(editPart);
+ }
+ }
+
+ static class DrawerExpansion extends BaseMatcher<PaletteDrawer> {
+
+ private final PaletteViewer viewer;
+
+ private final boolean expanded;
+
+ DrawerExpansion(PaletteViewer viewer, boolean expanded) {
+ this.viewer = viewer;
+ this.expanded = expanded;
+ }
+
+ public void describeTo(Description description) {
+ description.appendText("drawer is ");
+ description.appendText(expanded ? "expanded" : "collapsed");
+ }
+
+ public boolean matches(Object item) {
+ return (item instanceof PaletteDrawer) && (isExpanded((PaletteDrawer)item) == expanded);
+ }
+
+ boolean isExpanded(PaletteDrawer drawer) {
+ return viewer.isExpanded(drawer);
+ }
+ }
+}
diff --git a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/Duck.java b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/Duck.java
index b7a253b003b..1abd00dea18 100644
--- a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/Duck.java
+++ b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/Duck.java
@@ -159,7 +159,7 @@ public class Duck {
Method[] scope = target.getClass().getMethods();
for(int i = 0; (result == null) && (i < scope.length); i++) {
Method next = scope[i];
- if(next.getName().equals(methodName) && (returning == null) && match(next, signature)) {
+ if(next.getName().equals(methodName) && matchReturn(next.getReturnType(), returning) && match(next, signature)) {
result = next;
}
}
diff --git a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/AbstractModelFixture.java b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/AbstractModelFixture.java
index 231adc4f384..5d0da4a751d 100644
--- a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/AbstractModelFixture.java
+++ b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/AbstractModelFixture.java
@@ -24,6 +24,7 @@ import java.net.URL;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.LinkedList;
+import java.util.List;
import java.util.Queue;
import java.util.Set;
@@ -55,6 +56,7 @@ import org.osgi.framework.FrameworkUtil;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
import com.google.common.io.ByteStreams;
@@ -87,6 +89,8 @@ public abstract class AbstractModelFixture<T extends EditingDomain> extends Test
private Class<?> testClass;
+ private Iterable<URI> initialResourceURIs;
+
public AbstractModelFixture() {
super();
}
@@ -146,15 +150,44 @@ public abstract class AbstractModelFixture<T extends EditingDomain> extends Test
@Override
protected void starting(Description description) {
domain = createEditingDomain();
- model = (Package)initModelResource(description).getContents().get(0);
+ model = (Package)Iterables.getFirst(initModelResources(description), null).getContents().get(0);
+
+ // We have finished initializing
+ initialResourceURIs = null;
}
- protected Resource initModelResource(Description description) {
- Annotation resourceAnnotation = getResourceAnnotation(description);
- ResourceKind kind = ResourceKind.getResourceKind(resourceAnnotation);
+ protected Iterable<Resource> initModelResources(Description description) {
+ List<Resource> result;
+
+ // Don't initialize the resources more than once (subclasses such as PapyrusEditorFixture can repeat this)
+ if(initialResourceURIs == null) {
+ Annotation resourceAnnotation = getResourceAnnotation(description);
+ ResourceKind kind = ResourceKind.getResourceKind(resourceAnnotation);
+
+ final String[] paths = kind.getResourcePaths(resourceAnnotation);
+ result = Lists.newArrayListWithCapacity(paths.length);
+
+ for(String path : paths) {
+ result.add(initModelResource(new Path(path), kind));
+ }
+
+ List<URI> uris = Lists.newArrayListWithCapacity(result.size());
+ for(Resource next : result) {
+ uris.add(next.getURI());
+ }
+ initialResourceURIs = uris;
+ } else {
+ ResourceSet rset = getResourceSet();
+ result = Lists.newArrayList();
+ for(URI next : initialResourceURIs) {
+ result.add(rset.getResource(next, true));
+ }
+ }
- IPath resourcePath = new Path(kind.getResourcePath(resourceAnnotation));
+ return result;
+ }
+ private Resource initModelResource(IPath resourcePath, ResourceKind kind) {
String targetResourceName = "model";
if(isDIModel(resourcePath)) {
// We will be initializing all three resources, and they have cross-references, so must not change
@@ -309,6 +342,7 @@ public abstract class AbstractModelFixture<T extends EditingDomain> extends Test
protected void finished(Description description) {
final ResourceSet resourceSet = getResourceSet();
+ initialResourceURIs = null;
model = null;
if(domain instanceof TransactionalEditingDomain) {
@@ -359,7 +393,7 @@ public abstract class AbstractModelFixture<T extends EditingDomain> extends Test
return (resourceAnnotation instanceof JavaResource) ? JAVA : (resourceAnnotation instanceof PluginResource) ? BUNDLE : null;
}
- String getResourcePath(Annotation resourceAnnotation) {
+ String[] getResourcePaths(Annotation resourceAnnotation) {
switch(this) {
case JAVA:
return ((JavaResource)resourceAnnotation).value();
diff --git a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/JavaResource.java b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/JavaResource.java
index d9aa6b14340..23d870281ba 100644
--- a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/JavaResource.java
+++ b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/JavaResource.java
@@ -19,7 +19,7 @@ import java.lang.annotation.Target;
/**
- * Annotation indicating the classpath-relative path to a resource from which to load the test model of an {@link AbstractModelFixture}.
+ * Annotation indicating the classpath-relative path to one or more resources from which to load the test model of an {@link AbstractModelFixture}.
*
* @see AbstractModelFixture
* @see PluginResource
@@ -28,5 +28,5 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
public @interface JavaResource {
- String value();
+ String[] value();
}
diff --git a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PapyrusEditorFixture.java b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PapyrusEditorFixture.java
index c0f21173585..de24d1c0d43 100644
--- a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PapyrusEditorFixture.java
+++ b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PapyrusEditorFixture.java
@@ -17,26 +17,44 @@ import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.fail;
+import java.util.Collection;
import java.util.Iterator;
+import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainerElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
+import org.eclipse.e4.ui.model.application.ui.basic.MStackElement;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.GraphicalEditPart;
+import org.eclipse.gef.ui.palette.PaletteViewer;
import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditor;
+import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditorWithFlyOutPalette;
import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramWorkbenchPart;
-import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.gmf.runtime.notation.View;
+import org.eclipse.papyrus.editor.PapyrusMultiDiagramEditor;
import org.eclipse.papyrus.infra.core.editor.IMultiDiagramEditor;
import org.eclipse.papyrus.infra.core.resource.ModelSet;
import org.eclipse.papyrus.infra.core.resource.sasheditor.DiModel;
import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageManager;
+import org.eclipse.papyrus.infra.core.sasheditor.editor.IComponentPage;
+import org.eclipse.papyrus.infra.core.sasheditor.editor.IEditorPage;
+import org.eclipse.papyrus.infra.core.sasheditor.editor.IPageVisitor;
+import org.eclipse.papyrus.infra.core.sasheditor.editor.ISashWindowsContainer;
import org.eclipse.papyrus.infra.core.services.ServiceException;
import org.eclipse.papyrus.infra.core.services.ServicesRegistry;
import org.eclipse.papyrus.infra.core.utils.AdapterUtils;
@@ -48,14 +66,18 @@ import org.eclipse.papyrus.views.modelexplorer.ModelExplorerPageBookView;
import org.eclipse.papyrus.views.modelexplorer.ModelExplorerView;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IPartListener;
+import org.eclipse.ui.ISaveablePart;
import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.IPage;
+import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.UMLPackage;
import org.junit.runner.Description;
@@ -63,7 +85,10 @@ import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
+import com.google.common.collect.Iterators;
+import com.google.common.collect.Lists;
/**
@@ -72,14 +97,20 @@ import com.google.common.collect.Iterables;
*/
public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEditingDomain> {
+ private final Collection<IEditorPart> editorsToClose = Lists.newArrayList();
+
private IMultiDiagramEditor editor;
+ private DiagramEditorWithFlyOutPalette activeDiagramEditor;
+
private ModelExplorerView modelExplorer;
private Class<?> testClass;
private Description testDescription;
+ private Collection<IViewPart> viewsToClose;
+
public PapyrusEditorFixture() {
super();
}
@@ -88,12 +119,29 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
return editor;
}
+ public IMultiDiagramEditor getEditor(String path) {
+ IMultiDiagramEditor result = null;
+
+ final String fileName = new Path(path).lastSegment();
+ for(IEditorReference next : getWorkbenchPage().getEditorReferences()) {
+ if(PapyrusMultiDiagramEditor.EDITOR_ID.equals(next.getId()) && fileName.equals(next.getName())) {
+ result = (IMultiDiagramEditor)next.getEditor(true);
+ }
+ }
+
+ return result;
+ }
+
@Override
protected void starting(Description description) {
testClass = description.getTestClass();
testDescription = description;
- open(description);
+ if(hasRequiredViews()) {
+ openRequiredViews();
+ }
+
+ openAll(description);
super.starting(description);
}
@@ -101,12 +149,34 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
@Override
protected void finished(Description description) {
try {
- if(editor != null) {
- close(editor);
- editor = null;
+ Exception exception = null;
+
+ for(IEditorPart editor : ImmutableList.copyOf(editorsToClose)) {
+ try {
+ close(editor);
+ } catch (Exception e) {
+ if(exception == null) {
+ exception = e;
+ }
+ }
+ }
+
+ if(exception != null) {
+ exception.printStackTrace();
+ fail("Failed to close an editor: " + exception.getLocalizedMessage());
}
} finally {
- super.finished(description);
+ editorsToClose.clear();
+ editor = null;
+ activeDiagramEditor = null;
+
+ try {
+ if(hasRequiredViews()) {
+ closeRequiredViews();
+ }
+ } finally {
+ super.finished(description);
+ }
}
}
@@ -115,15 +185,23 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
TransactionalEditingDomain result = null;
if(editor != null) {
- try {
- result = getServiceRegistry().getService(TransactionalEditingDomain.class);
- } catch (ServiceException e) {
- e.printStackTrace();
- fail("Failed to get editing domain from Papyrus editor: " + e.getLocalizedMessage());
- }
+ result = getEditingDomain(editor);
}
+
return result;
+ }
+
+ public TransactionalEditingDomain getEditingDomain(IMultiDiagramEditor editor) {
+ TransactionalEditingDomain result = null;
+ try {
+ result = getServiceRegistry(editor).getService(TransactionalEditingDomain.class);
+ } catch (ServiceException e) {
+ e.printStackTrace();
+ fail("Failed to get editing domain from Papyrus editor: " + e.getLocalizedMessage());
+ }
+
+ return result;
}
@Override
@@ -133,11 +211,14 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
}
protected IMultiDiagramEditor open(final IFile modelFile) {
+ final boolean firstEditor = editorsToClose.isEmpty();
+
Display.getDefault().syncExec(new Runnable() {
public void run() {
try {
editor = EditorUtils.openPapyrusEditor(modelFile);
+ editorsToClose.add(editor);
} catch (Exception e) {
e.printStackTrace();
fail("Failed to open Papyrus editor: " + e.getLocalizedMessage());
@@ -145,45 +226,63 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
}
});
- final IWorkbenchPage page = editor.getSite().getPage();
- page.addPartListener(new IPartListener() {
+ if(firstEditor && !editorsToClose.isEmpty()) {
+ final IWorkbenchPage page = editor.getSite().getPage();
+ page.addPartListener(new IPartListener() {
+
+ public void partClosed(IWorkbenchPart part) {
+ editorsToClose.remove(part);
+
+ if(part == editor) {
+ editor = null;
+ }
- public void partClosed(IWorkbenchPart part) {
- if(part == editor) {
- editor = null;
+ if(editorsToClose.isEmpty()) {
+ page.removePartListener(this);
+ }
}
- page.removePartListener(this);
- }
- public void partOpened(IWorkbenchPart part) {
- // Pass
- }
+ public void partOpened(IWorkbenchPart part) {
+ // Pass
+ }
- public void partDeactivated(IWorkbenchPart part) {
- // Pass
- }
+ public void partDeactivated(IWorkbenchPart part) {
+ // Pass
+ }
- public void partBroughtToTop(IWorkbenchPart part) {
- // Pass
- }
+ public void partBroughtToTop(IWorkbenchPart part) {
+ // Pass
+ }
- public void partActivated(IWorkbenchPart part) {
- // Pass
- }
- });
+ public void partActivated(IWorkbenchPart part) {
+ // Pass
+ }
+ });
+ }
flushDisplayEvents();
return editor;
}
- protected IMultiDiagramEditor open(Description description) {
- IFile papyrusModel = getProject().getFile(initModelResource(description).getURI().trimFileExtension().appendFileExtension(DiModel.DI_FILE_EXTENSION));
+ protected IMultiDiagramEditor openOne(Description description) {
+ IFile papyrusModel = getProject().getFile(Iterables.getOnlyElement(initModelResources(description)).getURI().trimFileExtension().appendFileExtension(DiModel.DI_FILE_EXTENSION));
return open(papyrusModel);
}
+ protected Iterable<IMultiDiagramEditor> openAll(Description description) {
+ List<IMultiDiagramEditor> result = Lists.newArrayList();
+
+ for(Resource resource : initModelResources(description)) {
+ IFile papyrusModel = getProject().getFile(resource.getURI().trimFileExtension().appendFileExtension(DiModel.DI_FILE_EXTENSION));
+ result.add(open(papyrusModel));
+ }
+
+ return result;
+ }
+
public IMultiDiagramEditor open() {
- return open(testDescription);
+ return openOne(testDescription);
}
public IMultiDiagramEditor open(String resourcePath) {
@@ -206,7 +305,12 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
}
public void activate(IWorkbenchPart part) {
- part.getSite().getPage().activate(part);
+ IWorkbenchPage page = part.getSite().getPage();
+
+ if(page.getActivePart() != part) {
+ page.activate(part);
+ flushDisplayEvents();
+ }
}
public void close() {
@@ -226,11 +330,9 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
Display.getDefault().syncExec(new Runnable() {
public void run() {
- IWorkbenchWindow activeWorkbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
-
ModelExplorerPageBookView view;
try {
- view = (ModelExplorerPageBookView)activeWorkbenchWindow.getActivePage().showView(AbstractEditorTest.MODELEXPLORER_VIEW_ID);
+ view = (ModelExplorerPageBookView)getWorkbenchPage().showView(AbstractEditorTest.MODELEXPLORER_VIEW_ID);
} catch (PartInitException e) {
e.printStackTrace();
return;
@@ -246,13 +348,30 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
return modelExplorer;
}
+ protected final IWorkbenchPage getWorkbenchPage() {
+ IWorkbench bench = PlatformUI.getWorkbench();
+ IWorkbenchWindow window = bench.getActiveWorkbenchWindow();
+ if(window == null) {
+ window = bench.getWorkbenchWindows()[0];
+ }
+ return window.getActivePage();
+ }
+
public ServicesRegistry getServiceRegistry() {
+ return getServiceRegistry(editor);
+ }
+
+ public ServicesRegistry getServiceRegistry(IMultiDiagramEditor editor) {
return editor.getServicesRegistry();
}
public ModelSet getModelSet() {
+ return getModelSet(editor);
+ }
+
+ public ModelSet getModelSet(IMultiDiagramEditor editor) {
try {
- return getServiceRegistry().getService(ModelSet.class);
+ return getServiceRegistry(editor).getService(ModelSet.class);
} catch (ServiceException e) {
e.printStackTrace();
fail("Failed to get model set from Papyrus editor: " + e.getLocalizedMessage());
@@ -262,9 +381,14 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
@Override
public Package getModel() {
+ return getModel(editor);
+ }
+
+ public Package getModel(IMultiDiagramEditor editor) {
Package result = null;
- UmlModel uml = (UmlModel)getModelSet().getModel(UmlModel.MODEL_ID);
+ ModelSet modelSet = getModelSet(editor);
+ UmlModel uml = (UmlModel)modelSet.getModel(UmlModel.MODEL_ID);
assertThat("No UML model present in resource set", uml.getResource(), notNullValue());
result = (Package)EcoreUtil.getObjectByType(uml.getResource().getContents(), UMLPackage.Literals.PACKAGE);
@@ -274,8 +398,12 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
}
public IPageManager getPageManager() {
+ return getPageManager(editor);
+ }
+
+ public IPageManager getPageManager(IMultiDiagramEditor editor) {
try {
- return getServiceRegistry().getService(IPageManager.class);
+ return getServiceRegistry(editor).getService(IPageManager.class);
} catch (ServiceException e) {
e.printStackTrace();
fail("Failed to get page manager from Papyrus editor: " + e.getLocalizedMessage());
@@ -284,20 +412,67 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
}
public PapyrusEditorFixture activateDiagram(String name) {
- for(Diagram diagram : Iterables.filter(getPageManager().allPages(), Diagram.class)) {
- if(name.equals(diagram.getName())) {
- getPageManager().selectPage(diagram);
- break;
+ return activateDiagram(editor, name);
+ }
+
+ public PapyrusEditorFixture activateDiagram(IMultiDiagramEditor editor, final String name) {
+ activate(editor);
+
+ final ISashWindowsContainer sashContainer = AdapterUtils.adapt(editor, ISashWindowsContainer.class, null);
+ final org.eclipse.papyrus.infra.core.sasheditor.editor.IPage[] select = { null };
+
+ sashContainer.visit(new IPageVisitor() {
+
+ public void accept(IEditorPage page) {
+ if(name.equals(page.getPageTitle()) && (page.getIEditorPart() instanceof DiagramEditorWithFlyOutPalette)) {
+ select[0] = page;
+ activeDiagramEditor = (DiagramEditorWithFlyOutPalette)page.getIEditorPart();
+ }
+ }
+
+ public void accept(IComponentPage page) {
+ // Pass
}
+ });
+
+ if(select[0] != null) {
+ sashContainer.selectPage(select[0]);
+ flushDisplayEvents();
}
return this;
}
+ public DiagramEditorWithFlyOutPalette getActiveDiagramEditor() {
+ DiagramEditorWithFlyOutPalette result = activeDiagramEditor;
+
+ if(result == null) {
+ IEditorPart activeEditor = getWorkbenchPage().getActiveEditor();
+ if(activeEditor instanceof IMultiDiagramEditor) {
+ activeEditor = ((IMultiDiagramEditor)activeEditor).getActiveEditor();
+ if(activeEditor instanceof DiagramEditorWithFlyOutPalette) {
+ result = (DiagramEditorWithFlyOutPalette)activeEditor;
+ }
+ }
+ }
+
+ assertThat("No diagram active", result, notNullValue());
+
+ return result;
+ }
+
public EditPart findEditPart(EObject modelElement) {
- IEditorPart activeEditor = getEditor().getActiveEditor();
- assertThat("No diagram active", activeEditor, instanceOf(IDiagramWorkbenchPart.class));
- DiagramEditPart diagram = ((IDiagramWorkbenchPart)activeEditor).getDiagramEditPart();
+ return findEditPart(getActiveDiagramEditor(), modelElement);
+ }
+
+ public EditPart findEditPart(IMultiDiagramEditor editor, EObject modelElement) {
+ IEditorPart activeEditor = editor.getActiveEditor();
+ assertThat("No diagram active", activeEditor, instanceOf(DiagramEditor.class));
+ return findEditPart((DiagramEditor)activeEditor, modelElement);
+ }
+
+ public EditPart findEditPart(IDiagramWorkbenchPart editor, EObject modelElement) {
+ DiagramEditPart diagram = editor.getDiagramEditPart();
return findEditPart(diagram, modelElement);
}
@@ -326,6 +501,49 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
return result;
}
+ public EditPart findEditPart(String name, Class<? extends NamedElement> type) {
+ return findEditPart(getActiveDiagramEditor(), name, type);
+ }
+
+ public EditPart findEditPart(IMultiDiagramEditor editor, String name, Class<? extends NamedElement> type) {
+ IEditorPart activeEditor = editor.getActiveEditor();
+ assertThat("No diagram active", activeEditor, instanceOf(DiagramEditor.class));
+ return findEditPart((DiagramEditor)activeEditor, name, type);
+ }
+
+ public EditPart findEditPart(IDiagramWorkbenchPart editor, String name, Class<? extends NamedElement> type) {
+ EditPart result = null;
+
+ for(Iterator<View> views = Iterators.filter(editor.getDiagram().eAllContents(), View.class); views.hasNext();) {
+ View next = views.next();
+ EObject element = next.getElement();
+ if(type.isInstance(element) && name.equals(type.cast(element).getName())) {
+ result = (EditPart)editor.getDiagramGraphicalViewer().getEditPartRegistry().get(next);
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ public void select(EditPart editPart) {
+ editPart.getViewer().getSelectionManager().appendSelection(editPart);
+ }
+
+ public PaletteViewer getPalette() {
+ return getPalette(getActiveDiagramEditor());
+ }
+
+ public PaletteViewer getPalette(IMultiDiagramEditor editor) {
+ IEditorPart activeEditor = editor.getActiveEditor();
+ assertThat("No diagram active", activeEditor, instanceOf(DiagramEditor.class));
+ return getPalette((DiagramEditor)activeEditor);
+ }
+
+ public PaletteViewer getPalette(IDiagramWorkbenchPart editor) {
+ return editor.getDiagramEditPart().getViewer().getEditDomain().getPaletteViewer();
+ }
+
public void flushDisplayEvents() {
for(;;) {
try {
@@ -342,12 +560,12 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
public IViewPart getView(String id, boolean open) {
IViewPart result = null;
- IWorkbenchWindow activeWorkbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ IWorkbenchPage wbPage = getWorkbenchPage();
try {
- result = activeWorkbenchWindow.getActivePage().findView(id);
+ result = wbPage.findView(id);
if((result == null) && open) {
- result = activeWorkbenchWindow.getActivePage().showView(id);
+ result = wbPage.showView(id);
}
if(result != null) {
@@ -363,4 +581,189 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
return result;
}
+
+ public void save(ISaveablePart part) {
+ if(part.isDirty()) {
+ try {
+ part.doSave(new NullProgressMonitor());
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail("Failed to save editor/view: " + e.getLocalizedMessage());
+ } finally {
+ // Must flush display events because some steps (e.g. dependent editor reload)
+ // are done asynchronously in a UI job
+ flushDisplayEvents();
+ }
+ }
+ }
+
+ public void saveAll() {
+ try {
+ IWorkbenchPage page = editor.getSite().getPage();
+ page.saveAllEditors(false);
+ } finally {
+ // Must flush display events because some steps (e.g. dependent editor reload)
+ // are done asynchronously in a UI job
+ flushDisplayEvents();
+ }
+ }
+
+ public void splitEditorArea(IEditorPart editorToMove, boolean splitHorizontally) {
+ MPart editorPart = (MPart)editorToMove.getSite().getService(MPart.class);
+ EModelService modelService = editorPart.getContext().get(EModelService.class);
+ MPartStack oldStack = (MPartStack)modelService.getContainer(editorPart);
+ MPartStack newStack = modelService.createModelElement(MPartStack.class);
+ modelService.insert(newStack, oldStack, splitHorizontally ? EModelService.RIGHT_OF : EModelService.BELOW, 0.5f);
+ newStack.getChildren().add(editorPart);
+
+ activate(editorToMove);
+ }
+
+ public List<IWorkbenchPart> getPartStack(IWorkbenchPart part) {
+ List<IWorkbenchPart> result;
+
+ MPart mpart = (MPart)part.getSite().getService(MPart.class);
+ EModelService modelService = mpart.getContext().get(EModelService.class);
+ MPartStack stack = (MPartStack)modelService.getContainer(mpart);
+
+ result = Lists.newArrayListWithCapacity(stack.getChildren().size());
+ for(MPart next : Iterables.filter(stack.getChildren(), MPart.class)) {
+ IWorkbenchPart wbPart = next.getContext().get(IWorkbenchPart.class);
+ if(wbPart != null) {
+ result.add(wbPart);
+ }
+ }
+
+ return result;
+ }
+
+ protected final boolean hasRequiredViews() {
+ return getRequiredViews() != null;
+ }
+
+ protected final ShowView getRequiredViews() {
+ ShowView result = testDescription.getAnnotation(ShowView.class);
+
+ if(result == null) {
+ for(Class<?> clazz = testClass; (result == null) && (clazz != null) && (clazz != Object.class); clazz = clazz.getSuperclass()) {
+ result = clazz.getAnnotation(ShowView.class);
+ }
+ }
+
+ return result;
+ }
+
+ protected void openRequiredViews() {
+ IWorkbenchPage page = getWorkbenchPage();
+
+ for(ShowViewDescriptor next : ShowViewDescriptor.getDescriptors(getRequiredViews())) {
+ IViewPart part = page.findView(next.viewID());
+ if(part == null) {
+ // Must open it
+ try {
+ part = page.showView(next.viewID());
+ movePartRelativeTo(part, next.relativeTo(), next.location());
+
+ if(viewsToClose == null) {
+ viewsToClose = Lists.newArrayListWithExpectedSize(1);
+ }
+ viewsToClose.add(part);
+ } catch (PartInitException e) {
+ e.printStackTrace();
+ fail("Failed to open required view: " + e.getLocalizedMessage());
+ }
+ }
+ }
+
+ flushDisplayEvents();
+ }
+
+ private void movePartRelativeTo(IWorkbenchPart part, String relativeTo, int where) {
+ MPart mPart = (MPart)part.getSite().getService(MPart.class);
+ EModelService modelService = mPart.getContext().get(EModelService.class);
+ MUIElement relativePart = modelService.find(relativeTo, modelService.getTopLevelWindowFor(mPart));
+ if(relativePart instanceof MPartSashContainerElement) {
+ MStackElement toMove = mPart;
+ MPlaceholder placeHolder = mPart.getCurSharedRef();
+ if(placeHolder != null) {
+ toMove = placeHolder;
+ }
+
+ if(where < 0) {
+ // Add it to the relative part's containing stack
+ if(relativePart instanceof MPart) {
+ MPart relativeMPart = (MPart)relativePart;
+ if(relativeMPart.getCurSharedRef() != null) {
+ // This is where the part is stacked
+ relativePart = relativeMPart.getCurSharedRef();
+ }
+ }
+ relativePart.getParent().getChildren().add(toMove);
+ } else {
+ // Insert it next to the relative part
+ MPartStack newStack = modelService.createModelElement(MPartStack.class);
+ newStack.getChildren().add(toMove);
+ modelService.insert(newStack, (MPartSashContainerElement)relativePart, where, 0.3f);
+ }
+ }
+ }
+
+ protected void closeRequiredViews() {
+ // Only close the Palette view if we opened it
+ if(viewsToClose != null) {
+ for(IViewPart closeMe : viewsToClose) {
+ closeMe.getSite().getPage().hideView(closeMe);
+ }
+ viewsToClose = null;
+ flushDisplayEvents();
+ }
+ }
+
+ private static final class ShowViewDescriptor {
+
+ private static final String DEFAULT_RELATIVE_TO = "org.eclipse.ui.editorss"; //$NON-NLS-1$
+
+ private static final ShowView.Location DEFAULT_LOCATION_EDITORS = ShowView.Location.RIGHT;
+
+ private static final ShowView.Location DEFAULT_LOCATION_VIEW = ShowView.Location.STACKED;
+
+ private final String viewID;
+
+ private final String relativeTo;
+
+ private final ShowView.Location location;
+
+ private ShowViewDescriptor(ShowView annotation, int index) {
+ this.viewID = annotation.value()[index];
+
+ String[] relativeTo = annotation.relativeTo();
+ this.relativeTo = (relativeTo.length == 0) ? null : (relativeTo.length == 1) ? relativeTo[0] : relativeTo[index];
+
+ ShowView.Location[] location = annotation.location();
+ this.location = (location.length == 0) ? null : (location.length == 1) ? location[0] : location[index];
+ }
+
+ static Iterable<ShowViewDescriptor> getDescriptors(final ShowView annotation) {
+ ImmutableList.Builder<ShowViewDescriptor> result = ImmutableList.builder();
+
+ String[] ids = annotation.value();
+ for(int i = 0; i < ids.length; i++) {
+ result.add(new ShowViewDescriptor(annotation, i));
+ }
+
+ return result.build();
+ }
+
+ String viewID() {
+ return viewID;
+ }
+
+ String relativeTo() {
+ return (relativeTo != null) ? relativeTo : DEFAULT_RELATIVE_TO;
+ }
+
+ int location() {
+ return ((location != null) ? location : (relativeTo == null) ? DEFAULT_LOCATION_EDITORS : DEFAULT_LOCATION_VIEW).toModelServiceLocation();
+ }
+ }
}
diff --git a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PluginResource.java b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PluginResource.java
index dc1e7e6eacd..aba01b2b74e 100644
--- a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PluginResource.java
+++ b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PluginResource.java
@@ -19,7 +19,7 @@ import java.lang.annotation.Target;
/**
- * Annotation indicating the bundle-relative path to a resource from which to load the test model of an {@link AbstractModelFixture}.
+ * Annotation indicating the bundle-relative path to one or more resources from which to load the test model of an {@link AbstractModelFixture}.
*
* @see AbstractModelFixture
* @see JavaResource
@@ -28,5 +28,5 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
public @interface PluginResource {
- String value();
+ String[] value();
}
diff --git a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/ShowView.java b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/ShowView.java
new file mode 100644
index 00000000000..103db0b1d37
--- /dev/null
+++ b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/ShowView.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2014 CEA 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:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.junit.utils.rules;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+
+
+/**
+ * An annotation on tests using the {@link PapyrusEditorFixture} that need the palette view to be open before initializing the
+ * test (which generally entails opening one or more editors).
+ */
+@Target({ ElementType.METHOD, ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ShowView {
+
+ /** The IDs of the views to show before the editor is opened. */
+ String[] value();
+
+ /**
+ * The IDs of workbench parts relative to which the views specified by the annotation are to be shown. If unspecified,
+ * the default is the workbench's editor area. If exactly part ID is specified, it is used for all views. Otherwise, a
+ * corresponding value is required for each view ID to be shown.
+ */
+ String[] relativeTo() default {};
+
+ /**
+ * The relative locations of the views to show. If unspecified, the default is {@link Location#STACKED} when the {@linkplain #relativeTo()
+ * relative part} is a view, otherwise {@link Location#RIGHT} when the relative part is the editor area.
+ * If exactly one value is specified, it is used for all views. Otherwise, a corresponding value is
+ * required for each view ID.
+ */
+ Location[] location() default {};
+
+ /**
+ * Enumeration of locations in which to open a view relative to some other workbench part.
+ */
+ enum Location {
+ /** Stacked with the relative part. */
+ STACKED(-1),
+ /** To the left of the relative part. */
+ LEFT(EModelService.LEFT_OF),
+ /** To the right of the relative part. */
+ RIGHT(EModelService.RIGHT_OF),
+ /** Above the relative part. */
+ ABOVE(EModelService.ABOVE),
+ /** Below the relative part. */
+ BELOW(EModelService.BELOW);
+
+ private final int modelServiceLocation;
+
+ private Location(int modelServiceLocation) {
+ this.modelServiceLocation = modelServiceLocation;
+ }
+
+ public int toModelServiceLocation() {
+ return modelServiceLocation;
+ }
+ }
+}

Back to the top