Merge "Add xtext adapter feature"
diff --git a/features/org.eclipse.emf.henshin.sdk/feature.xml b/features/org.eclipse.emf.henshin.sdk/feature.xml
index e92b371..6e0ae03 100644
--- a/features/org.eclipse.emf.henshin.sdk/feature.xml
+++ b/features/org.eclipse.emf.henshin.sdk/feature.xml
@@ -197,6 +197,13 @@
          install-size="0"
          version="1.5.0.qualifier"
          unpack="false"/> 
+
+   <plugin
+         id="org.eclipse.emf.henshin.adapters.xtext"
+         download-size="0"
+         install-size="0"
+         version="1.5.0.qualifier"
+         unpack="false"/>
          
    <plugin
          id="org.eclipse.emf.henshin.text"
diff --git a/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/META-INF/MANIFEST.MF b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/META-INF/MANIFEST.MF
index bbd2f4b..adac9ee 100644
--- a/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/META-INF/MANIFEST.MF
+++ b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/META-INF/MANIFEST.MF
@@ -1,10 +1,20 @@
 Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
 Bundle-Name: Henshinsupport
-Bundle-SymbolicName: org.eclipse.emf.henshin.adapters.xtext
+Bundle-SymbolicName: org.eclipse.emf.henshin.adapters.xtext;singleton:=true
 Bundle-Version: 1.0.0.qualifier
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
-Export-Package: org.eclipse.emf.henshin.adapters.xtext
-Require-Bundle: org.eclipse.emf.henshin.model;bundle-version="1.4.0",
- org.eclipse.xtext.xbase;bundle-version="2.10.0",
- org.eclipse.xtext;bundle-version="2.10.0"
+Bundle-Activator: org.eclipse.emf.henshin.adapters.xtext.ui.Activator
+Export-Package: org.eclipse.emf.henshin.adapters.xtext.ui,
+ org.eclipse.emf.henshin.adapters.xtext
+Require-Bundle: org.eclipse.emf.henshin.model;bundle-version="1.4.0";visibility:=reexport,
+ org.eclipse.xtext.xbase;bundle-version="2.12.0",
+ org.eclipse.ui,
+ org.eclipse.core.runtime,
+ com.google.inject;bundle-version="3.0.0",
+ org.eclipse.emf.henshin.adapters.xtext;bundle-version="1.0.0";visibility:=reexport,
+ org.eclipse.xtext.ui.shared;bundle-version="2.12.0",
+ org.eclipse.xtext;bundle-version="2.12.0",
+ org.eclipse.xtext.ui;bundle-version="2.12.0",
+ org.eclipse.xtext.xbase.lib;bundle-version="2.12.0"
+Automatic-Module-Name: org.eclipse.emf.henshin.adapters.xtext
diff --git a/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/plugin.xml b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/plugin.xml
new file mode 100644
index 0000000..1ed37fe
--- /dev/null
+++ b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/plugin.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+	<!-- register the Xtext UI language services for Henshin to Xtext's registry -->
+   	<extension
+         point="org.eclipse.xtext.extension_resourceServiceProvider">
+	    <resourceServiceProvider
+	          class="org.eclipse.emf.henshin.adapters.xtext.ui.HenshinExecutableExtensionFactory:org.eclipse.xtext.ui.resource.generic.EmfResourceUIServiceProvider"
+	          uriExtension="henshin">
+	    </resourceServiceProvider>
+   	</extension>
+
+</plugin>
diff --git a/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/pom.xml b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/pom.xml
new file mode 100644
index 0000000..d62ac56
--- /dev/null
+++ b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/pom.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <relativePath>../../../pom.xml</relativePath>
+    <groupId>org.eclipse.emf.henshin</groupId>
+    <artifactId>parent</artifactId>
+    <version>1.5.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>org.eclipse.emf.henshin.adapters.xtext</artifactId>
+  <packaging>eclipse-plugin</packaging>
+
+</project>
diff --git a/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/src/org/eclipse/emf/henshin/adapters/xtext/HenshinQualifiedNameProvider.xtend b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/src/org/eclipse/emf/henshin/adapters/xtext/HenshinQualifiedNameProvider.xtend
index bbc46df..62e2511 100644
--- a/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/src/org/eclipse/emf/henshin/adapters/xtext/HenshinQualifiedNameProvider.xtend
+++ b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/src/org/eclipse/emf/henshin/adapters/xtext/HenshinQualifiedNameProvider.xtend
@@ -11,10 +11,10 @@
 
 class HenshinQualifiedNameProvider extends IQualifiedNameProvider.AbstractImpl {
 	
-	private static val HENSHIN_CACHE_KEY ="HENSHIN_CACHE_KEY"
+	static val HENSHIN_CACHE_KEY ="HENSHIN_CACHE_KEY"
 	
 	@Inject
-	private val IResourceScopeCache cache = IResourceScopeCache.NullImpl.INSTANCE;
+	val IResourceScopeCache cache = IResourceScopeCache.NullImpl.INSTANCE;
 	
 	override getFullyQualifiedName(EObject obj) {
 		cache.get(Tuples.pair(obj, HENSHIN_CACHE_KEY), obj.eResource(), [
diff --git a/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/src/org/eclipse/emf/henshin/adapters/xtext/NamingHelper.xtend b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/src/org/eclipse/emf/henshin/adapters/xtext/NamingHelper.xtend
index e1e361a..48bf642 100644
--- a/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/src/org/eclipse/emf/henshin/adapters/xtext/NamingHelper.xtend
+++ b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/src/org/eclipse/emf/henshin/adapters/xtext/NamingHelper.xtend
@@ -1,5 +1,6 @@
 package org.eclipse.emf.henshin.adapters.xtext
 
+import javax.inject.Provider
 import org.eclipse.emf.ecore.EObject
 import org.eclipse.emf.henshin.model.Attribute
 import org.eclipse.emf.henshin.model.Edge
@@ -8,6 +9,14 @@
 class NamingHelper {
 	static dispatch def name(EObject eo) { null }
 	static dispatch def name(NamedElement ne) { ne.name }
-	static dispatch def name(Edge e) { '''[«e.source.name»->«e.target.name»:«e.type.name»]'''.toString }
+	static dispatch def name(Edge e) { '''[«safe([e.source.name])»->«safe([e.target.name])»:«safe([e.type.name])»]'''.toString }
 	static dispatch def name(Attribute a) { if (a.type !== null) { a.type.name } else "" }
+	
+	private static def safe(Provider<String> expression) {
+		try {
+			expression.get
+		} catch (NullPointerException npe) {
+			""
+		}
+	}
 }
\ No newline at end of file
diff --git a/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/src/org/eclipse/emf/henshin/adapters/xtext/ui/Activator.java b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/src/org/eclipse/emf/henshin/adapters/xtext/ui/Activator.java
new file mode 100644
index 0000000..c48f8f5
--- /dev/null
+++ b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/src/org/eclipse/emf/henshin/adapters/xtext/ui/Activator.java
@@ -0,0 +1,72 @@
+package org.eclipse.emf.henshin.adapters.xtext.ui;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.eclipse.xtext.ui.shared.SharedStateModule;
+import org.osgi.framework.BundleContext;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+import com.google.inject.util.Modules;
+
+import org.eclipse.emf.henshin.adapters.xtext.HenshinRuntimeModule;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+	// The plug-in ID
+	public static final String PLUGIN_ID = "org.eclipse.emf.henshin.adapters.xtext.ui"; //$NON-NLS-1$
+
+	// The shared instance
+	private static Activator plugin;
+	
+	private Injector injector;
+
+	/**
+	 * The constructor
+	 */
+	public Activator() {
+	}
+
+	public Injector getInjector() {
+		return injector;
+	}
+
+	private void initializeInjector() {
+		injector = Guice.createInjector(
+			Modules.override(Modules.override(new HenshinRuntimeModule()).with(new HenshinUiModule(plugin))).with(
+				new SharedStateModule()));
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+		plugin = this;
+		initializeInjector();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+	 */
+	public void stop(BundleContext context) throws Exception {
+		plugin = null;
+		injector = null;
+		super.stop(context);
+	}
+
+	/**
+	 * Returns the shared instance
+	 *
+	 * @return the shared instance
+	 */
+	public static Activator getDefault() {
+		return plugin;
+	}
+
+}
diff --git a/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/src/org/eclipse/emf/henshin/adapters/xtext/ui/HenshinExecutableExtensionFactory.xtend b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/src/org/eclipse/emf/henshin/adapters/xtext/ui/HenshinExecutableExtensionFactory.xtend
new file mode 100644
index 0000000..2fa3f2a
--- /dev/null
+++ b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/src/org/eclipse/emf/henshin/adapters/xtext/ui/HenshinExecutableExtensionFactory.xtend
@@ -0,0 +1,19 @@
+package org.eclipse.emf.henshin.adapters.xtext.ui
+
+import org.eclipse.xtext.ui.guice.AbstractGuiceAwareExecutableExtensionFactory
+import org.osgi.framework.Bundle
+import com.google.inject.Injector
+
+/** 
+ * Instantiates classes declared in the plugin.xml using the DI container.
+ */
+class HenshinExecutableExtensionFactory extends AbstractGuiceAwareExecutableExtensionFactory {
+	
+	override protected Bundle getBundle() {
+		return Activator.getDefault().getBundle()
+	}
+
+	override protected Injector getInjector() {
+		return Activator.getDefault().getInjector()
+	}
+}
diff --git a/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/src/org/eclipse/emf/henshin/adapters/xtext/ui/HenshinUiModule.xtend b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/src/org/eclipse/emf/henshin/adapters/xtext/ui/HenshinUiModule.xtend
new file mode 100644
index 0000000..6ddc608
--- /dev/null
+++ b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/src/org/eclipse/emf/henshin/adapters/xtext/ui/HenshinUiModule.xtend
@@ -0,0 +1,11 @@
+package org.eclipse.emf.henshin.adapters.xtext.ui
+
+import org.eclipse.ui.plugin.AbstractUIPlugin
+import org.eclipse.xtext.ui.resource.generic.EmfUiModule
+
+class HenshinUiModule extends EmfUiModule {
+
+	new(AbstractUIPlugin plugin) {
+		super(plugin)
+	}
+}
diff --git a/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/xtend-gen/org/eclipse/emf/henshin/adapters/xtext/.HenshinQualifiedNameProvider.java._trace b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/xtend-gen/org/eclipse/emf/henshin/adapters/xtext/.HenshinQualifiedNameProvider.java._trace
index 9fa4594..c29bcb1 100644
--- a/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/xtend-gen/org/eclipse/emf/henshin/adapters/xtext/.HenshinQualifiedNameProvider.java._trace
+++ b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/xtend-gen/org/eclipse/emf/henshin/adapters/xtext/.HenshinQualifiedNameProvider.java._trace
Binary files differ
diff --git a/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/xtend-gen/org/eclipse/emf/henshin/adapters/xtext/.HenshinQualifiedNameProvider.xtendbin b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/xtend-gen/org/eclipse/emf/henshin/adapters/xtext/.HenshinQualifiedNameProvider.xtendbin
index 0ff70b9..79e4462 100644
--- a/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/xtend-gen/org/eclipse/emf/henshin/adapters/xtext/.HenshinQualifiedNameProvider.xtendbin
+++ b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/xtend-gen/org/eclipse/emf/henshin/adapters/xtext/.HenshinQualifiedNameProvider.xtendbin
Binary files differ
diff --git a/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/xtend-gen/org/eclipse/emf/henshin/adapters/xtext/.NamingHelper.java._trace b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/xtend-gen/org/eclipse/emf/henshin/adapters/xtext/.NamingHelper.java._trace
index f1ad9c6..ba7b43d 100644
--- a/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/xtend-gen/org/eclipse/emf/henshin/adapters/xtext/.NamingHelper.java._trace
+++ b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/xtend-gen/org/eclipse/emf/henshin/adapters/xtext/.NamingHelper.java._trace
Binary files differ
diff --git a/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/xtend-gen/org/eclipse/emf/henshin/adapters/xtext/.NamingHelper.xtendbin b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/xtend-gen/org/eclipse/emf/henshin/adapters/xtext/.NamingHelper.xtendbin
index fda6f7e..c5bfc19 100644
--- a/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/xtend-gen/org/eclipse/emf/henshin/adapters/xtext/.NamingHelper.xtendbin
+++ b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/xtend-gen/org/eclipse/emf/henshin/adapters/xtext/.NamingHelper.xtendbin
Binary files differ
diff --git a/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/xtend-gen/org/eclipse/emf/henshin/adapters/xtext/HenshinQualifiedNameProvider.java b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/xtend-gen/org/eclipse/emf/henshin/adapters/xtext/HenshinQualifiedNameProvider.java
index 605df59..d358fc8 100644
--- a/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/xtend-gen/org/eclipse/emf/henshin/adapters/xtext/HenshinQualifiedNameProvider.java
+++ b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/xtend-gen/org/eclipse/emf/henshin/adapters/xtext/HenshinQualifiedNameProvider.java
@@ -1,27 +1,23 @@
 package org.eclipse.emf.henshin.adapters.xtext;
 
+import com.google.inject.Inject;
+import com.google.inject.Provider;
 import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.henshin.adapters.xtext.NamingHelper;
 import org.eclipse.xtext.naming.IQualifiedNameProvider;
 import org.eclipse.xtext.naming.QualifiedName;
 import org.eclipse.xtext.util.IResourceScopeCache;
-import org.eclipse.xtext.util.Pair;
 import org.eclipse.xtext.util.Tuples;
 
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
 @SuppressWarnings("all")
 public class HenshinQualifiedNameProvider extends IQualifiedNameProvider.AbstractImpl {
-  private final static String HENSHIN_CACHE_KEY = "HENSHIN_CACHE_KEY";
+  private static final String HENSHIN_CACHE_KEY = "HENSHIN_CACHE_KEY";
   
   @Inject
   private final IResourceScopeCache cache = IResourceScopeCache.NullImpl.INSTANCE;
   
   @Override
   public QualifiedName getFullyQualifiedName(final EObject obj) {
-    Pair<EObject, String> _pair = Tuples.<EObject, String>pair(obj, HenshinQualifiedNameProvider.HENSHIN_CACHE_KEY);
-    Resource _eResource = obj.eResource();
     final Provider<QualifiedName> _function = () -> {
       QualifiedName _xblockexpression = null;
       {
@@ -39,8 +35,7 @@
             if (_tripleNotEquals) {
               QualifiedName _xblockexpression_2 = null;
               {
-                EObject _eContainer_1 = obj.eContainer();
-                final QualifiedName parentsQualifiedName = this.getFullyQualifiedName(_eContainer_1);
+                final QualifiedName parentsQualifiedName = this.getFullyQualifiedName(obj.eContainer());
                 QualifiedName _xifexpression_2 = null;
                 if ((parentsQualifiedName == null)) {
                   _xifexpression_2 = null;
@@ -61,6 +56,6 @@
       }
       return _xblockexpression;
     };
-    return this.cache.<QualifiedName>get(_pair, _eResource, _function);
+    return this.cache.<QualifiedName>get(Tuples.<EObject, String>pair(obj, HenshinQualifiedNameProvider.HENSHIN_CACHE_KEY), obj.eResource(), _function);
   }
 }
diff --git a/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/xtend-gen/org/eclipse/emf/henshin/adapters/xtext/NamingHelper.java b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/xtend-gen/org/eclipse/emf/henshin/adapters/xtext/NamingHelper.java
index 4be4cae..c9cf01f 100644
--- a/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/xtend-gen/org/eclipse/emf/henshin/adapters/xtext/NamingHelper.java
+++ b/plugins/adapters/org.eclipse.emf.henshin.adapters.xtext/xtend-gen/org/eclipse/emf/henshin/adapters/xtext/NamingHelper.java
@@ -1,15 +1,14 @@
 package org.eclipse.emf.henshin.adapters.xtext;
 
 import java.util.Arrays;
-
+import javax.inject.Provider;
 import org.eclipse.emf.ecore.EAttribute;
 import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.EReference;
 import org.eclipse.emf.henshin.model.Attribute;
 import org.eclipse.emf.henshin.model.Edge;
 import org.eclipse.emf.henshin.model.NamedElement;
-import org.eclipse.emf.henshin.model.Node;
 import org.eclipse.xtend2.lib.StringConcatenation;
+import org.eclipse.xtext.xbase.lib.Exceptions;
 
 @SuppressWarnings("all")
 public class NamingHelper {
@@ -24,17 +23,23 @@
   protected static String _name(final Edge e) {
     StringConcatenation _builder = new StringConcatenation();
     _builder.append("[");
-    Node _source = e.getSource();
-    String _name = _source.getName();
-    _builder.append(_name, "");
+    final Provider<String> _function = () -> {
+      return e.getSource().getName();
+    };
+    String _safe = NamingHelper.safe(_function);
+    _builder.append(_safe);
     _builder.append("->");
-    Node _target = e.getTarget();
-    String _name_1 = _target.getName();
-    _builder.append(_name_1, "");
+    final Provider<String> _function_1 = () -> {
+      return e.getTarget().getName();
+    };
+    String _safe_1 = NamingHelper.safe(_function_1);
+    _builder.append(_safe_1);
     _builder.append(":");
-    EReference _type = e.getType();
-    String _name_2 = _type.getName();
-    _builder.append(_name_2, "");
+    final Provider<String> _function_2 = () -> {
+      return e.getType().getName();
+    };
+    String _safe_2 = NamingHelper.safe(_function_2);
+    _builder.append(_safe_2);
     _builder.append("]");
     return _builder.toString();
   }
@@ -44,14 +49,27 @@
     EAttribute _type = a.getType();
     boolean _tripleNotEquals = (_type != null);
     if (_tripleNotEquals) {
-      EAttribute _type_1 = a.getType();
-      _xifexpression = _type_1.getName();
+      _xifexpression = a.getType().getName();
     } else {
       _xifexpression = "";
     }
     return _xifexpression;
   }
   
+  private static String safe(final Provider<String> expression) {
+    String _xtrycatchfinallyexpression = null;
+    try {
+      _xtrycatchfinallyexpression = expression.get();
+    } catch (final Throwable _t) {
+      if (_t instanceof NullPointerException) {
+        _xtrycatchfinallyexpression = "";
+      } else {
+        throw Exceptions.sneakyThrow(_t);
+      }
+    }
+    return _xtrycatchfinallyexpression;
+  }
+  
   public static String name(final EObject a) {
     if (a instanceof Attribute) {
       return _name((Attribute)a);
diff --git a/pom.xml b/pom.xml
index 816faf4..cf17fa4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -31,6 +31,7 @@
 		<module>plugins/org.eclipse.emf.henshin.text.ide</module>
 		<module>plugins/org.eclipse.emf.henshin.text.transformation</module>
 		<module>plugins/org.eclipse.emf.henshin.text.ui</module>
+		<module>plugins/adapters/org.eclipse.emf.henshin.adapters.xtext</module>
 		<module>plugins/variability/org.eclipse.emf.henshin.variability</module>
 		<module>plugins/variability/org.eclipse.emf.henshin.variability.configuration</module>
 		<module>plugins/variability/org.eclipse.emf.henshin.variability.configuration.ui</module>