Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre-Charles David2016-04-29 13:41:17 +0000
committerPierre-Charles David2016-05-13 15:03:50 +0000
commita1eb96a92a216a922f9cafe4b964affd5a29e113 (patch)
tree70b3f55c55f130a17ba34fb15a4d8641e6fa789c
parent407a3a24d89c963d1bc01ae0dce3ae732eed4eb8 (diff)
downloadorg.eclipse.sirius-a1eb96a92a216a922f9cafe4b964affd5a29e113.tar.gz
org.eclipse.sirius-a1eb96a92a216a922f9cafe4b964affd5a29e113.tar.xz
org.eclipse.sirius-a1eb96a92a216a922f9cafe4b964affd5a29e113.zip
[482831] Expose EMF Edit features in new standard service class
Bug: 482831 Change-Id: Iec8707b35ef9407c7efdd9382682eb804607bffa Signed-off-by: Pierre-Charles David <pierre-charles.david@obeo.fr>
-rw-r--r--plugins/org.eclipse.sirius.doc/doc/Release_Notes.html6
-rw-r--r--plugins/org.eclipse.sirius.doc/doc/Release_Notes.textile1
-rw-r--r--plugins/org.eclipse.sirius.doc/doc/specifier/general/Writing_Queries.html200
-rw-r--r--plugins/org.eclipse.sirius.doc/doc/specifier/general/Writing_Queries.textile75
-rw-r--r--plugins/org.eclipse.sirius.doc/doc/toc.xml1
-rw-r--r--plugins/org.eclipse.sirius.ext.emf.edit/META-INF/MANIFEST.MF4
-rw-r--r--plugins/org.eclipse.sirius.ext.emf.edit/src/org/eclipse/sirius/ext/emf/edit/EditingDomainServices.java674
7 files changed, 961 insertions, 0 deletions
diff --git a/plugins/org.eclipse.sirius.doc/doc/Release_Notes.html b/plugins/org.eclipse.sirius.doc/doc/Release_Notes.html
index d9683a44f4..9e052ce636 100644
--- a/plugins/org.eclipse.sirius.doc/doc/Release_Notes.html
+++ b/plugins/org.eclipse.sirius.doc/doc/Release_Notes.html
@@ -115,6 +115,12 @@
<a href="specifier/general/Specifying_Viewpoints.html#translatable_messages">the corresponding section</a> in the documentation for more details.
</li>
<li><span class="label label-success">Added</span> It is possible to create Typed Variable under Variable Filter.</li>
+ <li><span class="label label-success">Added</span> A new class
+ <code>org.eclipse.sirius.ext.emf.edit.EditingDomainServices</code> (from plug-in
+ <code>org.eclipse.sirius.ext.emf.edit</code>) has been added with a complete set of service methods to leverage most of the features of the &#8220;EMF Edit&#8221; framework, for example the various
+ <em>Item Providers</em> associated to semantic elements. See
+ <a href="specifier/general/Writing_Queries.html#editing_domain_services">the documentation</a> for details.
+ </li>
<li><span class="label label-info">Added</span> The specifier can now restrict the border node authorized sides. This new option is available in the advanced tab of the border node style. See the specifier documentation for more details.</li>
<li><span class="label label-info">Modified</span>
<strong>Warning</strong>: Before this version, a style customization of an
diff --git a/plugins/org.eclipse.sirius.doc/doc/Release_Notes.textile b/plugins/org.eclipse.sirius.doc/doc/Release_Notes.textile
index a42852d198..7d88ca25e3 100644
--- a/plugins/org.eclipse.sirius.doc/doc/Release_Notes.textile
+++ b/plugins/org.eclipse.sirius.doc/doc/Release_Notes.textile
@@ -22,6 +22,7 @@ h3. Specifier-Visible Changes
* <span class="label label-success">Added</span> All static strings defined in the VSMs which are visible to the end-user of the modeler, like viewpoint and tools names, can now be internationalized. Simply replace the name with a translation key reference of the form @%myUniqueKey@ in the VSM, and define the value in the _Viewpoint Specification Project_'s @plugin.properties@ (for the default value), or @plugin_XX.properties@ for locale @XX@. The underlying mechanism is the same as for Eclipse/OSGi plug-ins, so translations can even be contributed by physically separate plug-in fragments. See "the corresponding section":specifier/general/Specifying_Viewpoints.html#translatable_messages in the documentation for more details.
* <span class="label label-success">Added</span> It is possible to create Typed Variable under Variable Filter.
+* <span class="label label-success">Added</span> A new class @org.eclipse.sirius.ext.emf.edit.EditingDomainServices@ (from plug-in @org.eclipse.sirius.ext.emf.edit@) has been added with a complete set of service methods to leverage most of the features of the "EMF Edit" framework, for example the various _Item Providers_ associated to semantic elements. See "the documentation":specifier/general/Writing_Queries.html#editing_domain_services for details.
* <span class="label label-info">Added</span> The specifier can now restrict the border node authorized sides. This new option is available in the advanced tab of the border node style. See the specifier documentation for more details.
* <span class="label label-info">Modified</span> *Warning*: Before this version, a style customization of an @EEnum@ attribute, like @labelFormat@, worked with a value expression using a Java service returning a @EEnumLiteral@. It is now forbidden. You must return an @Enumerator@. The documentation about "Styles Customization":specifier/diagrams/Diagrams.html#enum_customization now details this case.
* <span class="label label-info">Modified</span> The @BorderSizeComputationExpression@ migration has been corrected to recursively handle the sub container mappings. VSM created or migrated with Sirius 3.1.0, 3.1.1 or 3.1.2 might require a manual modification for the style descriptions of sub container mappings with border size computation equals to 0 as we cannot determine if they were added (or updated) after or before the migration: starting with Sirius 3.1.0, no border will be displayed for a 0 pixel value whereas with older version container always had at least a 1 pixel border.
diff --git a/plugins/org.eclipse.sirius.doc/doc/specifier/general/Writing_Queries.html b/plugins/org.eclipse.sirius.doc/doc/specifier/general/Writing_Queries.html
index f9aa3d1454..863319171d 100644
--- a/plugins/org.eclipse.sirius.doc/doc/specifier/general/Writing_Queries.html
+++ b/plugins/org.eclipse.sirius.doc/doc/specifier/general/Writing_Queries.html
@@ -36,6 +36,14 @@
<li>
<a href="#service_methods">Writing Java Services</a>
</li>
+ <li>
+ <a href="#standard_services">Standard Services</a>
+ <ol style="list-style: disc;">
+ <li>
+ <a href="#editing_domain_services">Editing Domain Services and EMF Edit Integration</a>
+ </li>
+ </ol>
+ </li>
</ol>
</li>
</ol>
@@ -340,5 +348,197 @@
<code>void</code>. You can return any value instead, for example target argument (the service method&#8217;s first parameter).
</li>
</ul>
+ <h2 id="standard_services">Standard Services</h2>
+ <p>Sirius provides some standard services that can be used from any VSM simply by adding the appropriate reference (as a
+ <em>Java Extension</em>) to the implementation class&#8217;s fully qualified name. When using such a service class, make sure your
+ <em>Viewpoint Specification Project</em> has a dependency towards the Sirius plug-in which provides said class.
+ </p>
+ <h3 id="editing_domain_services">Editing Domain Services and EMF Edit Integration</h3>
+ <p>Starting from Sirius 4.0, the
+ <code>org.eclipse.sirius.ext.emf.edit</code> plug-in provides the
+ <code>org.eclipse.sirius.ext.emf.edit.EditingDomainServices</code> service class which can be referenced from any VSM (once properly declared). This class provides a large set of methods which give access to many useful features of the
+ <em>EMF Edit</em> framework, in particular all kinds of
+ <em>Item Providers</em>, in a way that is directly accessible as service invocations from interpreted expressions.
+ </p>
+ <h4 id="GeneralEditingDomainrelatedServices">General EditingDomain-related Services</h4>
+ <p>The following general services are made available:</p>
+ <ul>
+ <li>
+ <code>getEditingDomain(EObject)</code>
+ </li>
+ <li>
+ <code>isStale(EObject)</code>
+ </li>
+ <li>
+ <code>isControlled(EObject)</code>
+ </li>
+ <li>
+ <code>getAdapterFactory(EObject)</code>
+ </li>
+ <li>
+ <code>getAdapter(EObject, Class)</code>
+ </li>
+ </ul>
+ <h4 id="ItemProvidersServices">Item Providers Services</h4>
+ <p>Most public methods of the following interfaces are available as services on any
+ <code>EObject</code> (typically from a Sirius session):
+ </p>
+ <ul>
+ <li>
+ <code>org.eclipse.emf.edit.provider.IItemLabelProvider</code>
+ </li>
+ <li>
+ <code>org.eclipse.emf.edit.provider.IItemColorProvider</code>
+ </li>
+ <li>
+ <code>org.eclipse.emf.edit.provider.IItemFontProvider</code>
+ </li>
+ <li>
+ <code>org.eclipse.emf.edit.provider.IItemStyledLabelProvider</code> (only available in EMF 2.10 and later)
+ </li>
+ <li>
+ <code>org.eclipse.emf.edit.provider.IStructuredItemContentProvider</code>
+ </li>
+ <li>
+ <code>org.eclipse.emf.edit.provider.ITreeItemContentProvider</code>
+ </li>
+ <li>
+ <code>org.eclipse.emf.edit.provider.ITableItemLabelProvider</code>
+ </li>
+ <li>
+ <code>org.eclipse.emf.edit.provider.ITableItemColorProvider</code>
+ </li>
+ <li>
+ <code>org.eclipse.emf.edit.provider.ITableItemFontProvider</code>
+ </li>
+ </ul>
+ <p>In all cases, a
+ <code>getXXXProvider()</code> service method is also made available (for example
+ <code>getLabelProvider(EObject)</code>, which returns the item provider itself (or
+ <code>null</code>). The item provider is located using the
+ <code>ItemProviderAdapter</code> returned by the
+ <code>AdapterFactory</code> associated to the element&#8217;s editing domain. This assumes said domain is an
+ <code>AdapterFactoryEditingDomain</code> (which is true in practice in Sirius, which uses a
+ <code>TransactionalEditingDomain</code> that inherits from this).
+ </p>
+ <p>All service methods return an explicit
+ <code>null</code> value (or
+ <code>false</code> for services that return a boolean) if the corresponding item provider could not be found. Note that this is indistinguishable from an item provider method which actually returns
+ <code>null</code> or
+ <code>false</code>.
+ </p>
+ <h4 id="ItemPropertyRelatedServices">Item Property-Related Services</h4>
+ <p>The
+ <code>IItemPropertySource</code> associated with an element and its
+ <code>IItemPropertyDescriptors</code> can be obtained using the following services:
+ </p>
+ <ul>
+ <li>
+ <code>getItemPropertySource(EObject)</code>
+ </li>
+ <li>
+ <code>getPropertyDescriptors(EObject)</code> to obtain
+ <strong>all</strong> the
+ <code>IItemPropertyDescriptor</code> of the element.
+ </li>
+ <li>
+ <code>getPropertyDescriptorForFeature(EObject, String)</code> to obtain the
+ <code>IItemPropertyDescriptor</code> of an element&#8217;s specific feature
+ </li>
+ </ul>
+ <p>The following services, which all take a feature name as a second argument (the first explicit one when invoked as a service) give access to the corresponding methods in the
+ <code>IItemPropertyDescriptor</code> associated to the corresponding element&#8217;s feature:
+ </p>
+ <ul>
+ <li>
+ <code>getPropertyDescriptorPropertyValue()</code>
+ </li>
+ <li>
+ <code>isPropertyDescriptorPropertySet()</code>
+ </li>
+ <li>
+ <code>canSetPropertyDescriptorProperty()</code>
+ </li>
+ <li>
+ <code>resetPropertyDescriptorPropertyValue()</code>
+ </li>
+ <li>
+ <code>setPropertyDescriptorPropertyValue()</code>
+ </li>
+ <li>
+ <code>getPropertyDescriptorCategory()</code>
+ </li>
+ <li>
+ <code>getPropertyDescriptorDescription()</code>
+ </li>
+ <li>
+ <code>getPropertyDescriptorDisplayName()</code>
+ </li>
+ <li>
+ <code>getPropertyDescriptorFilterFlags()</code>
+ </li>
+ <li>
+ <code>getPropertyDescriptorHelpContextIds()</code>
+ </li>
+ <li>
+ <code>getPropertyDescriptorId()</code>
+ </li>
+ <li>
+ <code>getPropertyDescriptorLabelProvider()</code>
+ </li>
+ <li>
+ <code>getPropertyDescriptorFeature()</code>
+ </li>
+ <li>
+ <code>isPropertyDescriptorMany()</code>
+ </li>
+ <li>
+ <code>getPropertyDescriptorChoiceOfValues()</code>
+ </li>
+ <li>
+ <code>isPropertyDescriptorMultiLine()</code>
+ </li>
+ <li>
+ <code>isPropertyDescriptorSortChoices()</code>
+ </li>
+ </ul>
+ <h4 id="CommandrelatedServices">Command-related Services</h4>
+ <p>A series of service methods can be used to invoke the standard EMF Commands available from
+ <code>ItemProviderAdapter</code> 's various
+ <code>createXXXCommand()</code> methods. Note that contrary to the
+ <code>createXXXCommand()</code> methods which simply returns a
+ <code>Command</code> instance, the service methods exposed in this class will directly
+ <strong>execute</strong> the command on the editing domains
+ <code>CommandStack</code>.
+ <br/>Their names follow the
+ <code>perfomXXXCommand()</code> pattern to reflect this. They all return the
+ <code>self</code> element (the
+ <code>EObject</code> on which the service was invoked.
+ </p>
+ <p>The command-related services available are:</p>
+ <ul>
+ <li>
+ <code>performSetCommand()</code>
+ </li>
+ <li>
+ <code>performUnsetCommand()</code>
+ </li>
+ <li>
+ <code>performAddCommand()</code>
+ </li>
+ <li>
+ <code>performRemoveCommand()</code>
+ </li>
+ <li>
+ <code>performReplaceCommand()</code>
+ </li>
+ <li>
+ <code>performMoveCommand()</code>
+ </li>
+ </ul>
+ <p>The implementation of these services delegate to the
+ <code>ItemProviderAdapter.createCommand()</code> method, so any customization made in the
+ <code>ItemProviderAdapter</code> 's implementation will be taken into account.
+ </p>
</body>
</html> \ No newline at end of file
diff --git a/plugins/org.eclipse.sirius.doc/doc/specifier/general/Writing_Queries.textile b/plugins/org.eclipse.sirius.doc/doc/specifier/general/Writing_Queries.textile
index fafcd8f71c..9648f73119 100644
--- a/plugins/org.eclipse.sirius.doc/doc/specifier/general/Writing_Queries.textile
+++ b/plugins/org.eclipse.sirius.doc/doc/specifier/general/Writing_Queries.textile
@@ -151,3 +151,78 @@ _Warning:_ Java service methods should be stateless. There is no guarantee that
_Warning:_ There are currently some limitations on the use of Java services from Acceleo:
* primitive types can not be used as arguments or return types for service methods invoked from Acceleo 3 expressions. The workaround is to use the corresponding wrapper type (e.g. @Integer@ instead of @int@).
* service methods invoked from Acceleo 3 expressions can not return @void@. You can return any value instead, for example target argument (the service method's first parameter).
+
+h2(#standard_services). Standard Services
+
+Sirius provides some standard services that can be used from any VSM simply by adding the appropriate reference (as a _Java Extension_) to the implementation class's fully qualified name. When using such a service class, make sure your _Viewpoint Specification Project_ has a dependency towards the Sirius plug-in which provides said class.
+
+h3(#editing_domain_services). Editing Domain Services and EMF Edit Integration
+
+Starting from Sirius 4.0, the @org.eclipse.sirius.ext.emf.edit@ plug-in provides the @org.eclipse.sirius.ext.emf.edit.EditingDomainServices@ service class which can be referenced from any VSM (once properly declared). This class provides a large set of methods which give access to many useful features of the _EMF Edit_ framework, in particular all kinds of _Item Providers_, in a way that is directly accessible as service invocations from interpreted expressions.
+
+h4. General EditingDomain-related Services
+
+The following general services are made available:
+* @getEditingDomain(EObject)@
+* @isStale(EObject)@
+* @isControlled(EObject)@
+* @getAdapterFactory(EObject)@
+* @getAdapter(EObject, Class)@
+
+h4. Item Providers Services
+
+Most public methods of the following interfaces are available as services on any @EObject@ (typically from a Sirius session):
+* @org.eclipse.emf.edit.provider.IItemLabelProvider@
+* @org.eclipse.emf.edit.provider.IItemColorProvider@
+* @org.eclipse.emf.edit.provider.IItemFontProvider@
+* @org.eclipse.emf.edit.provider.IItemStyledLabelProvider@ (only available in EMF 2.10 and later)
+* @org.eclipse.emf.edit.provider.IStructuredItemContentProvider@
+* @org.eclipse.emf.edit.provider.ITreeItemContentProvider@
+* @org.eclipse.emf.edit.provider.ITableItemLabelProvider@
+* @org.eclipse.emf.edit.provider.ITableItemColorProvider@
+* @org.eclipse.emf.edit.provider.ITableItemFontProvider@
+
+In all cases, a @getXXXProvider()@ service method is also made available (for example @getLabelProvider(EObject)@, which returns the item provider itself (or @null@). The item provider is located using the @ItemProviderAdapter@ returned by the @AdapterFactory@ associated to the element's editing domain. This assumes said domain is an @AdapterFactoryEditingDomain@ (which is true in practice in Sirius, which uses a @TransactionalEditingDomain@ that inherits from this).
+
+All service methods return an explicit @null@ value (or @false@ for services that return a boolean) if the corresponding item provider could not be found. Note that this is indistinguishable from an item provider method which actually returns @null@ or @false@.
+
+h4. Item Property-Related Services
+
+The @IItemPropertySource@ associated with an element and its @IItemPropertyDescriptors@ can be obtained using the following services:
+* @getItemPropertySource(EObject)@
+* @getPropertyDescriptors(EObject)@ to obtain *all* the @IItemPropertyDescriptor@ of the element.
+* @getPropertyDescriptorForFeature(EObject, String)@ to obtain the @IItemPropertyDescriptor@ of an element's specific feature
+
+The following services, which all take a feature name as a second argument (the first explicit one when invoked as a service) give access to the corresponding methods in the @IItemPropertyDescriptor@ associated to the corresponding element's feature:
+* @getPropertyDescriptorPropertyValue()@
+* @isPropertyDescriptorPropertySet()@
+* @canSetPropertyDescriptorProperty()@
+* @resetPropertyDescriptorPropertyValue()@
+* @setPropertyDescriptorPropertyValue()@
+* @getPropertyDescriptorCategory()@
+* @getPropertyDescriptorDescription()@
+* @getPropertyDescriptorDisplayName()@
+* @getPropertyDescriptorFilterFlags()@
+* @getPropertyDescriptorHelpContextIds()@
+* @getPropertyDescriptorId()@
+* @getPropertyDescriptorLabelProvider()@
+* @getPropertyDescriptorFeature()@
+* @isPropertyDescriptorMany()@
+* @getPropertyDescriptorChoiceOfValues()@
+* @isPropertyDescriptorMultiLine()@
+* @isPropertyDescriptorSortChoices()@
+
+h4. Command-related Services
+
+A series of service methods can be used to invoke the standard EMF Commands available from @ItemProviderAdapter@ 's various @createXXXCommand()@ methods. Note that contrary to the @createXXXCommand()@ methods which simply returns a @Command@ instance, the service methods exposed in this class will directly *execute* the command on the editing domains @CommandStack@.
+Their names follow the @perfomXXXCommand()@ pattern to reflect this. They all return the @self@ element (the @EObject@ on which the service was invoked.
+
+The command-related services available are:
+* @performSetCommand()@
+* @performUnsetCommand()@
+* @performAddCommand()@
+* @performRemoveCommand()@
+* @performReplaceCommand()@
+* @performMoveCommand()@
+
+The implementation of these services delegate to the @ItemProviderAdapter.createCommand()@ method, so any customization made in the @ItemProviderAdapter@ 's implementation will be taken into account.
diff --git a/plugins/org.eclipse.sirius.doc/doc/toc.xml b/plugins/org.eclipse.sirius.doc/doc/toc.xml
index 90bcf8f8e5..841ccfbb70 100644
--- a/plugins/org.eclipse.sirius.doc/doc/toc.xml
+++ b/plugins/org.eclipse.sirius.doc/doc/toc.xml
@@ -129,6 +129,7 @@
<topic href="doc/specifier/general/Writing_Queries.html#ocl" label="Using Raw OCL" />
<topic href="doc/specifier/general/Writing_Queries.html#custom" label="Providing a Custom Language" />
<topic href="doc/specifier/general/Writing_Queries.html#service_methods" label="Writing Java Services" />
+ <topic href="doc/specifier/general/Writing_Queries.html#standard_services" label="Standard Services" />
</topic>
<anchor id="moreSpecifierRefs" />
</topic>
diff --git a/plugins/org.eclipse.sirius.ext.emf.edit/META-INF/MANIFEST.MF b/plugins/org.eclipse.sirius.ext.emf.edit/META-INF/MANIFEST.MF
index 24c31f6db3..ca34769029 100644
--- a/plugins/org.eclipse.sirius.ext.emf.edit/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.sirius.ext.emf.edit/META-INF/MANIFEST.MF
@@ -6,3 +6,7 @@ Bundle-Version: 4.0.0.qualifier
Bundle-Vendor: %providerName
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Bundle-Localization: plugin
+Export-Package: org.eclipse.sirius.ext.emf.edit;version="4.0.0"
+Require-Bundle: org.eclipse.emf.common;bundle-version="2.8.0",
+ org.eclipse.emf.ecore;bundle-version="2.8.0",
+ org.eclipse.emf.edit;bundle-version="2.8.0"
diff --git a/plugins/org.eclipse.sirius.ext.emf.edit/src/org/eclipse/sirius/ext/emf/edit/EditingDomainServices.java b/plugins/org.eclipse.sirius.ext.emf.edit/src/org/eclipse/sirius/ext/emf/edit/EditingDomainServices.java
new file mode 100644
index 0000000000..01beb07e3d
--- /dev/null
+++ b/plugins/org.eclipse.sirius.ext.emf.edit/src/org/eclipse/sirius/ext/emf/edit/EditingDomainServices.java
@@ -0,0 +1,674 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Obeo.
+ * 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:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.sirius.ext.emf.edit;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.common.command.CommandStack;
+import org.eclipse.emf.common.notify.Adapter;
+import org.eclipse.emf.common.notify.AdapterFactory;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.edit.command.AddCommand;
+import org.eclipse.emf.edit.command.CommandParameter;
+import org.eclipse.emf.edit.command.MoveCommand;
+import org.eclipse.emf.edit.command.RemoveCommand;
+import org.eclipse.emf.edit.command.ReplaceCommand;
+import org.eclipse.emf.edit.command.SetCommand;
+import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
+import org.eclipse.emf.edit.domain.EditingDomain;
+import org.eclipse.emf.edit.provider.IItemColorProvider;
+import org.eclipse.emf.edit.provider.IItemFontProvider;
+import org.eclipse.emf.edit.provider.IItemLabelProvider;
+import org.eclipse.emf.edit.provider.IItemPropertyDescriptor;
+import org.eclipse.emf.edit.provider.IItemPropertySource;
+import org.eclipse.emf.edit.provider.IItemStyledLabelProvider;
+import org.eclipse.emf.edit.provider.IStructuredItemContentProvider;
+import org.eclipse.emf.edit.provider.ITableItemColorProvider;
+import org.eclipse.emf.edit.provider.ITableItemFontProvider;
+import org.eclipse.emf.edit.provider.ITableItemLabelProvider;
+import org.eclipse.emf.edit.provider.ITreeItemContentProvider;
+import org.eclipse.emf.edit.provider.ItemPropertyDescriptor;
+import org.eclipse.emf.edit.provider.ItemProviderAdapter;
+
+/**
+ * Provides access to common {@link EditingDomain} and
+ * {@link AdapterFactoryEditingDomain} methods in a way that is compatible with
+ * "Java services" invocation from Sirius interpreted expressions.
+ * <p>
+ * <h4>General EditingDomain-related Services</h4>
+ * <p>
+ * The following general services are made available:
+ * <ul>
+ * <li>{@link #getEditingDomain(EObject)}</li>
+ * <li>{@link #isStale(EObject)}</li>
+ * <li>{@link #isControlled(EObject)}</li>
+ * <li>{@link #getAdapterFactory(EObject)}</li>
+ * <li>{@link #getAdapter(EObject, Class)}</li>
+ * </ul>
+ * <p>
+ * <h4>Item Providers Services</h4>
+ * <p>
+ * Most public methods of the following interfaces are available as services on
+ * any {@link EObject} (typically from a Sirius session):
+ * <ul>
+ * <li>{@link org.eclipse.emf.edit.provider.IItemLabelProvider}</li>
+ * <li>{@link org.eclipse.emf.edit.provider.IItemColorProvider}</li>
+ * <li>{@link org.eclipse.emf.edit.provider.IItemFontProvider}</li>
+ * <li>{@link org.eclipse.emf.edit.provider.IItemStyledLabelProvider} (only
+ * available in EMF 2.10 and later)</li>
+ * <li>{@link org.eclipse.emf.edit.provider.IStructuredItemContentProvider}</li>
+ * <li>{@link org.eclipse.emf.edit.provider.ITreeItemContentProvider}</li>
+ * <li>{@link org.eclipse.emf.edit.provider.ITableItemLabelProvider}</li>
+ * <li>{@link org.eclipse.emf.edit.provider.ITableItemColorProvider}</li>
+ * <li>{@link org.eclipse.emf.edit.provider.ITableItemFontProvider}</li>
+ * </ul>
+ * <p>
+ * In all cases, a {@code getXXXProvider()} service method is also made
+ * available (for example {@link #getLabelProvider(EObject)}, which returns the
+ * item provider itself (or <code>null</code>). The item provider is located
+ * using the {@link ItemProviderAdapter} returned by the {@link AdapterFactory}
+ * associated to the element's editing domain. This assumes said domain is an
+ * {@link AdapterFactoryEditingDomain} (which is true in practice in Sirius,
+ * which uses a <code>TransactionalEditingDomain</code> that inherits from
+ * this).
+ * <p>
+ * All service methods return an explicit <code>null</code> value (or
+ * <code>false</code> for services that return a boolean) if the corresponding
+ * item provider could not be found. Note that this is indistinguishable from an
+ * item provider method which actually returns <code>null</code>/
+ * <code>false</code>.
+ * <h4>Item Property-Related Services</h4>
+ * <p>
+ * The {@link IItemPropertySource} associated with an element and its
+ * {@link IItemPropertyDescriptor}s can be obtained using the following
+ * services:
+ * <ul>
+ * <li>{@link #getItemPropertySource(EObject)}</li>
+ * <li>{@link #getPropertyDescriptors(EObject)} to obtain <em>all</em> the
+ * {@link IItemPropertyDescriptor} of the element.</li>
+ * <li>{@link #getPropertyDescriptorForFeature(EObject, String)} to obtain the
+ * {@link IItemPropertyDescriptor} of an element's specific feature</li>
+ * </ul>
+ * <p>
+ * The following services, which all take a feature name as a second argument
+ * (the first explicit one when invoked as a service) give access to the
+ * corresponding methods in the {@link IItemPropertyDescriptor} associated to
+ * the corresponding element's feature:
+ * <ul>
+ * <li>{@link #getPropertyDescriptorPropertyValue()}</li>
+ * <li>{@link #isPropertyDescriptorPropertySet()}</li>
+ * <li>{@link #canSetPropertyDescriptorProperty()}</li>
+ * <li>{@link #resetPropertyDescriptorPropertyValue()}</li>
+ * <li>{@link #setPropertyDescriptorPropertyValue()}</li>
+ * <li>{@link #getPropertyDescriptorCategory()}</li>
+ * <li>{@link #getPropertyDescriptorDescription()}</li>
+ * <li>{@link #getPropertyDescriptorDisplayName()}</li>
+ * <li>{@link #getPropertyDescriptorFilterFlags()}</li>
+ * <li>{@link #getPropertyDescriptorHelpContextIds()}</li>
+ * <li>{@link #getPropertyDescriptorId()}</li>
+ * <li>{@link #getPropertyDescriptorLabelProvider()}</li>
+ * <li>{@link #getPropertyDescriptorFeature()}</li>
+ * <li>{@link #isPropertyDescriptorMany()}</li>
+ * <li>{@link #getPropertyDescriptorChoiceOfValues()}</li>
+ * <li>{@link #isPropertyDescriptorMultiLine()}</li>
+ * <li>{@link #isPropertyDescriptorSortChoices()}</li>
+ * </ul>
+ * <p>
+ * <h4>Command-related Services</h4>
+ * <p>
+ * A series of service methods can be used to invoke the standard EMF Commands
+ * available from {@link ItemProviderAdapter}'s various
+ * {@code createXXXCommand()} methods. Note that contrary to the
+ * {@code createXXXCommand()} methods which simply returns a {@link Command}
+ * instance, the service methods exposed in this class will directly
+ * <em>execute</em> the command on the editing domains {@link CommandStack}.
+ * Their names follow the {@code perfomXXXCommand()} pattern to reflect this.
+ * They all return the {@code self} element (the {@link EObject} on which the
+ * service was invoked.
+ * <p>
+ * The command-related services available are:
+ * <ul>
+ * <li>{@link #performSetCommand()}</li>
+ * <li>{@link #performUnsetCommand()}</li>
+ * <li>{@link #performAddCommand()}</li>
+ * <li>{@link #performRemoveCommand()}</li>
+ * <li>{@link #performReplaceCommand()}</li>
+ * <li>{@link #performMoveCommand()}</li>
+ * </ul>
+ * <p>
+ * The implementation of these services delegate to the
+ * {@link ItemProviderAdapter#createCommand(Object, EditingDomain, Class, CommandParameter)}
+ * method, so any customization made in the {@link ItemProviderAdapter}'s
+ * implementation will be taken into account.
+ *
+ * @author pcdavid
+ */
+// CHECKSTYLE:OFF
+public class EditingDomainServices {
+
+ public EditingDomain getEditingDomain(EObject self) {
+ return AdapterFactoryEditingDomain.getEditingDomainFor(self);
+ }
+
+ // Services from AdapterFactoryEditingDomain
+
+ public boolean isStale(EObject self) {
+ return AdapterFactoryEditingDomain.isStale(self);
+ }
+
+ public boolean isControlled(EObject self) {
+ return AdapterFactoryEditingDomain.isControlled(self);
+ }
+
+ public AdapterFactory getAdapterFactory(EObject self) {
+ EditingDomain domain = getEditingDomain(self);
+ if (domain instanceof AdapterFactoryEditingDomain) {
+ return ((AdapterFactoryEditingDomain) domain).getAdapterFactory();
+ } else {
+ return null;
+ }
+ }
+
+ private <T> T getAdapter(EObject self, Class<T> type) {
+ AdapterFactory af = getAdapterFactory(self);
+ if (af != null) {
+ Adapter adapter = af.adapt(self, type);
+ if (type.isInstance(adapter)) {
+ return type.cast(adapter);
+ }
+ }
+ return null;
+ }
+
+ public ItemProviderAdapter getItemProviderAdapter(EObject self) {
+ return getAdapter(self, ItemProviderAdapter.class);
+ }
+
+ // Services from IItemLabelProvider
+
+ public IItemLabelProvider getLabelProvider(EObject self) {
+ return getAdapter(self, IItemLabelProvider.class);
+ }
+
+ public String getLabelProviderText(EObject self) {
+ IItemLabelProvider lp = getLabelProvider(self);
+ if (lp != null) {
+ return lp.getText(self);
+ } else {
+ return null;
+ }
+ }
+
+ public Object getLabelProviderImage(EObject self) {
+ IItemLabelProvider lp = getLabelProvider(self);
+ if (lp != null) {
+ return lp.getImage(self);
+ } else {
+ return null;
+ }
+ }
+
+ // Services from IItemColorProvider
+
+ public IItemColorProvider getColorProvider(EObject self) {
+ return getAdapter(self, IItemColorProvider.class);
+ }
+
+ public Object getColorProviderForeground(EObject self) {
+ IItemColorProvider cp = getColorProvider(self);
+ if (cp != null) {
+ return cp.getForeground(self);
+ } else {
+ return null;
+ }
+ }
+
+ public Object getColorProviderBackground(EObject self) {
+ IItemColorProvider cp = getColorProvider(self);
+ if (cp != null) {
+ return cp.getBackground(self);
+ } else {
+ return null;
+ }
+ }
+
+ // Services from IItemFontProvider
+
+ public IItemFontProvider getFontProvider(EObject self) {
+ return getAdapter(self, IItemFontProvider.class);
+ }
+
+ public Object getFontProviderFont(EObject self) {
+ IItemFontProvider fp = getFontProvider(self);
+ if (fp != null) {
+ return fp.getFont(self);
+ } else {
+ return null;
+ }
+ }
+
+ // Services from IItemStyledLabelProvider (EMF 2.10+)
+
+ public IItemStyledLabelProvider getStyledLabelProvider(EObject self) {
+ return getAdapter(self, IItemStyledLabelProvider.class);
+ }
+
+ public Object getStyledProviderStyledText(EObject self) {
+ IItemStyledLabelProvider slp = getStyledLabelProvider(self);
+ if (slp != null) {
+ return slp.getStyledText(self);
+ } else {
+ return null;
+ }
+ }
+
+ // Services from IStructuredItemContentProvider
+
+ public IStructuredItemContentProvider getStructuredItemContentProvider(EObject self) {
+ return getAdapter(self, IStructuredItemContentProvider.class);
+ }
+
+ public Collection<?> getStructuredItemContentProviderElements(EObject self) {
+ IStructuredItemContentProvider scp = getStructuredItemContentProvider(self);
+ if (scp != null) {
+ return scp.getElements(self);
+ } else {
+ return null;
+ }
+ }
+
+ // Services from ITreeItemContentProvider
+
+ public ITreeItemContentProvider getTreeContentProvider(EObject self) {
+ return getAdapter(self, ITreeItemContentProvider.class);
+ }
+
+ public Collection<?> getTreeContentProviderChildren(EObject self) {
+ ITreeItemContentProvider tp = getTreeContentProvider(self);
+ if (tp != null) {
+ return tp.getChildren(self);
+ } else {
+ return null;
+ }
+ }
+
+ public boolean hasTreeContentProviderChildren(EObject self) {
+ ITreeItemContentProvider tp = getTreeContentProvider(self);
+ if (tp != null) {
+ return tp.hasChildren(self);
+ } else {
+ return false;
+ }
+ }
+
+ public Object getTreeContentProviderParent(EObject self) {
+ ITreeItemContentProvider tp = getTreeContentProvider(self);
+ if (tp != null) {
+ return tp.getParent(self);
+ } else {
+ return false;
+ }
+ }
+
+ // Services from ITableItemLabelProvider
+
+ public ITableItemLabelProvider getTableLabelProvider(EObject self) {
+ return getAdapter(self, ITableItemLabelProvider.class);
+ }
+
+ public String getTableLabelProviderColumnText(EObject self, int columnIndex) {
+ ITableItemLabelProvider tlp = getTableLabelProvider(self);
+ if (tlp != null) {
+ return tlp.getColumnText(self, columnIndex);
+ } else {
+ return null;
+ }
+ }
+
+ public Object getTableLabelProviderColumnImage(EObject self, int columnIndex) {
+ ITableItemLabelProvider tlp = getTableLabelProvider(self);
+ if (tlp != null) {
+ return tlp.getColumnImage(self, columnIndex);
+ } else {
+ return null;
+ }
+ }
+
+ // Services from ITableItemColorProvider
+
+ public ITableItemColorProvider getTableColorProvider(EObject self) {
+ return getAdapter(self, ITableItemColorProvider.class);
+ }
+
+ public Object getTableColorProviderForeground(EObject self, int columnIndex) {
+ ITableItemColorProvider tcp = getTableColorProvider(self);
+ if (tcp != null) {
+ return tcp.getForeground(self, columnIndex);
+ } else {
+ return null;
+ }
+ }
+
+ public Object getTableColorProviderBackground(EObject self, int columnIndex) {
+ ITableItemColorProvider tcp = getTableColorProvider(self);
+ if (tcp != null) {
+ return tcp.getBackground(self, columnIndex);
+ } else {
+ return null;
+ }
+ }
+
+ // Services from ITableItemFontProvider
+
+ public ITableItemFontProvider getTableFontProvider(EObject self) {
+ return getAdapter(self, ITableItemFontProvider.class);
+ }
+
+ public Object getTableFontProviderFont(EObject self, int columnIndex) {
+ ITableItemFontProvider tfp = getTableFontProvider(self);
+ if (tfp != null) {
+ return tfp.getFont(self, columnIndex);
+ } else {
+ return null;
+ }
+ }
+
+ // Services from IItemPropertySource & IItemPropertyDescriptor
+
+ public IItemPropertySource getItemPropertySource(EObject self) {
+ return getAdapter(self, IItemPropertySource.class);
+ }
+
+ public List<IItemPropertyDescriptor> getPropertyDescriptors(EObject self) {
+ IItemPropertySource ips = getItemPropertySource(self);
+ if (ips != null) {
+ return ips.getPropertyDescriptors(self);
+ } else {
+ return null;
+ }
+ }
+
+ public IItemPropertyDescriptor getPropertyDescriptor(EObject self, Object propertyID) {
+ IItemPropertySource ips = getItemPropertySource(self);
+ if (ips != null) {
+ return ips.getPropertyDescriptor(self, propertyID);
+ } else {
+ return null;
+ }
+ }
+
+ public IItemPropertyDescriptor getPropertyDescriptorForFeature(EObject self, EStructuralFeature feature) {
+ if (feature.getEContainingClass().isSuperTypeOf(self.eClass())) {
+ IItemPropertySource ips = getItemPropertySource(self);
+ if (ips != null) {
+ for (IItemPropertyDescriptor propertyDescriptor : ips.getPropertyDescriptors(self)) {
+ if ((propertyDescriptor.getFeature(self)) == feature) {
+ return propertyDescriptor;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ public IItemPropertyDescriptor getPropertyDescriptorForFeature(EObject self, String featureName) {
+ EStructuralFeature feature = self.eClass().getEStructuralFeature(featureName);
+ if (feature != null) {
+ return getPropertyDescriptorForFeature(self, feature);
+ } else {
+ return null;
+ }
+ }
+
+ public Object getPropertyDescriptorPropertyValue(EObject self, String featureName) {
+ IItemPropertyDescriptor desc = getPropertyDescriptorForFeature(self, featureName);
+ if (desc != null) {
+ Object result = desc.getPropertyValue(self);
+ if (result instanceof ItemPropertyDescriptor.PropertyValueWrapper) {
+ return ((ItemPropertyDescriptor.PropertyValueWrapper) result).getEditableValue(self);
+ } else {
+ return result;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ public boolean isPropertyDescriptorPropertySet(EObject self, String featureName) {
+ IItemPropertyDescriptor desc = getPropertyDescriptorForFeature(self, featureName);
+ if (desc != null) {
+ return desc.isPropertySet(self);
+ } else {
+ return false;
+ }
+ }
+
+ public boolean canSetPropertyDescriptorProperty(EObject self, String featureName) {
+ IItemPropertyDescriptor desc = getPropertyDescriptorForFeature(self, featureName);
+ if (desc != null) {
+ return desc.canSetProperty(self);
+ } else {
+ return false;
+ }
+ }
+
+ public void resetPropertyDescriptorPropertyValue(EObject self, String featureName) {
+ IItemPropertyDescriptor desc = getPropertyDescriptorForFeature(self, featureName);
+ if (desc != null) {
+ desc.resetPropertyValue(self);
+ }
+ }
+
+ public void setPropertyDescriptorPropertyValue(EObject self, String featureName, Object value) {
+ IItemPropertyDescriptor desc = getPropertyDescriptorForFeature(self, featureName);
+ if (desc != null) {
+ desc.setPropertyValue(self, value);
+ }
+ }
+
+ public String getPropertyDescriptorCategory(EObject self, String featureName) {
+ IItemPropertyDescriptor desc = getPropertyDescriptorForFeature(self, featureName);
+ if (desc != null) {
+ return desc.getCategory(self);
+ } else {
+ return null;
+ }
+ }
+
+ public String getPropertyDescriptorDescription(EObject self, String featureName) {
+ IItemPropertyDescriptor desc = getPropertyDescriptorForFeature(self, featureName);
+ if (desc != null) {
+ return desc.getDescription(self);
+ } else {
+ return null;
+ }
+ }
+
+ public String getPropertyDescriptorDisplayName(EObject self, String featureName) {
+ IItemPropertyDescriptor desc = getPropertyDescriptorForFeature(self, featureName);
+ if (desc != null) {
+ return desc.getDisplayName(self);
+ } else {
+ return null;
+ }
+ }
+
+ public String[] getPropertyDescriptorFilterFlags(EObject self, String featureName) {
+ IItemPropertyDescriptor desc = getPropertyDescriptorForFeature(self, featureName);
+ if (desc != null) {
+ return desc.getFilterFlags(self);
+ } else {
+ return null;
+ }
+ }
+
+ public Object getPropertyDescriptorHelpContextIds(EObject self, String featureName) {
+ IItemPropertyDescriptor desc = getPropertyDescriptorForFeature(self, featureName);
+ if (desc != null) {
+ return desc.getHelpContextIds(self);
+ } else {
+ return null;
+ }
+ }
+
+ public String getPropertyDescriptorId(EObject self, String featureName) {
+ IItemPropertyDescriptor desc = getPropertyDescriptorForFeature(self, featureName);
+ if (desc != null) {
+ return desc.getId(self);
+ } else {
+ return null;
+ }
+ }
+
+ public IItemLabelProvider getPropertyDescriptorLabelProvider(EObject self, String featureName) {
+ IItemPropertyDescriptor desc = getPropertyDescriptorForFeature(self, featureName);
+ if (desc != null) {
+ return desc.getLabelProvider(self);
+ } else {
+ return null;
+ }
+ }
+
+ public Object getPropertyDescriptorFeature(EObject self, String featureName) {
+ IItemPropertyDescriptor desc = getPropertyDescriptorForFeature(self, featureName);
+ if (desc != null) {
+ return desc.getFeature(self);
+ } else {
+ return null;
+ }
+ }
+
+ public boolean isPropertyDescriptorMany(EObject self, String featureName) {
+ IItemPropertyDescriptor desc = getPropertyDescriptorForFeature(self, featureName);
+ if (desc != null) {
+ return desc.isMany(self);
+ } else {
+ return false;
+ }
+ }
+
+ public Collection<?> getPropertyDescriptorChoiceOfValues(EObject self, String featureName) {
+ IItemPropertyDescriptor desc = getPropertyDescriptorForFeature(self, featureName);
+ if (desc != null) {
+ return desc.getChoiceOfValues(self);
+ } else {
+ return null;
+ }
+ }
+
+ public boolean isPropertyDescriptorMultiLine(EObject self, String featureName) {
+ IItemPropertyDescriptor desc = getPropertyDescriptorForFeature(self, featureName);
+ if (desc != null) {
+ return desc.isMultiLine(self);
+ } else {
+ return false;
+ }
+ }
+
+ public boolean isPropertyDescriptorSortChoices(EObject self, String featureName) {
+ IItemPropertyDescriptor desc = getPropertyDescriptorForFeature(self, featureName);
+ if (desc != null) {
+ return desc.isSortChoices(self);
+ } else {
+ return false;
+ }
+ }
+
+ // Commands: createXXXCommand from ItemProviderAdapter
+
+ private void performCommand(EObject self, Class<? extends Command> cmdClass, CommandParameter param) {
+ ItemProviderAdapter ipa = getItemProviderAdapter(self);
+ if (ipa != null) {
+ EditingDomain domain = getEditingDomain(self);
+ if (domain != null) {
+ Command cmd = ipa.createCommand(self, domain, cmdClass, param);
+ CommandStack stack = domain.getCommandStack();
+ stack.execute(cmd);
+ }
+ }
+ }
+
+ public EObject performSetCommand(EObject self, String featureName, Object value, int index) {
+ EStructuralFeature feature = self.eClass().getEStructuralFeature(featureName);
+ if (feature != null) {
+ performCommand(self, SetCommand.class, new CommandParameter(self, feature, value, index));
+ }
+ return self;
+ }
+
+ public EObject performUnsetCommand(EObject self, String featureName, int index) {
+ EStructuralFeature feature = self.eClass().getEStructuralFeature(featureName);
+ if (feature != null) {
+ performCommand(self, SetCommand.class, new CommandParameter(self, feature, SetCommand.UNSET_VALUE, index));
+ }
+ return self;
+ }
+
+ public EObject performSetCommand(EObject self, String featureName, Object value) {
+ EStructuralFeature feature = self.eClass().getEStructuralFeature(featureName);
+ if (feature != null) {
+ performCommand(self, SetCommand.class, new CommandParameter(self, feature, value));
+ }
+ return self;
+ }
+
+ public EObject performUnsetCommand(EObject self, String featureName) {
+ EStructuralFeature feature = self.eClass().getEStructuralFeature(featureName);
+ if (feature != null) {
+ performCommand(self, SetCommand.class, new CommandParameter(self, feature, SetCommand.UNSET_VALUE));
+ }
+ return self;
+ }
+
+ public EObject performAddCommand(EObject self, String featureName, Collection<?> collection, int index) {
+ EStructuralFeature feature = self.eClass().getEStructuralFeature(featureName);
+ if (feature != null) {
+
+ performCommand(self, AddCommand.class, new CommandParameter(self, feature, collection, index));
+ }
+ return self;
+ }
+
+ public EObject performAddCommand(EObject self, String featureName, Collection<?> collection) {
+ EStructuralFeature feature = self.eClass().getEStructuralFeature(featureName);
+ if (feature != null) {
+ performCommand(self, AddCommand.class, new CommandParameter(self, feature, collection));
+ }
+ return self;
+ }
+
+ public EObject performRemoveCommand(EObject self, String featureName, Collection<?> collection) {
+ EStructuralFeature feature = self.eClass().getEStructuralFeature(featureName);
+ if (feature != null) {
+ performCommand(self, RemoveCommand.class, new CommandParameter(self, feature, collection));
+ }
+ return self;
+ }
+
+ public EObject performReplaceCommand(EObject self, String featureName, Object value, Collection<?> collection) {
+ EStructuralFeature feature = self.eClass().getEStructuralFeature(featureName);
+ if (feature != null) {
+ performCommand(self, ReplaceCommand.class, new CommandParameter(self, feature, value, collection));
+ }
+ return self;
+ }
+
+ public EObject performMoveCommand(EObject self, String featureName, Object value, int index) {
+ EStructuralFeature feature = self.eClass().getEStructuralFeature(featureName);
+ if (feature != null) {
+ performCommand(self, MoveCommand.class, new CommandParameter(self, feature, value, index));
+ }
+ return self;
+ }
+}

Back to the top