/*******************************************************************************
 * Copyright (c) 2016 Willink Transformations and others.
 * 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:
 *     Horacio Hoyos - initial research
 *     E.D.Willink - initial API and implementation based on MtcBroker
 ******************************************************************************/
package org.eclipse.qvtd.compiler.internal.common;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;

import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.WrappedException;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.Comment;
import org.eclipse.ocl.pivot.Element;
import org.eclipse.ocl.pivot.Import;
import org.eclipse.ocl.pivot.NamedElement;
import org.eclipse.ocl.pivot.NavigationCallExp;
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.Parameter;
import org.eclipse.ocl.pivot.ParameterVariable;
import org.eclipse.ocl.pivot.PivotFactory;
import org.eclipse.ocl.pivot.PivotPackage;
import org.eclipse.ocl.pivot.Property;
import org.eclipse.ocl.pivot.StandardLibrary;
import org.eclipse.ocl.pivot.Type;
import org.eclipse.ocl.pivot.Variable;
import org.eclipse.ocl.pivot.VariableDeclaration;
import org.eclipse.ocl.pivot.VariableExp;
import org.eclipse.ocl.pivot.util.Visitable;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.ocl.pivot.utilities.EnvironmentFactory;
import org.eclipse.ocl.pivot.utilities.NameUtil;
import org.eclipse.ocl.pivot.utilities.PivotConstants;
import org.eclipse.qvtd.pivot.qvtbase.Function;
import org.eclipse.qvtd.pivot.qvtbase.FunctionParameter;
import org.eclipse.qvtd.pivot.qvtbase.Predicate;
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.qvtbase.utilities.QVTbaseUtil;
import org.eclipse.qvtd.pivot.qvtcore.BottomPattern;
import org.eclipse.qvtd.pivot.qvtcore.BottomVariable;
import org.eclipse.qvtd.pivot.qvtcore.CoreDomain;
import org.eclipse.qvtd.pivot.qvtcore.CoreModel;
import org.eclipse.qvtd.pivot.qvtcore.GuardPattern;
import org.eclipse.qvtd.pivot.qvtcore.GuardVariable;
import org.eclipse.qvtd.pivot.qvtcore.Mapping;
import org.eclipse.qvtd.pivot.qvtcore.NavigationAssignment;
import org.eclipse.qvtd.pivot.qvtcore.OppositePropertyAssignment;
import org.eclipse.qvtd.pivot.qvtcore.PropertyAssignment;
import org.eclipse.qvtd.pivot.qvtcore.QVTcoreFactory;
import org.eclipse.qvtd.pivot.qvtcore.QVTcorePackage;
import org.eclipse.qvtd.pivot.qvtcore.RealizedVariable;
import org.eclipse.qvtd.pivot.qvtcore.VariableAssignment;
import org.eclipse.qvtd.pivot.qvtcore.util.AbstractExtendingQVTcoreVisitor;
import org.eclipse.qvtd.pivot.qvtcore.utilities.QVTcoreHelper;
import org.eclipse.qvtd.pivot.qvtcore.utilities.QVTcoreUtil;

/**
 * AbstractQVTc2QVTc provides shared functionality for steps in the QVTC/QVTu/QVTm chain.
 */
public abstract class AbstractQVTc2QVTc
{
	/**
	 * An ExpressionCopier deep copies an OCLExpression tree, exploiting the forward traceability of context to
	 * update references. Ambiguities should be resolved by performing the copy with respect to an appropriate
	 * stack of resolution scopes.
	 */
	@SuppressWarnings("serial")
	protected static class ExpressionCopier extends EcoreUtil.Copier
	{
		private final @NonNull AbstractQVTc2QVTc context;

		public ExpressionCopier(@NonNull AbstractQVTc2QVTc context) {
			this.context = context;
		}

		@Override
		public EObject get(Object oIn) {
			EObject eOut = super.get(oIn);
			if (eOut == null) {
				eOut = context.equivalentTarget((Element)oIn);
			}
			return eOut;
		}
	}

	/**
	 * The CreateVisitor performs the mostly 1:1 creation of the QVTm output tree from the QVTm input tree.
	 *
	 * References are left unresolved. OCLExpressions are not copied. doXXX methods provide join points for derived implementations.
	 */
	protected static abstract class AbstractCreateVisitor<@NonNull C extends AbstractQVTc2QVTc> extends AbstractExtendingQVTcoreVisitor<Element, C>
	{
		public AbstractCreateVisitor(@NonNull C context) {
			super(context);
		}

		public <T extends Element> @Nullable T create(@Nullable T source) {
			if (source == null) {
				return null;
			}
			@SuppressWarnings("unchecked") @Nullable T target = (T) source.accept(this);
			return target;
		}

		public <T extends Element> void createAll(/*@NonNull*/ Iterable<T> sources, /*@NonNull*/ List<? super T> targets) {
			for (@SuppressWarnings("null")@NonNull T source : sources) {
				@SuppressWarnings("unchecked") T target = (T) source.accept(this);
				if (target != null) {
					targets.add(target);
				}
			}
		}

		protected void doAssignments(@NonNull BottomPattern bIn, @NonNull BottomPattern bOut) {
			createAll(bIn.getAssignment(), bOut.getAssignment());
		}

		protected void doLocalMappings(@NonNull Mapping mIn, @NonNull Mapping mOut) {
			createAll(mIn.getLocal(), mOut.getLocal());
		}

		protected void doMapping(@NonNull Mapping mIn, @NonNull Mapping mOut) {
			context.addTrace(mIn, mOut);
			mOut.setName(mIn.getName());
			mOut.setGuardPattern(create(mIn.getGuardPattern()));
			mOut.setBottomPattern(create(mIn.getBottomPattern()));
			createAll(mIn.getDomain(), mOut.getDomain());
			doLocalMappings(mIn, mOut);
			//			createAll(mIn.getSpecification(), mOut.getSpecification());
			createAll(mIn.getOwnedComments(), mOut.getOwnedComments());
		}

		protected void doRealizedVariables(@NonNull BottomPattern bIn, @NonNull BottomPattern bOut) {
			createAll(bIn.getRealizedVariable(), bOut.getRealizedVariable());
		}

		protected void doRules(@NonNull Transformation tIn, @NonNull Transformation tOut) {
			createAll(tIn.getRule(), tOut.getRule());
		}

		//		public @NonNull EnvironmentFactory getEnvironmentFactory() {
		//			return context.getEnvironmentFactory();
		//		}

		@Override
		public @Nullable Element visiting(@NonNull Visitable visitable) {
			throw new IllegalArgumentException("Unsupported " + visitable.eClass().getName() + " for " + getClass().getSimpleName());
		}

		@Override
		public @NonNull BottomPattern visitBottomPattern(@NonNull BottomPattern bIn) {
			BottomPattern bOut = QVTcoreFactory.eINSTANCE.createBottomPattern();
			context.addTrace(bIn, bOut);
			doAssignments(bIn, bOut);
			createAll(bIn.getPredicate(), bOut.getPredicate());
			doRealizedVariables(bIn, bOut);
			createAll(bIn.getVariable(), bOut.getVariable());
			createAll(bIn.getOwnedComments(), bOut.getOwnedComments());
			return bOut;
		}

		@Override
		public @NonNull BottomVariable visitBottomVariable(@NonNull BottomVariable vIn) {
			BottomVariable vOut = QVTcoreFactory.eINSTANCE.createBottomVariable();
			context.addTrace(vIn, vOut);
			vOut.setName(vIn.getName());
			createAll(vIn.getOwnedComments(), vOut.getOwnedComments());
			return vOut;
		}

		@Override
		public @Nullable Element visitComment(@NonNull Comment cIn) {
			Comment cOut = PivotFactory.eINSTANCE.createComment();
			context.addTrace(cIn, cOut);
			cOut.setBody(cIn.getBody());
			createAll(cIn.getOwnedComments(), cOut.getOwnedComments());
			return cOut;
		}

		@Override
		public @NonNull CoreDomain visitCoreDomain(@NonNull CoreDomain dIn) {
			CoreDomain dOut = QVTcoreFactory.eINSTANCE.createCoreDomain();
			context.addTrace(dIn, dOut);
			dOut.setIsCheckable(dIn.isIsCheckable());
			dOut.setIsEnforceable(dIn.isIsEnforceable());
			dOut.setGuardPattern(create(dIn.getGuardPattern()));
			dOut.setBottomPattern(create(dIn.getBottomPattern()));
			createAll(dIn.getOwnedComments(), dOut.getOwnedComments());
			return dOut;
		}

		@Override
		public @NonNull CoreModel visitCoreModel(@NonNull CoreModel mIn) {
			CoreModel mOut = QVTcoreFactory.eINSTANCE.createCoreModel();
			context.pushScope(mOut);
			context.addTrace(mIn, mOut);
			createAll(mIn.getOwnedImports(), mOut.getOwnedImports());
			createAll(mIn.getOwnedPackages(), mOut.getOwnedPackages());
			createAll(mIn.getOwnedComments(), mOut.getOwnedComments());
			context.popScope();
			return mOut;
		}

		@Override
		public @NonNull Function visitFunction(@NonNull Function fIn) {
			Function fOut = QVTbaseFactory.eINSTANCE.createFunction();
			context.addTrace(fIn, fOut);				// Global
			context.pushScope(fOut);
			fOut.setName(fIn.getName());
			fOut.setIsRequired(fIn.isIsRequired());
			fOut.setIsStatic(fIn.isIsStatic());
			fOut.setIsTransient(fIn.isIsTransient());
			fOut.setIsTypeof(fIn.isIsTypeof());
			createAll(fIn.getOwnedParameters(), fOut.getOwnedParameters());
			createAll(fIn.getOwnedComments(), fOut.getOwnedComments());
			context.popScope();
			return fOut;
		}

		@Override
		public @NonNull FunctionParameter visitFunctionParameter(@NonNull FunctionParameter fpIn) {
			FunctionParameter fpOut = QVTbaseFactory.eINSTANCE.createFunctionParameter();
			context.addTrace(fpIn, fpOut);
			fpOut.setName(fpIn.getName());
			fpOut.setIsRequired(fpIn.isIsRequired());
			fpOut.setIsTypeof(fpIn.isIsTypeof());
			createAll(fpIn.getOwnedComments(), fpOut.getOwnedComments());
			return fpOut;
		}

		@Override
		public @NonNull GuardPattern visitGuardPattern(@NonNull GuardPattern gIn) {
			GuardPattern gOut = QVTcoreFactory.eINSTANCE.createGuardPattern();
			context.addTrace(gIn, gOut);
			createAll(gIn.getPredicate(), gOut.getPredicate());
			createAll(gIn.getVariable(), gOut.getVariable());
			createAll(gIn.getOwnedComments(), gOut.getOwnedComments());
			return gOut;
		}

		@Override
		public @NonNull GuardVariable visitGuardVariable(@NonNull GuardVariable vIn) {
			GuardVariable vOut = QVTcoreFactory.eINSTANCE.createGuardVariable();
			context.addTrace(vIn, vOut);
			vOut.setName(vIn.getName());
			createAll(vIn.getOwnedComments(), vOut.getOwnedComments());
			return vOut;
		}

		@Override
		public @Nullable Element visitImport(@NonNull Import iIn) {
			Import iOut = context.createImport(iIn);
			createAll(iIn.getOwnedComments(), iOut.getOwnedComments());
			return iOut;
		}

		@Override
		public @Nullable Element visitMapping(@NonNull Mapping mIn) {
			Mapping mOut = QVTcoreFactory.eINSTANCE.createMapping();
			context.pushScope(mOut);
			doMapping(mIn, mOut);
			context.popScope();
			return mOut;
		}

		@Override
		public final @Nullable Element visitNavigationAssignment(@NonNull NavigationAssignment object) {			// Override must be of derived classes
			return visiting(object);
		}

		@Override
		public @Nullable Element visitOppositePropertyAssignment(@NonNull OppositePropertyAssignment paIn) {
			OppositePropertyAssignment paOut = QVTcoreFactory.eINSTANCE.createOppositePropertyAssignment();
			context.addTrace(paIn, paOut);
			if (paIn.eIsSet(QVTcorePackage.Literals.ASSIGNMENT__IS_DEFAULT)) {
				paOut.setIsDefault(paIn.isIsDefault());
			}
			if (paIn.eIsSet(QVTcorePackage.Literals.ASSIGNMENT__IS_PARTIAL)) {
				paOut.setIsPartial(paIn.isIsPartial());
			}
			paOut.setTargetProperty(paIn.getTargetProperty());
			createAll(paIn.getOwnedComments(), paOut.getOwnedComments());
			return paOut;
		}

		@Override
		public @Nullable Element visitPackage(@NonNull Package pIn) {
			if (PivotConstants.ORPHANAGE_URI.equals(pIn.getURI())) {
				return null;
			}
			Package pOut = context.createPackage(pIn);
			createAll(pIn.getOwnedClasses(), pOut.getOwnedClasses());
			createAll(pIn.getOwnedPackages(), pOut.getOwnedPackages());
			createAll(pIn.getOwnedComments(), pOut.getOwnedComments());
			return pOut;
		}

		@Override
		public @NonNull ParameterVariable visitParameterVariable(@NonNull ParameterVariable vIn) {
			ParameterVariable vOut = PivotFactory.eINSTANCE.createParameterVariable();
			context.addTrace(vIn, vOut);
			vOut.setName(vIn.getName());
			createAll(vIn.getOwnedComments(), vOut.getOwnedComments());
			return vOut;
		}

		@Override
		public @Nullable Element visitPredicate(@NonNull Predicate pIn) {
			Predicate pOut = QVTbaseFactory.eINSTANCE.createPredicate();
			context.addTrace(pIn, pOut);
			// The condition expression is copied during update once replacement variables exist.
			createAll(pIn.getOwnedComments(), pOut.getOwnedComments());
			return pOut;
		}

		@Override
		public @Nullable Element visitPropertyAssignment(@NonNull PropertyAssignment paIn) {
			PropertyAssignment paOut = QVTcoreFactory.eINSTANCE.createPropertyAssignment();
			context.addTrace(paIn, paOut);
			if (paIn.eIsSet(QVTcorePackage.Literals.ASSIGNMENT__IS_DEFAULT)) {
				paOut.setIsDefault(paIn.isIsDefault());
			}
			if (paIn.eIsSet(QVTcorePackage.Literals.ASSIGNMENT__IS_PARTIAL)) {
				paOut.setIsPartial(paIn.isIsPartial());
			}
			paOut.setTargetProperty(paIn.getTargetProperty());
			createAll(paIn.getOwnedComments(), paOut.getOwnedComments());
			return paOut;
		}

		@Override
		public @NonNull Variable visitRealizedVariable(@NonNull RealizedVariable rvIn) {
			Variable rvOut = QVTcoreFactory.eINSTANCE.createRealizedVariable();
			context.addTrace(rvIn, rvOut);
			rvOut.setName(rvIn.getName());
			rvOut.setIsImplicit(rvIn.isIsImplicit());
			rvOut.setType(rvIn.getType());
			createAll(rvIn.getOwnedComments(), rvOut.getOwnedComments());
			return rvOut;
		}

		@Override
		public @NonNull Transformation visitTransformation(@NonNull Transformation tIn) {
			Transformation tOut = QVTbaseFactory.eINSTANCE.createTransformation();
			context.addTrace(tIn, tOut);
			tOut.setName(tIn.getName());
			tOut.setOwnedContext(create(tIn.getOwnedContext()));
			createAll(tIn.getOwnedOperations(), tOut.getOwnedOperations());
			createAll(tIn.getModelParameter(), tOut.getModelParameter());
			doRules(tIn, tOut);
			createAll(tIn.getOwnedComments(), tOut.getOwnedComments());
			return tOut;
		}

		@Override
		public @NonNull TypedModel visitTypedModel(@NonNull TypedModel tmIn) {
			TypedModel tmOut = QVTbaseFactory.eINSTANCE.createTypedModel();
			context.addTrace(tmIn, tmOut);
			String name = tmIn.getName();
			if (name == null) {
				//				name = QVTcoreUtil.MIDDLE_DOMAIN_NAME;
				context.setMiddleTypedModelTarget(tmOut);
			}
			tmOut.setName(name);
			tmOut.getUsedPackage().addAll(tmIn.getUsedPackage());
			createAll(tmIn.getOwnedComments(), tmOut.getOwnedComments());
			return tmOut;
		}

		@Override
		public @Nullable Element visitVariableAssignment(@NonNull VariableAssignment vaIn) {
			VariableAssignment vaOut = QVTcoreFactory.eINSTANCE.createVariableAssignment();
			context.addTrace(vaIn, vaOut);
			vaOut.setIsDefault(vaIn.isIsDefault());
			createAll(vaIn.getOwnedComments(), vaOut.getOwnedComments());
			return vaOut;
		}
	}

	/**
	 * The UpdateVisitor resolves the references and creates the OCLExpressions omitted by the CreateVisitor..
	 */
	protected static abstract class AbstractUpdateVisitor<@NonNull C extends AbstractQVTc2QVTc> extends AbstractExtendingQVTcoreVisitor<Object, C>
	{
		private Operation equalsOperation = null;
		protected final @NonNull QVTcoreHelper helper;

		public AbstractUpdateVisitor(@NonNull C context) {
			super(context);
			helper = context.getHelper();
		}

		/**
		 * Verify that variable references from the containment tree of outElement are to outElement's Resource.
		 *
		 * This may not be valid for multi-package transformations, but it's a very helpful debug for straightforward single package transformations.
		 */
		protected void checkOut(@NonNull Element pOut) {
			Resource eResource = pOut.eResource();
			assert eResource != null;
			for (TreeIterator<EObject> tit = pOut.eAllContents(); tit.hasNext(); ) {
				EObject eObject = tit.next();
				if (eObject instanceof VariableExp) {
					VariableDeclaration variable = ((VariableExp)eObject).getReferredVariable();
					Resource vResource = variable.eResource();
					//					assert vResource == eResource;
					if (vResource != eResource) {
						System.err.println(variable + " : " + NameUtil.debugFullName(variable) + " not in output resource.");
						vResource = variable.eResource();
					}
				}
			}
		}

		protected Object convertToPredicate(@NonNull NavigationAssignment paIn, @NonNull Predicate pOut) {
			OCLExpression slotExpression = copy(paIn.getSlotExpression());
			Property targetProperty = QVTcoreUtil.getTargetProperty(paIn);
			assert (slotExpression != null) && (targetProperty != null);
			OCLExpression valueExpression = copy(paIn.getValue());
			assert valueExpression != null;
			NavigationCallExp propertyCallExp = helper.createNavigationCallExp(slotExpression, targetProperty);
			context.addTrace(paIn, propertyCallExp);
			propertyCallExp.eUnset(PivotPackage.Literals.TYPED_ELEMENT__IS_REQUIRED);		// FIXME redundant compatibility
			Operation equalsOperation = getEqualsOperation();
			OperationCallExp operationCallExp = helper.createOperationCallExp(propertyCallExp, equalsOperation, Collections.singletonList(valueExpression));
			context.addTrace(paIn, operationCallExp);
			operationCallExp.setName(equalsOperation.getName());		// FIXME redundant compatibility
			pOut.setConditionExpression(operationCallExp);
			checkOut(pOut);
			return null;
		}

		protected @Nullable Object convertToVariableAssignment(@NonNull NavigationAssignment paIn, @NonNull VariableAssignment vaOut) {
			OCLExpression veIn = paIn.getValue();
			assert veIn instanceof VariableExp;
			VariableDeclaration vIn = ((VariableExp)veIn).getReferredVariable();
			assert vIn instanceof Variable;
			Variable vOut = context.equivalentTarget((Variable)vIn);
			vaOut.setTargetVariable(vOut);
			OCLExpression slotExpression = copy(paIn.getSlotExpression());
			Property targetProperty = QVTcoreUtil.getTargetProperty(paIn);
			assert (slotExpression != null) && (targetProperty != null);
			NavigationCallExp propertyCallExp = helper.createNavigationCallExp(slotExpression, targetProperty);
			context.addTrace(paIn, propertyCallExp);
			propertyCallExp.eUnset(PivotPackage.Literals.TYPED_ELEMENT__IS_REQUIRED);		// FIXME redundant compatibility
			vaOut.setValue(propertyCallExp);
			checkOut(vaOut);
			return null;
		}

		/**
		 * Copy the eIn tree replacing all references by their souce2targets mapping, using a non-null sibling to prefer a target
		 * in the same containing mapping.
		 */
		protected @Nullable <T extends Element> T copy(@Nullable T eIn) {
			if (eIn == null) {
				return null;
			}
			assert context != null;
			EcoreUtil.Copier copier = new ExpressionCopier(context);
			@SuppressWarnings("unchecked") T eOut = (T) copier.copy(eIn);
			copier.copyReferences();
			context.addDebugCopies(copier);
			return eOut;
		}

		public @Nullable OCLExpression createCastCopy(@Nullable OCLExpression eIn, @Nullable Type toType) {
			if ((eIn == null) || (toType == null)) {
				return null;
			}
			OCLExpression eOut = copy(eIn);
			if (eOut == null) {
				return null;
			}
			Type eType = eOut.getType();
			StandardLibrary standardLibrary = context.getEnvironmentFactory().getStandardLibrary();
			if (eType.conformsTo(standardLibrary, toType)) {
				return eOut;
			}
			assert (toType.conformsTo(standardLibrary, eType));
			return helper.createOperationCallExp(eOut, "oclAsType", helper.createTypeExp(toType));
		}

		protected @NonNull Mapping doMapping(@NonNull Mapping mOut) {
			Mapping mIn = context.equivalentSource(mOut);
			updateChild(mOut.getGuardPattern());
			updateChild(mOut.getBottomPattern());
			updateAllChildren(mOut.getDomain());
			updateAllChildren(mOut.getLocal());
			updateAllReferences(mIn.getSpecification(), mOut.getSpecification());
			Rule overriddenIn = mIn.getOverridden();
			if (overriddenIn != null) {
				mOut.setOverridden(context.equivalentTarget(overriddenIn));
			}
			return mIn;
		}

		public @NonNull Operation getEqualsOperation() {
			if (equalsOperation != null) {
				return equalsOperation;
			}
			for (Operation op : context.environmentFactory.getStandardLibrary().getOclAnyType().getOwnedOperations()) {
				if (op.getName().equals("=")) {
					equalsOperation = op;
					return op;
				}
			}
			throw new IllegalStateException();
		}

		protected <T extends Element> void updateAllChildren(/*@NonNull*/ List<T> targets) {
			for (@SuppressWarnings("null")@NonNull T target : targets) {
				target.accept(this);
			}
		}

		protected <T extends Element> void updateAllReferences(/*@NonNull*/ List<T> sources, /*@NonNull*/ List<T> targets) {
			for (@SuppressWarnings("null")@NonNull T source : sources) {
				targets.add(context.equivalentTarget(source));
			}
		}

		protected void updateChild(@Nullable Element target) {
			if (target != null) {
				target.accept(this);
			}
		}

		@Override
		public @Nullable Object visiting(@NonNull Visitable visitable) {
			throw new IllegalArgumentException("Unsupported " + visitable.eClass().getName() + " for " + getClass().getSimpleName());
		}

		@Override
		public @Nullable Object visitBottomPattern(@NonNull BottomPattern bOut) {
			updateAllChildren(bOut.getAssignment());
			updateAllChildren(bOut.getPredicate());
			updateAllChildren(bOut.getRealizedVariable());
			updateAllChildren(bOut.getVariable());
			return null;
		}

		@Override
		public @Nullable Object visitCoreDomain(@NonNull CoreDomain dOut) {
			Element dIn = context.basicEquivalentSource(dOut);
			TypedModel tmOut;
			if (dIn instanceof CoreDomain) {
				tmOut = context.equivalentTarget(QVTcoreUtil.getTypedModel((CoreDomain)dIn));
			}
			else {
				tmOut = context.getMiddleTypedModelTarget();
			}
			dOut.setTypedModel(tmOut);
			dOut.setName(tmOut.getName());
			updateChild(dOut.getGuardPattern());
			updateChild(dOut.getBottomPattern());
			return null;
		}

		@Override
		public @Nullable Object visitCoreModel(@NonNull CoreModel mOut) {
			@SuppressWarnings("unused")
			CoreModel mIn = context.equivalentSource(mOut);
			context.pushScope(mOut);
			updateAllChildren(mOut.getOwnedPackages());
			context.popScope();
			return null;
		}

		@Override
		public @Nullable Element visitFunction(@NonNull Function fOut) {
			context.pushScope(fOut);
			Function fIn = context.equivalentSource(fOut);
			fOut.setQueryExpression(copy(fIn.getQueryExpression()));
			fOut.setType(fIn.getType());
			//			fOut.setTypeValue(fIn.getTypeValue());
			updateAllChildren(fOut.getOwnedParameters());
			context.popScope();
			return null;
		}

		@Override
		public @Nullable Object visitFunctionParameter(@NonNull FunctionParameter fpOut) {
			FunctionParameter fpIn = context.equivalentSource(fpOut);
			fpOut.setType(fpIn.getType());
			fpOut.setTypeValue(fpIn.getTypeValue());
			return null;
		}

		@Override
		public @Nullable Object visitGuardPattern(@NonNull GuardPattern gOut) {
			updateAllChildren(gOut.getPredicate());
			updateAllChildren(gOut.getVariable());
			for (Variable vOut : gOut.getVariable()) {
				assert !(vOut instanceof RealizedVariable);
			}
			return null;
		}

		@Override
		public @NonNull Mapping visitMapping(@NonNull Mapping mOut) {
			context.pushScope(mOut);
			Mapping mIn = doMapping(mOut);
			context.popScope();
			return mIn;
		}

		@Override
		public final Object visitNavigationAssignment(@NonNull NavigationAssignment object) {			// Override must be of derived classes
			return visiting(object);
		}

		@Override
		public @Nullable Element visitOppositePropertyAssignment(@NonNull OppositePropertyAssignment paOut) {
			OppositePropertyAssignment paIn = context.equivalentSource(paOut);
			paOut.setSlotExpression(copy(paIn.getSlotExpression()));
			paOut.setValue(copy(paIn.getValue()));
			checkOut(paOut);
			return paIn;
		}

		@Override
		public @Nullable Object visitPackage(@NonNull Package pOut) {
			updateAllChildren(pOut.getOwnedClasses());
			updateAllChildren(pOut.getOwnedPackages());
			return null;
		}

		@Override
		public @Nullable Object visitParameter(@NonNull Parameter pOut) {
			Parameter pIn = context.equivalentSource(pOut);
			pOut.setName(pIn.getName());
			pOut.setIsRequired(pIn.isIsRequired());
			Type tVar = pIn.getType();
			pOut.setType(tVar);
			pOut.setTypeValue(pIn.getTypeValue());
			return pIn;
		}

		//
		//	Predicates that were PropertyAssignments need a comparison to be synthesized.
		//
		@Override
		public @Nullable Object visitPredicate(@NonNull Predicate pOut) {
			Element pIn = context.equivalentSource(pOut);
			if (pIn instanceof NavigationAssignment) {
				return convertToPredicate((NavigationAssignment)pIn, pOut);
			}
			else if (pIn instanceof Predicate) {
				pOut.setConditionExpression(copy(((Predicate)pIn).getConditionExpression()));
				checkOut(pOut);
				return null;
			}
			else {
				return visiting(pOut);
			}
		}

		@Override
		public @Nullable Element visitPropertyAssignment(@NonNull PropertyAssignment paOut) {
			PropertyAssignment paIn = context.equivalentSource(paOut);
			paOut.setSlotExpression(copy(paIn.getSlotExpression()));
			paOut.setValue(copy(paIn.getValue()));
			checkOut(paOut);
			return paIn;
		}

		@Override
		public @Nullable Object visitRealizedVariable(@NonNull RealizedVariable rvOut) {
			RealizedVariable rvIn = context.equivalentSource(rvOut);
			rvOut.setOwnedInit(copy(rvIn.getOwnedInit()));
			return rvIn;
		}

		@Override
		public @Nullable Transformation visitTransformation(@NonNull Transformation tOut) {
			Transformation tIn = context.equivalentSource(tOut);
			updateChild(tOut.getOwnedContext());
			updateAllChildren(tOut.getOwnedOperations());
			updateAllChildren(tOut.getModelParameter());
			updateAllChildren(tOut.getRule());
			updateAllReferences(tIn.getSuperClasses(), tOut.getSuperClasses());
			return null;
		}

		@Override
		public @Nullable Object visitTypedModel(@NonNull TypedModel tmOut) {
			TypedModel tmIn = context.equivalentSource(tmOut);
			updateAllReferences(tmIn.getDependsOn(), tmOut.getDependsOn());
			return null;
		}

		@Override
		public @Nullable Object visitVariable(@NonNull Variable vOut) {
			Variable vIn = context.equivalentSource(vOut);
			vOut.setName(vIn.getName());
			vOut.setIsImplicit(vIn.isIsImplicit());
			vOut.setIsRequired(vIn.isIsRequired());
			Type tIn = vIn.getType();
			Type tVar = tIn != null ? context.equivalentTarget(tIn) : null;
			vOut.setType(tVar);
			Type tvIn = vIn.getTypeValue();
			vOut.setTypeValue(tvIn != null ? context.equivalentTarget(tvIn) : null);
			vOut.setOwnedInit(createCastCopy(vIn.getOwnedInit(), tVar));
			return vIn;
		}

		@Override
		public @Nullable Object visitVariableAssignment(@NonNull VariableAssignment vaOut) {
			VariableAssignment vaIn = context.equivalentSource(vaOut);
			vaOut.setTargetVariable(context.equivalentTarget(vaIn.getTargetVariable()));
			vaOut.setValue(copy(vaIn.getValue()));
			return vaIn;
		}
	}

	protected final @NonNull EnvironmentFactory environmentFactory;
	protected final @NonNull QVTcoreHelper helper;
	protected final @NonNull AbstractCreateVisitor<@NonNull ?> createVisitor;
	protected final @NonNull AbstractUpdateVisitor<@NonNull ?> updateVisitor;
	private TypedModel middleTypedModelTarget = null;

	/**
	 * Forward traceability from a source object to its targets for the current mapping. Top level entries ourside a maping are indexed for the null mapping.
	 */
	private final @NonNull Map<@Nullable NamedElement, @NonNull Map<@NonNull Element, @NonNull List<@NonNull Element>>> scope2source2targets = new HashMap<>();

	private final @NonNull Stack<@NonNull NamedElement> scopeStack = new Stack<>();
	/**
	 * Reverse traceability from a target object to its source.
	 */
	private final @NonNull Map<@NonNull Element, @NonNull Element> target2source = new HashMap<>();

	/**
	 * Reverse traceability from a target object to its source.
	 */
	private final @NonNull Map<@NonNull Element, @NonNull Element> debugCopy2source = new HashMap<>();

	private @Nullable Resource debugSource = null;
	private @Nullable Resource debugTarget = null;

	/**
	 * Create a new QVTc to QVTc transformation using an environmentFactory.
	 *
	 * It may be used once by invoking transform(). Repeated transform() calls are beyond the current design.
	 */
	protected AbstractQVTc2QVTc(@NonNull EnvironmentFactory environmentFactory) {
		this.environmentFactory = environmentFactory;
		this.helper = new QVTcoreHelper(environmentFactory);
		this.createVisitor = createCreateVisitor();
		this.updateVisitor = createUpdateVisitor();
	}

	public void addDebugCopies(@NonNull Map<EObject, EObject> copier) {
		for (EObject eSource : copier.keySet()) {
			EObject eTarget = copier.get(eSource);
			assert (eSource != null) && (eTarget != null);
			debugCopy2source.put((Element)eTarget, (Element)eSource);
		}
	}

	/**
	 * Create a new trace for the given list of generated objects for the given
	 * context.
	 *
	 * @param source the source of the trace
	 * @param generated the list of generated objects
	 * @param context the context in which the trace is valid
	 */
	protected void addTrace(@NonNull Element source, @NonNull Element target) {
		target2source.put(target, source);
		//
		NamedElement scope = scopeStack.peek();
		Map<@NonNull Element, @NonNull List<@NonNull Element>> source2targets = scope2source2targets.get(scope);
		if (source2targets == null) {
			source2targets = new HashMap<>();
			scope2source2targets.put(scope, source2targets);
		}
		List<@NonNull Element> targets = source2targets.get(source);
		if (targets == null) {
			targets = new ArrayList<>();
			source2targets.put(source, targets);
		}
		assert !targets.contains(target);
		targets.add(target);
	}

	protected @Nullable Element basicEquivalentSource(@Nullable Element target) {
		if (target == null) {
			return null;
		}
		assert target.eResource() != debugSource : "source element used for basicEquivalentSource " + target;
		return target2source.get(target);
	}

	protected abstract @NonNull AbstractCreateVisitor<@NonNull ?> createCreateVisitor();

	protected @NonNull Import createImport(@NonNull Import iIn) {
		Import iOut = helper.createImport(iIn.getName(), ClassUtil.nonNull(iIn.getImportedNamespace()));
		addTrace(iIn, iOut);
		return iOut;
	}

	protected org.eclipse.ocl.pivot.@NonNull Package createPackage(org.eclipse.ocl.pivot.@NonNull Package pIn) {
		org.eclipse.ocl.pivot.Package pOut = helper.createPackage(ClassUtil.nonNull(pIn.getName()), pIn.getNsPrefix(), pIn.getURI());
		addTrace(pIn, pOut);
		return pOut;
	}

	protected abstract @NonNull AbstractUpdateVisitor<@NonNull ?> createUpdateVisitor();

	protected @NonNull <T extends Element> T equivalentSource(@NonNull T target) {
		assert target.eResource() != debugSource : "source element used for equivalentSource " + target;
		@SuppressWarnings("unchecked") T source = (T) target2source.get(target);
		assert source != null;
		return source;
	}

	protected @NonNull <T extends Element> T equivalentTarget(/*@NonNull*/ T source) {
		assert source != null;
		assert source.eResource() != debugTarget : "target element used for equivalentTarget " + source;
		List<@NonNull Element> targets = null;
		for (int i = scopeStack.size(); (targets == null) && (--i >= 0); ) {
			NamedElement scope = scopeStack.get(i);
			Map<@NonNull Element, @NonNull List<@NonNull Element>> source2targets = scope2source2targets.get(scope);
			if (source2targets != null) {
				targets = source2targets.get(source);
			}
		}
		if (targets != null) {
			//		    assert targets.size() == 1;			-- multiple entries are allowed, the first/primary entry is used
			@SuppressWarnings("unchecked") T target = (T)targets.get(0);
			assert target != null;
			return target;
		}
		else {
			return source;
		}
	}

	public @NonNull EnvironmentFactory getEnvironmentFactory() {
		return environmentFactory;
	}

	public @NonNull QVTcoreHelper getHelper() {
		return helper;
	}

	protected @NonNull TypedModel getMiddleTypedModelTarget() {
		assert middleTypedModelTarget != null;
		return middleTypedModelTarget;
	}

	//    protected @NonNull NamedElement getScope() {
	//    	return scopeStack.peek();
	//    }

	public void popScope() {
		scopeStack.pop();
	}

	public void pushScope(@NonNull NamedElement scope) {
		assert !scopeStack.contains(scope);
		scopeStack.push(scope);
	}

	protected void setDebugSource(@NonNull Resource debugSource) {
		this.debugSource =  debugSource;
	}

	protected void setMiddleTypedModelTarget(@NonNull TypedModel middleTypedModelTarget) {
		this.middleTypedModelTarget = middleTypedModelTarget;
	}

	public void transform(@NonNull Resource source, @NonNull Resource target) throws IOException {
		debugSource = source;
		debugTarget = target;
		//
		//	Do the transformation for each CoreModel. First a createVisitor descent of the input, then an updateVisitor descent of the output.
		//
		for (EObject eContent : source.getContents()) {
			if (eContent instanceof CoreModel) {
				CoreModel mIn = (CoreModel) eContent;
				transform(mIn, target.getContents());
			}
		}
		//
		//	Debug code to conform that every output object is traceable to some input object.
		//
		for (TreeIterator<EObject> tit = target.getAllContents(); tit.hasNext(); ) {
			EObject eTarget = tit.next();
			EObject eSource = target2source.get(eTarget);
			EObject eCopied = debugCopy2source.get(eTarget);
			if ((eSource == null) && (eCopied == null)) {
				System.err.println("No source for " + eTarget.eClass().getName() + "@" + Integer.toString(System.identityHashCode(eTarget)) + ":" + eTarget + " / " + eTarget.eContainer().eClass().getName() + "@" + Integer.toString(System.identityHashCode(eTarget.eContainer())));
			}
		}

		// FIXME the following lines should go obsolete
		List<OperationCallExp> missingOperationCallSources = QVTbaseUtil.rewriteMissingOperationCallSources(environmentFactory, target);
		if (missingOperationCallSources != null) {
			System.err.println("Missing OperationCallExp sources  were fixed up for '" + target.getURI() + "'");
		}
	}

	protected void transform(@NonNull CoreModel mIn, @NonNull List<@NonNull EObject> mOuts) throws IOException {
		try {
			CoreModel mOut = (CoreModel) mIn.accept(createVisitor);
			assert mOut != null;
			mOuts.add(mOut);
			mOut.accept(updateVisitor);
		}
		catch (WrappedException e) {
			Throwable t = e.getCause();
			if (t instanceof IOException) {
				throw (IOException)t;
			}
			throw e;
		}
	}
}
