diff options
author | Christian W. Damus | 2014-07-25 19:18:18 +0000 |
---|---|---|
committer | Christian W. Damus | 2014-07-25 19:20:56 +0000 |
commit | 7b9fa63b694baf79bb2d9d6f5d7d2c5c24dde46d (patch) | |
tree | 1ea999875c87ae54579284444432b520306da1fa /plugins/infra/emf | |
parent | 43af1aa06fba01ee95ad7b72f07cabf80321bce2 (diff) | |
download | org.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')
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); + } } |