Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--extraplugins/cdo/org.eclipse.papyrus.cdo.core/plugin.xml3
-rw-r--r--extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/core/resource/CDOReadOnlyHandler.java40
-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
-rw-r--r--plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/handlers/DeleteFromModelCommandHandler.java10
-rw-r--r--plugins/uml/org.eclipse.papyrus.uml.controlmode.profile/plugin.xml3
-rw-r--r--plugins/uml/org.eclipse.papyrus.uml.controlmode.profile/src/org/eclipse/papyrus/uml/controlmode/profile/ControlledElementReadOnlyHandler.java16
-rw-r--r--plugins/uml/org.eclipse.papyrus.uml.modelrepair/src/org/eclipse/papyrus/uml/modelrepair/ui/SwitchProfileDialog.java11
-rw-r--r--plugins/uml/org.eclipse.papyrus.uml.modelrepair/src/org/eclipse/papyrus/uml/modelrepair/ui/providers/ResourceLabelProvider.java14
-rw-r--r--plugins/uml/org.eclipse.papyrus.uml.profile/plugin.xml3
-rw-r--r--plugins/uml/org.eclipse.papyrus.uml.profile/src/org/eclipse/papyrus/uml/profile/readonly/AppliedProfileReadOnlyHandler.java19
-rw-r--r--plugins/views/modelexplorer/org.eclipse.papyrus.views.modelexplorer/src/org/eclipse/papyrus/views/modelexplorer/ModelExplorerView.java37
-rw-r--r--tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/src/org/eclipse/papyrus/cdo/core/resource/tests/CDOAwareModelSetTest.java4
-rw-r--r--tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/Bug323802.uml3
-rw-r--r--tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/PapyrusROTransactionalEditingDomainTest.java64
-rw-r--r--tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyManagerTest.java88
-rw-r--r--tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyTesterTest.java88
-rw-r--r--tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/ReferencedModelReadOnlyHandlerTest.java15
-rw-r--r--tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/tests/AllTests.java3
-rw-r--r--tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/tests/PapyrusModelSetFixture.java82
-rw-r--r--tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/tests/PapyrusROEditingDomainFixture.java33
-rw-r--r--tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/AbstractModelFixture.java187
-rw-r--r--tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/JavaResource.java32
-rw-r--r--tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PluginResource.java32
-rw-r--r--tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/ProjectFixture.java39
45 files changed, 2187 insertions, 560 deletions
diff --git a/extraplugins/cdo/org.eclipse.papyrus.cdo.core/plugin.xml b/extraplugins/cdo/org.eclipse.papyrus.cdo.core/plugin.xml
index c3a91523985..4da738bd7f5 100644
--- a/extraplugins/cdo/org.eclipse.papyrus.cdo.core/plugin.xml
+++ b/extraplugins/cdo/org.eclipse.papyrus.cdo.core/plugin.xml
@@ -67,6 +67,9 @@
<readOnlyHandler
class="org.eclipse.papyrus.cdo.core.resource.CDOReadOnlyHandler"
priority="16">
+ <affinity
+ axis="permission">
+ </affinity>
</readOnlyHandler>
</extension>
diff --git a/extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/core/resource/CDOReadOnlyHandler.java b/extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/core/resource/CDOReadOnlyHandler.java
index 92498ce468f..08886591c1a 100644
--- a/extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/core/resource/CDOReadOnlyHandler.java
+++ b/extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/core/resource/CDOReadOnlyHandler.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2013 CEA LIST.
+ * Copyright (c) 2013, 2014 CEA LIST and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,21 +8,26 @@
*
* Contributors:
* CEA LIST - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 429826
+ *
*****************************************************************************/
package org.eclipse.papyrus.cdo.core.resource;
+import java.util.Set;
+
import org.eclipse.emf.cdo.CDOObject;
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.cdo.internal.core.CDOUtils;
-import org.eclipse.papyrus.infra.emf.readonly.AbstractReadOnlyHandler;
+import org.eclipse.papyrus.infra.core.resource.AbstractReadOnlyHandler;
+import org.eclipse.papyrus.infra.core.resource.ReadOnlyAxis;
import com.google.common.base.Optional;
/**
- * This is the CDOReadOnlyHandler type. Enjoy.
+ * The CDO read handler is permission-based.
*/
public class CDOReadOnlyHandler extends AbstractReadOnlyHandler {
@@ -30,10 +35,11 @@ public class CDOReadOnlyHandler extends AbstractReadOnlyHandler {
super(editingDomain);
}
- public Optional<Boolean> anyReadOnly(URI[] uris) {
+ @Override
+ public Optional<Boolean> anyReadOnly(Set<ReadOnlyAxis> axes, URI[] uris) {
Optional<Boolean> result = Optional.absent();
- if((uris.length > 0) && CDOUtils.isCDOEditingDomain(getEditingDomain())) {
+ if(axes.contains(ReadOnlyAxis.PERMISSION) && (uris.length > 0) && CDOUtils.isCDOEditingDomain(getEditingDomain())) {
for(int i = 0; !result.or(Boolean.FALSE) && (i < uris.length); i++) {
// if it's a cdo:// URI, then I have a definitive answer
if(CDOUtils.isCDOURI(uris[i])) {
@@ -57,31 +63,31 @@ public class CDOReadOnlyHandler extends AbstractReadOnlyHandler {
}
@Override
- public Optional<Boolean> isReadOnly(EObject eObject) {
-
+ public Optional<Boolean> isReadOnly(Set<ReadOnlyAxis> axes, EObject eObject) {
Optional<Boolean> result = Optional.absent();
- Resource resource = eObject.eResource();
- if((resource == null) || CDOUtils.isCDOURI(resource.getURI())) {
- CDOObject cdo = CDOUtils.getCDOObject(eObject);
- if(cdo != null) {
- // I have a definitive answer for CDO objects
- result = Optional.of(CDOUtils.isReadOnly(cdo));
+ if(axes.contains(ReadOnlyAxis.PERMISSION)) {
+ Resource resource = eObject.eResource();
+ if((resource == null) || CDOUtils.isCDOURI(resource.getURI())) {
+ CDOObject cdo = CDOUtils.getCDOObject(eObject);
+ if(cdo != null) {
+ // I have a definitive answer for CDO objects
+ result = Optional.of(CDOUtils.isReadOnly(cdo));
+ }
}
}
return result;
}
- public Optional<Boolean> makeWritable(URI[] uris) {
-
+ @Override
+ public Optional<Boolean> makeWritable(Set<ReadOnlyAxis> axes, URI[] uris) {
// CDO requires the administrative UI to edit user permissions
return Optional.absent();
}
@Override
- public Optional<Boolean> makeWritable(EObject eObject) {
-
+ public Optional<Boolean> makeWritable(Set<ReadOnlyAxis> axes, EObject eObject) {
// CDO requires the administrative UI to edit user permissions
return Optional.absent();
}
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;
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/handlers/DeleteFromModelCommandHandler.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/handlers/DeleteFromModelCommandHandler.java
index 5fe91cae260..8c4aac11912 100644
--- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/handlers/DeleteFromModelCommandHandler.java
+++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.common/src/org/eclipse/papyrus/uml/diagram/common/handlers/DeleteFromModelCommandHandler.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2010 CEA LIST.
+ * Copyright (c) 2010, 2014 CEA LIST and others.
*
*
* All rights reserved. This program and the accompanying materials
@@ -9,6 +9,7 @@
*
* Contributors:
* Yann Tanguy (CEA LIST) yann.tanguy@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 429826
*
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.common.handlers;
@@ -37,7 +38,8 @@ import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialogWithToggle;
import org.eclipse.jface.preference.IPreferenceStore;
-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.readonly.ReadOnlyManager;
import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.infra.gmfdiag.common.helper.NotationHelper;
@@ -94,7 +96,7 @@ public class DeleteFromModelCommandHandler extends GraphicalCommandHandler imple
@Override
protected boolean computeEnabled() {
TransactionalEditingDomain editingDomain = getEditingDomain();
- IReadOnlyHandler readOnly = ReadOnlyManager.getReadOnlyHandler(editingDomain);
+ IReadOnlyHandler2 readOnly = ReadOnlyManager.getReadOnlyHandler(editingDomain);
for(IGraphicalEditPart editPart : getSelectedElements()) {
EObject semantic = EMFHelper.getEObject(editPart);
@@ -117,7 +119,7 @@ public class DeleteFromModelCommandHandler extends GraphicalCommandHandler imple
uris.add(EcoreUtil.getURI(graphical));
}
- Optional<Boolean> result = readOnly.anyReadOnly(uris.toArray(new URI[uris.size()]));
+ Optional<Boolean> result = readOnly.anyReadOnly(ReadOnlyAxis.anyAxis(), uris.toArray(new URI[uris.size()]));
if(result.isPresent() && result.get()) {
return false;
}
diff --git a/plugins/uml/org.eclipse.papyrus.uml.controlmode.profile/plugin.xml b/plugins/uml/org.eclipse.papyrus.uml.controlmode.profile/plugin.xml
index 69fb1520f38..29bd6891f6f 100644
--- a/plugins/uml/org.eclipse.papyrus.uml.controlmode.profile/plugin.xml
+++ b/plugins/uml/org.eclipse.papyrus.uml.controlmode.profile/plugin.xml
@@ -48,6 +48,9 @@
class="org.eclipse.papyrus.uml.controlmode.profile.ControlledElementReadOnlyHandler"
id="org.eclipse.papyrus.uml.controlmode.profile.ControlledElementReadOnlyHandler"
priority="50">
+ <affinity
+ axis="discretion">
+ </affinity>
</readOnlyHandler>
</extension>
diff --git a/plugins/uml/org.eclipse.papyrus.uml.controlmode.profile/src/org/eclipse/papyrus/uml/controlmode/profile/ControlledElementReadOnlyHandler.java b/plugins/uml/org.eclipse.papyrus.uml.controlmode.profile/src/org/eclipse/papyrus/uml/controlmode/profile/ControlledElementReadOnlyHandler.java
index 78020d006ce..cbd577fa771 100644
--- a/plugins/uml/org.eclipse.papyrus.uml.controlmode.profile/src/org/eclipse/papyrus/uml/controlmode/profile/ControlledElementReadOnlyHandler.java
+++ b/plugins/uml/org.eclipse.papyrus.uml.controlmode.profile/src/org/eclipse/papyrus/uml/controlmode/profile/ControlledElementReadOnlyHandler.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2013 Atos.
+ * Copyright (c) 2013, 2014 Atos, CEA, and others.
*
*
* All rights reserved. This program and the accompanying materials
@@ -9,16 +9,20 @@
*
* Contributors:
* Arthur Daussy (Atos) arthur.daussy@atos.net - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 429826
*
*****************************************************************************/
package org.eclipse.papyrus.uml.controlmode.profile;
+import java.util.Set;
+
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.edit.domain.EditingDomain;
-import org.eclipse.papyrus.infra.emf.readonly.AbstractReadOnlyHandler;
+import org.eclipse.papyrus.infra.core.resource.AbstractReadOnlyHandler;
+import org.eclipse.papyrus.infra.core.resource.ReadOnlyAxis;
import org.eclipse.papyrus.infra.widgets.toolbox.notification.builders.NotificationBuilder;
import org.eclipse.papyrus.uml.tools.model.UmlModel;
import org.eclipse.uml2.uml.Element;
@@ -30,7 +34,7 @@ import com.google.common.base.Optional;
/**
* Read only handler that will prevent model fragment to be modified it the root element is not a package
* This restriction is because of the UML2 implementation which delete stereotype applications if the current model can not find the corresponding profile
- * application
+ * application. This handler is discretion-based.
*
* @author adaussy
*
@@ -41,8 +45,8 @@ public class ControlledElementReadOnlyHandler extends AbstractReadOnlyHandler {
super(editingDomain);
}
- public Optional<Boolean> anyReadOnly(URI[] uris) {
- if(getEditingDomain() == null) {
+ public Optional<Boolean> anyReadOnly(Set<ReadOnlyAxis> axes, URI[] uris) {
+ if((getEditingDomain() == null) || !axes.contains(ReadOnlyAxis.DISCRETION)) {
return Optional.absent();
}
ResourceSet resourceSet = getEditingDomain().getResourceSet();
@@ -65,7 +69,7 @@ public class ControlledElementReadOnlyHandler extends AbstractReadOnlyHandler {
return Optional.absent();
}
- public Optional<Boolean> makeWritable(URI[] uris) {
+ public Optional<Boolean> makeWritable(Set<ReadOnlyAxis> axes, URI[] uris) {
//Never authorize write
NotificationBuilder.createErrorPopup("This model fragment can not be modified independently from the rest of the model").run();
return Optional.absent();
diff --git a/plugins/uml/org.eclipse.papyrus.uml.modelrepair/src/org/eclipse/papyrus/uml/modelrepair/ui/SwitchProfileDialog.java b/plugins/uml/org.eclipse.papyrus.uml.modelrepair/src/org/eclipse/papyrus/uml/modelrepair/ui/SwitchProfileDialog.java
index a172fb66fa7..b19b4395a4c 100644
--- a/plugins/uml/org.eclipse.papyrus.uml.modelrepair/src/org/eclipse/papyrus/uml/modelrepair/ui/SwitchProfileDialog.java
+++ b/plugins/uml/org.eclipse.papyrus.uml.modelrepair/src/org/eclipse/papyrus/uml/modelrepair/ui/SwitchProfileDialog.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2013 CEA LIST.
+ * Copyright (c) 2013, 2014 CEA LIST and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,6 +8,8 @@
*
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 429826
+ *
*****************************************************************************/
package org.eclipse.papyrus.uml.modelrepair.ui;
@@ -47,8 +49,9 @@ import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.window.Window;
-import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler;
+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.core.services.ServiceException;
import org.eclipse.papyrus.infra.emf.readonly.ReadOnlyManager;
import org.eclipse.papyrus.infra.emf.resource.DependencyManagementHelper;
@@ -306,9 +309,9 @@ public class SwitchProfileDialog extends SelectionDialog {
}
});
- IReadOnlyHandler handler = ReadOnlyManager.getReadOnlyHandler(editingDomain);
+ IReadOnlyHandler2 handler = ReadOnlyManager.getReadOnlyHandler(editingDomain);
for(Resource resource : modelSet.getResources()) {
- if(handler.anyReadOnly(new URI[]{ resource.getURI() }).get()) {
+ if(handler.anyReadOnly(ReadOnlyAxis.anyAxis(), new URI[]{ resource.getURI() }).get()) {
continue;
}
try {
diff --git a/plugins/uml/org.eclipse.papyrus.uml.modelrepair/src/org/eclipse/papyrus/uml/modelrepair/ui/providers/ResourceLabelProvider.java b/plugins/uml/org.eclipse.papyrus.uml.modelrepair/src/org/eclipse/papyrus/uml/modelrepair/ui/providers/ResourceLabelProvider.java
index 8d507133d95..45c7f978125 100644
--- a/plugins/uml/org.eclipse.papyrus.uml.modelrepair/src/org/eclipse/papyrus/uml/modelrepair/ui/providers/ResourceLabelProvider.java
+++ b/plugins/uml/org.eclipse.papyrus.uml.modelrepair/src/org/eclipse/papyrus/uml/modelrepair/ui/providers/ResourceLabelProvider.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2013 CEA LIST.
+ * Copyright (c) 2013, 2014 CEA LIST and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,6 +8,8 @@
*
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 429826
+ *
*****************************************************************************/
package org.eclipse.papyrus.uml.modelrepair.ui.providers;
@@ -18,6 +20,7 @@ import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ViewerCell;
+import org.eclipse.papyrus.infra.core.resource.ReadOnlyAxis;
import org.eclipse.papyrus.infra.emf.readonly.ReadOnlyManager;
import org.eclipse.swt.graphics.Image;
@@ -75,13 +78,8 @@ public class ResourceLabelProvider extends ColumnLabelProvider {
}
EditingDomain domain = TransactionalEditingDomain.Factory.INSTANCE.getEditingDomain(resourceSet);
- Optional<Boolean> readOnly = ReadOnlyManager.getReadOnlyHandler(domain).anyReadOnly(new URI[]{ uri });
- if(readOnly.isPresent()) {
- return readOnly.get() ? "true" : "false";
- } else {
- return "false";
- }
-
+ Optional<Boolean> readOnly = ReadOnlyManager.getReadOnlyHandler(domain).anyReadOnly(ReadOnlyAxis.anyAxis(), new URI[]{ uri });
+ return readOnly.or(false) ? "true" : "false";
}
public String getResourceText(Object element) {
diff --git a/plugins/uml/org.eclipse.papyrus.uml.profile/plugin.xml b/plugins/uml/org.eclipse.papyrus.uml.profile/plugin.xml
index 38eaf4a5831..a9d6d447afd 100644
--- a/plugins/uml/org.eclipse.papyrus.uml.profile/plugin.xml
+++ b/plugins/uml/org.eclipse.papyrus.uml.profile/plugin.xml
@@ -115,6 +115,9 @@
class="org.eclipse.papyrus.uml.profile.readonly.AppliedProfileReadOnlyHandler"
id="org.eclipse.papyrus.uml.profile.readonly.AppliedProfileReadOnlyHandler"
priority="15">
+ <affinity
+ axis="discretion">
+ </affinity>
</readOnlyHandler>
</extension>
<extension
diff --git a/plugins/uml/org.eclipse.papyrus.uml.profile/src/org/eclipse/papyrus/uml/profile/readonly/AppliedProfileReadOnlyHandler.java b/plugins/uml/org.eclipse.papyrus.uml.profile/src/org/eclipse/papyrus/uml/profile/readonly/AppliedProfileReadOnlyHandler.java
index 6c13310f271..1c7da5f5ca6 100644
--- a/plugins/uml/org.eclipse.papyrus.uml.profile/src/org/eclipse/papyrus/uml/profile/readonly/AppliedProfileReadOnlyHandler.java
+++ b/plugins/uml/org.eclipse.papyrus.uml.profile/src/org/eclipse/papyrus/uml/profile/readonly/AppliedProfileReadOnlyHandler.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,28 +8,35 @@
*
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 429826
+ *
*****************************************************************************/
package org.eclipse.papyrus.uml.profile.readonly;
+import java.util.Set;
+
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
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.emf.readonly.AbstractReadOnlyHandler;
+import org.eclipse.papyrus.infra.core.resource.ReadOnlyAxis;
import org.eclipse.papyrus.uml.tools.model.UmlModel;
import org.eclipse.uml2.uml.Profile;
import com.google.common.base.Optional;
-
+/**
+ * Discretion-based read-only handler for applied profiles.
+ */
public class AppliedProfileReadOnlyHandler extends AbstractReadOnlyHandler {
public AppliedProfileReadOnlyHandler(EditingDomain editingDomain) {
super(editingDomain);
}
- public Optional<Boolean> anyReadOnly(URI[] uris) {
- if(getEditingDomain() != null) {
+ public Optional<Boolean> anyReadOnly(Set<ReadOnlyAxis> axes, URI[] uris) {
+ if((getEditingDomain() != null) && axes.contains(ReadOnlyAxis.DISCRETION)) {
Resource mainUmlResource = null;
if(getEditingDomain().getResourceSet() instanceof ModelSet) {
UmlModel umlModel = (UmlModel)((ModelSet)getEditingDomain().getResourceSet()).getModel(UmlModel.MODEL_ID);
@@ -62,7 +69,7 @@ public class AppliedProfileReadOnlyHandler extends AbstractReadOnlyHandler {
return false;
}
- public Optional<Boolean> makeWritable(URI[] uris) {
+ public Optional<Boolean> makeWritable(Set<ReadOnlyAxis> axes, URI[] uris) {
return Optional.absent(); //Applied profiles should remain read-only
}
diff --git a/plugins/views/modelexplorer/org.eclipse.papyrus.views.modelexplorer/src/org/eclipse/papyrus/views/modelexplorer/ModelExplorerView.java b/plugins/views/modelexplorer/org.eclipse.papyrus.views.modelexplorer/src/org/eclipse/papyrus/views/modelexplorer/ModelExplorerView.java
index 99c1a9cfbb3..ba00ac932ac 100644
--- a/plugins/views/modelexplorer/org.eclipse.papyrus.views.modelexplorer/src/org/eclipse/papyrus/views/modelexplorer/ModelExplorerView.java
+++ b/plugins/views/modelexplorer/org.eclipse.papyrus.views.modelexplorer/src/org/eclipse/papyrus/views/modelexplorer/ModelExplorerView.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2010, 2013 CEA LIST.
+ * Copyright (c) 2010, 2014 CEA LIST and others.
*
*
* All rights reserved. This program and the accompanying materials
@@ -10,6 +10,7 @@
* Contributors:
* Patrick Tessier (CEA LIST) Patrick.tessier@cea.fr - Initial API and implementation
* Christian W. Damus (CEA) - post refreshes for transaction commit asynchronously (CDO)
+ * Christian W. Damus (CEA) - bug 429826
*
*****************************************************************************/
package org.eclipse.papyrus.views.modelexplorer;
@@ -54,7 +55,10 @@ import org.eclipse.jface.window.ToolTip;
import org.eclipse.papyrus.infra.core.editor.IMultiDiagramEditor;
import org.eclipse.papyrus.infra.core.lifecycleevents.IEditorInputChangedListener;
import org.eclipse.papyrus.infra.core.lifecycleevents.ISaveAndDirtyService;
+import org.eclipse.papyrus.infra.core.resource.IReadOnlyHandler2;
+import org.eclipse.papyrus.infra.core.resource.IReadOnlyListener;
import org.eclipse.papyrus.infra.core.resource.ModelSet;
+import org.eclipse.papyrus.infra.core.resource.ReadOnlyEvent;
import org.eclipse.papyrus.infra.core.resource.additional.AdditionalResourcesModel;
import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageManager;
import org.eclipse.papyrus.infra.core.sasheditor.editor.IPage;
@@ -62,6 +66,7 @@ import org.eclipse.papyrus.infra.core.sasheditor.editor.IPageLifeCycleEventsList
import org.eclipse.papyrus.infra.core.sasheditor.editor.ISashWindowsContainer;
import org.eclipse.papyrus.infra.core.services.ServiceException;
import org.eclipse.papyrus.infra.core.services.ServicesRegistry;
+import org.eclipse.papyrus.infra.core.utils.AdapterUtils;
import org.eclipse.papyrus.infra.core.utils.ServiceUtils;
import org.eclipse.papyrus.infra.emf.providers.SemanticFromModelExplorer;
import org.eclipse.papyrus.infra.services.labelprovider.service.LabelProviderService;
@@ -726,6 +731,10 @@ public class ModelExplorerView extends CommonNavigator implements IRevealSemanti
getCommonViewer().setInput(serviceRegistry);
}
editingDomain.addResourceSetListener(resourceSetListener);
+ IReadOnlyHandler2 readOnlyHandler = AdapterUtils.adapt(editingDomain, IReadOnlyHandler2.class, null);
+ if (readOnlyHandler != null) {
+ readOnlyHandler.addReadOnlyListener(createReadOnlyListener());
+ }
} catch (ServiceException e) {
// Can't get EditingDomain, skip
}
@@ -1068,4 +1077,30 @@ public class ModelExplorerView extends CommonNavigator implements IRevealSemanti
//Nothing
}
+ private IReadOnlyListener createReadOnlyListener() {
+ return new IReadOnlyListener() {
+
+ public void readOnlyStateChanged(ReadOnlyEvent event) {
+ switch (event.getEventType()) {
+ case ReadOnlyEvent.RESOURCE_READ_ONLY_STATE_CHANGED:
+ if (!isRefreshing.get()) {
+ refresh();
+ }
+ break;
+ case ReadOnlyEvent.OBJECT_READ_ONLY_STATE_CHANGED:
+ CommonViewer viewer = getCommonViewer();
+ if ((viewer != null) && (viewer.getControl() != null) && !viewer.getControl().isDisposed()) {
+ viewer.refresh(event.getObject());
+ }
+ break;
+ default:
+ Activator.log.warn("Unsupported read-only event type: " + event.getEventType());
+ break;
+ }
+ if (!isRefreshing.get()) {
+ refresh();
+ }
+ }
+ };
+ }
}
diff --git a/tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/src/org/eclipse/papyrus/cdo/core/resource/tests/CDOAwareModelSetTest.java b/tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/src/org/eclipse/papyrus/cdo/core/resource/tests/CDOAwareModelSetTest.java
index 5d69a8cb927..27a69ac726b 100644
--- a/tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/src/org/eclipse/papyrus/cdo/core/resource/tests/CDOAwareModelSetTest.java
+++ b/tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/src/org/eclipse/papyrus/cdo/core/resource/tests/CDOAwareModelSetTest.java
@@ -9,6 +9,7 @@
* Contributors:
* CEA LIST - Initial API and implementation
* Christian W. Damus (CEA) - bug 429242
+ * Christian W. Damus (CEA) - bug 429826
*
*****************************************************************************/
package org.eclipse.papyrus.cdo.core.resource.tests;
@@ -38,6 +39,7 @@ import org.eclipse.papyrus.cdo.core.resource.PapyrusCDOResourceFactory;
import org.eclipse.papyrus.cdo.core.tests.AbstractPapyrusCDOTest;
import org.eclipse.papyrus.infra.core.Activator;
import org.eclipse.papyrus.infra.core.resource.ModelSet;
+import org.eclipse.papyrus.infra.core.resource.ReadOnlyAxis;
import org.eclipse.papyrus.infra.core.services.ExtensionServicesRegistry;
import org.eclipse.papyrus.infra.core.services.ServiceMultiException;
import org.eclipse.papyrus.infra.core.services.ServiceNotFoundException;
@@ -107,7 +109,7 @@ public class CDOAwareModelSetTest extends AbstractPapyrusCDOTest {
CDOTransaction transaction = getTransaction(fixture);
Resource resource = transaction.getOrCreateResource(getResourcePath(MODEL_FILENAME));
- assertThat(fixture.getReadOnlyHandler().anyReadOnly(new URI[]{ resource.getURI() }), is(Optional.of(false)));
+ assertThat(fixture.getReadOnlyHandler().anyReadOnly(ReadOnlyAxis.anyAxis(), new URI[]{ resource.getURI() }), is(Optional.of(false)));
}
@Test
diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/Bug323802.uml b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/Bug323802.uml
index cccdefe7e34..6c61fbbcb57 100644
--- a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/Bug323802.uml
+++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/Bug323802.uml
@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<uml:Model xmi:version="20110701" xmlns:xmi="http://www.omg.org/spec/XMI/20110701" xmlns:uml="http://www.eclipse.org/uml2/4.0.0/UML" xmi:id="_-3u4cJW3EeOfoK3RwHm3pQ" name="bug323802">
+ <packageImport xmi:id="_ycYPAKkTEeOizeYRjNFxJg">
+ <importedPackage xmi:type="uml:Model" href="pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#_0"/>
+ </packageImport>
<packagedElement xmi:type="uml:Class" xmi:id="_C3c2UJW4EeOfoK3RwHm3pQ" name="A" useCase="_0S-V8KYuEeO-ZNuEJamMWA"/>
<packagedElement xmi:type="uml:UseCase" xmi:id="_0S-V8KYuEeO-ZNuEJamMWA" name="DoIt" subject="_C3c2UJW4EeOfoK3RwHm3pQ"/>
</uml:Model>
diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/PapyrusROTransactionalEditingDomainTest.java b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/PapyrusROTransactionalEditingDomainTest.java
index 8cd46a7768c..808347fffcb 100644
--- a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/PapyrusROTransactionalEditingDomainTest.java
+++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/PapyrusROTransactionalEditingDomainTest.java
@@ -15,6 +15,7 @@ package org.eclipse.papyrus.infra.emf.readonly;
import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.fail;
@@ -34,11 +35,17 @@ import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.transaction.RecordingCommand;
+import org.eclipse.emf.transaction.RollbackException;
+import org.eclipse.emf.transaction.TransactionalCommandStack;
import org.eclipse.emf.workspace.AbstractEMFOperation;
import org.eclipse.emf.workspace.IWorkspaceCommandStack;
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.junit.utils.rules.ProjectFixture;
import org.eclipse.uml2.common.util.UML2Util;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.Model;
@@ -48,6 +55,7 @@ import org.eclipse.uml2.uml.UseCase;
import org.eclipse.uml2.uml.resource.UMLResource;
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import com.google.common.collect.Iterables;
@@ -58,6 +66,9 @@ import com.google.common.collect.Iterables;
*/
public class PapyrusROTransactionalEditingDomainTest {
+ @Rule
+ public final ProjectFixture project = new ProjectFixture();
+
private PapyrusROTransactionalEditingDomain fixture;
private Model model;
@@ -161,6 +172,56 @@ public class PapyrusROTransactionalEditingDomainTest {
assertThat(Iterables.filter(status[0].getCausalObjects(), Type.class), hasItem(string[0]));
}
+ /**
+ * Test that transaction options can be used to influence the domain's read-only check.
+ */
+ @Test
+ public void testReadOnlyAxisTransactionOption() throws Exception {
+ // Make our model read-only on the filesystem
+ project.setReadOnly(model.eResource());
+ TransactionalCommandStack stack = (TransactionalCommandStack)fixture.getCommandStack();
+
+ RecordingCommand cmd = new RecordingCommand(fixture) {
+
+ @Override
+ protected void doExecute() {
+ UseCase doIt = (UseCase)model.getOwnedType("DoIt");
+ assertThat(doIt, notNullValue());
+
+ // try to delete from the read-only model
+ EcoreUtil.remove(doIt);
+ }
+ };
+
+ try {
+ stack.execute(cmd, TransactionHelper.interactiveOption(false));
+ fail("Should have thrown RollbackException.");
+ } catch (RollbackException e) {
+ // Success
+ }
+
+ // The command was rolled back, so it wasn't stacked
+ assertThat(fixture.getCommandStack().canUndo(), is(false));
+
+ // The change was rolled back
+ UseCase doIt = (UseCase)model.getOwnedType("DoIt");
+ assertThat(doIt, notNullValue());
+ assertThat(doIt.getSubjects().size(), is(1));
+ assertThat(doIt.getSubjects().get(0).getName(), is("A"));
+
+ // Now, try again with only the discretionary read-only-ness enforced
+ stack.execute(cmd, TransactionHelper.readOnlyAxisOption(ReadOnlyAxis.DISCRETION));
+
+ // The command was *not* rolled back, so it *was* stacked
+ assertThat(fixture.getCommandStack().canUndo(), is(true));
+
+ // The change was *not* rolled back
+ assertThat(doIt.eResource(), nullValue());
+ assertThat(doIt.eContainer(), nullValue());
+ doIt = (UseCase)model.getOwnedType("DoIt");
+ assertThat(doIt, nullValue());
+ }
+
//
// Test framework
//
@@ -169,13 +230,14 @@ public class PapyrusROTransactionalEditingDomainTest {
public void createFixture() throws Exception {
fixture = (PapyrusROTransactionalEditingDomain)new PapyrusROTransactionalEditingDomainProvider().createTransactionalEditingDomain(new ResourceSetImpl());
- Resource res = fixture.getResourceSet().createResource(URI.createURI("platform:/resource/bogus/model.uml"));
+ Resource res = fixture.getResourceSet().createResource(project.getURI("model.uml"));
InputStream input = PapyrusROTransactionalEditingDomainTest.class.getResourceAsStream("Bug323802.uml");
try {
res.load(input, null);
} finally {
input.close();
}
+ res.save(null);
model = (Model)res.getContents().get(0);
}
diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyManagerTest.java b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyManagerTest.java
index 585d7e5309f..584282cb6a8 100644
--- a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyManagerTest.java
+++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyManagerTest.java
@@ -14,20 +14,12 @@ package org.eclipse.papyrus.infra.emf.readonly;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.fail;
-import java.io.InputStream;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.ResourceAttributes;
-import org.eclipse.core.runtime.CoreException;
import org.eclipse.emf.common.util.URI;
-import org.eclipse.emf.ecore.resource.Resource;
-import org.eclipse.emf.ecore.resource.ResourceSet;
-import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
-import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.papyrus.infra.core.resource.ReadOnlyAxis;
+import org.eclipse.papyrus.infra.emf.readonly.tests.PapyrusModelSetFixture;
+import org.eclipse.papyrus.junit.utils.rules.JavaResource;
import org.eclipse.papyrus.junit.utils.rules.ProjectFixture;
-import org.eclipse.uml2.uml.Model;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
@@ -37,16 +29,15 @@ import org.junit.Test;
/**
* Test suite for the {@link ReadOnlyManager} class.
*/
+@JavaResource("Bug323802.uml")
public class ReadOnlyManagerTest {
@Rule
- public final ProjectFixture project = new ProjectFixture();
-
- private ReadOnlyManager fixture;
+ public final PapyrusModelSetFixture domain = new PapyrusModelSetFixture();
- private TransactionalEditingDomain domain;
+ private final ProjectFixture project = domain.getProject();
- private Model model;
+ private ReadOnlyManager fixture;
public ReadOnlyManagerTest() {
super();
@@ -54,78 +45,47 @@ public class ReadOnlyManagerTest {
@Test
public void testIsReadOnlyEObject() {
- setReadOnly(project.getFile(model.eResource().getURI()));
- assertThat(fixture.isReadOnly(model).or(false), is(true));
+ project.setReadOnly(domain.getModelResource());
+ assertThat(fixture.isReadOnly(ReadOnlyAxis.anyAxis(), domain.getModel()).or(false), is(true));
}
@Test
public void testCanMakeWritableEObject() {
- setReadOnly(project.getFile(model.eResource().getURI()));
- assertThat(fixture.canMakeWritable(model).or(false), is(true));
+ project.setReadOnly(domain.getModelResource());
+ assertThat(fixture.canMakeWritable(ReadOnlyAxis.anyAxis(), domain.getModel()).or(false), is(true));
}
@Test
public void testAnyReadOnlyURIs() {
- URI uri = model.eResource().getURI();
- setReadOnly(project.getFile(uri));
- assertThat(fixture.anyReadOnly(new URI[]{ uri }).or(false), is(true));
+ URI uri = domain.getModelResourceURI();
+ project.setReadOnly(domain.getModelResource());
+ assertThat(fixture.anyReadOnly(ReadOnlyAxis.anyAxis(), new URI[]{ uri }).or(false), is(true));
}
@Test
public void testCanMakeWritableURIs() {
- URI uri = model.eResource().getURI();
- setReadOnly(project.getFile(uri));
- assertThat(fixture.canMakeWritable(new URI[]{ uri }).or(false), is(true));
+ URI uri = domain.getModelResourceURI();
+ project.setReadOnly(domain.getModelResource());
+ assertThat(fixture.canMakeWritable(ReadOnlyAxis.anyAxis(), new URI[]{ uri }).or(false), is(true));
}
+ @Test
+ public void testSashModelReadOnlyIfPermissionReadOnly() {
+ URI sashModelURI = URI.createPlatformPluginURI("org.eclipse.papyrus.foo/models/bogus.di", true);
+ assertThat(fixture.anyReadOnly(ReadOnlyAxis.anyAxis(), new URI[]{ sashModelURI }).or(false), is(true));
+ }
+
//
// Test framework
//
@Before
public void createFixture() throws Exception {
- domain = (PapyrusROTransactionalEditingDomain)new PapyrusROTransactionalEditingDomainProvider().createTransactionalEditingDomain(new ResourceSetImpl());
- fixture = new ReadOnlyManager(domain);
-
- Resource res = domain.getResourceSet().createResource(project.getURI("model.uml"));
- InputStream input = ReadOnlyManagerTest.class.getResourceAsStream("Bug323802.uml");
- try {
- res.load(input, null);
- } finally {
- input.close();
- }
- res.save(null); // Make sure it exists
- model = (Model)res.getContents().get(0);
+ fixture = new ReadOnlyManager(domain.getEditingDomain());
}
@After
public void destroyFixture() {
- ResourceSet rset = domain.getResourceSet();
-
- model = null;
-
- domain.dispose();
- domain = null;
fixture = null;
-
- for(Resource next : rset.getResources()) {
- next.unload();
- next.eAdapters().clear();
- }
-
- rset.getResources().clear();
- rset.eAdapters().clear();
- }
-
- void setReadOnly(IFile file) {
- ResourceAttributes attr = file.getResourceAttributes();
- attr.setReadOnly(true);
-
- try {
- file.setResourceAttributes(attr);
- } catch (CoreException e) {
- e.getLocalizedMessage();
- fail("Failed to make workspace file read-only: " + e.getLocalizedMessage());
- }
}
}
diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyTesterTest.java b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyTesterTest.java
new file mode 100644
index 00000000000..7b1951eea28
--- /dev/null
+++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/ReadOnlyTesterTest.java
@@ -0,0 +1,88 @@
+/*
+ * 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.emf.readonly;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import org.eclipse.papyrus.infra.emf.readonly.tests.PapyrusROEditingDomainFixture;
+import org.eclipse.papyrus.junit.utils.rules.JavaResource;
+import org.eclipse.papyrus.junit.utils.rules.ProjectFixture;
+import org.eclipse.uml2.uml.Type;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import com.google.common.collect.Iterators;
+
+
+/**
+ * This is the ReadOnlyTesterTest type. Enjoy.
+ */
+@JavaResource("Bug323802.uml")
+public class ReadOnlyTesterTest {
+
+ @Rule
+ public final PapyrusROEditingDomainFixture domain = new PapyrusROEditingDomainFixture();
+
+ private final ProjectFixture project = domain.getProject();
+
+ private ReadOnlyTester fixture;
+
+ @Test
+ public void testAsBoolean() {
+ assertThat(fixture.asBoolean(true), is(true));
+ assertThat(fixture.asBoolean(false), is(false));
+ assertThat(fixture.asBoolean("hello"), is(true));
+ assertThat(fixture.asBoolean(null), is(true));
+ }
+
+ @Test
+ public void testIsReadOnly() {
+ assertThat(fixture.testIsReadOnly(Iterators.singletonIterator(domain.getModel()), false), is(true));
+
+ Type string = domain.getModel().getImportedPackages().get(0).getOwnedType("String");
+ assertThat(fixture.testIsReadOnly(Iterators.singletonIterator(string), true), is(true));
+
+ project.setReadOnly(domain.getModelResource());
+ assertThat(fixture.testIsReadOnly(Iterators.singletonIterator(domain.getModel()), true), is(true));
+ }
+
+ @Test
+ public void testCanMakeWritable() {
+ // If it's already writable, well, then it's trivially easy to make it writable
+ assertThat(fixture.canMakeWritable(Iterators.singletonIterator(domain.getModel()), true), is(true));
+
+ Type string = domain.getModel().getImportedPackages().get(0).getOwnedType("String");
+ assertThat(fixture.canMakeWritable(Iterators.singletonIterator(string), true), is(false));
+
+ project.setReadOnly(domain.getModelResource());
+ assertThat(fixture.canMakeWritable(Iterators.singletonIterator(domain.getModel()), true), is(true));
+ }
+
+ //
+ // Test framework
+ //
+
+ @Before
+ public void createFixture() throws Exception {
+ fixture = new ReadOnlyTester();
+ }
+
+ @After
+ public void destroyFixture() {
+ fixture = null;
+ }
+
+}
diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/ReferencedModelReadOnlyHandlerTest.java b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/ReferencedModelReadOnlyHandlerTest.java
index 6f638990388..b8bd67a125b 100644
--- a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/ReferencedModelReadOnlyHandlerTest.java
+++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/ReferencedModelReadOnlyHandlerTest.java
@@ -12,6 +12,7 @@
*/
package org.eclipse.papyrus.infra.emf.readonly;
+import static org.eclipse.papyrus.infra.core.resource.ReadOnlyAxis.discretionAxes;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -124,8 +125,8 @@ public class ReferencedModelReadOnlyHandlerTest {
public void testCrossReferencedWorkspaceModelElementsMadeWritable() {
Property ssn = person.getAttribute("ssn", null);
assumeReadOnly(ssn.getType());
- assertThat(fixture.canMakeWritable(ssn.getType()).or(false), is(true));
- assertThat(fixture.makeWritable(ssn.getType()).or(false), is(true));
+ assertThat(fixture.canMakeWritable(discretionAxes(), ssn.getType()).or(false), is(true));
+ assertThat(fixture.makeWritable(discretionAxes(), ssn.getType()).or(false), is(true));
assertNotReadOnly(ssn.getType());
assertNotReadOnly(person.getAttribute("registered", null).getType());
}
@@ -174,8 +175,8 @@ public class ReferencedModelReadOnlyHandlerTest {
public void testObjectURIsWithFragment() {
Property ssn = person.getAttribute("ssn", null);
URI uri = EcoreUtil.getURI(ssn);
- assertThat(fixture.anyReadOnly(new URI[]{ uri }).or(false), is(false));
- assertThat(fixture.canMakeWritable(new URI[]{ uri }).or(true), is(false));
+ assertThat(fixture.anyReadOnly(discretionAxes(), new URI[]{ uri }).or(false), is(false));
+ assertThat(fixture.canMakeWritable(discretionAxes(), new URI[]{ uri }).or(true), is(false));
}
//
@@ -310,17 +311,17 @@ public class ReferencedModelReadOnlyHandlerTest {
}
void assertReadOnly(EObject object) {
- Optional<Boolean> status = fixture.isReadOnly(object);
+ Optional<Boolean> status = fixture.isReadOnly(discretionAxes(), object);
assertThat("Not read-only", status.or(false), is(true));
}
void assertNotReadOnly(EObject object) {
- Optional<Boolean> status = fixture.isReadOnly(object);
+ Optional<Boolean> status = fixture.isReadOnly(discretionAxes(), object);
assertThat("Should not be either read-only or definitely writable", status.isPresent(), is(false));
}
void assumeReadOnly(EObject object) {
- Optional<Boolean> status = fixture.isReadOnly(object);
+ Optional<Boolean> status = fixture.isReadOnly(discretionAxes(), object);
assumeThat("Not read-only", status.or(false), is(true));
}
diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/tests/AllTests.java b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/tests/AllTests.java
index b7d564ad280..12d2f83dd10 100644
--- a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/tests/AllTests.java
+++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/tests/AllTests.java
@@ -14,6 +14,7 @@ package org.eclipse.papyrus.infra.emf.readonly.tests;
import org.eclipse.papyrus.infra.emf.readonly.PapyrusROTransactionalEditingDomainTest;
import org.eclipse.papyrus.infra.emf.readonly.ReadOnlyManagerTest;
+import org.eclipse.papyrus.infra.emf.readonly.ReadOnlyTesterTest;
import org.eclipse.papyrus.infra.emf.readonly.ReferencedModelReadOnlyHandlerTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@@ -25,7 +26,7 @@ import org.junit.runners.Suite.SuiteClasses;
*/
@RunWith(Suite.class)
@SuiteClasses({
-PapyrusROTransactionalEditingDomainTest.class, ReferencedModelReadOnlyHandlerTest.class, ReadOnlyManagerTest.class
+PapyrusROTransactionalEditingDomainTest.class, ReferencedModelReadOnlyHandlerTest.class, ReadOnlyManagerTest.class, ReadOnlyTesterTest.class
})
public class AllTests {
diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/tests/PapyrusModelSetFixture.java b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/tests/PapyrusModelSetFixture.java
new file mode 100644
index 00000000000..6f96df8d47e
--- /dev/null
+++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/tests/PapyrusModelSetFixture.java
@@ -0,0 +1,82 @@
+/*
+ * 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.emf.readonly.tests;
+
+import static org.junit.Assert.fail;
+
+import java.util.Collections;
+
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.papyrus.infra.core.resource.EditingDomainServiceFactory;
+import org.eclipse.papyrus.infra.core.resource.ModelSet;
+import org.eclipse.papyrus.infra.core.services.ServiceDescriptor;
+import org.eclipse.papyrus.infra.core.services.ServiceDescriptor.ServiceTypeKind;
+import org.eclipse.papyrus.infra.core.services.ServiceStartKind;
+import org.eclipse.papyrus.infra.core.services.ServicesRegistry;
+import org.eclipse.papyrus.infra.emf.readonly.PapyrusROTransactionalEditingDomain;
+import org.eclipse.papyrus.infra.emf.utils.ServiceUtilsForResourceInitializerService;
+import org.eclipse.papyrus.infra.emf.utils.ServiceUtilsForResourceSet;
+import org.eclipse.papyrus.junit.utils.rules.AbstractModelFixture;
+import org.junit.runner.Description;
+
+
+/**
+ * This is the PapyrusModelSetFixture type. Enjoy.
+ */
+public class PapyrusModelSetFixture extends AbstractModelFixture<PapyrusROTransactionalEditingDomain> {
+
+ public PapyrusModelSetFixture() {
+ super();
+ }
+
+ protected PapyrusROTransactionalEditingDomain createEditingDomain() {
+ try {
+ ServicesRegistry services = createServiceRegistry();
+ return (PapyrusROTransactionalEditingDomain)services.getService(ModelSet.class).getTransactionalEditingDomain();
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail("Failed to initialize service registry and/or editing domain: " + e.getLocalizedMessage());
+ return null; // unreachable
+ }
+ }
+
+ @Override
+ protected void finished(Description description) {
+ ResourceSet rset = getEditingDomain().getResourceSet();
+
+ try {
+ ServicesRegistry services = ServiceUtilsForResourceSet.getInstance().getServiceRegistry(rset);
+ services.disposeRegistry();
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ super.finished(description);
+ }
+ }
+
+ protected ServicesRegistry createServiceRegistry() throws Exception {
+ ServicesRegistry result = new ServicesRegistry();
+ result.add(ModelSet.class, 10, new ModelSet());
+ result.add(ServiceUtilsForResourceInitializerService.class, 10, new ServiceUtilsForResourceInitializerService());
+
+ ServiceDescriptor desc = new ServiceDescriptor(TransactionalEditingDomain.class, EditingDomainServiceFactory.class.getName(), ServiceStartKind.STARTUP, 10, Collections.singletonList(ModelSet.class.getName()));
+ desc.setServiceTypeKind(ServiceTypeKind.serviceFactory);
+ desc.setClassBundleID(org.eclipse.papyrus.infra.core.Activator.PLUGIN_ID);
+ result.add(desc);
+
+ result.startRegistry();
+
+ return result;
+ }
+}
diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/tests/PapyrusROEditingDomainFixture.java b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/tests/PapyrusROEditingDomainFixture.java
new file mode 100644
index 00000000000..3f1db0e0338
--- /dev/null
+++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.readonly.tests/src/org/eclipse/papyrus/infra/emf/readonly/tests/PapyrusROEditingDomainFixture.java
@@ -0,0 +1,33 @@
+/*
+ * 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.emf.readonly.tests;
+
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.papyrus.infra.emf.readonly.PapyrusROTransactionalEditingDomain;
+import org.eclipse.papyrus.infra.emf.readonly.PapyrusROTransactionalEditingDomainProvider;
+import org.eclipse.papyrus.junit.utils.rules.AbstractModelFixture;
+
+
+/**
+ * This is the PapyrusROEditingDomainFixture type. Enjoy.
+ */
+public class PapyrusROEditingDomainFixture extends AbstractModelFixture<PapyrusROTransactionalEditingDomain> {
+
+ public PapyrusROEditingDomainFixture() {
+ super();
+ }
+
+ protected PapyrusROTransactionalEditingDomain createEditingDomain() {
+ return (PapyrusROTransactionalEditingDomain)new PapyrusROTransactionalEditingDomainProvider().createTransactionalEditingDomain(new ResourceSetImpl());
+ }
+}
diff --git a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/AbstractModelFixture.java b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/AbstractModelFixture.java
new file mode 100644
index 00000000000..25829351a1f
--- /dev/null
+++ b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/AbstractModelFixture.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2014 CEA and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.junit.utils.rules;
+
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.fail;
+
+import java.io.InputStream;
+import java.lang.reflect.Method;
+import java.net.URL;
+
+import org.eclipse.emf.common.util.URI;
+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.edit.domain.EditingDomain;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.papyrus.junit.utils.rules.ProjectFixture;
+import org.eclipse.uml2.uml.Model;
+import org.junit.Rule;
+import org.junit.rules.TestWatcher;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.FrameworkUtil;
+
+
+/**
+ * Abstract superclass for JUnit test fixture rules that provide:
+ * <ul>
+ * <li>an editing domain of some kind (subclasses must create it)</li>
+ * <li>a test project in the workspace, exposed via a nested {@link ProjectFixture} rule</li>
+ * <li>a test {@link Model} loaded from a resource in the plug-in and saved as <tt>model.uml</tt> in the test project. This model is specified using
+ * an annotation on the test, as described below</li>
+ * </ul>
+ * The test model template to load into the editing domain and project must be specified by one of the following annotations:
+ * <ul>
+ * <li>{@link JavaResource @JavaResource}: specifies the path to a resource to be loaded from the test class's classpath, using the
+ * {@link Class#getResource(String)} API</li>
+ * <li>{@link PluginResource @PluginResource}: specifies a path relative to the root of the OSGi bundle containing the test class, to be loaded via
+ * the {@link Bundle#getEntry(String)} API</li>
+ * </ul>
+ * The resource annotation may be specified either on the test method, in which case it applies to that test case, or on the test
+ * class, in which case it applies to all test methods in the class that do not have a resource annotation of their own (method
+ * annotations take precedence over the class annotation).
+ */
+public abstract class AbstractModelFixture<T extends EditingDomain> extends TestWatcher {
+
+ private final ProjectFixture project = new ProjectFixture();
+
+ private T domain;
+
+ private Model model;
+
+ public AbstractModelFixture() {
+ super();
+ }
+
+ public Statement apply(Statement base, Description description) {
+ // Wrap myself in the project rule so that the project exists when I start
+ Statement result = super.apply(base, description);
+ result = project.apply(result, description);
+ return result;
+ }
+
+ /**
+ * Obtains the nested project fixture rule. If stored in a field of the test class, it must not be annotated as a {@link Rule @Rule} because that
+ * would result in double initialization of the rule.
+ *
+ * @return the nested project fixture
+ */
+ public ProjectFixture getProject() {
+ return project;
+ }
+
+ public T getEditingDomain() {
+ return domain;
+ }
+
+ /**
+ * Obtains the test model, which is resident in the <tt>model.uml</tt> file in the test project (as indicated by its
+ * {@linkplain #getModelResourceURI() URI}).
+ *
+ * @return the test model
+ */
+ public Model getModel() {
+ return model;
+ }
+
+ public Resource getModelResource() {
+ return getModel().eResource();
+ }
+
+ public URI getModelResourceURI() {
+ return getModelResource().getURI();
+ }
+
+ public URI getModelURI() {
+ return EcoreUtil.getURI(getModel());
+ }
+
+ protected abstract T createEditingDomain();
+
+ @Override
+ protected void starting(Description description) {
+ domain = createEditingDomain();
+
+ Resource res = domain.getResourceSet().createResource(project.getURI("model.uml"));
+
+ try {
+ InputStream input = getResourceURL(description).openStream();
+ try {
+ res.load(input, null);
+ } finally {
+ input.close();
+ }
+ res.save(null); // Make sure it exists
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail("Failed to load test resource: " + e.getLocalizedMessage());
+ }
+
+ model = (Model)res.getContents().get(0);
+ }
+
+ @Override
+ protected void finished(Description description) {
+ ResourceSet rset = domain.getResourceSet();
+
+ model = null;
+
+ if(domain instanceof TransactionalEditingDomain) {
+ ((TransactionalEditingDomain)domain).dispose();
+ }
+ domain = null;
+
+ for(Resource next : rset.getResources()) {
+ next.unload();
+ next.eAdapters().clear();
+ }
+
+ rset.getResources().clear();
+ rset.eAdapters().clear();
+ }
+
+ protected URL getResourceURL(Description description) {
+ URL result = null;
+
+ Class<?> testClass = description.getTestClass();
+
+ Method testMethod = null;
+ try {
+ testMethod = testClass.getDeclaredMethod(description.getMethodName());
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail("Could not access test method via JUnit framework.");
+ }
+
+ if(testMethod.isAnnotationPresent(JavaResource.class)) {
+ result = testClass.getResource(testMethod.getAnnotation(JavaResource.class).value());
+ } else if(testMethod.isAnnotationPresent(PluginResource.class)) {
+ result = FrameworkUtil.getBundle(testClass).getEntry(testMethod.getAnnotation(PluginResource.class).value());
+ } else {
+ // The class must have an annotation
+ if(testClass.isAnnotationPresent(JavaResource.class)) {
+ result = testClass.getResource(testClass.getAnnotation(JavaResource.class).value());
+ } else if(testClass.isAnnotationPresent(PluginResource.class)) {
+ result = FrameworkUtil.getBundle(testClass).getEntry(testClass.getAnnotation(PluginResource.class).value());
+ }
+ }
+
+ assertThat("No JavaResource or PluginResource annotation found on test.", result, notNullValue());
+
+ return result;
+ }
+}
diff --git a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/JavaResource.java b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/JavaResource.java
new file mode 100644
index 00000000000..d9aa6b14340
--- /dev/null
+++ b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/JavaResource.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014 CEA and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.junit.utils.rules;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+/**
+ * Annotation indicating the classpath-relative path to a resource from which to load the test model of an {@link AbstractModelFixture}.
+ *
+ * @see AbstractModelFixture
+ * @see PluginResource
+ */
+@Target({ ElementType.METHOD, ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface JavaResource {
+
+ String value();
+}
diff --git a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PluginResource.java b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PluginResource.java
new file mode 100644
index 00000000000..dc1e7e6eacd
--- /dev/null
+++ b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PluginResource.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014 CEA and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.papyrus.junit.utils.rules;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+/**
+ * Annotation indicating the bundle-relative path to a resource from which to load the test model of an {@link AbstractModelFixture}.
+ *
+ * @see AbstractModelFixture
+ * @see JavaResource
+ */
+@Target({ ElementType.METHOD, ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface PluginResource {
+
+ String value();
+}
diff --git a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/ProjectFixture.java b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/ProjectFixture.java
index f808abda246..1cdd9f45c72 100644
--- a/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/ProjectFixture.java
+++ b/tests/junit/plugins/junit/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/ProjectFixture.java
@@ -12,6 +12,10 @@
*/
package org.eclipse.papyrus.junit.utils.rules;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.fail;
+
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
@@ -22,6 +26,8 @@ import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.workspace.util.WorkspaceSynchronizer;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
@@ -122,4 +128,37 @@ public class ProjectFixture implements TestRule {
resource.setResourceAttributes(attr);
}
}
+
+ public void setReadOnly(String projectRelativePath) {
+ setReadOnly(new Path(projectRelativePath));
+ }
+
+ public void setReadOnly(IPath projectRelativePath) {
+ setReadOnly(project.findMember(projectRelativePath));
+ }
+
+ public void setReadOnly(Resource resource) {
+ IFile file = WorkspaceSynchronizer.getFile(resource);
+ assertThat("Cannot set non-workspace resource read-only", file, notNullValue());
+ setReadOnly(file);
+ }
+
+ public void setReadOnly(IResource resource) {
+ setReadOnly(resource, true);
+ }
+
+ public void setReadOnly(IResource resource, boolean readOnly) {
+ ResourceAttributes attr = resource.getResourceAttributes();
+
+ if(attr.isReadOnly() != readOnly) {
+ attr.setReadOnly(readOnly);
+
+ try {
+ resource.setResourceAttributes(attr);
+ } catch (CoreException e) {
+ e.getLocalizedMessage();
+ fail(String.format("Failed to make workspace resource %s: %s", readOnly ? "read-only" : "writable", e.getLocalizedMessage()));
+ }
+ }
+ }
}

Back to the top