[ocl2qvtp] - Creating a selfcontained qvtp.qvtcas. i.e. no references to
external OCL documents
diff --git a/plugins/org.eclipse.qvtd.cs2as.compiler/src/org/eclipse/qvtd/cs2as/compiler/internal/OCL2QVTiCompilerChain.java b/plugins/org.eclipse.qvtd.cs2as.compiler/src/org/eclipse/qvtd/cs2as/compiler/internal/OCL2QVTiCompilerChain.java
index ab1218f..756c086 100644
--- a/plugins/org.eclipse.qvtd.cs2as.compiler/src/org/eclipse/qvtd/cs2as/compiler/internal/OCL2QVTiCompilerChain.java
+++ b/plugins/org.eclipse.qvtd.cs2as.compiler/src/org/eclipse/qvtd/cs2as/compiler/internal/OCL2QVTiCompilerChain.java
@@ -72,7 +72,7 @@
 	
 	protected Resource ocl2qvtp(URI oclURI) throws IOException {
 		OCL2QVTp ocl2qvtp = new OCL2QVTp(environmentFactory, traceabilityPropName);
-		Resource pResource = ocl2qvtp.run(environmentFactory.getMetamodelManager().getASResourceSet(), oclURI);
+		Resource pResource = ocl2qvtp.run(environmentFactory.getMetamodelManager().getASResourceSet(), oclURI, extendedASUris);
 		saveResource(pResource, QVTP_STEP);
 		return pResource;
 	}
diff --git a/plugins/org.eclipse.qvtd.cs2as.compiler/src/org/eclipse/qvtd/cs2as/compiler/internal/OCL2QVTp.java b/plugins/org.eclipse.qvtd.cs2as.compiler/src/org/eclipse/qvtd/cs2as/compiler/internal/OCL2QVTp.java
index 53de7ed..fd8e032 100644
--- a/plugins/org.eclipse.qvtd.cs2as.compiler/src/org/eclipse/qvtd/cs2as/compiler/internal/OCL2QVTp.java
+++ b/plugins/org.eclipse.qvtd.cs2as.compiler/src/org/eclipse/qvtd/cs2as/compiler/internal/OCL2QVTp.java
@@ -6,12 +6,15 @@
 import static org.eclipse.qvtd.cs2as.compiler.internal.OCL2QVTpUtil.getAllContentsIncludingSelf;
 import static org.eclipse.qvtd.cs2as.compiler.internal.OCL2QVTpUtil.getCreationMappingName;
 import static org.eclipse.qvtd.cs2as.compiler.internal.OCL2QVTpUtil.getExpressionContextType;
+import static org.eclipse.qvtd.cs2as.compiler.internal.OCL2QVTpUtil.getModel;
 import static org.eclipse.qvtd.cs2as.compiler.internal.OCL2QVTpUtil.getOwningPackage;
 import static org.eclipse.qvtd.cs2as.compiler.internal.OCL2QVTpUtil.getSuperClasses;
 import static org.eclipse.qvtd.cs2as.compiler.internal.OCL2QVTpUtil.getUpdateMappingName;
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -20,6 +23,7 @@
 import java.util.logging.Logger;
 import java.util.stream.Collectors;
 
+import org.eclipse.emf.common.util.TreeIterator;
 import org.eclipse.emf.common.util.URI;
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.resource.Resource;
@@ -31,6 +35,7 @@
 import org.eclipse.ocl.pivot.IfExp;
 import org.eclipse.ocl.pivot.Import;
 import org.eclipse.ocl.pivot.Model;
+import org.eclipse.ocl.pivot.Namespace;
 import org.eclipse.ocl.pivot.OCLExpression;
 import org.eclipse.ocl.pivot.Operation;
 import org.eclipse.ocl.pivot.OperationCallExp;
@@ -44,8 +49,11 @@
 import org.eclipse.ocl.pivot.TypeExp;
 import org.eclipse.ocl.pivot.Variable;
 import org.eclipse.ocl.pivot.VariableExp;
+import org.eclipse.ocl.pivot.ids.PackageId;
+import org.eclipse.ocl.pivot.ids.TypeId;
 import org.eclipse.ocl.pivot.utilities.EnvironmentFactory;
 import org.eclipse.qvtd.pivot.qvtbase.QVTbaseFactory;
+import org.eclipse.qvtd.pivot.qvtbase.Rule;
 import org.eclipse.qvtd.pivot.qvtbase.Transformation;
 import org.eclipse.qvtd.pivot.qvtbase.TypedModel;
 import org.eclipse.qvtd.pivot.qvtcore.CoreModel;
@@ -60,10 +68,123 @@
 
 public class OCL2QVTp {
 
+	private static class ClonsMap {
+		
+		private static class ImportKey {
+			
+			private Import anImport;
+			
+			public ImportKey (Import anImport) {
+				this.anImport = anImport;
+			}
+			
+			@Override
+			public String toString() {
+				// FIXME we may want to distinguish between Package and Model imports
+				return getModel().apply(anImport.getImportedNamespace()).toString();
+			}
+			
+			@Override
+			public int hashCode() {
+				return toString().hashCode();
+			}
+			
+			@Override
+			public boolean equals(Object obj) {
+				if (obj instanceof ImportKey) {
+					return obj.toString().equals(toString());
+				}
+				return super.equals(obj);
+			}
+		}
+		
+		private Model newModel;
+		private Map<PackageId, Package> p2p = new HashMap<PackageId,Package>();
+		private Map<TypeId, Class> c2c = new HashMap<TypeId,Class>();
+		private Map<Operation, Operation> o2o = new HashMap<Operation,Operation>();
+		private Map<ImportKey, Import> i2i = new HashMap<ImportKey,Import>();
+		
+		public ClonsMap(Model newModel) {
+			this.newModel = newModel;
+			for (Import anImport : newModel.getOwnedImports()) { // We introduce the newModel ownedImports as if they were clonned to avoid duplications
+				ImportKey importKey = new ImportKey(anImport);
+				i2i.put(importKey,anImport);
+			}
+		}
+		
+		@NonNull
+		public Operation getNewOperation(Operation oldOperation) { 
+		
+			Operation id = oldOperation;
+			Operation newOp = o2o.get(id);
+			if (newOp == null) { // If not cloned yet
+				newOp = EcoreUtil.copy(oldOperation); // NB self variable should be copied
+				o2o.put(id,newOp);
+				Class newClass = getNewClass(oldOperation.getOwningClass());
+				newClass.getOwnedOperations().add(newOp);
+			}
+			return newOp;
+		}
+		
+		@Nullable
+		public Operation getCachedOperation(Operation oldOperation) {
+			Operation op = o2o.get(oldOperation);
+			assert(op != null);
+			return op; 
+		}
+		
+		@NonNull
+		private Class getNewClass(Class oldClass) { 
+			
+			TypeId id = oldClass.getTypeId();
+			Class newClass = c2c.get(id);
+			if (newClass == null) { // If not cloned yet
+				newClass = EcoreUtil.copy(oldClass);
+				newClass.getOwnedOperations().clear(); // We remove all operations. They we will be manually cloned
+				c2c.put(id,newClass);
+				Package newPackage = getNewPackage(oldClass.getOwningPackage());
+				newPackage.getOwnedClasses().add(newClass);
+			}
+			return newClass;
+		}		
+		
+		
+		@NonNull
+		private Package getNewPackage(Package oldPackage) { 
+			
+			PackageId id = oldPackage.getPackageId();
+			Package newPackage = p2p.get(id);
+			if (newPackage == null) { // If not cloned yet
+				newPackage = PivotFactory.eINSTANCE.createPackage();
+				newPackage.setName(oldPackage.getName());
+				newPackage.setURI(oldPackage.getURI());
+				newPackage.setNsPrefix(oldPackage.getNsPrefix());
+				p2p.put(id,newPackage);
+				newModel.getOwnedPackages().add(newPackage);
+			}
+			return newPackage;
+		}	
+		
+		@NonNull
+		public Import getNewPackageImport(Import anImport) {
+			
+			ImportKey importKey = new ImportKey(anImport);
+			Import newImport = i2i.get(importKey);
+			if (newImport == null) {
+				newImport = EcoreUtil.copy(anImport);
+				i2i.put(importKey, newImport);
+				newModel.getOwnedImports().add(newImport);
+			}
+			return newImport;
+		}
+	}
 	private @NonNull Logger logger = Logger.getLogger(getClass().getName());
 	private @NonNull EnvironmentFactory envFact;
 	private @NonNull String traceabilityPropName;
 	private @Nullable Map<?,?> saveOptions;
+	private Operation oclAsTypeOp;
+	//private Operation oclAnyEqualsOp;
+	private Operation notOp;
 	
 	public static final @NonNull String RIGHT_MODEL_TYPE_NAME = "rightAS";
 	public static final @NonNull String LEFT_MODEL_TYPE_NAME = "leftCS";
@@ -71,9 +192,22 @@
 	public OCL2QVTp(@NonNull EnvironmentFactory envFact, @NonNull String traceabilityPropName) {
 		this.envFact = envFact;
 		this.traceabilityPropName = traceabilityPropName;
+		this.oclAsTypeOp = getOclAnyOclAsTypeOp();
+	//	this.oclAnyEqualsOp = getOclAnyEqualsOp();
+		this.notOp = getBooleanNotOp();
 	}
 	
-	public Resource run(ResourceSet resourceSet, URI oclDocURI) {
+	public Resource run(ResourceSet resourceSet, URI oclDocURI, List<URI> extendedURIs) {
+		return run(resourceSet, oclDocURI, extendedURIs,true); 
+	}
+	
+	/**
+	 * @param resourceSet
+	 * @param oclDocURI
+	 * @param selfContainedTransformation <code>true</code> if any referred OCL operation (from imported OCL docs) should be cloned in the new QVT transformation
+	 * @return
+	 */
+	public Resource run(ResourceSet resourceSet, URI oclDocURI, List<URI> extendedURIs, boolean selfContainedTransformation) {
 		
 		if (!"oclas".equals(oclDocURI.fileExtension())) {
 			throw new IllegalArgumentException(oclDocURI.toString() + " is not an .oclas URI");
@@ -82,12 +216,16 @@
 		EObject rootModel = input.getContents().get(0);
 		if (rootModel instanceof Model) {
 			Model model = (Model) rootModel;
-			CoreModel outputModel = oclModelToImperativeModel().apply(model);
+			CoreModel outputModel = oclModelToImperativeModel(selfContainedTransformation).apply(model);
 			
 			// We create the output resource
 			URI outputURI = oclDocURI.trimFileExtension().trimFileExtension().appendFileExtension("qvtp.qvtcas");
 			Resource outputResource = resourceSet.createResource(outputURI);
 			outputResource.getContents().add(outputModel);
+			if (selfContainedTransformation) {
+				ClonsMap copyHelper = cloneImportedOperationsAndEcoreImports(model, outputModel, extendedURIs);
+				updateOpCallExpressions(outputModel, copyHelper);
+			}
 			return outputResource;
 		
 		} else {
@@ -98,7 +236,7 @@
 	private TypedModel leftTypedModel = QVTbaseFactory.eINSTANCE.createTypedModel();
 	private TypedModel rightTypedModel = QVTbaseFactory.eINSTANCE.createTypedModel();
 	
-	public Function<Model, CoreModel> oclModelToImperativeModel() {
+	public Function<Model, CoreModel> oclModelToImperativeModel(boolean selfContainedTransf) {
 		return oclModel -> {
 		
 			CoreModel iModel = QVTcoreFactory.eINSTANCE.createCoreModel();
@@ -117,6 +255,7 @@
 		
 		iModel.setExternalURI(oclModel.getExternalURI().replace(".ocl", ".qvtp.qvtcas")); // When the externalURI is set, also is its name
 		iModel.getOwnedImports().addAll(oclModel.getOwnedImports().stream()
+				.filter(importToImportGuard(selfContainedTransf))
 				.map(importToImport())
 				.collect(Collectors.toList()));
 		
@@ -155,6 +294,16 @@
 		};
 	}
 	
+	// When we have a selfContainedTransf, we want to skip those imports related to .ocl documents
+	protected Predicate<@NonNull Import> importToImportGuard(boolean selfContainedTransf) {
+		return oclImport -> {
+			if (selfContainedTransf &&
+				isOclDocImport().test(oclImport)) {
+				return false;
+			}
+			return true;
+		};
+	}
 	public Function<@NonNull Import, @NonNull Import> importToImport(){
 		return oclImport -> {
 		Import pImport = PivotFactory.eINSTANCE.createImport();
@@ -243,7 +392,7 @@
 			
 			OperationCallExp asTypeOpCallExp = PivotFactory.eINSTANCE.createOperationCallExp();
 			asTypeOpCallExp.setOwnedSource(astPropCallExp);
-			asTypeOpCallExp.setReferredOperation(getOclAnyOclAsTypeOp());
+			asTypeOpCallExp.setReferredOperation(oclAsTypeOp);
 			asTypeOpCallExp.setType(shadowExp.getType());
 			
 			TypeExp argTypeExp = PivotFactory.eINSTANCE.createTypeExp();
@@ -337,7 +486,81 @@
 		//We need to replace the OCL refered "self" varible by the QVTi domain "leftVar" and ast op calls
 		return doReplacements(newInitExp, leftVar);
 	}
+
 	
+	private  ClonsMap cloneImportedOperationsAndEcoreImports(Model oldModel, Model newModel, List<URI> extendedASURIs) {
+		
+		ClonsMap clonsMap = new ClonsMap(newModel);
+		doCloneImportedOperationsAndImports(oldModel, clonsMap, new HashSet<Model>(), extendedASURIs);
+		return clonsMap;
+	}
+	
+	private void doCloneImportedOperationsAndImports(Model oldModel, ClonsMap clonsMap, Set<Model> visitedModels, List<URI> extendedASURIs) {
+		
+		if (!visitedModels.contains(oldModel)) {
+			visitedModels.add(oldModel);
+			for (Import anImport : oldModel.getOwnedImports()) {
+				if (isOclDocImport().test(anImport)
+					&& ! isExtendedCS2ASImport(extendedASURIs).test(anImport)) {
+					Model model = getModel().apply(anImport.getImportedNamespace());
+					for (Package p : model.getOwnedPackages()) {
+						for (Class c : p.getOwnedClasses()) {
+							for (Operation o : c.getOwnedOperations()) {
+								clonsMap.getNewOperation(o);
+							}
+						}
+					}
+					doCloneImportedOperationsAndImports(model,clonsMap,visitedModels, extendedASURIs);
+				} else if (isEcoreDocImport().test(anImport)) {
+					clonsMap.getNewPackageImport(anImport);
+				}
+			}
+		}
+	}
+	
+	private void updateOpCallExpressions(Model newModel, ClonsMap copyHelper) {
+		
+		for (Package p : newModel.getOwnedPackages()) {
+			for (Class c : p.getOwnedClasses()) {
+				for (Operation o : c.getOwnedOperations()) {
+					TreeIterator<EObject> contents = o.eAllContents();
+					while (contents.hasNext()) {
+						EObject eObject = contents.next();
+						if (eObject instanceof OperationCallExp) {
+							OperationCallExp opCallExp = (OperationCallExp) eObject;
+							if (isAstOpCallExp().test(opCallExp)) {
+								EcoreUtil.replace(opCallExp, rewriteAstOperationCallAsTypeCastedPropertyCall(opCallExp));
+							} else {
+								updateOpCallExpression(opCallExp, copyHelper);
+							}
+						}
+					}
+				}
+				if (c instanceof Transformation) {
+					Transformation t = (Transformation) c;
+					for (Rule r : t.getRule()) {
+						TreeIterator<EObject> contents = r.eAllContents();
+						while (contents.hasNext()) {
+							EObject eObject = contents.next();
+							if (eObject instanceof OperationCallExp) {
+								updateOpCallExpression((OperationCallExp) eObject, copyHelper);
+							}
+						}
+					}
+				}
+			}
+		}
+
+	}
+	
+	private void updateOpCallExpression(OperationCallExp opCallExp, ClonsMap copyHelper) {
+		Operation oclOp = opCallExp.getReferredOperation();
+		if (isOclDocOp().test(oclOp) // We are only interested in ops belonging to a model corresponding to an Ocl Doc
+			&& !refersToContainingOperation().test(opCallExp)) { // and opCallExps that refer to operation that contains them
+			Operation newOp = copyHelper.getCachedOperation(oclOp);
+			opCallExp.setReferredOperation(newOp);
+		}
+	}
 	private OCLExpression doReplacements(OCLExpression oclExp, Variable leftVar) {
 		
 		List<OCLExpression> result = new ArrayList<OCLExpression>();// Simple work aroound to the forEach constraint ;
@@ -347,34 +570,7 @@
 				((VariableExp)x).setReferredVariable(leftVar);
 			} else if(isAstOpCallExp().test(x)) {
 				OperationCallExp exp = (OperationCallExp) x;
-				PropertyCallExp astPropCallExp = PivotFactory.eINSTANCE.createPropertyCallExp();
-				astPropCallExp.setOwnedSource(exp.getOwnedSource());
-				astPropCallExp.setReferredProperty(getTraceabilityProperty(astPropCallExp.getOwnedSource().getType()));
-				astPropCallExp.setType(astPropCallExp.getReferredProperty().getType());
-				// Copying remaining changeable OpCallExp properties (excepting ownedArguments and referredOperation)
-				astPropCallExp.setTypeValue(exp.getTypeValue());
-				astPropCallExp.getOwnedComments().addAll(exp.getOwnedComments());
-				astPropCallExp.getOwnedExtensions().addAll(exp.getOwnedExtensions());
-				astPropCallExp.setName(exp.getName());
-				astPropCallExp.setIsSafe(exp.isIsSafe());
-				astPropCallExp.setIsRequired(exp.isIsRequired());
-				astPropCallExp.setIsImplicit(exp.isIsImplicit());
-				astPropCallExp.setIsPre(exp.isIsPre());
-				// end of copy
-				
-				Type castType = exp.getType();
-				OperationCallExp asTypeOpCallExp = PivotFactory.eINSTANCE.createOperationCallExp();
-				asTypeOpCallExp.setOwnedSource(astPropCallExp);
-				asTypeOpCallExp.setReferredOperation(getOclAnyOclAsTypeOp());
-				asTypeOpCallExp.setType(castType);
-				asTypeOpCallExp.setIsSafe(astPropCallExp.isIsSafe());
-				
-				TypeExp argTypeExp = PivotFactory.eINSTANCE.createTypeExp();
-				argTypeExp.setReferredType(castType);
-				argTypeExp.setType(getOclMetaClass());
-				
-				asTypeOpCallExp.getOwnedArguments().add(argTypeExp);
-				
+				OperationCallExp asTypeOpCallExp = rewriteAstOperationCallAsTypeCastedPropertyCall(exp);
 				if (result.contains(exp)) { // if exp is the initial oclExp, the new asTypeOpCallExp will be the new result
 					result.remove(exp);
 					result.add(asTypeOpCallExp);
@@ -387,6 +583,39 @@
 		return result.get(0);
 	}
 	
+	private OperationCallExp rewriteAstOperationCallAsTypeCastedPropertyCall(OperationCallExp astOpCallExp) {
+		PropertyCallExp astPropCallExp = PivotFactory.eINSTANCE.createPropertyCallExp();
+		OCLExpression tmp = astOpCallExp.getOwnedSource();
+		astOpCallExp.setOwnedSource(null);
+		astPropCallExp.setOwnedSource(tmp);
+		astPropCallExp.setReferredProperty(getTraceabilityProperty(astPropCallExp.getOwnedSource().getType()));
+		astPropCallExp.setType(astPropCallExp.getReferredProperty().getType());
+		// Copying remaining changeable OpCallExp properties (excepting ownedArguments and referredOperation)
+		astPropCallExp.setTypeValue(astOpCallExp.getTypeValue());
+		astPropCallExp.getOwnedComments().addAll(astOpCallExp.getOwnedComments());
+		astPropCallExp.getOwnedExtensions().addAll(astOpCallExp.getOwnedExtensions());
+		astPropCallExp.setName(astOpCallExp.getName());
+		astPropCallExp.setIsSafe(astOpCallExp.isIsSafe());
+		astPropCallExp.setIsRequired(astOpCallExp.isIsRequired());
+		astPropCallExp.setIsImplicit(astOpCallExp.isIsImplicit());
+		astPropCallExp.setIsPre(astOpCallExp.isIsPre());
+		// end of copy
+		
+		Type castType = astOpCallExp.getType();
+		OperationCallExp asTypeOpCallExp = PivotFactory.eINSTANCE.createOperationCallExp();
+		asTypeOpCallExp.setOwnedSource(astPropCallExp);
+		asTypeOpCallExp.setReferredOperation(oclAsTypeOp);
+		asTypeOpCallExp.setType(castType);
+		asTypeOpCallExp.setIsSafe(astPropCallExp.isIsSafe());
+		
+		TypeExp argTypeExp = PivotFactory.eINSTANCE.createTypeExp();
+		argTypeExp.setReferredType(castType);
+		argTypeExp.setType(getOclMetaClass());
+		
+		asTypeOpCallExp.getOwnedArguments().add(argTypeExp);
+		return asTypeOpCallExp;
+	}
+	
 	/**
 	 * Function which takes into account that the shadow is embedded inside of an IfExp
 	 * so that the guard pattern have the proper guards associated to the the IfExp
@@ -431,7 +660,7 @@
 		} else {
 			OperationCallExp notOpCallExp = PivotFactory.eINSTANCE.createOperationCallExp();
 			notOpCallExp.setName("not");
-			notOpCallExp.setReferredOperation(getBooleanNotOp());
+			notOpCallExp.setReferredOperation(notOp);
 			notOpCallExp.setType(getBooleanPrimitiveType());
 			notOpCallExp.setOwnedSource(EcoreUtil.copy(oclExp));
 			return notOpCallExp;
@@ -454,11 +683,109 @@
 	
 	private Predicate<EObject> isAstOp() {
 		return element -> {
-				return element instanceof Operation &&
-				"ast".equals(((Operation)element).getName());
+			return element instanceof Operation &&
+			"ast".equals(((Operation)element).getName());
 		};
 	}
 	
+	private Predicate<Operation> isOclDocOp() { 
+		return element -> {
+			Model model = getModel().apply(element);
+			if (model == null) {
+				return false;
+			} else {
+				return isOclModel().test(model);
+			}
+		};
+	}
+	
+//	private Predicate<Operation> isOclLibOp() { 
+//		return element -> {
+//			Class pClass = element.getOwningClass();
+//			if (pClass == null) return false;
+//			Package pPackage = pClass.getOwningPackage();
+//			if (pPackage == null) return false;
+//			return OCLstdlibPackage.eNS_URI.equals(pPackage.getURI());
+//		};
+//	}
+	
+	private Predicate<@NonNull Import> isOclDocImport() {
+		return element -> {
+			Namespace referredNamespace = element.getImportedNamespace();
+			if (referredNamespace instanceof Model) {
+				Model model = (Model) referredNamespace;
+				return isOclModel().test(model);
+			}
+			return false;
+		};
+	}
+	
+	private Predicate<@NonNull Model> isOclModel() {
+		return element -> {
+			URI extURI = URI.createURI(element.getExternalURI());
+			if ("oclas".equals(extURI.fileExtension())
+				|| "ocl".equals(extURI.fileExtension())
+				|| "qvtcas".equals(extURI.fileExtension())) {
+				return true;
+			} else {
+				return false;
+			}
+		};
+	}
+	
+	private Predicate<@NonNull Import> isEcoreDocImport() {
+		return element -> {
+			Namespace ns = element.getImportedNamespace();
+			if (ns instanceof Package) {
+				ns = getModel().apply(ns);
+			}
+			if (ns instanceof Model) {
+				Model model = (Model) ns;
+				return isEcoreModel().test(model);
+			}
+			return  false;
+		};
+	}
+	
+	private Predicate<@NonNull Model> isEcoreModel() {
+		return element -> {
+			URI extURI = URI.createURI(element.getExternalURI());
+			if ("ecore".equals(extURI.fileExtension())
+				|| "ecoreas".equals(extURI.fileExtension())) {
+				return true;
+			} else {
+				return false;
+			}
+		};
+	}
+	 
+	private Predicate<@NonNull Import> isExtendedCS2ASImport(List<URI> extendedASURIs) {
+		return element -> {
+			if (!isOclDocImport().test(element) || extendedASURIs.isEmpty()) {
+				return false;
+			}
+			URI importURI = URI.createURI(getModel().apply(element.getImportedNamespace()).getExternalURI());
+			if (!"oclas".equals(importURI.fileExtension())) {
+				importURI = importURI.appendFileExtension("oclas");	// We are interested in OCL AS uris	
+			}
+			return extendedASURIs.contains(importURI);
+		};
+	}
+	
+	private Predicate<OperationCallExp> refersToContainingOperation() {
+		return element -> {
+			EObject container = element.eContainer();
+			while (container != null) {
+				if (container instanceof Operation) {
+					Operation containingOp = (Operation) container;
+					return containingOp.equals(element.getReferredOperation());
+				}
+				container = container.eContainer();
+			}
+			return false;
+		};
+		
+	}
 	/*private List<OperationCallExp> getAstCalls(ShadowPart shadowPart) {
 		return getAllContentsIncludingSelf().apply(shadowPart.getOwnedInit())
 			.filter(isAstOpCallExp())
@@ -478,20 +805,18 @@
 	}
 	
 
-	private @NonNull Operation getOclAnyEqualsOp() {
-		Class oclAny = envFact.getStandardLibrary().getOclAnyType();
-		return envFact.getMetamodelManager().getPrimaryClass(oclAny).getOwnedOperations().stream()
-			.filter(x -> "=".equals(x.getName()))
-			.findFirst().get();
-	}
+//	private @NonNull Operation getOclAnyEqualsOp() {
+//		return envFact.getStandardLibrary().getOclAnyType().getOwnedOperations().stream()
+//			.filter(x -> "=".equals(x.getName()))
+//			.findFirst().get();
+//	}
 	
 	private @NonNull Class getOclMetaClass() { 
 		return envFact.getStandardLibrary().getClassType();
 	}
 	
 	private @NonNull Operation getOclAnyOclAsTypeOp() {
-		Class oclAny = envFact.getStandardLibrary().getOclAnyType();
-		return envFact.getMetamodelManager().getPrimaryClass(oclAny).getOwnedOperations().stream()
+		return envFact.getStandardLibrary().getOclAnyType().getOwnedOperations().stream()
 			.filter(x -> "oclAsType".equals(x.getName()))
 			.findFirst().get();
 	}
@@ -502,8 +827,7 @@
 	}
 	
 	private @NonNull Operation getBooleanNotOp() {
-		Class boolType = envFact.getStandardLibrary().getBooleanType();
-		return envFact.getMetamodelManager().getPrimaryClass(boolType).getOwnedOperations().stream()
+		return envFact.getStandardLibrary().getBooleanType().getOwnedOperations().stream()
 				.filter(x -> "not".equals(x.getName()))
 				.findFirst().get();
 	}
@@ -511,7 +835,7 @@
 	private Predicate<OCLExpression> isBooleanNotOpCallExp() {
 		return exp -> {
 			return exp instanceof OperationCallExp &&
-					((OperationCallExp)exp).getReferredOperation() == getBooleanNotOp();
+					((OperationCallExp)exp).getReferredOperation() == notOp;
 		};
 	}
 	
diff --git a/plugins/org.eclipse.qvtd.cs2as.compiler/src/org/eclipse/qvtd/cs2as/compiler/internal/OCL2QVTpUtil.java b/plugins/org.eclipse.qvtd.cs2as.compiler/src/org/eclipse/qvtd/cs2as/compiler/internal/OCL2QVTpUtil.java
index 89e1c4a..432d687 100644
--- a/plugins/org.eclipse.qvtd.cs2as.compiler/src/org/eclipse/qvtd/cs2as/compiler/internal/OCL2QVTpUtil.java
+++ b/plugins/org.eclipse.qvtd.cs2as.compiler/src/org/eclipse/qvtd/cs2as/compiler/internal/OCL2QVTpUtil.java
@@ -12,8 +12,11 @@
 
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.ocl.pivot.Class;
+import org.eclipse.ocl.pivot.Element;
 import org.eclipse.ocl.pivot.ExpressionInOCL;
+import org.eclipse.ocl.pivot.Model;
 import org.eclipse.ocl.pivot.NamedElement;
 import org.eclipse.ocl.pivot.OCLExpression;
 import org.eclipse.ocl.pivot.Package;
@@ -70,6 +73,19 @@
 		};
 	}
 	
+	public static Function<Element, @Nullable Model> getModel() {
+		return element -> {
+			EObject eObject = element;
+			while (eObject != null) {
+				if (eObject instanceof Model) {
+					return (Model)eObject;
+				}
+				eObject = eObject.eContainer();
+			}
+			return null;
+		};
+	}
+	
 
 	public static Function<@NonNull String, @NonNull String> firstToLowerCase() {
 		return input -> {