[573449] Detect workspace metamodels during blackbox resolution
diff --git a/plugins/org.eclipse.m2m.qvt.oml.runtime.jdt/src/org/eclipse/m2m/internal/qvt/oml/jdt/runtime/blackbox/JdtBlackboxProvider.java b/plugins/org.eclipse.m2m.qvt.oml.runtime.jdt/src/org/eclipse/m2m/internal/qvt/oml/jdt/runtime/blackbox/JdtBlackboxProvider.java
index 7cde9ea..a595e0e 100644
--- a/plugins/org.eclipse.m2m.qvt.oml.runtime.jdt/src/org/eclipse/m2m/internal/qvt/oml/jdt/runtime/blackbox/JdtBlackboxProvider.java
+++ b/plugins/org.eclipse.m2m.qvt.oml.runtime.jdt/src/org/eclipse/m2m/internal/qvt/oml/jdt/runtime/blackbox/JdtBlackboxProvider.java
@@ -25,10 +25,14 @@
 import org.eclipse.core.resources.IResourceProxyVisitor;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.emf.ecore.EPackage;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.m2m.internal.qvt.oml.QvtPlugin;
+import org.eclipse.m2m.internal.qvt.oml.blackbox.BlackboxException;
+import org.eclipse.m2m.internal.qvt.oml.blackbox.BlackboxUnit;
 import org.eclipse.m2m.internal.qvt.oml.blackbox.BlackboxUnitDescriptor;
+import org.eclipse.m2m.internal.qvt.oml.blackbox.LoadContext;
 import org.eclipse.m2m.internal.qvt.oml.blackbox.ResolutionContext;
 import org.eclipse.m2m.internal.qvt.oml.blackbox.java.JavaBlackboxProvider;
 import org.eclipse.m2m.internal.qvt.oml.emf.util.URIUtils;
@@ -40,6 +44,8 @@
 	
 	private static Map<IProject, Map<String, JdtDescriptor>> descriptors = new HashMap<IProject, Map<String, JdtDescriptor>>();
 	
+	private EPackage.Registry fPackageRegistry;
+	
 	@Override
 	public Collection<? extends BlackboxUnitDescriptor> getUnitDescriptors(ResolutionContext resolutionContext) {
 		IProject project = getProject(resolutionContext);
@@ -251,6 +257,16 @@
 						
 			return result;
 		}
+				
+		@Override
+		public BlackboxUnit load(LoadContext context) throws BlackboxException {
+			if (fPackageRegistry != context.getMetamodelRegistry()) {
+				unload();
+				fPackageRegistry = context.getMetamodelRegistry();
+			}
+						
+			return super.load(context);
+		}
 	}
 
 }
diff --git a/plugins/org.eclipse.m2m.qvt.oml/META-INF/MANIFEST.MF b/plugins/org.eclipse.m2m.qvt.oml/META-INF/MANIFEST.MF
index 5481b5a..f94eb6b 100644
--- a/plugins/org.eclipse.m2m.qvt.oml/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.m2m.qvt.oml/META-INF/MANIFEST.MF
@@ -106,7 +106,8 @@
  org.eclipse.m2m.qvt.oml.cst.parser;bundle-version="[3.0.0,4.0.0)";visibility:=reexport,
  org.eclipse.ocl.ecore;bundle-version="[3.1.0,4.0.0)";visibility:=reexport,
  org.eclipse.m2m.qvt.oml.ecore.imperativeocl;bundle-version="[3.0.0,4.0.0)";visibility:=reexport,
- org.eclipse.ocl;visibility:=reexport
+ org.eclipse.ocl;visibility:=reexport,
+ org.eclipse.emf.codegen.ecore;bundle-version="[2.8.0,3.0.0)"
 Eclipse-BuddyPolicy: registered
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/plugins/org.eclipse.m2m.qvt.oml/src/org/eclipse/m2m/internal/qvt/oml/blackbox/java/Java2QVTTypeResolver.java b/plugins/org.eclipse.m2m.qvt.oml/src/org/eclipse/m2m/internal/qvt/oml/blackbox/java/Java2QVTTypeResolver.java
index fbb6ca9..85a33f6 100644
--- a/plugins/org.eclipse.m2m.qvt.oml/src/org/eclipse/m2m/internal/qvt/oml/blackbox/java/Java2QVTTypeResolver.java
+++ b/plugins/org.eclipse.m2m.qvt.oml/src/org/eclipse/m2m/internal/qvt/oml/blackbox/java/Java2QVTTypeResolver.java
@@ -20,22 +20,31 @@
 import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
 
+import org.eclipse.emf.codegen.ecore.genmodel.GenClassifier;
 import org.eclipse.emf.common.util.BasicDiagnostic;
 import org.eclipse.emf.common.util.DiagnosticChain;
+import org.eclipse.emf.common.util.URI;
 import org.eclipse.emf.ecore.EClassifier;
 import org.eclipse.emf.ecore.EGenericType;
+import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.EOperation;
 import org.eclipse.emf.ecore.EPackage;
 import org.eclipse.emf.ecore.EStructuralFeature;
 import org.eclipse.emf.ecore.ETypeParameter;
 import org.eclipse.emf.ecore.EcoreFactory;
+import org.eclipse.emf.ecore.plugin.EcorePlugin;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.util.EcoreUtil;
 import org.eclipse.m2m.internal.qvt.oml.NLS;
 import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalModuleEnv;
 import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalStdLibrary;
+import org.eclipse.m2m.internal.qvt.oml.emf.util.EmfUtil;
+import org.eclipse.m2m.internal.qvt.oml.emf.util.ModelContent;
 import org.eclipse.m2m.qvt.oml.blackbox.java.JavaModelInstance;
 import org.eclipse.m2m.qvt.oml.util.Dictionary;
 import org.eclipse.m2m.qvt.oml.util.MutableList;
@@ -233,7 +242,7 @@
 		
 		SortedSet<EClassifier> subtypes = new TreeSet<EClassifier>(HIERARCHY_COMPARATOR_DESC);
 		SortedSet<EClassifier> supertypes = new TreeSet<EClassifier>(HIERARCHY_COMPARATOR_ASC);
-				
+								
 		Iterable<String> packageURIs = fPackageURIs.isEmpty() ? fEnv.getEPackageRegistry().keySet() : fPackageURIs;
 				
 		for (String nsURI : packageURIs) {
@@ -243,15 +252,18 @@
 				// early return for same-named classifier
 				EClassifier sameNamedClassifier = ePackage.getEClassifier(type.getSimpleName());
 								
-				if (sameNamedClassifier != null && type == sameNamedClassifier.getInstanceClass()) {
-					return sameNamedClassifier;
+				if (sameNamedClassifier != null) {
+					if (isMatchingInstanceClass(sameNamedClassifier, type)) {
+						return sameNamedClassifier;
+					}
 				}
 				
 				for (EClassifier eClassifier : ePackage.getEClassifiers()) {
-					Class<?> instanceClass = eClassifier.getInstanceClass();
-					if(type == instanceClass) {
+					if (isMatchingInstanceClass(eClassifier, type)) {
 						return eClassifier;
 					}
+					
+					Class<?> instanceClass = eClassifier.getInstanceClass();
 	
 					// fall-back strategy for resolving sub/super types 
 					if ((relationship & ALLOW_SUBTYPE) == ALLOW_SUBTYPE) {
@@ -278,7 +290,7 @@
 		
 		return null;
 	}
-	
+		
 	private boolean isAssignableFromTo(Class<?> from, Class<?> to) {
 		return from != null && to != null && to.isAssignableFrom(from);
 	}
@@ -391,5 +403,50 @@
 		
 		return null;
 	}
+	
+	private static boolean isMatchingInstanceClass(EClassifier eClassifier, Class<?> type) {
+		
+		Class<?> instanceClass = eClassifier.getInstanceClass();
+		
+		if(type == instanceClass) {
+			return true;
+		}
+		else if (instanceClass == null && EmfUtil.isDynamic(eClassifier)) {
+			EPackage ePackage = eClassifier.getEPackage();
+			String nsURI = ePackage.getNsURI();
+			
+			Map<String, URI> genModelMap = EcorePlugin.getEPackageNsURIToGenModelLocationMap(true);
+			URI genModelUri = genModelMap.get(nsURI);
+			
+			if (genModelUri != null) {														
+				ResourceSet resourceSet = ePackage.eResource().getResourceSet();
+				ModelContent genModelContent = EmfUtil.safeLoadModel(genModelUri, resourceSet);
+				
+				if (genModelContent != null) {
+					Iterator<EObject> iterator = EcoreUtil.getAllContents(genModelContent.getContent());
+									
+					while (iterator.hasNext()) {
+						EObject eObject = iterator.next();
+						
+						if (eObject instanceof GenClassifier) {
+							GenClassifier genClassifier = (GenClassifier) eObject;
+							
+							EClassifier ecoreClassifier = genClassifier.getEcoreClassifier();
+																
+							if (ecoreClassifier == eClassifier) {
+								String classifierInstanceName = genClassifier.getRawInstanceClassName();
+								
+								if (type.getName().equals(classifierInstanceName)) {
+									return true;
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+		
+		return false;
+	}
 
 }
diff --git a/plugins/org.eclipse.m2m.qvt.oml/src/org/eclipse/m2m/internal/qvt/oml/blackbox/java/JavaBlackboxProvider.java b/plugins/org.eclipse.m2m.qvt.oml/src/org/eclipse/m2m/internal/qvt/oml/blackbox/java/JavaBlackboxProvider.java
index cc000d7..8a85562 100644
--- a/plugins/org.eclipse.m2m.qvt.oml/src/org/eclipse/m2m/internal/qvt/oml/blackbox/java/JavaBlackboxProvider.java
+++ b/plugins/org.eclipse.m2m.qvt.oml/src/org/eclipse/m2m/internal/qvt/oml/blackbox/java/JavaBlackboxProvider.java
@@ -242,6 +242,14 @@
 			return unit;
 		}
 		
+		protected void unload() {
+			for (Map<String, List<EOperation>> operations : fModules.values()) {
+				operations.clear();
+			}
+			
+			unit = null;
+		}
+		
 	}
 
 }