Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian W. Damus2014-07-25 19:18:18 +0000
committerChristian W. Damus2014-07-25 19:20:56 +0000
commit7b9fa63b694baf79bb2d9d6f5d7d2c5c24dde46d (patch)
tree1ea999875c87ae54579284444432b520306da1fa /plugins/infra/emf
parent43af1aa06fba01ee95ad7b72f07cabf80321bce2 (diff)
downloadorg.eclipse.papyrus-7b9fa63b694baf79bb2d9d6f5d7d2c5c24dde46d.tar.gz
org.eclipse.papyrus-7b9fa63b694baf79bb2d9d6f5d7d2c5c24dde46d.tar.xz
org.eclipse.papyrus-7b9fa63b694baf79bb2d9d6f5d7d2c5c24dde46d.zip
437217: [Editors] In-place reloading of model resources in the editors
https://bugs.eclipse.org/bugs/show_bug.cgi?id=437217 Add capture and restoration of writable library models in the reference library read-only handler so that the same libraries are writable after re-load as before.
Diffstat (limited to 'plugins/infra/emf')
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyManager.java124
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReferencedModelReadOnlyHandler.java59
2 files changed, 132 insertions, 51 deletions
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyManager.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyManager.java
index ae4c3fa7851..b75f3910247 100644
--- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyManager.java
+++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyManager.java
@@ -13,6 +13,7 @@
* Christian W. Damus (CEA) - bug 323802
* Christian W. Damus (CEA) - bug 429826
* Christian W. Damus (CEA) - bug 422257
+ * Christian W. Damus (CEA) - bug 437217
*
*****************************************************************************/
package org.eclipse.papyrus.infra.emf.readonly;
@@ -38,30 +39,39 @@ import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.domain.EditingDomain;
-import org.eclipse.papyrus.infra.core.Activator;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+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.AbstractReadOnlyHandler;
import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler;
import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler2;
import org.eclipse.papyrus.infra.core.resource.IReadOnlyListener;
import org.eclipse.papyrus.infra.core.resource.ReadOnlyAxis;
import org.eclipse.papyrus.infra.core.resource.ReadOnlyEvent;
+import org.eclipse.papyrus.infra.core.services.ServiceException;
+import org.eclipse.papyrus.infra.core.utils.AdapterUtils;
+import org.eclipse.papyrus.infra.emf.utils.ServiceUtilsForResourceSet;
import com.google.common.base.Optional;
import com.google.common.collect.MapMaker;
+import com.google.common.collect.Maps;
-public class ReadOnlyManager implements IReadOnlyHandler2 {
+public class ReadOnlyManager implements IReadOnlyHandler2, IEditorReloadListener {
// Use weak values because the values otherwise retain the keys (indirectly)
protected static final ConcurrentMap<EditingDomain, IReadOnlyHandler2> roHandlers = new MapMaker().weakKeys().weakValues().makeMap();
private final CopyOnWriteArrayList<IReadOnlyListener> listeners = new CopyOnWriteArrayList<IReadOnlyListener>();
-
+
private IReadOnlyListener forwardingListener;
-
+
public static IReadOnlyHandler2 getReadOnlyHandler(EditingDomain editingDomain) {
IReadOnlyHandler2 roHandler = IReadOnlyHandler2.NULL;
-
+
if(editingDomain != null) {
roHandler = roHandlers.get(editingDomain);
if(roHandler == null) {
@@ -73,7 +83,7 @@ public class ReadOnlyManager implements IReadOnlyHandler2 {
}
}
}
-
+
return roHandler;
}
@@ -82,7 +92,7 @@ public class ReadOnlyManager implements IReadOnlyHandler2 {
public Class<?> handlerClass;
public int priority;
-
+
public Set<ReadOnlyAxis> axes;
public int compareTo(HandlerPriorityPair o) {
@@ -112,18 +122,18 @@ public class ReadOnlyManager implements IReadOnlyHandler2 {
handlerPriorityPair.handlerClass = Platform.getBundle(elem.getContributor().getName()).loadClass(className);
handlerPriorityPair.priority = Integer.parseInt(elem.getAttribute("priority"));
-
+
IConfigurationElement[] affinities = elem.getChildren("affinity");
- if ((affinities == null) || (affinities.length == 0)) {
+ if((affinities == null) || (affinities.length == 0)) {
// implicit affinity is with any axis
handlerPriorityPair.axes = ReadOnlyAxis.anyAxis();
} else {
handlerPriorityPair.axes = EnumSet.noneOf(ReadOnlyAxis.class);
- for (IConfigurationElement next : affinities) {
+ for(IConfigurationElement next : affinities) {
handlerPriorityPair.axes.add(ReadOnlyAxis.valueOf(next.getAttribute("axis").toUpperCase()));
}
}
-
+
String id = elem.getAttribute("id");
if(id != null) {
//if any then the handler could be overrided by another registration
@@ -199,10 +209,10 @@ public class ReadOnlyManager implements IReadOnlyHandler2 {
IReadOnlyHandler2 h = create(roClass.getKey(), editingDomain);
if(h != null) {
h.addReadOnlyListener(getForwardingListener());
-
- for (ReadOnlyAxis axis : roClass.getValue()) {
+
+ for(ReadOnlyAxis axis : roClass.getValue()) {
List<IReadOnlyHandler2> list = handlers.get(axis);
- if (list == null) {
+ if(list == null) {
list = new ArrayList<IReadOnlyHandler2>();
handlers.put(axis, list);
}
@@ -210,7 +220,7 @@ public class ReadOnlyManager implements IReadOnlyHandler2 {
}
}
}
-
+
// Iterate the enumeration to make sure all axes are represented (even if only by an empty array)
orderedHandlersByAxis = new EnumMap<ReadOnlyAxis, IReadOnlyHandler2[]>(ReadOnlyAxis.class);
for(ReadOnlyAxis axis : ReadOnlyAxis.values()) {
@@ -221,6 +231,19 @@ public class ReadOnlyManager implements IReadOnlyHandler2 {
orderedHandlersByAxis.put(axis, list.toArray(new IReadOnlyHandler2[list.size()]));
}
}
+
+ // Is this editing domain associated with an editor?
+ try {
+ IMultiDiagramEditor editor = ServiceUtilsForResourceSet.getInstance().getService(IMultiDiagramEditor.class, editingDomain.getResourceSet());
+ if(editor != null) {
+ IReloadableEditor reloadable = IReloadableEditor.Adapter.getAdapter(editor);
+ if(reloadable != null) {
+ reloadable.addEditorReloadListener(this);
+ }
+ }
+ } catch (ServiceException e) {
+ // That's OK. We're not in the context of an editor
+ }
}
public Optional<Boolean> anyReadOnly(Set<ReadOnlyAxis> axes, URI[] uris) {
@@ -404,15 +427,15 @@ public class ReadOnlyManager implements IReadOnlyHandler2 {
return result;
}
-
+
public void addReadOnlyListener(IReadOnlyListener listener) {
listeners.addIfAbsent(listener);
}
-
+
public void removeReadOnlyListener(IReadOnlyListener listener) {
listeners.remove(listener);
}
-
+
private IReadOnlyListener getForwardingListener() {
if(forwardingListener == null) {
forwardingListener = new IReadOnlyListener() {
@@ -436,7 +459,7 @@ public class ReadOnlyManager implements IReadOnlyHandler2 {
return forwardingListener;
}
-
+
protected void notifyReadOnlyStateChanged(ReadOnlyEvent event) {
if(!listeners.isEmpty()) {
for(IReadOnlyListener next : listeners) {
@@ -448,31 +471,80 @@ public class ReadOnlyManager implements IReadOnlyHandler2 {
}
}
}
-
+
+ public void editorAboutToReload(EditorReloadEvent event) {
+ Map<Class<? extends IReadOnlyHandler2>, Object> reloadContexts = Maps.newHashMap();
+
+ for(IReadOnlyHandler2[] partition : orderedHandlersByAxis.values()) {
+ for(IReadOnlyHandler2 next : partition) {
+ if(!reloadContexts.containsKey(next.getClass())) {
+ IReloadContextProvider provider = AdapterUtils.adapt(next, IReloadContextProvider.class, null);
+ if(provider != null) {
+ reloadContexts.put(next.getClass(), provider.createReloadContext());
+ }
+ }
+ }
+ }
+
+ if(!reloadContexts.isEmpty()) {
+ event.putContext(reloadContexts);
+ }
+ }
+
+ public void editorReloaded(EditorReloadEvent event) {
+ // I will have been replaced by a new read-only manager
+ ReadOnlyManager manager = this;
+ try {
+ manager = (ReadOnlyManager)getReadOnlyHandler(event.getEditor().getServicesRegistry().getService(TransactionalEditingDomain.class));
+ IReloadableEditor reloadable = IReloadableEditor.Adapter.getAdapter(event.getEditor());
+ reloadable.removeEditorReloadListener(this);
+ reloadable.addEditorReloadListener(manager);
+ } catch (ServiceException e) {
+ Activator.log.error(e);
+ }
+
+ Object context = event.getContext();
+ if(context instanceof Map<?, ?>) {
+ @SuppressWarnings("unchecked")
+ Map<Class<? extends IReadOnlyHandler2>, Object> reloadContexts = (Map<Class<? extends IReadOnlyHandler2>, Object>)context;
+ for(IReadOnlyHandler2[] partition : manager.orderedHandlersByAxis.values()) {
+ for(IReadOnlyHandler2 next : partition) {
+ Object reloadContext = reloadContexts.get(next.getClass());
+ if(reloadContext != null) {
+ IReloadContextProvider provider = AdapterUtils.adapt(next, IReloadContextProvider.class, null);
+ if(provider != null) {
+ provider.restore(reloadContext);
+ }
+ }
+ }
+ }
+ }
+ }
+
//
// Deprecated API
//
-
+
@Deprecated
public Optional<Boolean> anyReadOnly(URI[] uris) {
return anyReadOnly(permissionAxes(), uris);
}
-
+
@Deprecated
public Optional<Boolean> isReadOnly(EObject eObject) {
return isReadOnly(permissionAxes(), eObject);
}
-
+
@Deprecated
public Optional<Boolean> makeWritable(URI[] uris) {
return makeWritable(permissionAxes(), uris);
}
-
+
@Deprecated
public Optional<Boolean> makeWritable(EObject eObject) {
return makeWritable(permissionAxes(), eObject);
}
-
+
//
// Legacy adapters
//
@@ -508,4 +580,4 @@ public class ReadOnlyManager implements IReadOnlyHandler2 {
return delegateResult ? Optional.<Boolean> absent() : Optional.of(Boolean.FALSE);
}
}
-} \ No newline at end of file
+}
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReferencedModelReadOnlyHandler.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReferencedModelReadOnlyHandler.java
index fc16ee6a1d7..a378ca25d25 100644
--- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReferencedModelReadOnlyHandler.java
+++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReferencedModelReadOnlyHandler.java
@@ -22,6 +22,7 @@ import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.URIConverter;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.papyrus.infra.core.editor.reload.IReloadContextProvider;
import org.eclipse.papyrus.infra.core.resource.AbstractReadOnlyHandler;
import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler2;
import org.eclipse.papyrus.infra.core.resource.ModelSet;
@@ -35,16 +36,16 @@ import com.google.common.base.Optional;
/**
* A {@linkplain IReadOnlyHandler2 read-only handler} for objects in referenced models, which by default shouldn't be editable in the context of the
- * model referencing them. This is a discretion-based handler.
+ * model referencing them. This is a discretion-based handler.
*/
-public class ReferencedModelReadOnlyHandler extends AbstractReadOnlyHandler {
+public class ReferencedModelReadOnlyHandler extends AbstractReadOnlyHandler implements IReloadContextProvider {
private final ControlledResourceTracker controlledResourceTracker;
- private final Set<URI> readableReferencedModels = new HashSet<URI>();
+ private final Set<URI> writableReferencedModels = new HashSet<URI>();
private boolean interactive = true;
-
+
public ReferencedModelReadOnlyHandler(EditingDomain editingDomain) {
super(editingDomain);
@@ -59,7 +60,7 @@ public class ReferencedModelReadOnlyHandler extends AbstractReadOnlyHandler {
public boolean isInteractive() {
return interactive;
}
-
+
/**
* Sets whether I interact with the user to confirm making resources writable.
*
@@ -69,26 +70,26 @@ public class ReferencedModelReadOnlyHandler extends AbstractReadOnlyHandler {
public void setInteractive(boolean interactive) {
this.interactive = interactive;
}
-
+
public Optional<Boolean> anyReadOnly(Set<ReadOnlyAxis> axes, URI[] uris) {
Optional<Boolean> result = Optional.absent();
if(axes.contains(ReadOnlyAxis.DISCRETION)) {
final URIConverter converter = getEditingDomain().getResourceSet().getURIConverter();
-
+
for(int i = 0; i < uris.length; i++) {
// Clients may pass object URIs (including fragments), so trim to a resource URI because we operate on the resource level
URI next = uris[i].trimFragment();
-
+
// If the resource doesn't exist, then it can't be opened in some other editor, so
// we needn't be concerned about editing it in the context of a referencing model
- if(!readableReferencedModels.contains(next.trimFileExtension()) && isNotModelSetMainModel(next) && converter.exists(next, null)) {
+ if(!writableReferencedModels.contains(next.trimFileExtension()) && isNotModelSetMainModel(next) && converter.exists(next, null)) {
result = Optional.of(true);
break;
}
}
}
-
+
return result;
}
@@ -100,7 +101,7 @@ public class ReferencedModelReadOnlyHandler extends AbstractReadOnlyHandler {
for(int i = 0; i < uris.length; i++) {
// Clients may pass object URIs (including fragments), so trim to a resource URI because we operate on the resource level
URI next = uris[i].trimFragment();
-
+
if(isNotModelSetMainModel(next)) {
result = Optional.of(true);
} else {
@@ -110,7 +111,7 @@ public class ReferencedModelReadOnlyHandler extends AbstractReadOnlyHandler {
}
}
}
-
+
return result;
}
@@ -119,26 +120,26 @@ public class ReferencedModelReadOnlyHandler extends AbstractReadOnlyHandler {
if(axes.contains(ReadOnlyAxis.DISCRETION)) {
final List<URI> toMakeWritable = new ArrayList<URI>(uris.length);
-
+
for(int i = 0; i < uris.length; i++) {
// Clients may pass object URIs (including fragments), so trim to a resource URI because we operate on the resource level
URI next = uris[i].trimFragment();
-
+
if(isNotModelSetMainModel(next)) {
toMakeWritable.add(next);
}
}
-
+
if(!toMakeWritable.isEmpty()) {
final boolean[] enableWrite = { !isInteractive() };
-
+
if(isInteractive()) {
- Display currentDisplay=Display.getCurrent();
- if(currentDisplay==null){
- currentDisplay=Display.getDefault();
+ Display currentDisplay = Display.getCurrent();
+ if(currentDisplay == null) {
+ currentDisplay = Display.getDefault();
}
currentDisplay.syncExec(new Runnable() {
-
+
public void run() {
StringBuilder message = new StringBuilder(Messages.ReferencedModelReadOnlyHandler_promptMsg);
for(URI uri : toMakeWritable) {
@@ -150,7 +151,7 @@ public class ReferencedModelReadOnlyHandler extends AbstractReadOnlyHandler {
} else {
path = uri.toString();
}
-
+
message.append(path);
message.append("\n"); //$NON-NLS-1$
}
@@ -158,18 +159,18 @@ public class ReferencedModelReadOnlyHandler extends AbstractReadOnlyHandler {
}
});
}
-
+
if(enableWrite[0]) {
for(URI next : toMakeWritable) {
- readableReferencedModels.add(next.trimFileExtension());
+ writableReferencedModels.add(next.trimFileExtension());
fireReadOnlyStateChanged(ReadOnlyAxis.DISCRETION, next, true);
}
}
-
+
result = Optional.of(enableWrite[0]);
}
}
-
+
return result;
}
@@ -202,4 +203,12 @@ public class ReferencedModelReadOnlyHandler extends AbstractReadOnlyHandler {
return controlledResourceTracker.getRootResourceURI(uri);
}
+ public Object createReloadContext() {
+ return writableReferencedModels;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void restore(Object reloadContext) {
+ writableReferencedModels.addAll((Set<URI>)reloadContext);
+ }
}

Back to the top