Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian W. Damus2014-03-12 11:58:27 +0000
committerChristian W. Damus2014-03-12 11:58:27 +0000
commit3f0b27435989e21957c241c3bc77c0df6e56ee99 (patch)
tree90eff22edd97e109cf577e55fd2a0127959307ff /plugins/infra
parent0e890bb85514e5d2af38d21275c47f5e62a04293 (diff)
parente20612278b0b49dadd45e5421c103a42c365abd0 (diff)
downloadorg.eclipse.papyrus-3f0b27435989e21957c241c3bc77c0df6e56ee99.tar.gz
org.eclipse.papyrus-3f0b27435989e21957c241c3bc77c0df6e56ee99.tar.xz
org.eclipse.papyrus-3f0b27435989e21957c241c3bc77c0df6e56ee99.zip
Merge branch 'refs/heads/bugs/429826-ro-axes'
Diffstat (limited to 'plugins/infra')
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/AbstractReadOnlyHandler.java185
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/IReadOnlyHandler.java20
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/IReadOnlyHandler2.java124
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/IReadOnlyListener.java24
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ModelSet.java22
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ReadOnlyAxis.java83
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ReadOnlyEvent.java83
-rw-r--r--plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/utils/TransactionHelper.java171
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/plugin.xml18
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/schema/readOnlyHandler.exsd260
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/AbstractReadOnlyHandler.java52
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/EMFReadOnlyHandler.java26
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/FSReadOnlyHandler.java91
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/PapyrusROTransactionalEditingDomain.java63
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyAdapterFactory.java6
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyManager.java357
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyOneFileApprover.java20
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyTester.java25
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReferencedModelReadOnlyHandler.java143
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/SashModelReadOnlyHandler.java30
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/handlers/EnableWriteCommandHandler.java5
-rw-r--r--plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/utils/EMFHelper.java113
22 files changed, 1481 insertions, 440 deletions
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/AbstractReadOnlyHandler.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/AbstractReadOnlyHandler.java
new file mode 100644
index 00000000000..097f6a5d9a9
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/AbstractReadOnlyHandler.java
@@ -0,0 +1,185 @@
+/*****************************************************************************
+ * Copyright (c) 2013, 2014 Atos Origin, 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:
+ * Mathieu Velten (Atos Origin) mathieu.velten@atosorigin.com - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 323802
+ * Christian W. Damus (CEA) - bug 429826
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.infra.core.resource;
+
+import static org.eclipse.papyrus.infra.core.resource.ReadOnlyAxis.permissionAxes;
+
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.edit.domain.EditingDomain;
+import org.eclipse.papyrus.infra.core.Activator;
+import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler2;
+import org.eclipse.papyrus.infra.core.resource.ReadOnlyAxis;
+
+import com.google.common.base.Optional;
+
+public abstract class AbstractReadOnlyHandler implements IReadOnlyHandler2 {
+
+ private EditingDomain editingDomain;
+
+ private CopyOnWriteArrayList<IReadOnlyListener> listeners = new CopyOnWriteArrayList<IReadOnlyListener>();
+
+ public AbstractReadOnlyHandler(EditingDomain editingDomain) {
+ this.editingDomain = editingDomain;
+ }
+
+ public static IReadOnlyHandler2 adapt(IReadOnlyHandler handler, EditingDomain domain) {
+ return new Adapter(handler, domain);
+ }
+
+ public EditingDomain getEditingDomain() {
+ return editingDomain;
+ }
+
+ @Deprecated
+ public Optional<Boolean> anyReadOnly(URI[] uris) {
+ return anyReadOnly(permissionAxes(), uris);
+ }
+
+ @Deprecated
+ public Optional<Boolean> isReadOnly(EObject eObject) {
+ return isReadOnly(permissionAxes(), eObject);
+ }
+
+ public Optional<Boolean> isReadOnly(Set<ReadOnlyAxis> axes, EObject eObject) {
+ Resource res = eObject.eResource();
+ if (res != null && res.getURI() != null) {
+ return anyReadOnly(axes, new URI[] {res.getURI()});
+ }
+ return Optional.absent();
+ }
+
+ @Deprecated
+ public Optional<Boolean> makeWritable(URI[] uris) {
+ return makeWritable(permissionAxes(), uris);
+ }
+
+ @Deprecated
+ public Optional<Boolean> makeWritable(EObject eObject) {
+ return makeWritable(permissionAxes(), eObject);
+ }
+
+ public Optional<Boolean> makeWritable(Set<ReadOnlyAxis> axes, EObject eObject) {
+ Resource res = eObject.eResource();
+ if (res != null && res.getURI() != null) {
+ return makeWritable(axes, new URI[] {res.getURI()});
+ }
+ return Optional.absent();
+ }
+
+ /**
+ * By default, we do not handle writability of these resources.
+ */
+ public Optional<Boolean> canMakeWritable(Set<ReadOnlyAxis> axes, URI[] uris) {
+ return Optional.absent();
+ }
+
+ public Optional<Boolean> canMakeWritable(Set<ReadOnlyAxis> axes, EObject object) {
+ Resource res = object.eResource();
+ if((res != null) && (res.getURI() != null)) {
+ return canMakeWritable(axes, new URI[]{ res.getURI() });
+ }
+ return Optional.absent();
+ }
+
+ @Override
+ public void addReadOnlyListener(IReadOnlyListener listener) {
+ listeners.addIfAbsent(listener);
+ }
+
+ @Override
+ public void removeReadOnlyListener(IReadOnlyListener listener) {
+ listeners.remove(listener);
+ }
+
+ protected void fireReadOnlyStateChanged(ReadOnlyAxis axis, URI resourceURI, boolean readOnly) {
+ if(!listeners.isEmpty()) {
+ ReadOnlyEvent event = new ReadOnlyEvent(this, axis, resourceURI, readOnly);
+ for(IReadOnlyListener next : listeners) {
+ try {
+ next.readOnlyStateChanged(event);
+ } catch (Exception e) {
+ Activator.log.error("Uncaught exception in read-only state change listener.", e); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+
+ protected void fireReadOnlyStateChanged(ReadOnlyAxis axis, EObject object, boolean readOnly) {
+ if(!listeners.isEmpty()) {
+ ReadOnlyEvent event = new ReadOnlyEvent(this, axis, object, readOnly);
+ for(IReadOnlyListener next : listeners) {
+ try {
+ next.readOnlyStateChanged(event);
+ } catch (Exception e) {
+ Activator.log.error("Uncaught exception in read-only state change listener.", e); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+
+ //
+ // Nested types
+ //
+
+ private static class Adapter extends AbstractReadOnlyHandler {
+ private final IReadOnlyHandler delegate;
+
+ Adapter(IReadOnlyHandler handler, EditingDomain editingDomain) {
+ super(editingDomain);
+
+ this.delegate = handler;
+ }
+
+ public Optional<Boolean> anyReadOnly(Set<ReadOnlyAxis> axes, URI[] uris) {
+ // these handlers implicitly only deal with permission-based read-only-ness
+ return !axes.contains(ReadOnlyAxis.PERMISSION) ? Optional.<Boolean> absent() : delegate.anyReadOnly(uris);
+ }
+
+ @Override
+ public Optional<Boolean> isReadOnly(Set<ReadOnlyAxis> axes, EObject eObject) {
+ return !axes.contains(ReadOnlyAxis.PERMISSION) ? Optional.<Boolean> absent() : delegate.isReadOnly(eObject);
+ }
+
+ public Optional<Boolean> makeWritable(Set<ReadOnlyAxis> axes, URI[] uris) {
+ // these handlers implicitly only deal with permission-based read-only-ness
+ Optional<Boolean> result = !axes.contains(ReadOnlyAxis.PERMISSION) ? Optional.<Boolean> absent() : delegate.makeWritable(uris);
+
+ if (result.or(false)) {
+ for (URI next : uris) {
+ fireReadOnlyStateChanged(ReadOnlyAxis.PERMISSION, next, true);
+ }
+ }
+
+ return result;
+ }
+
+ @Override
+ public Optional<Boolean> makeWritable(Set<ReadOnlyAxis> axes, EObject eObject) {
+ Optional<Boolean> result = !axes.contains(ReadOnlyAxis.PERMISSION) ? Optional.<Boolean> absent() : delegate.makeWritable(eObject);
+
+ if (result.or(false)) {
+ fireReadOnlyStateChanged(ReadOnlyAxis.PERMISSION, eObject, true);
+ }
+
+ return result;
+ }
+ }
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/IReadOnlyHandler.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/IReadOnlyHandler.java
index 5443ae7e690..8c69dd47aa2 100644
--- a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/IReadOnlyHandler.java
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/IReadOnlyHandler.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2011, 2013 Atos Origin, CEA, and others.
+ * Copyright (c) 2011, 2014 Atos Origin, CEA, and others.
*
*
* All rights reserved. This program and the accompanying materials
@@ -9,7 +9,7 @@
*
* Contributors:
* Mathieu Velten (Atos Origin) mathieu.velten@atosorigin.com - Initial API and implementation
- * Christian W. Damus (CEA)
+ * Christian W. Damus (CEA) - bug 429826
*
*****************************************************************************/
package org.eclipse.papyrus.infra.core.resource;
@@ -20,6 +20,14 @@ import org.eclipse.emf.edit.domain.EditingDomain;
import com.google.common.base.Optional;
+/**
+ * A pluggable handler determining whether a resource is "read only" (not writable). Implementations
+ * of this interface, if they do not implement {@link IReadOnlyHandler2}, implicitly determine
+ * read-only-ness according to the {@linkplain ReadOnlyAxis#PERMISSION permission axis}.
+ *
+ * @see IReadOnlyHandler2
+ * @see ReadOnlyAxis#PERMISSION
+ */
public interface IReadOnlyHandler {
/**
@@ -28,8 +36,6 @@ public interface IReadOnlyHandler {
*
* @param uris
* the URIs about which read-only-ness is to be determined
- * @param editingDomain
- * the domain in the context of which editing is being done
*
* @return {@link Optional#absent() absent} if I do not know whether any of
* the URIs is read-only or a {@link Optional#isPresent() present}
@@ -45,8 +51,6 @@ public interface IReadOnlyHandler {
* @param uris
* the URIs of resources to make writable (not all are
* necessarily read-only)
- * @param editingDomain
- * the domain in the context of which editing is being done
*
* @return {@link Optional#absent() absent} if I do not know how to make
* these resources writable and the next provider should be given a
@@ -63,8 +67,6 @@ public interface IReadOnlyHandler {
*
* @param eObject
* an element in some model resource
- * @param editingDomain
- * the contextual editing domain
*
* @return {@link Optional#absent() absent} if I do not know whether the
* {@code eObject} is read-only or a {@link Optional#isPresent()
@@ -79,8 +81,6 @@ public interface IReadOnlyHandler {
* @param eObject
* a {@linkplain #isReadOnly(EObject, EditingDomain) read-only}
* element in some model resource
- * @param editingDomain
- * the domain in the context of which editing is being done
*
* @return {@link Optional#absent() absent} if I do not know how to make
* this object writable and the next provider should be given a
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/IReadOnlyHandler2.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/IReadOnlyHandler2.java
index 8c266376d1c..143eed81a37 100644
--- a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/IReadOnlyHandler2.java
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/IReadOnlyHandler2.java
@@ -12,34 +12,148 @@
*/
package org.eclipse.papyrus.infra.core.resource;
+import java.util.Set;
+
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.edit.domain.EditingDomain;
import com.google.common.base.Optional;
/**
- * An optional extension interface for {@linkplain IReadOnlyHandler read-only handlers} that support making files writable.
+ * An optional extension interface for {@linkplain IReadOnlyHandler read-only handlers} that support making files writable
+ * and pertain to other concerns than simply {@linkplain ReadOnlyAxis#PERMISSION permissions}.
+ *
+ * @see ReadOnlyAxis
*/
public interface IReadOnlyHandler2 extends IReadOnlyHandler {
/**
- * Queries whether I can make the resources indicated by the given URIs writable.
+ * A shortcut for {@link #anyReadOnly(Set, URI[])} with a singleton set
+ * of {@linkplain ReadOnlyAxis#PERMISSION}.
+ *
+ * @deprecated Use {@linkplain #anyReadOnly(Set, URI[])}, instead.
+ */
+ Optional<Boolean> anyReadOnly(URI[] uris);
+
+ /**
+ * A shortcut for {@link #makeWritable(Set, URI[])} with a singleton set
+ * of {@linkplain ReadOnlyAxis#PERMISSION}.
+ *
+ * @deprecated Use {@linkplain #makeWritable(Set, URI[])}, instead.
+ */
+ Optional<Boolean> makeWritable(URI[] uris);
+
+ /**
+ * A shortcut for {@link #isReadOnly(Set, EObject)} with a singleton set
+ * of {@linkplain ReadOnlyAxis#PERMISSION}.
+ *
+ * @deprecated Use {@linkplain #isReadOnly(Set, EObject)}, instead.
+ */
+ Optional<Boolean> isReadOnly(EObject eObject);
+
+ /**
+ * A shortcut for {@link #makeWritable(Set, EObject)} with a singleton set
+ * of {@linkplain ReadOnlyAxis#PERMISSION}.
+ *
+ * @deprecated Use {@linkplain #makeWritable(Set, EObject)}, instead.
+ */
+ Optional<Boolean> makeWritable(EObject eObject);
+
+ /**
+ * Queries whether any of the resources identified by the given URIs is
+ * read-only in any of the given {@code axes} of concern.
+ *
+ * @param axes
+ * the set of axes on which to query read-only state
+ * @param uris
+ * the URIs about which read-only-ness is to be determined
+ *
+ * @return {@link Optional#absent() absent} if I do not know whether any of
+ * the URIs is read-only or a {@link Optional#isPresent() present}
+ * boolean indicating whether any definitively is or they all
+ * definitively are not read-only
+ */
+ Optional<Boolean> anyReadOnly(Set<ReadOnlyAxis> axes, URI[] uris);
+
+ /**
+ * Attempt to ensure that the resources identified by the given URIs are
+ * writable in any of the given {@code axes} of concern.
+ *
+ * @param axes
+ * the set of axes on which to query read-only state
+ * @param uris
+ * the URIs of resources to make writable (not all are
+ * necessarily read-only)
+ *
+ * @return {@link Optional#absent() absent} if I do not know how to make
+ * these resources writable and the next provider should be given a
+ * chance, or a {@link Optional#isPresent() present} boolean
+ * indicating that I made the resources writable ({@code true}) or
+ * they cannot be made writable ({@code false})
+ */
+ Optional<Boolean> makeWritable(Set<ReadOnlyAxis> axes, URI[] uris);
+
+ /**
+ * Queries whether an {@code eObject} is individually read-only in a given
+ * editing domain, if it is in a resource that supports object-level
+ * read/write permissions in any of the given {@code axes} of concern.
+ *
+ * @param axes
+ * the set of axes on which to query read-only state
+ * @param eObject
+ * an element in some model resource
+ *
+ * @return {@link Optional#absent() absent} if I do not know whether the
+ * {@code eObject} is read-only or a {@link Optional#isPresent()
+ * present} boolean indicating whether it definitively is or is not
+ * read-only
+ */
+ Optional<Boolean> isReadOnly(Set<ReadOnlyAxis> axes, EObject eObject);
+
+ /**
+ * Attempt to ensure that the given {@code eObject} is writable in any of the given {@code axes} of concern.
+ *
+ * @param axes
+ * the set of axes on which to query read-only state
+ * @param eObject
+ * a {@linkplain #isReadOnly(EObject, EditingDomain) read-only}
+ * element in some model resource
+ *
+ * @return {@link Optional#absent() absent} if I do not know how to make
+ * this object writable and the next provider should be given a
+ * chance, or a {@link Optional#isPresent() present} boolean
+ * indicating that I made it writable ({@code true}) or it cannot be
+ * made writable ({@code false})
+ */
+ Optional<Boolean> makeWritable(Set<ReadOnlyAxis> axes, EObject eObject);
+
+ /**
+ * Queries whether I can make the resources indicated by the given URIs writable in any of the given {@code axes} of concern.
*
+ * @param axes
+ * the set of axes on which to query read-only state
* @param uris
* indicate a set of resources (presumed read-only)
* @return a {@linkplain Optional#isPresent() present} boolean indicating either that I can make the resources writable or that I handle these
* kinds of resources and they cannot be made writable; an {@linkplain Optional#absent() absent} value, otherwise
*/
- Optional<Boolean> canMakeWritable(URI[] uris);
+ Optional<Boolean> canMakeWritable(Set<ReadOnlyAxis> axes, URI[] uris);
/**
- * Queries whether I can make the given {@code object} writable.
+ * Queries whether I can make the given {@code object} writable in any of the given {@code axes} of concern.
*
+ * @param axes
+ * the set of axes on which to query read-only state
* @param object
* a model element (presumed read-only)
* @return a {@linkplain Optional#isPresent() present} boolean indicating either that I can make the {@code object writable or that I handle its
* kind of resources and it cannot be made writable; an {@linkplain Optional#absent() absent} value, otherwise
*/
- Optional<Boolean> canMakeWritable(EObject object);
+ Optional<Boolean> canMakeWritable(Set<ReadOnlyAxis> axes, EObject object);
+
+ void addReadOnlyListener(IReadOnlyListener listener);
+
+ void removeReadOnlyListener(IReadOnlyListener listener);
}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/IReadOnlyListener.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/IReadOnlyListener.java
new file mode 100644
index 00000000000..ae90c14aab7
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/IReadOnlyListener.java
@@ -0,0 +1,24 @@
+/*
+ * 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.resource;
+
+import java.util.EventListener;
+
+
+/**
+ * This is the IReadOnlyListener type. Enjoy.
+ */
+public interface IReadOnlyListener extends EventListener {
+
+ public void readOnlyStateChanged(ReadOnlyEvent event);
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ModelSet.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ModelSet.java
index 96f02ae8f5d..ac45d457169 100644
--- a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ModelSet.java
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ModelSet.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2008, 2013 CEA LIST and others.
+ * Copyright (c) 2008, 2014 CEA LIST and others.
*
*
* All rights reserved. This program and the accompanying materials
@@ -14,6 +14,7 @@
* Christian W. Damus (CEA) - Support read-only state at object level (CDO)
* Christian W. Damus (CEA) - Refactoring of Create Model Wizard (CDO)
* Christian W. Damus (CEA LIST) - Controlled resources in CDO repositories
+ * Christian W. Damus (CEA) - bug 429826
*
*****************************************************************************/
package org.eclipse.papyrus.infra.core.resource;
@@ -108,7 +109,7 @@ public class ModelSet extends ResourceSetImpl {
protected Adapter modificationTrackingAdapter;
- protected IReadOnlyHandler roHandler;
+ protected IReadOnlyHandler2 roHandler;
/**
* URI pointing to resource on which back end should be deleted on save
@@ -678,12 +679,13 @@ public class ModelSet extends ResourceSetImpl {
Collection<IModel> modelList = models.values();
monitor.beginTask("Saving resources", modelList.size());
- if(isTrackingModification() && getReadOnlyHandler() != null) {
+ IReadOnlyHandler2 roHandler = getReadOnlyHandler();
+ if(isTrackingModification() && (roHandler != null)) {
Set<URI> roUris = new HashSet<URI>();
for(IModel model : modelList) {
Set<URI> uris = model.getModifiedURIs();
for(URI u : uris) {
- Optional<Boolean> res = getReadOnlyHandler().anyReadOnly(new URI[]{ u });
+ Optional<Boolean> res = (roHandler.anyReadOnly(ReadOnlyAxis.permissionAxes(), new URI[]{ u }));
if(res.isPresent() && res.get()) {
roUris.add(u);
}
@@ -691,14 +693,14 @@ public class ModelSet extends ResourceSetImpl {
}
for(URI u : getResourcesToDeleteOnSave()) {
- Optional<Boolean> res = getReadOnlyHandler().anyReadOnly(new URI[]{ u });
+ Optional<Boolean> res = roHandler.anyReadOnly(ReadOnlyAxis.permissionAxes(), new URI[]{ u });
if(res.isPresent() && res.get()) {
roUris.add(u);
}
}
if(!roUris.isEmpty()) {
- Optional<Boolean> authorizeSave = getReadOnlyHandler().makeWritable(roUris.toArray(new URI[roUris.size()]));
+ Optional<Boolean> authorizeSave = roHandler.makeWritable(ReadOnlyAxis.permissionAxes(), roUris.toArray(new URI[roUris.size()]));
if(authorizeSave.isPresent() && !authorizeSave.get()) {
monitor.done();
@@ -938,12 +940,14 @@ public class ModelSet extends ResourceSetImpl {
}
}
- public IReadOnlyHandler getReadOnlyHandler() {
+ public IReadOnlyHandler2 getReadOnlyHandler() {
if(roHandler == null) {
EditingDomain editingDomain = getTransactionalEditingDomain();
Object handler = PlatformHelper.getAdapter(editingDomain, IReadOnlyHandler.class);
- if(handler instanceof IReadOnlyHandler) {
- roHandler = (IReadOnlyHandler)handler;
+ if(handler instanceof IReadOnlyHandler2) {
+ roHandler = (IReadOnlyHandler2)handler;
+ } else if(handler instanceof IReadOnlyHandler) {
+ roHandler = AbstractReadOnlyHandler.adapt((IReadOnlyHandler)handler, editingDomain);
}
}
return roHandler;
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ReadOnlyAxis.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ReadOnlyAxis.java
new file mode 100644
index 00000000000..bde0a900c44
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ReadOnlyAxis.java
@@ -0,0 +1,83 @@
+/*
+ * 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.resource;
+
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+
+import com.google.common.collect.Sets;
+
+
+/**
+ * The "read-only-ness" of resources can be partitioned according to a number of othogonal concerns, or <em>axes</em>.
+ * Being orthogonal, these concerns are independent, although any particular resource may be considered as read-only
+ * according to more than one of these simultaneously (or one or none at all).
+ */
+public enum ReadOnlyAxis {
+ /**
+ * The most basic and obvious axis is the permission, or access control, concern. This typically maps to
+ * permissions in the storage layer (file system, database, network, etc.).
+ */
+ PERMISSION,
+
+ /**
+ * Some resources may be considered as read-only for discretionary reasons: there is no obstacle of {@linkplain #PERMISSION permissions}, but
+ * merely that the user is discouraged from making modifications
+ * to such a resource or its contents as a matter of policy.
+ */
+ DISCRETION;
+
+ private static final Set<ReadOnlyAxis> ANY_AXIS = Sets.immutableEnumSet(EnumSet.allOf(ReadOnlyAxis.class));
+
+ private static final Set<ReadOnlyAxis> PERMISSION_AXES = Collections.singleton(PERMISSION);
+
+ private static final Set<ReadOnlyAxis> DISCRETION_AXES = Collections.singleton(DISCRETION);
+
+ /**
+ * Efficiently obtains me as a singleton set.
+ *
+ * @return a singleton set containing me only
+ */
+ public Set<ReadOnlyAxis> singleton() {
+ switch(this) {
+ case PERMISSION:
+ return PERMISSION_AXES;
+ case DISCRETION:
+ return DISCRETION_AXES;
+ default:
+ throw new IllegalStateException("Impossible enumeration value: " + this); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * The set of axes for queries pertaining to any axis. That is to say, the complete set of all axes.
+ */
+ public static Set<ReadOnlyAxis> anyAxis() {
+ return ANY_AXIS;
+ }
+
+ /**
+ * The set of axes for queries pertaining to permission. That is to say, the singleton containing {@link #PERMISSION}.
+ */
+ public static Set<ReadOnlyAxis> permissionAxes() {
+ return PERMISSION_AXES;
+ }
+
+ /**
+ * The set of axes for queries pertaining to discretion. That is to say, the singleton containing {@link #DISCRETION}.
+ */
+ public static Set<ReadOnlyAxis> discretionAxes() {
+ return DISCRETION_AXES;
+ }
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ReadOnlyEvent.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ReadOnlyEvent.java
new file mode 100644
index 00000000000..8235b7b357e
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/resource/ReadOnlyEvent.java
@@ -0,0 +1,83 @@
+/*
+ * 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.resource;
+
+import java.util.EventObject;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+
+
+/**
+ * This is the ReadOnlyEvent type. Enjoy.
+ */
+public class ReadOnlyEvent extends EventObject {
+
+ public static final int RESOURCE_READ_ONLY_STATE_CHANGED = 0;
+
+ public static final int OBJECT_READ_ONLY_STATE_CHANGED = 1;
+
+ private static final long serialVersionUID = 1L;
+
+ private final int eventType;
+
+ private final ReadOnlyAxis axis;
+
+ private final URI resourceURI;
+
+ private final EObject object;
+
+ private final boolean readOnly;
+
+ private ReadOnlyEvent(IReadOnlyHandler2 source, int eventType, ReadOnlyAxis axis, URI resourceURI, EObject object, boolean readOnly) {
+ super(source);
+
+ this.eventType = eventType;
+ this.axis = axis;
+ this.resourceURI = resourceURI;
+ this.object = object;
+ this.readOnly = readOnly;
+ }
+
+ public ReadOnlyEvent(IReadOnlyHandler2 source, ReadOnlyAxis axis, URI resourceURI, boolean readOnly) {
+ this(source, RESOURCE_READ_ONLY_STATE_CHANGED, axis, resourceURI, null, readOnly);
+ }
+
+ public ReadOnlyEvent(IReadOnlyHandler2 source, ReadOnlyAxis axis, EObject object, boolean readOnly) {
+ this(source, RESOURCE_READ_ONLY_STATE_CHANGED, axis, null, object, readOnly);
+ }
+
+ public IReadOnlyHandler2 getHandler() {
+ return (IReadOnlyHandler2)getSource();
+ }
+
+ public int getEventType() {
+ return eventType;
+ }
+
+ public ReadOnlyAxis getAxis() {
+ return axis;
+ }
+
+ public URI getResourceURI() {
+ return resourceURI;
+ }
+
+ public EObject getObject() {
+ return object;
+ }
+
+ public boolean isReadOnly() {
+ return readOnly;
+ }
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/utils/TransactionHelper.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/utils/TransactionHelper.java
index 060c29865d2..a697a09ee26 100644
--- a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/utils/TransactionHelper.java
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/utils/TransactionHelper.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2014 CEA LIST.
+ * Copyright (c) 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,9 +8,21 @@
*
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 429826
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.core.utils;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.emf.transaction.Transaction;
+import org.eclipse.papyrus.infra.core.resource.ReadOnlyAxis;
+
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
/**
* This helper can be used to run (safe) transactions outside the CommandStack
@@ -22,4 +34,161 @@ public class TransactionHelper extends org.eclipse.papyrus.infra.core.sasheditor
//Refactoring needed. The sasheditor contentprovider should have dependencies to infra.EMF...
+ public static final String TRANSACTION_OPTION_READ_ONLY_AXIS = "papyrus.read_only_axis"; //$NON-NLS-1$
+
+ public static final String TRANSACTION_OPTION_INTERACTIVE = "papyrus.interactive"; //$NON-NLS-1$
+
+ /**
+ * Merges the read-only {@code axis} option into an existing map of {@code options}.
+ *
+ * @param options
+ * an existing (non-{@code null}) options map
+ * @param axis
+ * the axis option to merge
+ * @return the augmented {@code options}
+ */
+ public static Map<String, Object> mergeReadOnlyAxisOption(Map<String, Object> options, ReadOnlyAxis axis) {
+ return mergeReadOnlyAxisOption(options, Collections.singleton(axis));
+ }
+
+ /**
+ * Merges the read-only {@code axes} option into an existing map of {@code options}.
+ *
+ * @param options
+ * an existing (non-{@code null}) options map
+ * @param axes
+ * the axes option to merge
+ * @return the augmented {@code options}
+ */
+ public static Map<String, Object> mergeReadOnlyAxisOption(Map<String, Object> options, Set<ReadOnlyAxis> axes) {
+ options.put(TRANSACTION_OPTION_READ_ONLY_AXIS, axes);
+ return options;
+ }
+
+ /**
+ * Adds the read-only {@code axis} option to a transaction's {@code options}.
+ *
+ * @param options
+ * an options map, which may be {@code null} or immutable
+ * @param axis
+ * the axis option to add
+ * @return a new map based on the {@code options} and including the {@code axis}
+ */
+ public static Map<String, Object> addReadOnlyAxisOption(Map<String, ?> options, ReadOnlyAxis axis) {
+ return addReadOnlyAxisOption(options, Collections.singleton(axis));
+ }
+
+ /**
+ * Adds the read-only {@code axes} option to a transaction's {@code options}.
+ *
+ * @param options
+ * an options map, which may be {@code null} or immutable
+ * @param axes
+ * the axes option to add
+ * @return a new map based on the {@code options} and including the {@code axes}
+ */
+ public static Map<String, Object> addReadOnlyAxisOption(Map<String, ?> options, Set<ReadOnlyAxis> axes) {
+ Map<String, Object> result = (options == null) ? Maps.<String, Object> newHashMap() : Maps.newHashMap(options);
+ result.put(TRANSACTION_OPTION_READ_ONLY_AXIS, axes);
+ return result;
+ }
+
+ /**
+ * Creates a new mutable transaction options map with a read-only {@code axis}.
+ *
+ * @param axis
+ * the axis option
+ * @return a new mutable map including the {@code axis}
+ */
+ public static Map<String, Object> readOnlyAxisOption(ReadOnlyAxis axis) {
+ return readOnlyAxisOption(Collections.singleton(axis));
+ }
+
+ /**
+ * Creates a new mutable transaction options map with a read-only {@code axes}.
+ *
+ * @param axes
+ * the axes option
+ * @return a new mutable map including the {@code axes}
+ */
+ public static Map<String, Object> readOnlyAxisOption(Set<ReadOnlyAxis> axes) {
+ return addReadOnlyAxisOption(null, axes);
+ }
+
+ /**
+ * Queries the read-only axes to be enforced by a {@code transaction}.
+ *
+ * @param transaction
+ * a transaction
+ * @return its read-only axes, which are {@linkplain ReadOnlyAxis#anyAxis() all of them} by default if the option is absent
+ */
+ @SuppressWarnings("unchecked")
+ public static Set<ReadOnlyAxis> getReadOnlyAxisOption(Transaction transaction) {
+ Set<ReadOnlyAxis> result;
+
+ Object value = transaction.getOptions().get(TRANSACTION_OPTION_READ_ONLY_AXIS);
+ if(value instanceof Set<?>) {
+ result = (Set<ReadOnlyAxis>)value;
+ } else if(value instanceof Iterable<?>) {
+ result = Sets.immutableEnumSet((Iterable<ReadOnlyAxis>)value);
+ } else {
+ result = ReadOnlyAxis.anyAxis();
+ }
+
+ return result;
+ }
+
+ /**
+ * Merges the {@code interactive} transaction option into an existing map of {@code options}.
+ *
+ * @param options
+ * an existing (non-{@code null}) options map
+ * @param interactive
+ * whether the transaction is in an user-interactive context
+ * @return the augmented {@code options}
+ */
+ public static Map<String, Object> mergeInteractiveOption(Map<String, Object> options, boolean interactive) {
+ options.put(TRANSACTION_OPTION_INTERACTIVE, interactive);
+ return options;
+ }
+
+ /**
+ * Adds the {@code interactive} option option to a transaction's {@code options}.
+ *
+ * @param options
+ * an options map, which may be {@code null} or immutable
+ * @param interactive
+ * whether the transaction is in an user-interactive context
+ * @return a new map based on the {@code options} and including the {@code interactive} option
+ */
+ public static Map<String, Object> addInteractiveOption(Map<String, ?> options, boolean interactive) {
+ Map<String, Object> result = (options == null) ? Maps.<String, Object> newHashMap() : Maps.newHashMap(options);
+ result.put(TRANSACTION_OPTION_INTERACTIVE, interactive);
+ return result;
+ }
+
+ /**
+ * Creates a new mutable transaction options map with an {@code interactive} option.
+ *
+ * @param interactive
+ * whether the transaction is in an user-interactive context
+ * @return a new mutable map including the {@code interactive} option
+ */
+ public static Map<String, Object> interactiveOption(boolean interactive) {
+ return addInteractiveOption(null, interactive);
+ }
+
+ /**
+ * Queries whether a {@code transaction} is running in a user-interactive context. In practice, this means that it would be appropriate to
+ * prompt the user to make resources/objects writable if necessary.
+ *
+ * @param transaction
+ * a transaction
+ * @return {@code false} if the {@code transaction} has the {@linkplain #TRANSACTION_OPTION_INTERACTIVE interactive option} set {@code false};
+ * {@code true}, otherwise (including the default case of no option set)
+ */
+ public static boolean isInteractive(Transaction transaction) {
+ Object value = transaction.getOptions().get(TRANSACTION_OPTION_INTERACTIVE);
+ return (value instanceof Boolean) ? (Boolean)value : true;
+ }
}
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/plugin.xml b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/plugin.xml
index ea9f90089b1..6232c1f3e44 100644
--- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/plugin.xml
+++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/plugin.xml
@@ -8,20 +8,33 @@
class="org.eclipse.papyrus.infra.emf.readonly.ReferencedModelReadOnlyHandler"
id="org.eclipse.papyrus.infra.emf.readonly.ReferencedModelReadOnlyHandler"
priority="15">
+ <affinity
+ axis="discretion">
+ </affinity>
</readOnlyHandler>
<readOnlyHandler
class="org.eclipse.papyrus.infra.emf.readonly.FSReadOnlyHandler"
id="org.eclipse.papyrus.infra.emf.readonly.FSReadOnlyHandler"
priority="10">
+ <affinity
+ axis="permission">
+ </affinity>
</readOnlyHandler>
<readOnlyHandler
class="org.eclipse.papyrus.infra.emf.readonly.EMFReadOnlyHandler"
id="org.eclipse.papyrus.infra.emf.readonly.EMFReadOnlyHandler"
priority="5">
+ <affinity
+ axis="permission">
+ </affinity>
</readOnlyHandler>
<readOnlyHandler
class="org.eclipse.papyrus.infra.emf.readonly.SashModelReadOnlyHandler"
- priority="20"></readOnlyHandler>
+ priority="20">
+ <affinity
+ axis="discretion">
+ </affinity>
+ </readOnlyHandler>
</extension>
<extension
point="org.eclipse.ui.handlers">
@@ -133,6 +146,9 @@
<adapter
type="org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler">
</adapter>
+ <adapter
+ type="org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler2">
+ </adapter>
</factory>
</extension>
<!-- commented for Papyrus M4 build -->
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/schema/readOnlyHandler.exsd b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/schema/readOnlyHandler.exsd
index f6e1fa72735..cc704afdf94 100644
--- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/schema/readOnlyHandler.exsd
+++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/schema/readOnlyHandler.exsd
@@ -1,116 +1,144 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!-- Schema file written by PDE -->
-<schema targetNamespace="org.eclipse.papyrus.infra.emf.readonly" xmlns="http://www.w3.org/2001/XMLSchema">
-<annotation>
- <appinfo>
- <meta.schema plugin="org.eclipse.papyrus.infra.emf.readonly" id="readOnly" name="readOnly"/>
- </appinfo>
- <documentation>
- [Enter description of this extension point.]
- </documentation>
- </annotation>
-
- <element name="extension">
- <annotation>
- <appinfo>
- <meta.element />
- </appinfo>
- </annotation>
- <complexType>
- <sequence>
- <element ref="readOnlyHandler" minOccurs="0" maxOccurs="unbounded"/>
- </sequence>
- <attribute name="point" type="string" use="required">
- <annotation>
- <documentation>
-
- </documentation>
- </annotation>
- </attribute>
- <attribute name="id" type="string">
- <annotation>
- <documentation>
-
- </documentation>
- </annotation>
- </attribute>
- <attribute name="name" type="string">
- <annotation>
- <documentation>
-
- </documentation>
- <appinfo>
- <meta.attribute translatable="true"/>
- </appinfo>
- </annotation>
- </attribute>
- </complexType>
- </element>
-
- <element name="readOnlyHandler">
- <complexType>
- <attribute name="class" type="string">
- <annotation>
- <documentation>
-
- </documentation>
- <appinfo>
- <meta.attribute kind="java" basedOn=":org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler"/>
- </appinfo>
- </annotation>
- </attribute>
- <attribute name="priority" type="string">
- <annotation>
- <documentation>
-
- </documentation>
- </annotation>
- </attribute>
- <attribute name="id" type="string">
- <annotation>
- <documentation>
- optional id that can be used if this read only handler can be overriden.
- </documentation>
- </annotation>
- </attribute>
- </complexType>
- </element>
-
- <annotation>
- <appinfo>
- <meta.section type="since"/>
- </appinfo>
- <documentation>
- [Enter the first release in which this extension point appears.]
- </documentation>
- </annotation>
-
- <annotation>
- <appinfo>
- <meta.section type="examples"/>
- </appinfo>
- <documentation>
- [Enter extension point usage example here.]
- </documentation>
- </annotation>
-
- <annotation>
- <appinfo>
- <meta.section type="apiinfo"/>
- </appinfo>
- <documentation>
- [Enter API information here.]
- </documentation>
- </annotation>
-
- <annotation>
- <appinfo>
- <meta.section type="implementation"/>
- </appinfo>
- <documentation>
- [Enter information about supplied implementation of this extension point.]
- </documentation>
- </annotation>
-
-
-</schema>
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.papyrus.infra.emf.readonly" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+ <appinfo>
+ <meta.schema plugin="org.eclipse.papyrus.infra.emf.readonly" id="readOnly" name="readOnly"/>
+ </appinfo>
+ <documentation>
+ [Enter description of this extension point.]
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <annotation>
+ <appinfo>
+ <meta.element />
+ </appinfo>
+ </annotation>
+ <complexType>
+ <sequence>
+ <element ref="readOnlyHandler" minOccurs="0" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appinfo>
+ <meta.attribute translatable="true"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="readOnlyHandler">
+ <complexType>
+ <sequence>
+ <element ref="affinity" minOccurs="0" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="class" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appinfo>
+ <meta.attribute kind="java" basedOn=":org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ <attribute name="priority" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+ optional id that can be used if this read only handler can be overriden.
+ </documentation>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="affinity">
+ <annotation>
+ <documentation>
+ Declaration of a handler&apos;s affinity with a particular read-only axis.
+ </documentation>
+ </annotation>
+ <complexType>
+ <attribute name="axis" use="required">
+ <annotation>
+ <documentation>
+ The read-only axis (as enumerated in the &lt;tt&gt;ReadOnlyAxis&lt;/tt&gt; type) to which handler is applicable.
+ </documentation>
+ </annotation>
+ <simpleType>
+ <restriction base="string">
+ <enumeration value="discretion">
+ </enumeration>
+ <enumeration value="permission">
+ </enumeration>
+ </restriction>
+ </simpleType>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="since"/>
+ </appinfo>
+ <documentation>
+ [Enter the first release in which this extension point appears.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="examples"/>
+ </appinfo>
+ <documentation>
+ [Enter extension point usage example here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="apiinfo"/>
+ </appinfo>
+ <documentation>
+ [Enter API information here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="implementation"/>
+ </appinfo>
+ <documentation>
+ [Enter information about supplied implementation of this extension point.]
+ </documentation>
+ </annotation>
+
+
+</schema>
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/AbstractReadOnlyHandler.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/AbstractReadOnlyHandler.java
index e378e43c022..95bccb2e856 100644
--- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/AbstractReadOnlyHandler.java
+++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/AbstractReadOnlyHandler.java
@@ -10,58 +10,20 @@
* Contributors:
* Mathieu Velten (Atos Origin) mathieu.velten@atosorigin.com - Initial API and implementation
* Christian W. Damus (CEA) - bug 323802
+ * Christian W. Damus (CEA) - bug 429826
*
*****************************************************************************/
package org.eclipse.papyrus.infra.emf.readonly;
-import org.eclipse.emf.common.util.URI;
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.edit.domain.EditingDomain;
-import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler2;
-import com.google.common.base.Optional;
-
-public abstract class AbstractReadOnlyHandler implements IReadOnlyHandler2 {
-
- private EditingDomain editingDomain;
+/**
+ * @deprecated Use the {@link org.eclipse.papyrus.infra.core.resource.AbstractReadOnlyHandler} class, instead.
+ */
+@Deprecated
+public abstract class AbstractReadOnlyHandler extends org.eclipse.papyrus.infra.core.resource.AbstractReadOnlyHandler {
public AbstractReadOnlyHandler(EditingDomain editingDomain) {
- this.editingDomain = editingDomain;
- }
-
- public EditingDomain getEditingDomain() {
- return editingDomain;
- }
-
- public Optional<Boolean> isReadOnly(EObject eObject) {
- Resource res = eObject.eResource();
- if (res != null && res.getURI() != null) {
- return anyReadOnly(new URI[] {res.getURI()});
- }
- return Optional.absent();
- }
-
- public Optional<Boolean> makeWritable(EObject eObject) {
- Resource res = eObject.eResource();
- if (res != null && res.getURI() != null) {
- return makeWritable(new URI[] {res.getURI()});
- }
- return Optional.absent();
- }
-
- /**
- * By default, we do not handle writability of these resources.
- */
- public Optional<Boolean> canMakeWritable(URI[] uris) {
- return Optional.absent();
- }
-
- public Optional<Boolean> canMakeWritable(EObject object) {
- Resource res = object.eResource();
- if((res != null) && (res.getURI() != null)) {
- return canMakeWritable(new URI[]{ res.getURI() });
- }
- return Optional.absent();
+ super(editingDomain);
}
}
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/EMFReadOnlyHandler.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/EMFReadOnlyHandler.java
index c30bbe21ba6..dd3fd1226ca 100644
--- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/EMFReadOnlyHandler.java
+++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/EMFReadOnlyHandler.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2012 CEA LIST.
+ * Copyright (c) 2012, 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,32 +8,42 @@
*
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 429826
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.emf.readonly;
+import java.util.Set;
+
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.edit.domain.EditingDomain;
+import org.eclipse.papyrus.infra.core.resource.AbstractReadOnlyHandler;
+import org.eclipse.papyrus.infra.core.resource.ReadOnlyAxis;
import com.google.common.base.Optional;
-
+/**
+ * The EMF read-only handler is permission-based.
+ */
public class EMFReadOnlyHandler extends AbstractReadOnlyHandler {
public EMFReadOnlyHandler(EditingDomain editingDomain) {
super(editingDomain);
}
- public Optional<Boolean> anyReadOnly(URI[] uris) {
- for(URI uri : uris) {
- if(!uri.isPlatformResource()) {
- return Optional.of(Boolean.TRUE);
+ public Optional<Boolean> anyReadOnly(Set<ReadOnlyAxis> axes, URI[] uris) {
+ if(axes.contains(ReadOnlyAxis.PERMISSION)) {
+ for(URI uri : uris) {
+ if(!(uri.isPlatformResource() || uri.isFile())) {
+ return Optional.of(Boolean.TRUE);
+ }
}
}
-
+
return Optional.absent();
}
- public Optional<Boolean> makeWritable(URI[] uris) {
+ public Optional<Boolean> makeWritable(Set<ReadOnlyAxis> axes, URI[] uris) {
return Optional.absent(); //We cannot change the read-only status
}
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/FSReadOnlyHandler.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/FSReadOnlyHandler.java
index f035f201423..5df8b04d757 100644
--- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/FSReadOnlyHandler.java
+++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/FSReadOnlyHandler.java
@@ -10,12 +10,15 @@
* Contributors:
* Mathieu Velten (Atos Origin) mathieu.velten@atosorigin.com - Initial API and implementation
* Christian W. Damus (CEA) - bug 323802
+ * Christian W. Damus (CEA) - bug 429826
*
*****************************************************************************/
package org.eclipse.papyrus.infra.emf.readonly;
-import java.util.ArrayList;
-import java.util.Collection;
+import java.io.File;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.core.resources.IFile;
@@ -26,71 +29,95 @@ import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.papyrus.infra.core.resource.AbstractReadOnlyHandler;
+import org.eclipse.papyrus.infra.core.resource.ReadOnlyAxis;
import org.eclipse.swt.widgets.Display;
import com.google.common.base.Optional;
+/**
+ * The filesystem read-only handler is permission-based.
+ */
public class FSReadOnlyHandler extends AbstractReadOnlyHandler {
public FSReadOnlyHandler(EditingDomain editingDomain) {
super(editingDomain);
}
- public Optional<Boolean> anyReadOnly(URI[] uris) {
- for(URI uri : uris) {
-
- IFile file = getFile(uri);
- if(file != null && file.isReadOnly()) {
- return Optional.of(Boolean.TRUE);
+ public Optional<Boolean> anyReadOnly(Set<ReadOnlyAxis> axes, URI[] uris) {
+ if(axes.contains(ReadOnlyAxis.PERMISSION)) {
+ for(URI uri : uris) {
+ IFile ifile = getIFile(uri);
+ if(ifile != null) {
+ if(ifile.isReadOnly()) {
+ return Optional.of(Boolean.TRUE);
+ }
+ } else {
+ File file = getFile(uri);
+ if((file != null) && file.exists() && !file.canWrite()) {
+ return Optional.of(Boolean.TRUE);
+ }
+ }
}
}
return Optional.absent();
}
- private static IFile getFile(URI uri) {
+ private static IFile getIFile(URI uri) {
if(uri.isPlatform()) {
return ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(uri.toPlatformString(true)));
}
return null;
}
- public Optional<Boolean> makeWritable(final URI[] uris) {
+ private static File getFile(URI uri) {
+ if(uri.isFile()) {
+ return new File(uri.toFileString());
+ }
+ return null;
+ }
+
+ public Optional<Boolean> makeWritable(Set<ReadOnlyAxis> axes, final URI[] uris) {
+ if(!axes.contains(ReadOnlyAxis.PERMISSION)) {
+ return Optional.absent();
+ }
+
final AtomicBoolean doEnableWrite = new AtomicBoolean();
-
+
// We can't make a file writable if it already is (there are read-only handlers that treat files that
// are filesystem-writable as read-only for other reasons)
- Collection<IFile> readOnlyFiles = new ArrayList<IFile>(uris.length);
+ final Map<IFile, URI> readOnlyFiles = new LinkedHashMap<IFile, URI>();
for(int i = 0; i < uris.length; i++) {
- IFile file = getFile(uris[i]);
+ IFile file = getIFile(uris[i]);
if((file != null) && file.isReadOnly()) {
- readOnlyFiles.add(file);
+ readOnlyFiles.put(file, uris[i]);
}
}
-
- if (!readOnlyFiles.isEmpty()) {
+
+ if(!readOnlyFiles.isEmpty()) {
Display.getCurrent().syncExec(new Runnable() {
-
+
public void run() {
String message = "Do you want to remove read only flag on those files ?\n\n";
- for(URI uri : uris) {
- IFile file = getFile(uri);
- if(file != null && file.isReadOnly()) {
- message += file.getName() + "\n";
- }
+ for(IFile file : readOnlyFiles.keySet()) {
+ message += file.getName() + "\n";
}
doEnableWrite.set(MessageDialog.openConfirm(Display.getCurrent().getActiveShell(), "Enable Write", message));
}
});
}
-
+
if(doEnableWrite.get()) {
Boolean ok = true;
- for(IFile file : readOnlyFiles) {
+ for(Map.Entry<IFile, URI> next : readOnlyFiles.entrySet()) {
try {
+ IFile file = next.getKey();
ResourceAttributes att = file.getResourceAttributes();
att.setReadOnly(false);
file.setResourceAttributes(att);
+
+ fireReadOnlyStateChanged(ReadOnlyAxis.PERMISSION, next.getValue(), true);
} catch (CoreException e) {
ok = false;
}
@@ -105,15 +132,17 @@ public class FSReadOnlyHandler extends AbstractReadOnlyHandler {
* I can make workspace resources writable.
*/
@Override
- public Optional<Boolean> canMakeWritable(URI[] uris) {
+ public Optional<Boolean> canMakeWritable(Set<ReadOnlyAxis> axes, URI[] uris) {
Optional<Boolean> result = Optional.absent();
- for(int i = 0; (!result.isPresent() || result.get()) && (i < uris.length); i++) {
- if(uris[i].isPlatformResource()) {
- result = Optional.of(true);
- } else if(uris[i].isFile()) {
- // We don't make non-workspace (external but local) files writable
- result = Optional.of(false);
+ if(axes.contains(ReadOnlyAxis.PERMISSION)) {
+ for(int i = 0; (!result.isPresent() || result.get()) && (i < uris.length); i++) {
+ if(uris[i].isPlatformResource()) {
+ result = Optional.of(true);
+ } else if(uris[i].isFile()) {
+ // We don't make non-workspace (external but local) files writable
+ result = Optional.of(false);
+ }
}
}
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/PapyrusROTransactionalEditingDomain.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/PapyrusROTransactionalEditingDomain.java
index 0d178b8c6be..ebbacd5b4be 100644
--- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/PapyrusROTransactionalEditingDomain.java
+++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/PapyrusROTransactionalEditingDomain.java
@@ -11,10 +11,13 @@
* Mathieu Velten (Atos Origin) mathieu.velten@atosorigin.com - Initial API and implementation
* Christian W. Damus (CEA) - Support object-level read/write controls (CDO)
* Christian W. Damus (CEA) - bug 323802
+ * Christian W. Damus (CEA) - bug 429826
*
*****************************************************************************/
package org.eclipse.papyrus.infra.emf.readonly;
+import static org.eclipse.papyrus.infra.core.utils.TransactionHelper.isInteractive;
+
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
@@ -30,17 +33,17 @@ import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
-import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.transaction.NotificationFilter;
import org.eclipse.emf.transaction.Transaction;
import org.eclipse.emf.transaction.TransactionalCommandStack;
import org.eclipse.emf.transaction.impl.InternalTransaction;
import org.eclipse.emf.transaction.impl.TransactionChangeRecorder;
import org.eclipse.emf.transaction.impl.TransactionalEditingDomainImpl;
-import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler;
import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler2;
import org.eclipse.papyrus.infra.core.resource.IRollbackStatus;
+import org.eclipse.papyrus.infra.core.resource.ReadOnlyAxis;
import org.eclipse.papyrus.infra.core.resource.RollbackStatus;
+import org.eclipse.papyrus.infra.core.utils.TransactionHelper;
import org.eclipse.papyrus.infra.onefile.model.IPapyrusFile;
import org.eclipse.papyrus.infra.onefile.model.PapyrusModelHelper;
import org.eclipse.papyrus.infra.onefile.utils.OneFileUtils;
@@ -54,14 +57,11 @@ public class PapyrusROTransactionalEditingDomain extends TransactionalEditingDom
@Override
public boolean isReadOnly(Resource resource) {
- if(resource != null && resource.getURI() != null) {
- return ReadOnlyManager.getReadOnlyHandler(this).anyReadOnly(new URI[]{ resource.getURI() }).get();
- }
- return false;
+ return isReadOnly(ReadOnlyAxis.anyAxis(), resource);
}
public boolean isReadOnly(EObject eObject) {
- return ReadOnlyManager.getReadOnlyHandler(this).isReadOnly(eObject).get();
+ return isReadOnly(ReadOnlyAxis.anyAxis(), eObject);
}
@Override
@@ -98,6 +98,7 @@ public class PapyrusROTransactionalEditingDomain extends TransactionalEditingDom
&& !Boolean.TRUE.equals(tx.getOptions().get(Transaction.OPTION_UNPROTECTED)) //
&& !willRollBack(tx)) {
+ final Set<ReadOnlyAxis> axes = TransactionHelper.getReadOnlyAxisOption(tx);
boolean readOnly;
// Check for Resource first because CDO resources *are* EObjects
@@ -107,10 +108,12 @@ public class PapyrusROTransactionalEditingDomain extends TransactionalEditingDom
// We must be able to modify read-only resources in order to load them
return;
}
- readOnly = isReadOnly(resource) && !makeWritable(resource);
+ // If it's not an interactive transaction, don't try to make the resource writable because that would prompt the user
+ readOnly = isReadOnly(axes, resource) && !(isInteractive(tx) && makeWritable(axes, resource));
} else if(object instanceof EObject) {
EObject eObject = (EObject)object;
- readOnly = isReadOnly(eObject) && !makeWritable(eObject);
+ // If it's not an interactive transaction, don't try to make the object writable because that would prompt the user
+ readOnly = isReadOnly(axes, eObject) && !(isInteractive(tx) && makeWritable(axes, eObject));
} else {
// If it's not an EMF-managed object, we don't care
readOnly = false;
@@ -123,41 +126,43 @@ public class PapyrusROTransactionalEditingDomain extends TransactionalEditingDom
}
}
}
-
+
private boolean willRollBack(Transaction tx) {
IStatus status = tx.getStatus();
return (status != null) && (status.getSeverity() >= IStatus.ERROR);
}
- protected boolean makeWritable(Resource resource) {
+ protected boolean isReadOnly(Set<ReadOnlyAxis> axes, Resource resource) {
+ if((resource != null) && (resource.getURI() != null)) {
+ return ReadOnlyManager.getReadOnlyHandler(this).anyReadOnly(axes, new URI[]{ resource.getURI() }).get();
+ }
+ return false;
+ }
+
+ protected boolean isReadOnly(Set<ReadOnlyAxis> axes, EObject eObject) {
+ return ReadOnlyManager.getReadOnlyHandler(this).isReadOnly(axes, eObject).get();
+ }
+
+ protected boolean makeWritable(Set<ReadOnlyAxis> axes, Resource resource) {
URI[] uris = getCompositeModelURIs(resource.getURI());
- IReadOnlyHandler handler = ReadOnlyManager.getReadOnlyHandler(this);
+ IReadOnlyHandler2 handler = ReadOnlyManager.getReadOnlyHandler(this);
- if(handler instanceof IReadOnlyHandler2) {
- if(!((IReadOnlyHandler2)handler).canMakeWritable(uris).or(false)) {
- return false;
- }
+ if(!handler.canMakeWritable(axes, uris).or(false)) {
+ return false;
}
- return handler.makeWritable(uris).get();
+ return handler.makeWritable(axes, uris).get();
}
- protected boolean makeWritable(EObject object) {
+ protected boolean makeWritable(Set<ReadOnlyAxis> axes, EObject object) {
boolean result;
- URI uri = EcoreUtil.getURI(object);
+ IReadOnlyHandler2 handler = ReadOnlyManager.getReadOnlyHandler(this);
- // If it's a workspace resource, we don't have to worry about object-level read-only state
- if(uri.isPlatformResource()) {
- result = makeWritable(object.eResource());
+ if(!handler.canMakeWritable(axes, object).or(false)) {
+ result = false;
} else {
- IReadOnlyHandler handler = ReadOnlyManager.getReadOnlyHandler(this);
-
- if((handler instanceof IReadOnlyHandler2) && !((IReadOnlyHandler2)handler).canMakeWritable(object).or(false)) {
- result = false;
- } else {
- result = handler.makeWritable(object).get();
- }
+ result = handler.makeWritable(axes, object).get();
}
return result;
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyAdapterFactory.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyAdapterFactory.java
index 621235a1af2..5444e6fd48f 100644
--- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyAdapterFactory.java
+++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyAdapterFactory.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2012 Atos Origin.
+ * Copyright (c) 2012, 2014 Atos Origin, CEA, and others.
*
*
* All rights reserved. This program and the accompanying materials
@@ -9,6 +9,7 @@
*
* Contributors:
* Mathieu Velten (Atos Origin) mathieu.velten@atosorigin.com - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 429826
*
*****************************************************************************/
package org.eclipse.papyrus.infra.emf.readonly;
@@ -16,12 +17,13 @@ package org.eclipse.papyrus.infra.emf.readonly;
import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler;
+import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler2;
@SuppressWarnings("rawtypes")
public class ReadOnlyAdapterFactory implements IAdapterFactory {
public Object getAdapter(Object adaptableObject, Class adapterType) {
- if(IReadOnlyHandler.class == adapterType && adaptableObject instanceof EditingDomain) {
+ if(((IReadOnlyHandler.class == adapterType) || (IReadOnlyHandler2.class == adapterType)) && (adaptableObject instanceof EditingDomain)) {
return ReadOnlyManager.getReadOnlyHandler((EditingDomain) adaptableObject);
}
return null;
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 f09bd0e39df..9e849a4120a 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
@@ -11,30 +11,42 @@
* Mathieu Velten (Atos Origin) mathieu.velten@atosorigin.com - Initial API and implementation
* Christian W. Damus (CEA) - support non-IFile resources and object-level permissions (CDO)
* Christian W. Damus (CEA) - bug 323802
+ * Christian W. Damus (CEA) - bug 429826
*
*****************************************************************************/
package org.eclipse.papyrus.infra.emf.readonly;
+import static org.eclipse.papyrus.infra.core.resource.ReadOnlyAxis.permissionAxes;
+
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.EnumMap;
+import java.util.EnumSet;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
import org.eclipse.core.runtime.IConfigurationElement;
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.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 com.google.common.base.Optional;
-@SuppressWarnings("deprecation")
public class ReadOnlyManager implements IReadOnlyHandler2 {
//Using a WeakHashMap leads to a Memory Leak, because only the Key is weak.
@@ -42,10 +54,14 @@ public class ReadOnlyManager implements IReadOnlyHandler2 {
//which prevents garbage collection of the EditingDomain
//Workaround: when the (Papyrus) editing domain is disposed, it removes itself from this map
//This won't work for non-papyrus editing domains, which are still leaked (But we do not use non-papyrus editing domains which this ReadOnlyManager)
- protected static Map<EditingDomain, IReadOnlyHandler> roHandlers = new HashMap<EditingDomain, IReadOnlyHandler>();
+ protected static Map<EditingDomain, IReadOnlyHandler2> roHandlers = new HashMap<EditingDomain, IReadOnlyHandler2>();
- public static IReadOnlyHandler getReadOnlyHandler(EditingDomain editingDomain) {
- IReadOnlyHandler roHandler = roHandlers.get(editingDomain);
+ private final CopyOnWriteArrayList<IReadOnlyListener> listeners = new CopyOnWriteArrayList<IReadOnlyListener>();
+
+ private IReadOnlyListener forwardingListener;
+
+ public static IReadOnlyHandler2 getReadOnlyHandler(EditingDomain editingDomain) {
+ IReadOnlyHandler2 roHandler = roHandlers.get(editingDomain);
if(roHandler == null) {
roHandler = new ReadOnlyManager(editingDomain);
roHandlers.put(editingDomain, roHandler);
@@ -58,6 +74,8 @@ public class ReadOnlyManager implements IReadOnlyHandler2 {
public Class<?> handlerClass;
public int priority;
+
+ public Set<ReadOnlyAxis> axes;
public int compareTo(HandlerPriorityPair o) {
if(o.priority > priority) {
@@ -70,7 +88,7 @@ public class ReadOnlyManager implements IReadOnlyHandler2 {
}
}
- protected static final Class<?>[] orderedHandlerClassesArray;
+ protected static final Map<Class<?>, Set<ReadOnlyAxis>> orderedHandlerClasses;
static {
IConfigurationElement[] configElements = Platform.getExtensionRegistry().getConfigurationElementsFor("org.eclipse.papyrus.infra.emf.readonly", "readOnlyHandler");
@@ -86,6 +104,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)) {
+ // implicit affinity is with any axis
+ handlerPriorityPair.axes = ReadOnlyAxis.anyAxis();
+ } else {
+ handlerPriorityPair.axes = EnumSet.noneOf(ReadOnlyAxis.class);
+ 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
@@ -113,15 +143,16 @@ public class ReadOnlyManager implements IReadOnlyHandler2 {
Collections.sort(handlerPriorityPairs);
- orderedHandlerClassesArray = new Class<?>[handlerPriorityPairs.size()];
+ orderedHandlerClasses = new LinkedHashMap<Class<?>, Set<ReadOnlyAxis>>();
- for(int i = 0; i < orderedHandlerClassesArray.length; i++) {
- orderedHandlerClassesArray[i] = handlerPriorityPairs.get(i).handlerClass;
+ for(HandlerPriorityPair next : handlerPriorityPairs) {
+ orderedHandlerClasses.put(next.handlerClass, next.axes);
}
}
- protected static IReadOnlyHandler create(final Class<?> handlerClass, EditingDomain editingDomain) {
+ @SuppressWarnings("deprecation")
+ protected static IReadOnlyHandler2 create(final Class<?> handlerClass, EditingDomain editingDomain) {
boolean isEditingDomainConstructor = true;
Constructor<?> constructor = null;
try {
@@ -131,14 +162,20 @@ public class ReadOnlyManager implements IReadOnlyHandler2 {
constructor = handlerClass.getConstructor();
}
- if(IReadOnlyHandler.class.isAssignableFrom(constructor.getDeclaringClass())) {
+ if(IReadOnlyHandler2.class.isAssignableFrom(constructor.getDeclaringClass())) {
+ if(isEditingDomainConstructor) {
+ return (IReadOnlyHandler2)constructor.newInstance(editingDomain);
+ } else {
+ return (IReadOnlyHandler2)constructor.newInstance();
+ }
+ } else if(IReadOnlyHandler.class.isAssignableFrom(constructor.getDeclaringClass())) {
if(isEditingDomainConstructor) {
- return (IReadOnlyHandler)constructor.newInstance(editingDomain);
+ return AbstractReadOnlyHandler.adapt((IReadOnlyHandler)constructor.newInstance(editingDomain), editingDomain);
} else {
- return (IReadOnlyHandler)constructor.newInstance();
+ return AbstractReadOnlyHandler.adapt((IReadOnlyHandler)constructor.newInstance(), editingDomain);
}
} else if(org.eclipse.papyrus.infra.emf.readonly.IReadOnlyHandler.class.isAssignableFrom(constructor.getDeclaringClass())) {
- return new HandlerAdapter((org.eclipse.papyrus.infra.emf.readonly.IReadOnlyHandler)constructor.newInstance(), editingDomain);
+ return new OldStyleHandlerAdapter((org.eclipse.papyrus.infra.emf.readonly.IReadOnlyHandler)constructor.newInstance(), editingDomain);
}
} catch (Exception e) {
}
@@ -146,142 +183,320 @@ public class ReadOnlyManager implements IReadOnlyHandler2 {
return null;
}
- protected IReadOnlyHandler[] orderedHandlersArray;
+ protected Map<ReadOnlyAxis, IReadOnlyHandler2[]> orderedHandlersByAxis;
public ReadOnlyManager(EditingDomain editingDomain) {
- ArrayList<IReadOnlyHandler> handlers = new ArrayList<IReadOnlyHandler>();
- for(Class<?> roClass : orderedHandlerClassesArray) {
- IReadOnlyHandler h = create(roClass, editingDomain);
+ Map<ReadOnlyAxis, List<IReadOnlyHandler2>> handlers = new EnumMap<ReadOnlyAxis, List<IReadOnlyHandler2>>(ReadOnlyAxis.class);
+ for(Map.Entry<Class<?>, Set<ReadOnlyAxis>> roClass : orderedHandlerClasses.entrySet()) {
+ IReadOnlyHandler2 h = create(roClass.getKey(), editingDomain);
if(h != null) {
- handlers.add(h);
+ h.addReadOnlyListener(getForwardingListener());
+
+ for (ReadOnlyAxis axis : roClass.getValue()) {
+ List<IReadOnlyHandler2> list = handlers.get(axis);
+ if (list == null) {
+ list = new ArrayList<IReadOnlyHandler2>();
+ handlers.put(axis, list);
+ }
+ list.add(h);
+ }
+ }
+ }
+
+ // 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()) {
+ List<IReadOnlyHandler2> list = handlers.get(axis);
+ if(list == null) {
+ orderedHandlersByAxis.put(axis, new IReadOnlyHandler2[0]);
+ } else {
+ orderedHandlersByAxis.put(axis, list.toArray(new IReadOnlyHandler2[list.size()]));
}
}
- orderedHandlersArray = handlers.toArray(new IReadOnlyHandler[handlers.size()]);
}
- public Optional<Boolean> anyReadOnly(URI[] uris) {
+ public Optional<Boolean> anyReadOnly(Set<ReadOnlyAxis> axes, URI[] uris) {
Optional<Boolean> result = Optional.absent();
- for(int i = 0; (i < orderedHandlersArray.length) && !result.isPresent(); i++) {
- result = orderedHandlersArray[i].anyReadOnly(uris);
+ ReadOnlyAxis[] all = ReadOnlyAxis.values();
+ for(int i = 0; (i < all.length) && !result.or(Boolean.FALSE); i++) {
+ if(axes.contains(all[i])) {
+ result = anyReadOnly(all[i], uris);
+ }
}
return result.isPresent() ? result : Optional.of(Boolean.FALSE);
}
- public Optional<Boolean> isReadOnly(EObject eObject) {
+ private Optional<Boolean> anyReadOnly(ReadOnlyAxis axis, URI[] uris) {
+ Set<ReadOnlyAxis> axes = axis.singleton();
Optional<Boolean> result = Optional.absent();
- for(int i = 0; (i < orderedHandlersArray.length) && !result.isPresent(); i++) {
- result = orderedHandlersArray[i].isReadOnly(eObject);
+ IReadOnlyHandler2[] orderedHandlers = orderedHandlersByAxis.get(axis);
+ for(int i = 0; (i < orderedHandlers.length) && !result.isPresent(); i++) {
+ result = orderedHandlers[i].anyReadOnly(axes, uris);
}
return result.isPresent() ? result : Optional.of(Boolean.FALSE);
}
- public Optional<Boolean> makeWritable(URI[] uris) {
+ public Optional<Boolean> isReadOnly(Set<ReadOnlyAxis> axes, EObject eObject) {
+ Optional<Boolean> result = Optional.absent();
+
+ ReadOnlyAxis[] all = ReadOnlyAxis.values();
+ for(int i = 0; (i < all.length) && !result.or(Boolean.FALSE); i++) {
+ if(axes.contains(all[i])) {
+ result = isReadOnly(all[i], eObject);
+ }
+ }
+
+ return result.isPresent() ? result : Optional.of(Boolean.FALSE);
+ }
+
+ private Optional<Boolean> isReadOnly(ReadOnlyAxis axis, EObject eObject) {
+ Set<ReadOnlyAxis> axes = axis.singleton();
+ Optional<Boolean> result = Optional.absent();
+
+ IReadOnlyHandler2[] orderedHandlers = orderedHandlersByAxis.get(axis);
+ for(int i = 0; (i < orderedHandlers.length) && !result.isPresent(); i++) {
+ result = orderedHandlers[i].isReadOnly(axes, eObject);
+ }
+
+ return result.isPresent() ? result : Optional.of(Boolean.FALSE);
+ }
+
+ public Optional<Boolean> makeWritable(Set<ReadOnlyAxis> axes, URI[] uris) {
+ Boolean finalResult = true;
+
+ ReadOnlyAxis[] all = ReadOnlyAxis.values();
+ for(int i = 0; (i < all.length) && finalResult; i++) {
+ if(axes.contains(all[i])) {
+ finalResult = makeWritable(all[i], uris);
+ }
+ }
+
+ return Optional.of(finalResult);
+ }
+
+ private Boolean makeWritable(ReadOnlyAxis axis, URI[] uris) {
+ Set<ReadOnlyAxis> axes = axis.singleton();
Boolean finalResult = true;
- for(int i = 0; (i < orderedHandlersArray.length); i++) {
- Optional<Boolean> isRO = orderedHandlersArray[i].anyReadOnly(uris);
- if(isRO.isPresent() && isRO.get()) {
- Optional<Boolean> result = orderedHandlersArray[i].makeWritable(uris);
+ IReadOnlyHandler2[] orderedHandlers = orderedHandlersByAxis.get(axis);
+ for(int i = 0; (i < orderedHandlers.length); i++) {
+ Optional<Boolean> isRO = orderedHandlers[i].anyReadOnly(axes, uris);
+ if(isRO.or(Boolean.FALSE)) {
+ Optional<Boolean> result = orderedHandlers[i].makeWritable(axes, uris);
// makeWritable should provide an answer since anyReadOnly returned a positive value.
// If no answer consider it a failure
- if(!result.isPresent() || !result.get()) {
+ if(!result.or(Boolean.FALSE)) {
finalResult = false;
break;
}
}
}
+ return finalResult;
+ }
+
+ public Optional<Boolean> makeWritable(Set<ReadOnlyAxis> axes, EObject eObject) {
+ Boolean finalResult = true;
+
+ ReadOnlyAxis[] all = ReadOnlyAxis.values();
+ for(int i = 0; (i < all.length) && finalResult; i++) {
+ if(axes.contains(all[i])) {
+ finalResult = makeWritable(all[i], eObject);
+ }
+ }
+
return Optional.of(finalResult);
}
- public Optional<Boolean> makeWritable(EObject eObject) {
+ private Boolean makeWritable(ReadOnlyAxis axis, EObject eObject) {
+ Set<ReadOnlyAxis> axes = axis.singleton();
Boolean finalResult = true;
- for(int i = 0; (i < orderedHandlersArray.length); i++) {
- Optional<Boolean> isRO = orderedHandlersArray[i].isReadOnly(eObject);
- if(isRO.isPresent() && isRO.get()) {
- Optional<Boolean> result = orderedHandlersArray[i].makeWritable(eObject);
+ IReadOnlyHandler2[] orderedHandlers = orderedHandlersByAxis.get(axis);
+ for(int i = 0; (i < orderedHandlers.length); i++) {
+ Optional<Boolean> isRO = orderedHandlers[i].isReadOnly(axes, eObject);
+ if(isRO.or(Boolean.FALSE)) {
+ Optional<Boolean> result = orderedHandlers[i].makeWritable(axes, eObject);
// makeWritable should provide an answer since anyReadOnly returned a positive value
- // if no answer consider it fails
- if(result.isPresent() && !result.get()) {
+ // if no answer consider it a failure
+ if(!result.or(Boolean.FALSE)) {
finalResult = false;
+ break;
}
}
}
- return Optional.of(finalResult);
+ return finalResult;
}
-
- public Optional<Boolean> canMakeWritable(URI[] uris) {
+
+ public Optional<Boolean> canMakeWritable(Set<ReadOnlyAxis> axes, URI[] uris) {
Boolean result = false;
- for(int i = 0; (i < orderedHandlersArray.length); i++) {
- if(orderedHandlersArray[i] instanceof IReadOnlyHandler2) {
- IReadOnlyHandler2 h2 = (IReadOnlyHandler2)orderedHandlersArray[i];
- if (h2.anyReadOnly(uris).or(false)) {
- // Only ask a handler about making writable what it considers to be read-only
- Optional<Boolean> canMakeWritable = h2.canMakeWritable(uris);
- if(canMakeWritable.isPresent()) {
- result = canMakeWritable.get();
- break;
- }
+ ReadOnlyAxis[] all = ReadOnlyAxis.values();
+ for(int i = 0; (i < all.length) && !result; i++) {
+ if(axes.contains(all[i])) {
+ result = canMakeWritable(all[i], uris);
+ }
+ }
+
+ return Optional.of(result);
+ }
+
+ private Boolean canMakeWritable(ReadOnlyAxis axis, URI[] uris) {
+ Set<ReadOnlyAxis> axes = axis.singleton();
+ Boolean result = false;
+
+ IReadOnlyHandler2[] orderedHandlers = orderedHandlersByAxis.get(axis);
+ for(int i = 0; (i < orderedHandlers.length); i++) {
+ if(orderedHandlers[i].anyReadOnly(axes, uris).or(false)) {
+ // Only ask a handler about making writable what it considers to be read-only
+ Optional<Boolean> canMakeWritable = orderedHandlers[i].canMakeWritable(axes, uris);
+ if(canMakeWritable.isPresent()) {
+ result = canMakeWritable.get();
+ break;
}
}
}
+ return result;
+ }
+
+ public Optional<Boolean> canMakeWritable(Set<ReadOnlyAxis> axes, EObject object) {
+ Boolean result = false;
+
+ ReadOnlyAxis[] all = ReadOnlyAxis.values();
+ for(int i = 0; (i < all.length) && !result; i++) {
+ if(axes.contains(all[i])) {
+ result = canMakeWritable(all[i], object);
+ }
+ }
+
return Optional.of(result);
}
-
- public Optional<Boolean> canMakeWritable(EObject object) {
+
+ private Boolean canMakeWritable(ReadOnlyAxis axis, EObject object) {
+ Set<ReadOnlyAxis> axes = axis.singleton();
Boolean result = false;
- for(int i = 0; (i < orderedHandlersArray.length); i++) {
- if(orderedHandlersArray[i] instanceof IReadOnlyHandler2) {
- IReadOnlyHandler2 h2 = (IReadOnlyHandler2)orderedHandlersArray[i];
- if (h2.isReadOnly(object).or(false)) {
- // Only ask a handler about making writable what it considers to be read-only
- Optional<Boolean> canMakeWritable = h2.canMakeWritable(object);
- if(canMakeWritable.isPresent()) {
- result = canMakeWritable.get();
+ IReadOnlyHandler2[] orderedHandlers = orderedHandlersByAxis.get(axis);
+ for(int i = 0; (i < orderedHandlers.length); i++) {
+ if(orderedHandlers[i].isReadOnly(axes, object).or(false)) {
+ // Only ask a handler about making writable what it considers to be read-only
+ Optional<Boolean> canMakeWritable = orderedHandlers[i].canMakeWritable(axes, object);
+ if(canMakeWritable.isPresent()) {
+ result = canMakeWritable.get();
+ break;
+ }
+ }
+ }
+
+ 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() {
+
+ public void readOnlyStateChanged(ReadOnlyEvent event) {
+ ReadOnlyEvent myEvent;
+
+ switch(event.getEventType()) {
+ case ReadOnlyEvent.OBJECT_READ_ONLY_STATE_CHANGED:
+ myEvent = new ReadOnlyEvent(ReadOnlyManager.this, event.getAxis(), event.getObject(), event.isReadOnly());
+ break;
+ default:
+ myEvent = new ReadOnlyEvent(ReadOnlyManager.this, event.getAxis(), event.getResourceURI(), event.isReadOnly());
break;
}
+
+ notifyReadOnlyStateChanged(myEvent);
}
- }
+ };
}
- return Optional.of(result);
+ return forwardingListener;
}
+
+ protected void notifyReadOnlyStateChanged(ReadOnlyEvent event) {
+ if(!listeners.isEmpty()) {
+ for(IReadOnlyListener next : listeners) {
+ try {
+ next.readOnlyStateChanged(event);
+ } catch (Exception e) {
+ Activator.log.error("Uncaught exception in read-only state change listener.", e); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+
+ //
+ // 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
+ //
- private static final class HandlerAdapter extends AbstractReadOnlyHandler {
+ @SuppressWarnings("deprecation")
+ private static final class OldStyleHandlerAdapter extends AbstractReadOnlyHandler {
private final org.eclipse.papyrus.infra.emf.readonly.IReadOnlyHandler delegate;
- HandlerAdapter(org.eclipse.papyrus.infra.emf.readonly.IReadOnlyHandler handler, EditingDomain editingDomain) {
+ OldStyleHandlerAdapter(org.eclipse.papyrus.infra.emf.readonly.IReadOnlyHandler handler, EditingDomain editingDomain) {
super(editingDomain);
this.delegate = handler;
}
- public Optional<Boolean> anyReadOnly(URI[] uris) {
+ public Optional<Boolean> anyReadOnly(Set<ReadOnlyAxis> axes, URI[] uris) {
// the old API contract is that handlers only return true if they
// know it to be true, because the manager takes the first positive
- // answer
- boolean delegateResult = delegate.isReadOnly(uris, getEditingDomain());
+ // answer. Moreover, they only dealt with permission-based read-only-ness
+ boolean delegateResult = axes.contains(ReadOnlyAxis.PERMISSION) && delegate.isReadOnly(uris, getEditingDomain());
return delegateResult ? Optional.of(Boolean.TRUE) : Optional.<Boolean> absent();
}
- public Optional<Boolean> makeWritable(URI[] uris) {
+ public Optional<Boolean> makeWritable(Set<ReadOnlyAxis> axes, URI[] uris) {
// the old API contract is that handlers only return false if they
// tried to but could not make the resources writable, because the
// manager takes the first negative answer (this is opposite to the
- // isReadOnly logic)
- boolean delegateResult = delegate.enableWrite(uris, getEditingDomain());
+ // isReadOnly logic). Moreover, they only dealt with permission-based
+ // read-only-ness
+ boolean delegateResult = axes.contains(ReadOnlyAxis.PERMISSION) && delegate.enableWrite(uris, getEditingDomain());
return delegateResult ? Optional.<Boolean> absent() : Optional.of(Boolean.FALSE);
}
}
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyOneFileApprover.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyOneFileApprover.java
index 03a5388e717..67df44387de 100644
--- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyOneFileApprover.java
+++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyOneFileApprover.java
@@ -10,6 +10,7 @@
* Contributors:
* Mathieu Velten (Atos Origin) mathieu.velten@atosorigin.com - Initial API and implementation
* Christian W. Damus (CEA) - bug 323802
+ * Christian W. Damus (CEA) - bug 429826
*
*****************************************************************************/
package org.eclipse.papyrus.infra.emf.readonly;
@@ -38,8 +39,9 @@ import org.eclipse.emf.workspace.EMFCommandOperation;
import org.eclipse.gmf.runtime.common.core.command.CommandResult;
import org.eclipse.gmf.runtime.common.core.command.ICommand;
import org.eclipse.gmf.runtime.common.core.command.ICompositeCommand;
-import org.eclipse.gmf.runtime.common.core.internal.command.ICommandWithSettableResult;
import org.eclipse.papyrus.commands.wrappers.GMFtoEMFCommandWrapper;
+import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler2;
+import org.eclipse.papyrus.infra.core.resource.ReadOnlyAxis;
import org.eclipse.papyrus.infra.onefile.model.IPapyrusFile;
import org.eclipse.papyrus.infra.onefile.model.PapyrusModelHelper;
import org.eclipse.papyrus.infra.onefile.utils.OneFileUtils;
@@ -98,8 +100,9 @@ public class ReadOnlyOneFileApprover implements IOperationApprover2 {
EditingDomain editingDomain = getEditingDomain(operation);
URI[] filesToCheckForLockArray = filesToCheckForLock.toArray(new URI[filesToCheckForLock.size()]);
- if(ReadOnlyManager.getReadOnlyHandler(editingDomain).anyReadOnly(filesToCheckForLockArray).get()) {
- Optional<Boolean> ok = ReadOnlyManager.getReadOnlyHandler(editingDomain).makeWritable(filesToCheckForLockArray);
+ IReadOnlyHandler2 roHandler = ReadOnlyManager.getReadOnlyHandler(editingDomain);
+ if(roHandler.anyReadOnly(ReadOnlyAxis.anyAxis(), filesToCheckForLockArray).get()) {
+ Optional<Boolean> ok = roHandler.makeWritable(ReadOnlyAxis.anyAxis(), filesToCheckForLockArray);
if(!ok.get()) {
return Status.CANCEL_STATUS;
}
@@ -115,7 +118,7 @@ public class ReadOnlyOneFileApprover implements IOperationApprover2 {
}
if (editingDomain == null && command instanceof ICompositeCommand) {
- Iterator it = ((ICompositeCommand)command).iterator();
+ Iterator<?> it = ((ICompositeCommand)command).iterator();
while (editingDomain == null && it.hasNext()) {
IUndoableOperation c = (IUndoableOperation)it.next();
editingDomain = getEditingDomain(c);
@@ -134,9 +137,10 @@ public class ReadOnlyOneFileApprover implements IOperationApprover2 {
* IStatus of the CommandResult that will be set on the
* command
*/
+ @SuppressWarnings("restriction")
protected void setCommandResult(ICommand command, IStatus status) {
- if(command instanceof ICommandWithSettableResult) {
- ((ICommandWithSettableResult)command).internalSetResult(new CommandResult(status));
+ if(command instanceof org.eclipse.gmf.runtime.common.core.internal.command.ICommandWithSettableResult) {
+ ((org.eclipse.gmf.runtime.common.core.internal.command.ICommandWithSettableResult)command).internalSetResult(new CommandResult(status));
}
}
@@ -147,7 +151,9 @@ public class ReadOnlyOneFileApprover implements IOperationApprover2 {
protected Set<IFile> getAffectedFiles(IUndoableOperation operation, Set<IFile> result) {
if(operation instanceof ICommand) {
- result = appendFiles(result, ((ICommand)operation).getAffectedFiles());
+ @SuppressWarnings("unchecked")
+ Collection<IFile> files = ((ICommand)operation).getAffectedFiles();
+ result = appendFiles(result, files);
} else if(operation instanceof GMFtoEMFCommandWrapper) {
result = getAffectedFiles(((GMFtoEMFCommandWrapper)operation).getGMFCommand(), result);
} else if(operation instanceof EMFCommandOperation) {
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyTester.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyTester.java
index eaef7d7c325..8ffdca3198a 100644
--- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyTester.java
+++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyTester.java
@@ -11,6 +11,7 @@
* Mathieu Velten (Atos Origin) mathieu.velten@atosorigin.com - Initial API and implementation
* Christian W. Damus (CEA) - Support read-only state at object level (CDO)
* Christian W. Damus (CEA) - bug 323802
+ * Christian W. Damus (CEA) - bug 429826
*
*****************************************************************************/
package org.eclipse.papyrus.infra.emf.readonly;
@@ -19,12 +20,12 @@ import java.util.Iterator;
import org.eclipse.core.expressions.PropertyTester;
import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.resource.Resource;
-import org.eclipse.emf.workspace.WorkspaceEditingDomainFactory;
+import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler;
import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler2;
+import org.eclipse.papyrus.infra.core.resource.ReadOnlyAxis;
import org.eclipse.papyrus.infra.emf.utils.BusinessModelResolver;
+import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import com.google.common.base.Objects;
@@ -59,9 +60,9 @@ public class ReadOnlyTester extends PropertyTester {
if(businessObject instanceof EObject) {
EObject eObject = (EObject)businessObject;
- Resource resource = eObject.eResource();
- if((resource != null) && (resource.getResourceSet() != null)) {
- return Objects.equal(ReadOnlyManager.getReadOnlyHandler(WorkspaceEditingDomainFactory.INSTANCE.getEditingDomain(resource.getResourceSet())).isReadOnly(eObject).get(), expectedValue);
+ EditingDomain domain = EMFHelper.resolveEditingDomain(eObject);
+ if(domain != null) {
+ return Objects.equal(ReadOnlyManager.getReadOnlyHandler(domain).isReadOnly(ReadOnlyAxis.anyAxis(), eObject).or(false), expectedValue);
}
}
}
@@ -75,11 +76,13 @@ public class ReadOnlyTester extends PropertyTester {
if(businessObject instanceof EObject) {
EObject eObject = (EObject)businessObject;
- Resource resource = eObject.eResource();
- if((resource != null) && (resource.getResourceSet() != null)) {
- IReadOnlyHandler handler = ReadOnlyManager.getReadOnlyHandler(WorkspaceEditingDomainFactory.INSTANCE.getEditingDomain(resource.getResourceSet()));
- boolean isAlreadyOrCanMakeWritable = !handler.isReadOnly(eObject).or(false) //
- || ((handler instanceof IReadOnlyHandler2) && ((IReadOnlyHandler2)handler).canMakeWritable(eObject).or(false));
+ EditingDomain domain = EMFHelper.resolveEditingDomain(eObject);
+ if(domain != null) {
+ IReadOnlyHandler2 handler = ReadOnlyManager.getReadOnlyHandler(domain);
+
+ boolean isAlreadyOrCanMakeWritable = !handler.isReadOnly(ReadOnlyAxis.anyAxis(), eObject).or(false) //
+ || handler.canMakeWritable(ReadOnlyAxis.anyAxis(), eObject).or(false);
+
return Objects.equal(isAlreadyOrCanMakeWritable, expectedValue);
}
}
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 6d909461712..8d55efe222f 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,8 +22,10 @@ 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.resource.IReadOnlyHandler;
+import org.eclipse.papyrus.infra.core.resource.AbstractReadOnlyHandler;
+import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler2;
import org.eclipse.papyrus.infra.core.resource.ModelSet;
+import org.eclipse.papyrus.infra.core.resource.ReadOnlyAxis;
import org.eclipse.papyrus.infra.emf.readonly.internal.messages.Messages;
import org.eclipse.swt.widgets.Display;
@@ -32,8 +34,8 @@ import com.google.common.base.Optional;
/**
- * A {@linkplain IReadOnlyHandler read-only handler} for objects in referenced models, which by default shouldn't be editable in the context of the
- * model referencing them.
+ * 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.
*/
public class ReferencedModelReadOnlyHandler extends AbstractReadOnlyHandler {
@@ -68,95 +70,102 @@ public class ReferencedModelReadOnlyHandler extends AbstractReadOnlyHandler {
this.interactive = interactive;
}
- public Optional<Boolean> anyReadOnly(URI[] uris) {
+ public Optional<Boolean> anyReadOnly(Set<ReadOnlyAxis> axes, URI[] uris) {
Optional<Boolean> result = Optional.absent();
- 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(axes.contains(ReadOnlyAxis.DISCRETION)) {
+ final URIConverter converter = getEditingDomain().getResourceSet().getURIConverter();
- // 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)) {
- result = Optional.of(true);
- break;
+ 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)) {
+ result = Optional.of(true);
+ break;
+ }
}
}
-
+
return result;
}
@Override
- public Optional<Boolean> canMakeWritable(URI[] uris) {
+ public Optional<Boolean> canMakeWritable(Set<ReadOnlyAxis> axes, URI[] uris) {
Optional<Boolean> result = Optional.absent();
- 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 {
- // If it's not something I handle, then bomb
- result = Optional.of(false);
- break;
+ if(axes.contains(ReadOnlyAxis.DISCRETION)) {
+ 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 {
+ // If it's not something I handle, then bomb
+ result = Optional.of(false);
+ break;
+ }
}
}
-
+
return result;
}
- public Optional<Boolean> makeWritable(URI[] uris) {
+ public Optional<Boolean> makeWritable(Set<ReadOnlyAxis> axes, URI[] uris) {
Optional<Boolean> result = Optional.absent();
- 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(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.getCurrent().syncExec(new Runnable() {
-
- public void run() {
- StringBuilder message = new StringBuilder(Messages.ReferencedModelReadOnlyHandler_promptMsg);
- for(URI uri : toMakeWritable) {
- String path;
- if(uri.isPlatformResource()) {
- path = uri.toPlatformString(true);
- } else if(uri.isFile()) {
- path = uri.toFileString();
- } else {
- path = uri.toString();
+
+ if(!toMakeWritable.isEmpty()) {
+ final boolean[] enableWrite = { !isInteractive() };
+
+ if(isInteractive()) {
+ Display.getCurrent().syncExec(new Runnable() {
+
+ public void run() {
+ StringBuilder message = new StringBuilder(Messages.ReferencedModelReadOnlyHandler_promptMsg);
+ for(URI uri : toMakeWritable) {
+ String path;
+ if(uri.isPlatformResource()) {
+ path = uri.toPlatformString(true);
+ } else if(uri.isFile()) {
+ path = uri.toFileString();
+ } else {
+ path = uri.toString();
+ }
+
+ message.append(path);
+ message.append("\n"); //$NON-NLS-1$
}
-
- message.append(path);
- message.append("\n"); //$NON-NLS-1$
+ enableWrite[0] = MessageDialog.openConfirm(Display.getCurrent().getActiveShell(), Messages.ReferencedModelReadOnlyHandler_promptTitle, message.toString());
}
- enableWrite[0] = MessageDialog.openConfirm(Display.getCurrent().getActiveShell(), Messages.ReferencedModelReadOnlyHandler_promptTitle, message.toString());
+ });
+ }
+
+ if(enableWrite[0]) {
+ for(URI next : toMakeWritable) {
+ readableReferencedModels.add(next.trimFileExtension());
+ fireReadOnlyStateChanged(ReadOnlyAxis.DISCRETION, next, true);
}
- });
- }
-
- if(enableWrite[0]) {
- for(URI next : toMakeWritable) {
- readableReferencedModels.add(next.trimFileExtension());
}
+
+ result = Optional.of(enableWrite[0]);
}
-
- result = Optional.of(enableWrite[0]);
}
-
+
return result;
}
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/SashModelReadOnlyHandler.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/SashModelReadOnlyHandler.java
index bf0a1a1a086..260ec8e371a 100644
--- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/SashModelReadOnlyHandler.java
+++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/SashModelReadOnlyHandler.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2014 CEA LIST.
+ * Copyright (c) 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,12 +8,18 @@
*
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 429826
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.emf.readonly;
+import java.util.Set;
+
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.edit.domain.EditingDomain;
+import org.eclipse.papyrus.infra.core.resource.AbstractReadOnlyHandler;
import org.eclipse.papyrus.infra.core.resource.ModelSet;
+import org.eclipse.papyrus.infra.core.resource.ReadOnlyAxis;
import org.eclipse.papyrus.infra.core.resource.sasheditor.DiModel;
import org.eclipse.papyrus.infra.core.resource.sasheditor.SashModel;
@@ -25,7 +31,9 @@ import com.google.common.base.Optional;
* If the model is located in the user preferences space, it may be considered
* read-only by other read-only handlers, whereas it shouldn't.
*
- * Its priority should be greater than EMFReadOnlyHandler, FSReadOnlyHandler and
+ * Its priority should be greater than EMFReadOnlyHandler, FSReadOnlyHandler and ...
+ *
+ * This handler is discretion-based.
*
* @author Camille Letavernier
*
@@ -45,28 +53,26 @@ public class SashModelReadOnlyHandler extends AbstractReadOnlyHandler {
/**
* {@inheritDoc}
*/
- public Optional<Boolean> anyReadOnly(URI[] uris) {
- if(modelSet == null) {
+ public Optional<Boolean> anyReadOnly(Set<ReadOnlyAxis> axes, URI[] uris) {
+ if((modelSet == null) || !axes.contains(ReadOnlyAxis.DISCRETION)) {
return Optional.absent();
}
+ // Only answer false if all of the resources in question are ones that we know must be allowed to be written
+ int knownWritableCount = 0;
for(URI uri : uris) {
- if(SashModel.SASH_MODEL_FILE_EXTENSION.equals(uri.fileExtension())) {
- return Optional.of(false);
- }
-
- if(DiModel.DI_FILE_EXTENSION.equals(uri.fileExtension())) {
- return Optional.of(false);
+ if(SashModel.SASH_MODEL_FILE_EXTENSION.equals(uri.fileExtension()) || DiModel.DI_FILE_EXTENSION.equals(uri.fileExtension())) {
+ knownWritableCount++;
}
}
- return Optional.absent();
+ return (knownWritableCount == uris.length) ? Optional.of(false) : Optional.<Boolean> absent();
}
/**
* {@inheritDoc}
*/
- public Optional<Boolean> makeWritable(URI[] uris) {
+ public Optional<Boolean> makeWritable(Set<ReadOnlyAxis> axes, URI[] uris) {
return Optional.absent(); //If the file is read-only, it can probably made writable by other read-only handlers (e.g. FSReadOnlyHandler).
}
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/handlers/EnableWriteCommandHandler.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/handlers/EnableWriteCommandHandler.java
index 8d6dd98630c..8f736f64fa6 100644
--- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/handlers/EnableWriteCommandHandler.java
+++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly/src/org/eclipse/papyrus/infra/emf/readonly/handlers/EnableWriteCommandHandler.java
@@ -9,6 +9,7 @@
* Contributors:
* Mathieu Velten (Atos Origin) mathieu.velten@atosorigin.com - Initial API and implementation
* Christian W. Damus (CEA) - bug 323802
+ * Christian W. Damus (CEA) - bug 429826
*
*****************************************************************************/
package org.eclipse.papyrus.infra.emf.readonly.handlers;
@@ -27,6 +28,7 @@ import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.workspace.WorkspaceEditingDomainFactory;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.papyrus.infra.core.resource.ReadOnlyAxis;
import org.eclipse.papyrus.infra.emf.readonly.ReadOnlyManager;
import org.eclipse.papyrus.infra.emf.utils.BusinessModelResolver;
import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
@@ -53,8 +55,7 @@ public class EnableWriteCommandHandler extends AbstractHandler {
associatedUris[i] = URI.createPlatformResourceURI(associatedFiles[i].getFullPath().toString(), true);
}
- ReadOnlyManager.getReadOnlyHandler(WorkspaceEditingDomainFactory.INSTANCE.getEditingDomain(rs))
- .makeWritable(associatedUris);
+ ReadOnlyManager.getReadOnlyHandler(WorkspaceEditingDomainFactory.INSTANCE.getEditingDomain(rs)).makeWritable(ReadOnlyAxis.anyAxis(), associatedUris);
}
}
return null;
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/utils/EMFHelper.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/utils/EMFHelper.java
index 3abfeb91979..e522cff9c02 100644
--- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/utils/EMFHelper.java
+++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/utils/EMFHelper.java
@@ -11,6 +11,7 @@
* Christian W. Damus (CEA) - filter out EObjects that are Resources (CDO)
* Christian W. Damus (CEA) - Support read-only state at object level (CDO)
* Christian W. Damus (CEA) - bug 323802
+ * Christian W. Damus (CEA) - bug 429826
*
*****************************************************************************/
package org.eclipse.papyrus.infra.emf.utils;
@@ -49,6 +50,7 @@ import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.facet.custom.ui.CustomizedContentProviderUtils;
import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler;
import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler2;
+import org.eclipse.papyrus.infra.core.resource.ReadOnlyAxis;
import org.eclipse.papyrus.infra.core.services.ServiceException;
import org.eclipse.papyrus.infra.core.utils.ServiceUtilsForActionHandlers;
import org.eclipse.papyrus.infra.emf.Activator;
@@ -431,33 +433,66 @@ public class EMFHelper {
}
/**
- * Tests if an EObject is read only
+ * Tests if an EObject is read only on any {@linkplain ReadOnlyAxis axis}.
* Delegates to the EObject's editing domain if it can be found
*
* @param eObject
* @return
- * True if the EObject is read only
+ * True if the EObject is read only on any axis
+ * @see #isReadOnly(Set, EObject, EditingDomain)
*/
public static boolean isReadOnly(final EObject eObject) {
+ return isReadOnly(ReadOnlyAxis.anyAxis(), eObject);
+ }
+
+ /**
+ * Tests if an EObject is read only on any of the specified {@code axes}.
+ * Delegates to the EObject's editing domain if it can be found
+ *
+ * @param axes
+ * a set if orthogonal axes of read-only-ness to consider. May be empty, but that would not be especially useful
+ * @param eObject
+ * @return
+ * True if the EObject is read only on any of the given {@code axes}
+ */
+ public static boolean isReadOnly(Set<ReadOnlyAxis> axes, final EObject eObject) {
EditingDomain domain = resolveEditingDomain(eObject);
- return isReadOnly(eObject, domain);
+ return isReadOnly(axes, eObject, domain);
}
/**
- * Tests if an EObject is read only
+ * Tests if an EObject is read only on any {@linkplain ReadOnlyAxis axis}.
* Delegates to the given editing domain if it isn't null
*
* @param eObject
+ * @param domain
+ * @return
+ * True if the EObject is read only on any axis
+ */
+ public static boolean isReadOnly(final EObject eObject, final EditingDomain domain) {
+ return isReadOnly(ReadOnlyAxis.anyAxis(), eObject, domain);
+ }
+
+ /**
+ * Tests if an EObject is read only on any of the specified {@code axes}.
+ * Delegates to the given editing domain if it isn't null
+ *
+ * @param axes
+ * a set if orthogonal axes of read-only-ness to consider. May be empty, but that would not be especially useful
+ * @param eObject
*
* @param domain
* @return
* True if the EObject is read only
*/
- public static boolean isReadOnly(final EObject eObject, final EditingDomain domain) {
+ public static boolean isReadOnly(Set<ReadOnlyAxis> axes, final EObject eObject, final EditingDomain domain) {
if(domain != null) {
Object handler = PlatformHelper.getAdapter(domain, IReadOnlyHandler.class);
- if(handler instanceof IReadOnlyHandler) {
- return ((IReadOnlyHandler)handler).isReadOnly(eObject).get();
+ if(handler instanceof IReadOnlyHandler2) {
+ return ((IReadOnlyHandler2)handler).isReadOnly(axes, eObject).get();
+ }else if(handler instanceof IReadOnlyHandler) {
+ // these handlers only deal with permission-based read-only-ness
+ return axes.contains(ReadOnlyAxis.PERMISSION) && ((IReadOnlyHandler)handler).isReadOnly(eObject).get();
}
if(eObject.eResource() != null) {
@@ -468,23 +503,41 @@ public class EMFHelper {
}
/**
- * Tests if the Resource is read only
+ * Tests if the Resource is read only on any {@linkplain ReadOnlyAxis axis}.
* Delegates to the given editing domain if it isn't null
*
* @param resource
* @param domain
* @return
- * True if the Resource is read only
+ * True if the Resource is read only on any axis
*/
public static boolean isReadOnly(final Resource resource, final EditingDomain domain) {
+ return isReadOnly(ReadOnlyAxis.anyAxis(), resource, domain);
+ }
+
+ /**
+ * Tests if the Resource is read only on any of the given {@code axes}.
+ * Delegates to the given editing domain if it isn't null
+ *
+ * @param axes
+ * a set if orthogonal axes of read-only-ness to consider. May be empty, but that would not be especially useful
+ * @param resource
+ * @param domain
+ * @return
+ * True if the Resource is read only on any of the given {@code axes}
+ */
+ public static boolean isReadOnly(Set<ReadOnlyAxis> axes, final Resource resource, final EditingDomain domain) {
if(resource == null) {
return false;
}
if(domain != null && resource.getURI() != null) {
Object handler = PlatformHelper.getAdapter(domain, IReadOnlyHandler.class);
- if(handler instanceof IReadOnlyHandler) {
- return ((IReadOnlyHandler)handler).anyReadOnly(new URI[]{ resource.getURI() }).get();
+ if(handler instanceof IReadOnlyHandler2) {
+ return ((IReadOnlyHandler2)handler).anyReadOnly(axes, new URI[]{ resource.getURI() }).get();
+ } else if(handler instanceof IReadOnlyHandler) {
+ // these handlers only deal with permission-based read-only-ness
+ return axes.contains(ReadOnlyAxis.PERMISSION) && ((IReadOnlyHandler)handler).anyReadOnly(new URI[]{ resource.getURI() }).get();
}
return domain.isReadOnly(resource);
}
@@ -514,10 +567,27 @@ public class EMFHelper {
* whether the {@code eObject} could be made writable
*/
public static boolean canMakeWritable(final EObject eObject, final EditingDomain domain) {
+ return canMakeWritable(ReadOnlyAxis.anyAxis(), eObject, domain);
+ }
+
+ /**
+ * Tests if an object that is read only could possibly be made writable according to any of
+ * the specified {@code axes} of read-only-ness.
+ *
+ * @param axes
+ * a set if orthogonal axes of read-only-ness to consider. May be empty, but that would not be especially useful
+ * @param eObject
+ * an object that is assumed to be read-only
+ * @param domain
+ * the editing domain context of the {@link eObject}
+ * @return
+ * whether the {@code eObject} could be made writable
+ */
+ public static boolean canMakeWritable(Set<ReadOnlyAxis> axes, final EObject eObject, final EditingDomain domain) {
if(domain != null) {
Object handler = PlatformHelper.getAdapter(domain, IReadOnlyHandler.class);
if(handler instanceof IReadOnlyHandler2) {
- return ((IReadOnlyHandler2)handler).canMakeWritable(eObject).or(false);
+ return ((IReadOnlyHandler2)handler).canMakeWritable(axes, eObject).or(false);
}
}
return false;
@@ -535,10 +605,27 @@ public class EMFHelper {
* whether the {@code resource} could be made writable
*/
public static boolean canMakeWritable(final Resource resource, final EditingDomain domain) {
+ return canMakeWritable(ReadOnlyAxis.anyAxis(), resource, domain);
+ }
+
+ /**
+ * Tests if a resource that is read only could possibly be made writable according to any of
+ * the specified {@code axes} of read-only-ness.
+ *
+ * @param axes
+ * a set if orthogonal axes of read-only-ness to consider. May be empty, but that would not be especially useful
+ * @param resource
+ * a resource that is assumed to be read-only
+ * @param domain
+ * the editing domain context of the {@link resource}
+ * @return
+ * whether the {@code resource} could be made writable
+ */
+ public static boolean canMakeWritable(Set<ReadOnlyAxis> axes, final Resource resource, final EditingDomain domain) {
if(domain != null) {
Object handler = PlatformHelper.getAdapter(domain, IReadOnlyHandler.class);
if(handler instanceof IReadOnlyHandler2) {
- return ((IReadOnlyHandler2)handler).canMakeWritable(new URI[] { resource.getURI() }).or(false);
+ return ((IReadOnlyHandler2)handler).canMakeWritable(axes, new URI[] { resource.getURI() }).or(false);
}
}
return false;

Back to the top