Bugzilla 323349 - Enable external invocation of features
Create a command that invokes a CustomFeature, allowing it to be
called from key bindings, toolbar items, etc.

Change-Id: I827239bb96202e446681c0b50315684320db4071
diff --git a/plugins/org.eclipse.graphiti.ui/plugin.properties b/plugins/org.eclipse.graphiti.ui/plugin.properties
index 18d0de4..693c7a5 100644
--- a/plugins/org.eclipse.graphiti.ui/plugin.properties
+++ b/plugins/org.eclipse.graphiti.ui/plugin.properties
@@ -40,3 +40,6 @@
 _command_description_export_diagram = Export Diagram
 _command_name_toggle_context_pad=Hide Context Buttons
 _command_description_toggle_context_pad=Toggle hiding the context buttons
+_command_name_feature_execution=Feature execution
+_command_description_feature_execution=Execute a custom feature on selected Pictogram Elements
+_command_parameter_name_feature_execution_hint=Hint
diff --git a/plugins/org.eclipse.graphiti.ui/plugin.xml b/plugins/org.eclipse.graphiti.ui/plugin.xml
index dcc51e8..eb3609c 100644
--- a/plugins/org.eclipse.graphiti.ui/plugin.xml
+++ b/plugins/org.eclipse.graphiti.ui/plugin.xml
Binary files differ
diff --git a/plugins/org.eclipse.graphiti.ui/schema/diagramTypeProviders.exsd b/plugins/org.eclipse.graphiti.ui/schema/diagramTypeProviders.exsd
index 7f77756..b3bcbad 100644
--- a/plugins/org.eclipse.graphiti.ui/schema/diagramTypeProviders.exsd
+++ b/plugins/org.eclipse.graphiti.ui/schema/diagramTypeProviders.exsd
@@ -1,201 +1,213 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!-- Schema file written by PDE -->
-<schema targetNamespace="org.eclipse.graphiti.ui" xmlns="http://www.w3.org/2001/XMLSchema">
-<annotation>
-      <appInfo>
-         <meta.schema plugin="org.eclipse.graphiti.ui" id="diagramTypeProviders" name="Diagram Type Providers"/>
-      </appInfo>
-      <documentation>
-         Customers of Graphiti can use this extension point to register their own diagram type providers.
-      </documentation>
-   </annotation>
-
-   <element name="extension">
-      <annotation>
-         <appInfo>
-            <meta.element />
-         </appInfo>
-      </annotation>
-      <complexType>
-         <sequence>
-            <element ref="diagramTypeProvider" 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="diagramTypeProvider">
-      <annotation>
-         <appInfo>
-            <meta.element labelAttribute="id"/>
-         </appInfo>
-      </annotation>
-      <complexType>
-         <sequence minOccurs="0" maxOccurs="unbounded">
-            <element ref="diagramType"/>
-            <element ref="imageProvider"/>
-         </sequence>
-         <attribute name="id" type="string" use="required">
-            <annotation>
-               <documentation>
-                  a unique name in the Eclipse environment that will be used to identify this diagram type provider
-               </documentation>
-            </annotation>
-         </attribute>
-         <attribute name="name" type="string" use="required">
-            <annotation>
-               <documentation>
-                  a name that will be used in the editor UI for this diagram type provider
-               </documentation>
-            </annotation>
-         </attribute>
-         <attribute name="description" type="string">
-            <annotation>
-               <documentation>
-                  an optional description that will be used in the editor UI for this diagram type provider
-               </documentation>
-            </annotation>
-         </attribute>
-         <attribute name="class" type="string" use="required">
-            <annotation>
-               <documentation>
-                  the name of a class that implements &lt;samp&gt;org.eclipse.graphiti.dt.IDiagramTypeProviderr&lt;/samp&gt;.
-               </documentation>
-               <appInfo>
-                  <meta.attribute kind="java" basedOn="org.eclipse.graphiti.dt.AbstractDiagramTypeProvider:org.eclipse.graphiti.dt.IDiagramTypeProvider"/>
-               </appInfo>
-            </annotation>
-         </attribute>
-      </complexType>
-   </element>
-
-   <element name="diagramType">
-      <annotation>
-         <appInfo>
-            <meta.element labelAttribute="id"/>
-         </appInfo>
-         <documentation>
-            Advertises that the containing diagram type provider understands the given diagram type and is suitable for editing/viewing diagrams of that type.
-         </documentation>
-      </annotation>
-      <complexType>
-         <attribute name="id" type="string" use="required">
-            <annotation>
-               <documentation>
-                  the diagram type identifier. This is an ID defined by the &apos;org.eclipse.graphiti.ui.diagramTypes&apos; extension point.
-               </documentation>
-               <appInfo>
-                  <meta.attribute kind="identifier" basedOn="org.eclipse.graphiti.ui.diagramTypes/diagramType/@id"/>
-               </appInfo>
-            </annotation>
-         </attribute>
-      </complexType>
-   </element>
-
-   <element name="imageProvider">
-      <annotation>
-         <appInfo>
-            <meta.element labelAttribute="id"/>
-         </appInfo>
-         <documentation>
-            Advertises that the containing diagram type provider needs the given image provider for rendering purposes.
-         </documentation>
-      </annotation>
-      <complexType>
-         <attribute name="id" type="string" use="required">
-            <annotation>
-               <documentation>
-                  the image provider identifier. This is an ID defined by the &apos;org.eclipse.graphiti.ui.imageProviders&apos; extension point.
-               </documentation>
-               <appInfo>
-                  <meta.attribute kind="identifier" basedOn="org.eclipse.graphiti.ui.imageProviders/imageProvider/@id"/>
-               </appInfo>
-            </annotation>
-         </attribute>
-      </complexType>
-   </element>
-
-   <annotation>
-      <appInfo>
-         <meta.section type="examples"/>
-      </appInfo>
-      <documentation>
-         &lt;p&gt;
-&lt;pre&gt;
-   &lt;extension
-         point=&quot;org.eclipse.graphiti.ui.diagramTypeProviders&quot;&gt;
-      &lt;diagramTypeProvider
-            class=&quot;org.eclipse.graphiti.examples.ecore.TestDiagramTypeProvider&quot;
-            description=&quot;This is a small Ecore test editor for the automated junit tests&quot;
-            id=&quot;org.eclipse.graphiti.examples.ecore.TestDiagramTypeProvider&quot;
-            name=&quot;Ecore example editor&quot;&gt;
-         &lt;diagramType
-               id=&quot;org.eclipse.graphiti.examples.ecore.EcoreDiagramType&quot;&gt;
-         &lt;/diagramType&gt;
-         &lt;imageProvider
-               id=&quot;org.eclipse.graphiti.examples.common.SampleImageProvider&quot;&gt;
-         &lt;/imageProvider&gt;
-      &lt;/diagramTypeProvider&gt;
-   &lt;/extension&gt;
-&lt;/pre&gt;
-&lt;/p&gt;
-      </documentation>
-   </annotation>
-
-   <annotation>
-      <appInfo>
-         <meta.section type="apiInfo"/>
-      </appInfo>
-      <documentation>
-         Instead of implementing the interface &lt;samp&gt;&quot;org.eclipse.graphiti.dt.IDiagramTypeProvider&lt;/samp&gt; directly, the customer should extend the base class &lt;samp&gt;&quot;org.eclipse.graphiti.dt.AbstractDiagramTypeProvider&lt;/samp&gt;.
-      </documentation>
-   </annotation>
-
-   <annotation>
-      <appInfo>
-         <meta.section type="since"/>
-      </appInfo>
-      <documentation>
-         0.7.0
-      </documentation>
-   </annotation>
-
-
-   <annotation>
-      <appInfo>
-         <meta.section type="copyright"/>
-      </appInfo>
-      <documentation>
-         Copyright (c) 2005, 2010 SAP AG.&lt;br&gt;
-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 &lt;a 
-href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
-
-      </documentation>
-   </annotation>
-
-</schema>
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.graphiti.ui" xmlns="http://www.w3.org/2001/XMLSchema">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.graphiti.ui" id="diagramTypeProviders" name="Diagram Type Providers"/>

+      </appInfo>

+      <documentation>

+         Customers of Graphiti can use this extension point to register their own diagram type providers.

+      </documentation>

+   </annotation>

+

+   <element name="extension">

+      <annotation>

+         <appInfo>

+            <meta.element />

+         </appInfo>

+      </annotation>

+      <complexType>

+         <sequence>

+            <element ref="diagramTypeProvider" 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="diagramTypeProvider">

+      <annotation>

+         <appInfo>

+            <meta.element labelAttribute="id"/>

+         </appInfo>

+      </annotation>

+      <complexType>

+         <sequence minOccurs="0" maxOccurs="unbounded">

+            <element ref="diagramType"/>

+            <element ref="imageProvider"/>

+         </sequence>

+         <attribute name="id" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a unique name in the Eclipse environment that will be used to identify this diagram type provider

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a name that will be used in the editor UI for this diagram type provider

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="description" type="string">

+            <annotation>

+               <documentation>

+                  an optional description that will be used in the editor UI for this diagram type provider

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="class" type="string" use="required">

+            <annotation>

+               <documentation>

+                  the name of a class that implements &lt;samp&gt;org.eclipse.graphiti.dt.IDiagramTypeProvider&lt;/samp&gt;.

+               </documentation>

+               <appInfo>

+                  <meta.attribute kind="java" basedOn="org.eclipse.graphiti.dt.AbstractDiagramTypeProvider:org.eclipse.graphiti.dt.IDiagramTypeProvider"/>

+               </appInfo>

+            </annotation>

+         </attribute>

+         <attribute name="context" type="string" use="default" value="org.eclipse.graphiti.ui.diagramEditor">

+            <annotation>

+               <documentation>

+                  An optional org.eclipse.ui.context that will be activated on diagrams of this type. If not present, the default &lt;samp&gt;org.eclipse.graphiti.ui.diagramEditor&lt;/samp&gt; context will be used.

+

+Note: The selected context must have the &lt;samp&gt;org.eclipse.graphiti.ui.diagramEditor&lt;/samp&gt; context as an ancestor.

+               </documentation>

+               <appInfo>

+                  <meta.attribute kind="identifier" basedOn="org.eclipse.ui.contexts/context/@id"/>

+               </appInfo>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="diagramType">

+      <annotation>

+         <appInfo>

+            <meta.element labelAttribute="id"/>

+         </appInfo>

+         <documentation>

+            Advertises that the containing diagram type provider understands the given diagram type and is suitable for editing/viewing diagrams of that type.

+         </documentation>

+      </annotation>

+      <complexType>

+         <attribute name="id" type="string" use="required">

+            <annotation>

+               <documentation>

+                  the diagram type identifier. This is an ID defined by the &apos;org.eclipse.graphiti.ui.diagramTypes&apos; extension point.

+               </documentation>

+               <appInfo>

+                  <meta.attribute kind="identifier" basedOn="org.eclipse.graphiti.ui.diagramTypes/diagramType/@id"/>

+               </appInfo>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="imageProvider">

+      <annotation>

+         <appInfo>

+            <meta.element labelAttribute="id"/>

+         </appInfo>

+         <documentation>

+            Advertises that the containing diagram type provider needs the given image provider for rendering purposes.

+         </documentation>

+      </annotation>

+      <complexType>

+         <attribute name="id" type="string" use="required">

+            <annotation>

+               <documentation>

+                  the image provider identifier. This is an ID defined by the &apos;org.eclipse.graphiti.ui.imageProviders&apos; extension point.

+               </documentation>

+               <appInfo>

+                  <meta.attribute kind="identifier" basedOn="org.eclipse.graphiti.ui.imageProviders/imageProvider/@id"/>

+               </appInfo>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

+         &lt;p&gt;

+&lt;pre&gt;

+   &lt;extension

+         point=&quot;org.eclipse.graphiti.ui.diagramTypeProviders&quot;&gt;

+      &lt;diagramTypeProvider

+            class=&quot;org.eclipse.graphiti.examples.ecore.TestDiagramTypeProvider&quot;

+            description=&quot;This is a small Ecore test editor for the automated junit tests&quot;

+            context=&quot;org.eclipse.graphiti.examples.TestDiagramContext&quot;

+            id=&quot;org.eclipse.graphiti.examples.ecore.TestDiagramTypeProvider&quot;

+            name=&quot;Ecore example editor&quot;&gt;

+         &lt;diagramType

+               id=&quot;org.eclipse.graphiti.examples.ecore.EcoreDiagramType&quot;&gt;

+         &lt;/diagramType&gt;

+         &lt;imageProvider

+               id=&quot;org.eclipse.graphiti.examples.common.SampleImageProvider&quot;&gt;

+         &lt;/imageProvider&gt;

+      &lt;/diagramTypeProvider&gt;

+   &lt;/extension&gt;

+&lt;/pre&gt;

+&lt;/p&gt;

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="apiInfo"/>

+      </appInfo>

+      <documentation>

+         Instead of implementing the interface &lt;samp&gt;&quot;org.eclipse.graphiti.dt.IDiagramTypeProvider&lt;/samp&gt; directly, the customer should extend the base class &lt;samp&gt;&quot;org.eclipse.graphiti.dt.AbstractDiagramTypeProvider&quot;&lt;/samp&gt;.

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="since"/>

+      </appInfo>

+      <documentation>

+         0.7.0

+      </documentation>

+   </annotation>

+

+

+   <annotation>

+      <appInfo>

+         <meta.section type="copyright"/>

+      </appInfo>

+      <documentation>

+         Copyright (c) 2005, 2010 SAP AG.&lt;br&gt;

+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 &lt;a 

+href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;

+      </documentation>

+   </annotation>

+

+</schema>

diff --git a/plugins/org.eclipse.graphiti.ui/src/org/eclipse/graphiti/ui/editor/DiagramEditor.java b/plugins/org.eclipse.graphiti.ui/src/org/eclipse/graphiti/ui/editor/DiagramEditor.java
index 2a53f60..93ed0b2 100644
--- a/plugins/org.eclipse.graphiti.ui/src/org/eclipse/graphiti/ui/editor/DiagramEditor.java
+++ b/plugins/org.eclipse.graphiti.ui/src/org/eclipse/graphiti/ui/editor/DiagramEditor.java
@@ -28,6 +28,7 @@
  *    mwenz - Bug 376008 - Iterating through navigation history causes exceptions
  *    Felix Velasco - mwenz - Bug 379788 - Memory leak in DefaultMarkerBehavior
  *    mwenz - Bug 387971 - Features cant't be invoked from contextMenu
+ *    fvelasco - Bug 323349 - Enable external invocation of features
  *
  * </copyright>
  *
@@ -110,6 +111,7 @@
 import org.eclipse.graphiti.tb.IToolBehaviorProvider;
 import org.eclipse.graphiti.ui.internal.action.CopyAction;
 import org.eclipse.graphiti.ui.internal.action.DeleteAction;
+import org.eclipse.graphiti.ui.internal.action.FeatureExecutionHandler;
 import org.eclipse.graphiti.ui.internal.action.PasteAction;
 import org.eclipse.graphiti.ui.internal.action.PrintGraphicalViewerAction;
 import org.eclipse.graphiti.ui.internal.action.RemoveAction;
@@ -159,6 +161,7 @@
 import org.eclipse.ui.IWorkbenchPart;
 import org.eclipse.ui.PartInitException;
 import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.contexts.IContextService;
 import org.eclipse.ui.handlers.IHandlerService;
 import org.eclipse.ui.navigator.CommonNavigator;
 import org.eclipse.ui.part.MultiPageEditorPart;
@@ -225,6 +228,14 @@
 	 */
 	public static final String DIAGRAM_EDITOR_ID = "org.eclipse.graphiti.ui.editor.DiagramEditor"; //$NON-NLS-1$
 
+	/**
+	 * The ID of the context as it is registed with the org.eclipse.ui.contexts
+	 * extension point.
+	 * 
+	 * @since 0.10
+	 */
+	public static final String DIAGRAM_CONTEXT_ID = "org.eclipse.graphiti.ui.diagramEditor"; //$NON-NLS-1$
+
 	private final DefaultUpdateBehavior updateBehavior;
 	private final DefaultPaletteBehavior paletteBehaviour;
 	private final DefaultPersistencyBehavior persistencyBehavior;
@@ -457,6 +468,8 @@
 		getUpdateBehavior().init();
 
 		migrateDiagramModelIfNecessary();
+		IContextService contextService = (IContextService) getSite().getService(IContextService.class);
+		contextService.activateContext(getDiagramTypeProvider().getContextId());
 	}
 
 	/**
@@ -629,6 +642,9 @@
 		toggleContextButtonPad.setChecked(false);
 		actionRegistry.registerAction(toggleContextButtonPad);
 		// End bug 323351
+
+		IHandlerService hs = (IHandlerService) getSite().getService(IHandlerService.class);
+		hs.activateHandler(FeatureExecutionHandler.COMMAND_ID, new FeatureExecutionHandler(getConfigurationProvider()));
 	}
 
 	/**
diff --git a/plugins/org.eclipse.graphiti.ui/src/org/eclipse/graphiti/ui/internal/action/FeatureExecutionHandler.java b/plugins/org.eclipse.graphiti.ui/src/org/eclipse/graphiti/ui/internal/action/FeatureExecutionHandler.java
new file mode 100644
index 0000000..e515f1a
--- /dev/null
+++ b/plugins/org.eclipse.graphiti.ui/src/org/eclipse/graphiti/ui/internal/action/FeatureExecutionHandler.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * <copyright>
+ *
+ * Copyright (c) 2005, 2012 SAP AG.
+ * 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:
+ *    fvelasco - Bug 323349 External feature invocation
+ *
+ * </copyright>
+ *
+ *******************************************************************************/
+package org.eclipse.graphiti.ui.internal.action;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.commands.CommandStack;
+import org.eclipse.graphiti.features.IFeature;
+import org.eclipse.graphiti.features.context.impl.CustomContext;
+import org.eclipse.graphiti.internal.command.GenericFeatureCommandWithContext;
+import org.eclipse.graphiti.internal.command.ICommand;
+import org.eclipse.graphiti.mm.pictograms.PictogramElement;
+import org.eclipse.graphiti.tb.IToolBehaviorProvider;
+import org.eclipse.graphiti.ui.internal.command.GefCommandWrapper;
+import org.eclipse.graphiti.ui.platform.IConfigurationProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class FeatureExecutionHandler extends AbstractHandler {
+
+	public static final String COMMAND_ID = "org.eclipse.graphiti.ui.featureExecutionCommand"; //$NON-NLS-1$
+	// org.eclipse.graphiti.ui.featureExecutionCommand
+	// org.eclipse.graphiti.ui.featureExecutionCommand
+	private static final String HINT_PARAMETER_ID = "org.eclipse.graphiti.ui.featureHint";
+
+	private IConfigurationProvider configurationProvider;
+
+	public FeatureExecutionHandler(IConfigurationProvider configurationProvider) {
+		super();
+		this.configurationProvider = configurationProvider;
+	}
+
+	protected PictogramElement[] getSelectedPictogramElements(ExecutionEvent event) {
+		ISelection selectedObjects = HandlerUtil.getCurrentSelection(event);
+		List<Object> list = new ArrayList<Object>();
+		if (selectedObjects instanceof IStructuredSelection) {
+			for (Iterator<?> iter = ((IStructuredSelection) selectedObjects).iterator(); iter.hasNext();) {
+				Object o = iter.next();
+				if (o instanceof EditPart) {
+					EditPart editPart = (EditPart) o;
+					if (editPart.getModel() instanceof PictogramElement) {
+						list.add(editPart.getModel());
+					}
+				}
+			}
+		}
+
+		return list.toArray(new PictogramElement[0]);
+	}
+
+	public Object execute(ExecutionEvent event) throws ExecutionException {
+		final IToolBehaviorProvider featureProvider = getToolBehaviorProvider();
+		// CommandContainer commandContainer = new
+		// CommandContainer(featureProvider);
+
+		PictogramElement pes[] = getSelectedPictogramElements(event);
+		CustomContext context = new CustomContext(pes);
+		IFeature feature = featureProvider.getCommandFeature(context, event.getParameter(HINT_PARAMETER_ID));
+		if (feature != null && feature.canExecute(context)) {
+			// commandContainer.add(new
+			// GenericFeatureCommandWithContext(feature, context));
+			executeOnCommandStack(new GenericFeatureCommandWithContext(feature, context));
+		}
+
+		// executeOnCommandStack(cmd);
+
+		return null;
+	}
+
+	private IToolBehaviorProvider getToolBehaviorProvider() {
+		return getConfigurationProvider().getDiagramTypeProvider().getCurrentToolBehaviorProvider();
+	}
+
+	protected IConfigurationProvider getConfigurationProvider() {
+		return configurationProvider;
+	}
+
+	protected void executeOnCommandStack(ICommand command) {
+		CommandStack commandStack = getConfigurationProvider().getDiagramEditor().getEditDomain().getCommandStack();
+		commandStack.execute(new GefCommandWrapper(command, getConfigurationProvider().getDiagramEditor()
+				.getEditingDomain()));
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.graphiti.ui/src/org/eclipse/graphiti/ui/internal/platform/ExtensionManager.java b/plugins/org.eclipse.graphiti.ui/src/org/eclipse/graphiti/ui/internal/platform/ExtensionManager.java
index 7b2cc85..129bb71 100644
--- a/plugins/org.eclipse.graphiti.ui/src/org/eclipse/graphiti/ui/internal/platform/ExtensionManager.java
+++ b/plugins/org.eclipse.graphiti.ui/src/org/eclipse/graphiti/ui/internal/platform/ExtensionManager.java
@@ -10,7 +10,7 @@
  * Contributors:
  *    SAP AG - initial API, implementation and documentation
  *    mwenz - Bug 352709 - invalid image provider id crashes diagram editor
- *
+ *    fvelasco - Bug 323349 - Enable external invocation of features
  * </copyright>
  *
  *******************************************************************************/
@@ -36,6 +36,7 @@
 import org.eclipse.graphiti.features.IFeatureProvider;
 import org.eclipse.graphiti.internal.util.T;
 import org.eclipse.graphiti.mm.pictograms.Diagram;
+import org.eclipse.graphiti.ui.editor.DiagramEditor;
 import org.eclipse.graphiti.ui.internal.editor.DiagramEditorDummy;
 import org.eclipse.graphiti.ui.internal.util.ui.print.IDiagramsExporter;
 import org.eclipse.graphiti.ui.platform.IImageProvider;
@@ -76,6 +77,8 @@
 
 	private static final String EP_ATTRIBUTE_DESCRIPTION = "description"; //$NON-NLS-1$
 
+	private static final String EP_ATTRIBUTE_CONTEXT = "context"; //$NON-NLS-1$
+
 	private IDiagramType diagramTypes[] = null;
 
 	private IImageProvider imageProviders[] = null;
@@ -225,6 +228,10 @@
 					if (description == null) {
 						description = ""; //$NON-NLS-1$
 					}
+					String context = element.getAttribute(EP_ATTRIBUTE_CONTEXT);
+					if (context == null) {
+						context = DiagramEditor.DIAGRAM_CONTEXT_ID;
+					}
 					if (name != null) {
 						// read references to image extensions and try to
 						// instantiate image provider
@@ -249,6 +256,7 @@
 							if (executableExtension instanceof IDiagramTypeProvider) {
 								diagramTypeProvider = (IDiagramTypeProvider) executableExtension;
 								diagramTypeProvider.setProviderId(extensionId);
+								diagramTypeProvider.setContextId(context);
 								// TODO later store also name and description -
 								// is only necessary if this information
 								// are shown in the UI
diff --git a/plugins/org.eclipse.graphiti/src/org/eclipse/graphiti/dt/AbstractDiagramTypeProvider.java b/plugins/org.eclipse.graphiti/src/org/eclipse/graphiti/dt/AbstractDiagramTypeProvider.java
index b43df09..ecf5f7c 100644
--- a/plugins/org.eclipse.graphiti/src/org/eclipse/graphiti/dt/AbstractDiagramTypeProvider.java
+++ b/plugins/org.eclipse.graphiti/src/org/eclipse/graphiti/dt/AbstractDiagramTypeProvider.java
@@ -11,7 +11,7 @@
  *    SAP AG - initial API, implementation and documentation
  *    mwenz - Bug 329523 - Add notification of DiagramTypeProvider after saving a diagram
  *    mwenz - Bug 352109 - Enable auto-update option for saved editor
- *
+ *    fvelasco - Bug 323349 - Enable external invocation of features
  * </copyright>
  *
  *******************************************************************************/
@@ -48,6 +48,8 @@
 
 	private int currentToolBehaviorIndex = 0;
 
+	private String contextId;
+
 	/**
 	 * Creates a new {@link AbstractDiagramTypeProvider}.
 	 */
@@ -115,6 +117,20 @@
 		return this.featureProvider;
 	}
 
+	/**
+	 * @since 0.10
+	 */
+	public String getContextId() {
+		return contextId;
+	}
+
+	/**
+	 * @since 0.10
+	 */
+	public void setContextId(String contextId) {
+		this.contextId = contextId;
+	}
+
 	public void init(Diagram diagram, IDiagramEditor diagramEditor) {
 		setDiagram(diagram);
 		GraphitiInternal.getEmfService().wireDTPToDiagram(diagram, this);
diff --git a/plugins/org.eclipse.graphiti/src/org/eclipse/graphiti/dt/IDiagramTypeProvider.java b/plugins/org.eclipse.graphiti/src/org/eclipse/graphiti/dt/IDiagramTypeProvider.java
index 84e5af2..47ee838 100644
--- a/plugins/org.eclipse.graphiti/src/org/eclipse/graphiti/dt/IDiagramTypeProvider.java
+++ b/plugins/org.eclipse.graphiti/src/org/eclipse/graphiti/dt/IDiagramTypeProvider.java
@@ -12,7 +12,7 @@
  *    mwenz - Bug 329523 - Add notification of DiagramTypeProvider after saving a diagram
  *    mwenz - Bug 352109 - Enable auto-update option for saved editor
  *    Bug 336488 - DiagramEditor API
- *
+ *    fvelasco - Bug 323349 - Enable external invocation of features
  * </copyright>
  *
  *******************************************************************************/
@@ -197,4 +197,22 @@
 	 *            The resources that have been saved
 	 */
 	void resourcesSaved(Diagram diagram, Resource[] savedResources);
+
+	/**
+	 * Gets the context id.
+	 * 
+	 * @return the context id
+	 * @since 0.10
+	 */
+	String getContextId();
+
+	/**
+	 * Sets the context id.
+	 * 
+	 * @param contextId
+	 *            the new context id
+	 * @since 0.10
+	 */
+	void setContextId(String contextId);
+
 }
\ No newline at end of file
diff --git a/plugins/org.eclipse.graphiti/src/org/eclipse/graphiti/tb/DefaultToolBehaviorProvider.java b/plugins/org.eclipse.graphiti/src/org/eclipse/graphiti/tb/DefaultToolBehaviorProvider.java
index 51ef6ba..24ab652 100644
--- a/plugins/org.eclipse.graphiti/src/org/eclipse/graphiti/tb/DefaultToolBehaviorProvider.java
+++ b/plugins/org.eclipse.graphiti/src/org/eclipse/graphiti/tb/DefaultToolBehaviorProvider.java
@@ -14,7 +14,7 @@
  *    mgorning - Bug 363186 - Allow modification of selection and hover state also for anchors
  *    mgorning - Bug 386913 - Support also Single-Click-Features
  *    mgorning - Bug 391523 - Revise getSelectionInfo...() in IToolBehaviorProvider
- *
+ *    fvelasco - Bug 323349 - Enable external invocation of features
  * </copyright>
  *
  *******************************************************************************/
@@ -37,6 +37,7 @@
 import org.eclipse.graphiti.features.context.IDoubleClickContext;
 import org.eclipse.graphiti.features.context.IPictogramElementContext;
 import org.eclipse.graphiti.features.context.ISingleClickContext;
+import org.eclipse.graphiti.features.context.impl.CustomContext;
 import org.eclipse.graphiti.features.custom.ICustomFeature;
 import org.eclipse.graphiti.internal.Messages;
 import org.eclipse.graphiti.internal.datatypes.impl.LocationImpl;
@@ -300,6 +301,13 @@
 	}
 
 	/**
+	 * @since 0.10
+	 */
+	public ICustomFeature getCommandFeature(CustomContext context, String hint) {
+		return null;
+	}
+
+	/**
 	 * Default implementation: creates a connection and an object compartment.
 	 * Adds all connection creation features and creation features.
 	 * 
@@ -557,4 +565,4 @@
 	public int getLineSelectionWidth(Polyline polyline) {
 		return DEFAULT_LINE_SELECTION_WIDTH;
 	}
-}
\ No newline at end of file
+}
diff --git a/plugins/org.eclipse.graphiti/src/org/eclipse/graphiti/tb/IToolBehaviorProvider.java b/plugins/org.eclipse.graphiti/src/org/eclipse/graphiti/tb/IToolBehaviorProvider.java
index ac252f6..9104ead 100644
--- a/plugins/org.eclipse.graphiti/src/org/eclipse/graphiti/tb/IToolBehaviorProvider.java
+++ b/plugins/org.eclipse.graphiti/src/org/eclipse/graphiti/tb/IToolBehaviorProvider.java
@@ -13,7 +13,7 @@
  *    mwenz - Bug 363796 - Make setting of selection width of connections public
  *    mgorning - Bug 363186 - Allow modification of selection and hover state also for anchors
  *    mgorning - Bug 391523 - Revise getSelectionInfo...() in IToolBehaviorProvider
- *
+ *    fvelasco - Bug 323349 - Enable external invocation of features
  * </copyright>
  *
  *******************************************************************************/
@@ -27,6 +27,7 @@
 import org.eclipse.graphiti.features.context.IDoubleClickContext;
 import org.eclipse.graphiti.features.context.IPictogramElementContext;
 import org.eclipse.graphiti.features.context.ISingleClickContext;
+import org.eclipse.graphiti.features.context.impl.CustomContext;
 import org.eclipse.graphiti.features.custom.ICustomFeature;
 import org.eclipse.graphiti.features.impl.IIndependenceSolver;
 import org.eclipse.graphiti.mm.algorithms.AbstractText;
@@ -113,6 +114,21 @@
 	ICustomFeature getSingleClickFeature(ISingleClickContext context);
 
 	/**
+	 * Command features can do anything, but they are tied to an external
+	 * command. They can be invoked through a keybinding, a menu action or a
+	 * toolbar item.
+	 * 
+	 * @param context
+	 *            the context
+	 * @param hint
+	 *            the hint specified in the command binding
+	 * 
+	 * @return the feature
+	 * @since 0.10
+	 */
+	ICustomFeature getCommandFeature(CustomContext context, String hint);
+
+	/**
 	 * Returns decorators which will be used at rendering time to decorate the
 	 * graphical representation of the given pictogram element.<br>
 	 * Currently only decorators of type {@link IImageDecorator} are supported.
diff --git a/tests/org.eclipse.graphiti.testtool.sketch/icons/expand.png b/tests/org.eclipse.graphiti.testtool.sketch/icons/expand.png
new file mode 100644
index 0000000..35195f4
--- /dev/null
+++ b/tests/org.eclipse.graphiti.testtool.sketch/icons/expand.png
Binary files differ
diff --git a/tests/org.eclipse.graphiti.testtool.sketch/icons/shrink.png b/tests/org.eclipse.graphiti.testtool.sketch/icons/shrink.png
new file mode 100644
index 0000000..bd8b9c9
--- /dev/null
+++ b/tests/org.eclipse.graphiti.testtool.sketch/icons/shrink.png
Binary files differ
diff --git a/tests/org.eclipse.graphiti.testtool.sketch/plugin.xml b/tests/org.eclipse.graphiti.testtool.sketch/plugin.xml
index d022046..252f01a 100644
--- a/tests/org.eclipse.graphiti.testtool.sketch/plugin.xml
+++ b/tests/org.eclipse.graphiti.testtool.sketch/plugin.xml
@@ -55,6 +55,7 @@
             class="org.eclipse.graphiti.testtool.sketch.SketchDiagramTypeProvider"
             description="A sample sketch editor"
             id="org.eclipse.graphiti.testtool.sketch.SketchDiagramTypeProvider"
+            context="org.eclipse.graphiti.testtool.sketch.context"
             name="Sketch">
          <diagramType
                id="org.eclipse.graphiti.testtool.sketch.SketchDiagramType">
@@ -85,6 +86,108 @@
             id="org.eclipse.graphiti.testtool.sketch.SketchImageProvider">
       </imageProvider>
    </extension>
+   <extension
+         point="org.eclipse.ui.bindings">
+           <key
+        commandId="org.eclipse.graphiti.ui.featureExecutionCommand"
+        contextId="org.eclipse.graphiti.testtool.sketch.context"
+        schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
+        sequence="M1+J">
+     <parameter
+           id="org.eclipse.graphiti.ui.featureHint"
+           value="shrink">
+     </parameter>
+  </key>
+          <key
+        commandId="org.eclipse.graphiti.ui.featureExecutionCommand"
+        contextId="org.eclipse.graphiti.testtool.sketch.context"
+        schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
+        sequence="M1+L">
+     <parameter
+           id="org.eclipse.graphiti.ui.featureHint"
+           value="expand">
+     </parameter>
+  </key>
+          <key
+        commandId="org.eclipse.graphiti.ui.featureExecutionCommand"
+        contextId="org.eclipse.graphiti.testtool.sketch.context"
+        schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
+        sequence="M1+F2">
+     <parameter
+           id="org.eclipse.graphiti.ui.featureHint"
+           value="toggleColor">
+     </parameter>
+  </key>
+   </extension>
    
-  
+   <extension
+         point="org.eclipse.ui.menus">
+         <menuContribution
+            locationURI="toolbar:org.eclipse.ui.main.toolbar?after=additions">
+         <toolbar
+               label="Graphiti Sketch toolbar"
+               id="graphitiSketchToolbar">
+         </toolbar>
+      </menuContribution>
+      <menuContribution
+            allPopups="false"
+            locationURI="toolbar:graphitiSketchToolbar">
+         <command
+               commandId="org.eclipse.graphiti.ui.featureExecutionCommand"
+               icon="icons/shrink.png"
+               label="Shrink"
+               style="push"
+               tooltip="Shrink element">
+            <parameter
+                  name="org.eclipse.graphiti.ui.featureHint"
+                  value="shrink">
+            </parameter>
+            <visibleWhen
+                  checkEnabled="false">
+               <with
+                     variable="activeContexts">
+                  <iterate
+                        ifEmpty="false"
+                        operator="or">
+                     <equals
+                           value="org.eclipse.graphiti.testtool.sketch.context">
+                     </equals>
+                  </iterate>
+               </with>
+            </visibleWhen>
+         </command>
+         <command
+               commandId="org.eclipse.graphiti.ui.featureExecutionCommand"
+               icon="icons/expand.png"
+               label="Expand"
+               style="push"
+               tooltip="Expand element">
+            <parameter
+                  name="org.eclipse.graphiti.ui.featureHint"
+                  value="expand">
+            </parameter>
+            <visibleWhen
+                  checkEnabled="false">
+               <with
+                     variable="activeContexts">
+                  <iterate
+                        ifEmpty="false"
+                        operator="or">
+                     <equals
+                           value="org.eclipse.graphiti.testtool.sketch.context">
+                     </equals>
+                  </iterate>
+               </with>
+            </visibleWhen>
+         </command>
+      </menuContribution>
+   </extension>
+   <extension
+         point="org.eclipse.ui.contexts">
+      <context
+            id="org.eclipse.graphiti.testtool.sketch.context"
+            name="Sketch context"
+            parentId="org.eclipse.graphiti.ui.diagramEditor">
+      </context>
+   </extension>
 </plugin>
diff --git a/tests/org.eclipse.graphiti.testtool.sketch/src/org/eclipse/graphiti/testtool/sketch/ExpandFeature.java b/tests/org.eclipse.graphiti.testtool.sketch/src/org/eclipse/graphiti/testtool/sketch/ExpandFeature.java
new file mode 100644
index 0000000..5b7fd39
--- /dev/null
+++ b/tests/org.eclipse.graphiti.testtool.sketch/src/org/eclipse/graphiti/testtool/sketch/ExpandFeature.java
@@ -0,0 +1,56 @@
+/*******************************************************************************

+ * <copyright>

+ *

+ * Copyright (c) 2005, 2012 SAP AG.

+ * 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:

+ *    fvelasco - Bug 323349 External feature invocation

+ *

+ * </copyright>

+ *

+ *******************************************************************************/

+package org.eclipse.graphiti.testtool.sketch;

+

+import org.eclipse.graphiti.features.IFeatureProvider;

+import org.eclipse.graphiti.features.context.ICustomContext;

+import org.eclipse.graphiti.features.custom.AbstractCustomFeature;

+import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;

+import org.eclipse.graphiti.mm.pictograms.PictogramElement;

+

+public class ExpandFeature extends AbstractCustomFeature {

+

+	public static final String HINT = "expand"; //$NON-NLS-1$

+

+	public ExpandFeature(IFeatureProvider fp) {

+		super(fp);

+	}

+

+	@Override

+	public String getName() {

+		return "Expand"; //$NON-NLS-1$

+	}

+

+	@Override

+	public boolean canExecute(ICustomContext context) {

+		return context.getPictogramElements().length > 0;

+	}

+

+	public void execute(ICustomContext context) {

+		PictogramElement[] pes = context.getPictogramElements();

+		for (PictogramElement pe : pes) {

+			GraphicsAlgorithm ga = pe.getGraphicsAlgorithm();

+			if (ga == null)

+				continue;

+			int width = ga.getWidth();

+			int height = ga.getHeight();

+			ga.setWidth((int) (width * 1.1));

+			ga.setHeight((int) (height * 1.1));

+			layoutPictogramElement(pe);

+		}

+	}

+

+}

diff --git a/tests/org.eclipse.graphiti.testtool.sketch/src/org/eclipse/graphiti/testtool/sketch/ShrinkFeature.java b/tests/org.eclipse.graphiti.testtool.sketch/src/org/eclipse/graphiti/testtool/sketch/ShrinkFeature.java
new file mode 100644
index 0000000..c9f8732
--- /dev/null
+++ b/tests/org.eclipse.graphiti.testtool.sketch/src/org/eclipse/graphiti/testtool/sketch/ShrinkFeature.java
@@ -0,0 +1,56 @@
+/*******************************************************************************

+ * <copyright>

+ *

+ * Copyright (c) 2005, 2012 SAP AG.

+ * 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:

+ *    fvelasco - Bug 323349 External feature invocation

+ *

+ * </copyright>

+ *

+ *******************************************************************************/

+package org.eclipse.graphiti.testtool.sketch;

+

+import org.eclipse.graphiti.features.IFeatureProvider;

+import org.eclipse.graphiti.features.context.ICustomContext;

+import org.eclipse.graphiti.features.custom.AbstractCustomFeature;

+import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;

+import org.eclipse.graphiti.mm.pictograms.PictogramElement;

+

+public class ShrinkFeature extends AbstractCustomFeature {

+

+	public static final String HINT = "shrink"; //$NON-NLS-1$

+

+	public ShrinkFeature(IFeatureProvider fp) {

+		super(fp);

+	}

+

+	@Override

+	public String getName() {

+		return "Shrink"; //$NON-NLS-1$

+	}

+

+	@Override

+	public boolean canExecute(ICustomContext context) {

+		return context.getPictogramElements().length > 0;

+	}

+

+	public void execute(ICustomContext context) {

+		PictogramElement[] pes = context.getPictogramElements();

+		for (PictogramElement pe : pes) {

+			GraphicsAlgorithm ga = pe.getGraphicsAlgorithm();

+			if (ga == null)

+				continue;

+			int width = ga.getWidth();

+			int height = ga.getHeight();

+			ga.setWidth((int) (width * 0.9));

+			ga.setHeight((int) (height * 0.9));

+			layoutPictogramElement(pe);

+		}

+	}

+

+}

diff --git a/tests/org.eclipse.graphiti.testtool.sketch/src/org/eclipse/graphiti/testtool/sketch/SketchToolBehavior.java b/tests/org.eclipse.graphiti.testtool.sketch/src/org/eclipse/graphiti/testtool/sketch/SketchToolBehavior.java
index fdf4ae0..9706955 100644
--- a/tests/org.eclipse.graphiti.testtool.sketch/src/org/eclipse/graphiti/testtool/sketch/SketchToolBehavior.java
+++ b/tests/org.eclipse.graphiti.testtool.sketch/src/org/eclipse/graphiti/testtool/sketch/SketchToolBehavior.java
@@ -12,7 +12,7 @@
  *    mwenz - Bug 342869 - Image doesn't scale the contained SWT Image on resize
  *    mwenz - Bug 358255 - Add Border/Background decorators
  *    mgorning - Bug 391523 - Revise getSelectionInfo...() in IToolBehaviorProvider
- *
+ *    fvelasco - Bug 323349 - Enable external invocation of features
  * </copyright>
  *
  *******************************************************************************/
@@ -594,4 +594,19 @@
 		return "Edit Mode";
 	}
 
+	@Override
+	public ICustomFeature getCommandFeature(CustomContext context, String hint) {
+		PictogramElement[] pes = context.getPictogramElements();
+		if (pes.length > 0) {
+			if (ToggleColorFeature.HINT.equals(hint)) {
+				return new ToggleColorFeature(getFeatureProvider());
+			} else if (ShrinkFeature.HINT.equals(hint)) {
+				return new ShrinkFeature(getFeatureProvider());
+			} else if (ExpandFeature.HINT.equals(hint)) {
+				return new ExpandFeature(getFeatureProvider());
+			}
+		}
+		return super.getCommandFeature(context, hint);
+	}
+
 }
diff --git a/tests/org.eclipse.graphiti.testtool.sketch/src/org/eclipse/graphiti/testtool/sketch/ToggleColorFeature.java b/tests/org.eclipse.graphiti.testtool.sketch/src/org/eclipse/graphiti/testtool/sketch/ToggleColorFeature.java
new file mode 100644
index 0000000..4f06b8e
--- /dev/null
+++ b/tests/org.eclipse.graphiti.testtool.sketch/src/org/eclipse/graphiti/testtool/sketch/ToggleColorFeature.java
@@ -0,0 +1,56 @@
+/*******************************************************************************

+ * <copyright>

+ *

+ * Copyright (c) 2005, 2012 SAP AG.

+ * 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:

+ *    fvelasco - Bug 323349 External feature invocation

+ *

+ * </copyright>

+ *

+ *******************************************************************************/

+package org.eclipse.graphiti.testtool.sketch;

+

+import org.eclipse.graphiti.features.IFeatureProvider;

+import org.eclipse.graphiti.features.context.ICustomContext;

+import org.eclipse.graphiti.features.custom.AbstractCustomFeature;

+import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;

+import org.eclipse.graphiti.mm.algorithms.styles.Color;

+import org.eclipse.graphiti.mm.pictograms.PictogramElement;

+

+public class ToggleColorFeature extends AbstractCustomFeature {

+

+	public static final String HINT = "toggleColor"; //$NON-NLS-1$

+

+	public ToggleColorFeature(IFeatureProvider fp) {

+		super(fp);

+	}

+

+	@Override

+	public String getName() {

+		return "Toggle color"; //$NON-NLS-1$

+	}

+

+	@Override

+	public boolean canExecute(ICustomContext context) {

+		return context.getPictogramElements().length > 0;

+	}

+

+	public void execute(ICustomContext context) {

+		PictogramElement[] pes = context.getPictogramElements();

+		for (PictogramElement pe : pes) {

+			GraphicsAlgorithm ga = pe.getGraphicsAlgorithm();

+			if (ga == null)

+				continue;

+			Color background = ga.getBackground();

+			Color newBg = manageColor(background.getGreen(), background.getBlue(), background.getRed());

+			ga.setBackground(newBg);

+

+		}

+	}

+

+}