package org.eclipse.qvtd.cs2as.compiler.internal;

import static org.eclipse.qvtd.cs2as.compiler.internal.OCL2QVTpUtil.firstToUpperCase;
import static org.eclipse.qvtd.cs2as.compiler.internal.OCL2QVTpUtil.getAllContainers;
import static org.eclipse.qvtd.cs2as.compiler.internal.OCL2QVTpUtil.getAllContents;
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;
import java.util.function.Function;
import java.util.function.Predicate;
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;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.Class;
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;
import org.eclipse.ocl.pivot.Package;
import org.eclipse.ocl.pivot.PivotFactory;
import org.eclipse.ocl.pivot.Property;
import org.eclipse.ocl.pivot.PropertyCallExp;
import org.eclipse.ocl.pivot.ShadowExp;
import org.eclipse.ocl.pivot.ShadowPart;
import org.eclipse.ocl.pivot.Type;
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;
import org.eclipse.qvtd.pivot.qvtcore.Mapping;
import org.eclipse.qvtd.pivot.qvtcore.QVTcoreFactory;
import org.eclipse.qvtd.pivot.qvtcorebase.BottomPattern;
import org.eclipse.qvtd.pivot.qvtcorebase.CoreDomain;
import org.eclipse.qvtd.pivot.qvtcorebase.GuardPattern;
import org.eclipse.qvtd.pivot.qvtcorebase.PropertyAssignment;
import org.eclipse.qvtd.pivot.qvtcorebase.QVTcoreBaseFactory;
import org.eclipse.qvtd.pivot.qvtcorebase.RealizedVariable;

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";
	
	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, 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");
		}
		Resource input = resourceSet.getResource(oclDocURI, true);
		EObject rootModel = input.getContents().get(0);
		if (rootModel instanceof Model) {
			Model model = (Model) rootModel;
			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 {
			throw new IllegalArgumentException(oclDocURI.toString() + " doesn't contain an OCL Model");
		}
	}
	
	private TypedModel leftTypedModel = QVTbaseFactory.eINSTANCE.createTypedModel();
	private TypedModel rightTypedModel = QVTbaseFactory.eINSTANCE.createTypedModel();
	
	public Function<Model, CoreModel> oclModelToImperativeModel(boolean selfContainedTransf) {
		return oclModel -> {
		
			CoreModel iModel = QVTcoreFactory.eINSTANCE.createCoreModel();
		
		List<Operation> allAstOps = getAllContents().apply(oclModel)
					.filter(isAstOp())
					.map(Operation.class::cast).collect(Collectors.toList());
		List<ShadowExp> shadowExps = allAstOps.stream()
					.flatMap(getAllContents())
					.filter(ShadowExp.class::isInstance)
					.map(ShadowExp.class::cast).collect(Collectors.toList());
		List<ShadowPart> shadowParts =  allAstOps.stream()
					.flatMap(getAllContents())
					.filter(ShadowPart.class::isInstance)
					.map(ShadowPart.class::cast).collect(Collectors.toList());
		
		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()));
		
		Package pPackage = PivotFactory.eINSTANCE.createPackage();
		pPackage.setName("");
		iModel.getOwnedPackages().add(pPackage);
		
		Transformation pTx = QVTbaseFactory.eINSTANCE.createTransformation();
		pTx.setName(iModel.getName().replace('.', '_')); // FIXME . as part of the name is causing issues in the CG);
		pPackage.getOwnedClasses().add(pTx);
		
		leftTypedModel.setName(LEFT_MODEL_TYPE_NAME);
		leftTypedModel.getUsedPackage().addAll(shadowExps.stream()
				.map(getExpressionContextType())
				.map(getOwningPackage())
				.collect(Collectors.toSet()));
		pTx.getModelParameter().add(leftTypedModel);
		
		rightTypedModel.setName(RIGHT_MODEL_TYPE_NAME);
		rightTypedModel.getUsedPackage().addAll(shadowExps.stream()
				.map(x -> x.getType())
				.map(getOwningPackage())
				.collect(Collectors.toSet()));
		pTx.getModelParameter().add(rightTypedModel);
		
		pTx.getRule().addAll(shadowExps.stream()
				.filter(shadowExpToCreationMappingGuard())
				.map(shadowExpToCreationMapping())
				.collect(Collectors.toList()));
		
		pTx.getRule().addAll(shadowParts.stream()
				.filter(shadowPartToUpdateMappingGuard())
				.map(shadowPartToUpdateMapping())
				.collect(Collectors.toList()));
		return iModel;
		};
	}
	
	// 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();
		pImport.setName(oclImport.getName());
		pImport.setImportedNamespace(oclImport.getImportedNamespace());
		return pImport;
		};
	}
	
	protected Predicate<@NonNull ShadowExp> shadowExpToCreationMappingGuard() {
		return shadowExp -> {
			return ! getAllContainers().apply(shadowExp)
					.anyMatch(ShadowExp.class::isInstance);	
		};
	}
	
	public Function<@NonNull ShadowExp, @NonNull Mapping>  shadowExpToCreationMapping() {
		return shadowExp -> {
			Mapping mapping = QVTcoreFactory.eINSTANCE.createMapping();
			mapping.setName(getCreationMappingName().apply(shadowExp));
			
			CoreDomain leftDomain = createCreationMapping_LeftDomain(shadowExp);
			CoreDomain rightDomain = createCreationMapping_RightDomain(shadowExp);
			mapping.getDomain().add(leftDomain);
			mapping.getDomain().add(rightDomain);
			
			Variable leftVar = leftDomain.getGuardPattern().getVariable().get(0);
			
			GuardPattern guardPattern = QVTcoreBaseFactory.eINSTANCE.createGuardPattern();
			BottomPattern bottomPattern = QVTcoreBaseFactory.eINSTANCE.createBottomPattern();
			mapping.setGuardPattern(guardPattern);
			mapping.setBottomPattern(bottomPattern);
			
			PropertyAssignment pAssignment = QVTcoreBaseFactory.eINSTANCE.createPropertyAssignment();
			VariableExp value = PivotFactory.eINSTANCE.createVariableExp();
			value.setReferredVariable(rightDomain.getBottomPattern().getRealizedVariable().get(0));
			value.setType(value.getReferredVariable().getType());
			
			VariableExp slotExpression = PivotFactory.eINSTANCE.createVariableExp();
			slotExpression.setReferredVariable(leftVar);
			slotExpression.setType(slotExpression.getReferredVariable().getType());
			
			pAssignment.setValue(value);
			pAssignment.setSlotExpression(slotExpression);
			pAssignment.setTargetProperty(getTraceabilityProperty(slotExpression.getType()));
			
			bottomPattern.getAssignment().add(pAssignment);
			updateGuardPattern(shadowExp, guardPattern, leftVar);
			
			return mapping;
		};
	}
	
	
	protected Predicate<@NonNull ShadowPart> shadowPartToUpdateMappingGuard() {
		return shadowPart -> {
			ShadowExp containingShadowExp = (ShadowExp) shadowPart.eContainer(); // FIXME this should be in Pivot
			return shadowExpToCreationMappingGuard().test(containingShadowExp);	
		};
	}
	
	public Function<@NonNull ShadowPart, @NonNull Mapping>  shadowPartToUpdateMapping() {
		return shadowPart -> {
			Mapping mapping = QVTcoreFactory.eINSTANCE.createMapping();
			mapping.setName(getUpdateMappingName().apply(shadowPart));
			
			ShadowExp shadowExp = (ShadowExp) shadowPart.eContainer();
			Property refProp = shadowPart.getReferredProperty();
			
			CoreDomain leftDomain = createUpdateMapping_LeftDomain(shadowExp);
			CoreDomain rightDomain = createUpdateMapping_RightDomain(shadowExp);
			mapping.getDomain().add(leftDomain);
			mapping.getDomain().add(rightDomain);
			
			Variable leftVar = leftDomain.getGuardPattern().getVariable().get(0);
			
			VariableExp varExp = PivotFactory.eINSTANCE.createVariableExp();
			varExp.setReferredVariable(leftVar);
			varExp.setType(varExp.getReferredVariable().getType());
			Property tracebilityProperty = getTraceabilityProperty(varExp.getType());
			
			PropertyCallExp astPropCallExp = PivotFactory.eINSTANCE.createPropertyCallExp();
			astPropCallExp.setOwnedSource(varExp);
			astPropCallExp.setReferredProperty(tracebilityProperty);
			astPropCallExp.setType(astPropCallExp.getReferredProperty().getType());
			
			OperationCallExp asTypeOpCallExp = PivotFactory.eINSTANCE.createOperationCallExp();
			asTypeOpCallExp.setOwnedSource(astPropCallExp);
			asTypeOpCallExp.setReferredOperation(oclAsTypeOp);
			asTypeOpCallExp.setType(shadowExp.getType());
			
			TypeExp argTypeExp = PivotFactory.eINSTANCE.createTypeExp();
			argTypeExp.setReferredType(shadowExp.getType());
			argTypeExp.setType(getOclMetaClass());
			
			asTypeOpCallExp.getOwnedArguments().add(argTypeExp);
			
			PropertyAssignment pAssignment = QVTcoreBaseFactory.eINSTANCE.createPropertyAssignment();
			pAssignment.setTargetProperty(refProp);
			pAssignment.setValue(createPropertyAssignmentValue(shadowPart, leftVar));
			pAssignment.setSlotExpression(asTypeOpCallExp);
			
			GuardPattern guardPattern = QVTcoreBaseFactory.eINSTANCE.createGuardPattern();
			BottomPattern bottomPattern = QVTcoreBaseFactory.eINSTANCE.createBottomPattern();
			mapping.setGuardPattern(guardPattern);
			mapping.setBottomPattern(bottomPattern);
			
			bottomPattern.getAssignment().add(pAssignment);
			
			updateGuardPattern(shadowExp,  guardPattern, leftVar);
			return mapping;
		};
	}
	
	
	private CoreDomain createCreationMapping_LeftDomain(ShadowExp shadowExp) {
		
		Class contextType = getExpressionContextType().apply(shadowExp);
		CoreDomain domain = QVTcoreBaseFactory.eINSTANCE.createCoreDomain();
		domain.setTypedModel(leftTypedModel);
		domain.setIsCheckable(true);
		
		GuardPattern guardPattern = QVTcoreBaseFactory.eINSTANCE.createGuardPattern();
		BottomPattern bottomPattern = QVTcoreBaseFactory.eINSTANCE.createBottomPattern();
		domain.setGuardPattern(guardPattern);
		domain.setBottomPattern(bottomPattern);
		
		Variable variable = PivotFactory.eINSTANCE.createVariable();
		variable.setName("l"+firstToUpperCase().apply(contextType.getName()));
		variable.setType(contextType);
		
		guardPattern.getVariable().add(variable);
		
		return domain;
	}
	
	private CoreDomain createCreationMapping_RightDomain(ShadowExp shadowExp) {

		Class constructedType = shadowExp.getType();
		CoreDomain domain = QVTcoreBaseFactory.eINSTANCE.createCoreDomain();
		domain.setTypedModel(rightTypedModel);
		domain.setIsEnforceable(true);
		
		GuardPattern guardPattern = QVTcoreBaseFactory.eINSTANCE.createGuardPattern();
		BottomPattern bottomPattern = QVTcoreBaseFactory.eINSTANCE.createBottomPattern();
		domain.setGuardPattern(guardPattern);
		domain.setBottomPattern(bottomPattern);
		
		RealizedVariable variable = QVTcoreBaseFactory.eINSTANCE.createRealizedVariable();
		variable.setName("r"+firstToUpperCase().apply(constructedType.getName()));
		variable.setType(constructedType);
		
		bottomPattern.getRealizedVariable().add(variable);
		return domain;
	}
	
	private CoreDomain createUpdateMapping_LeftDomain(ShadowExp shadowExp) {
		// It's exactly the same domain as we have for the creation mappings
		return createCreationMapping_LeftDomain(shadowExp);
	}
	
	private CoreDomain createUpdateMapping_RightDomain(ShadowExp shadowExp) {
		CoreDomain domain = QVTcoreBaseFactory.eINSTANCE.createCoreDomain();
		domain.setTypedModel(rightTypedModel);
		domain.setIsEnforceable(true);
		
		GuardPattern guardPattern = QVTcoreBaseFactory.eINSTANCE.createGuardPattern();
		BottomPattern bottomPattern = QVTcoreBaseFactory.eINSTANCE.createBottomPattern();
		domain.setGuardPattern(guardPattern);
		domain.setBottomPattern(bottomPattern);
		
		return domain;
	}
	
	private OCLExpression createPropertyAssignmentValue(ShadowPart shadowPart, Variable leftVar) {
		
		// FIXME what happens with synthetised types ????
		OCLExpression initExp = shadowPart.getOwnedInit();
		OCLExpression newInitExp = EcoreUtil.copy(initExp);
		//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 ;
		result.add(oclExp);
		getAllContentsIncludingSelf().apply(oclExp).forEach(x -> {
			if (isSelfVarExp().test(x)) {
				((VariableExp)x).setReferredVariable(leftVar);
			} else if(isAstOpCallExp().test(x)) {
				OperationCallExp exp = (OperationCallExp) x;
				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);
				} else {
					EcoreUtil.replace(exp,asTypeOpCallExp);
				}
				EcoreUtil.delete(exp);
			}
		});
		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
	 */ 
	 private void updateGuardPattern(ShadowExp shadowExp, GuardPattern guardPattern, Variable leftVar) {

		EObject container = shadowExp.eContainer();		
		
		if (container instanceof IfExp) {
			IfExp ifExp = (IfExp) container;
			OCLExpression condition = ifExp.getOwnedCondition();
			List<OCLExpression> guardPredicates = new ArrayList<OCLExpression>();
			if (ifExp.getOwnedThen() == shadowExp) {
				guardPredicates.add(EcoreUtil.copy(condition));
			} else { // it's the else
				guardPredicates.add(createNegatedExpression(condition));
			}
			
			container = container.eContainer();
			// FIXME create a cached operation to improve performance
			while (container instanceof IfExp) {
				ifExp = (IfExp) container;
				guardPredicates.add(createNegatedExpression(ifExp.getOwnedCondition()));
				container = container.eContainer();
			}
			
			// We need to replace the OCL refered "self" varible by the QVTi domain "leftVar"
			Collections.reverse(guardPredicates);
			for (OCLExpression guardPredicate : guardPredicates ) {
				org.eclipse.qvtd.pivot.qvtbase.Predicate predicate = QVTbaseFactory.eINSTANCE.createPredicate();
				predicate.setConditionExpression(doReplacements(guardPredicate, leftVar));
				guardPattern.getPredicate().add(predicate);
			}
		}
	}
	 
	private OCLExpression createNegatedExpression(OCLExpression oclExp){
		// We don't want to create a 'not not conditionExp'
		if (isBooleanNotOpCallExp().test(oclExp)) {
			OperationCallExp notOpCallExp = (OperationCallExp) oclExp;
			return EcoreUtil.copy(notOpCallExp.getOwnedSource());
		} else {
			OperationCallExp notOpCallExp = PivotFactory.eINSTANCE.createOperationCallExp();
			notOpCallExp.setName("not");
			notOpCallExp.setReferredOperation(notOp);
			notOpCallExp.setType(getBooleanPrimitiveType());
			notOpCallExp.setOwnedSource(EcoreUtil.copy(oclExp));
			return notOpCallExp;
		}
	}  
	
	private Predicate<EObject> isSelfVarExp() {
		return element -> { 
			return element instanceof VariableExp && 
				"self".equals(((VariableExp)element).getReferredVariable().getName());
		};
	}
	
	private Predicate<EObject> isAstOpCallExp() {
		return element -> { 
			return element instanceof OperationCallExp &&
				isAstOp().test(((OperationCallExp)element).getReferredOperation());
		};
	}
	
	private Predicate<EObject> isAstOp() {
		return element -> {
			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())
			.map(OperationCallExp.class::cast)
			.collect(Collectors.toList());
	}*/
	
	private @NonNull Property getTraceabilityProperty(Type type) {
		Class aClass = type.isClass();
		assert(aClass != null);
		Set<Class> allClasses = getSuperClasses().apply(aClass);
		allClasses.add(aClass);
		return allClasses.stream()
			.flatMap(x -> x.getOwnedProperties().stream())
			.filter(x -> traceabilityPropName.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() {
		return envFact.getStandardLibrary().getOclAnyType().getOwnedOperations().stream()
			.filter(x -> "oclAsType".equals(x.getName()))
			.findFirst().get();
	}
	
	private @NonNull Class getBooleanPrimitiveType() {
		return envFact.getStandardLibrary().getBooleanType();
		
	}
	
	private @NonNull Operation getBooleanNotOp() {
		return envFact.getStandardLibrary().getBooleanType().getOwnedOperations().stream()
				.filter(x -> "not".equals(x.getName()))
				.findFirst().get();
	}
	
	private Predicate<OCLExpression> isBooleanNotOpCallExp() {
		return exp -> {
			return exp instanceof OperationCallExp &&
					((OperationCallExp)exp).getReferredOperation() == notOp;
		};
	}
	
}
