/*******************************************************************************
 * Copyright (c) 2016, 2018 Willink Transformations and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v20.html
 *
 * Contributors:
 *     E.D.Willink - initial API and implementation (inspired by Horacio Hoyos' prototype)
 ******************************************************************************/
package org.eclipse.qvtd.compiler.internal.qvtc2qvtu;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.CallExp;
import org.eclipse.ocl.pivot.Element;
import org.eclipse.ocl.pivot.IfExp;
import org.eclipse.ocl.pivot.LiteralExp;
import org.eclipse.ocl.pivot.LoopExp;
import org.eclipse.ocl.pivot.NullLiteralExp;
import org.eclipse.ocl.pivot.OCLExpression;
import org.eclipse.ocl.pivot.Operation;
import org.eclipse.ocl.pivot.OperationCallExp;
import org.eclipse.ocl.pivot.OppositePropertyCallExp;
import org.eclipse.ocl.pivot.PivotFactory;
import org.eclipse.ocl.pivot.PropertyCallExp;
import org.eclipse.ocl.pivot.Variable;
import org.eclipse.ocl.pivot.VariableDeclaration;
import org.eclipse.ocl.pivot.VariableExp;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.ocl.pivot.utilities.EnvironmentFactory;
import org.eclipse.qvtd.compiler.internal.common.AbstractQVTc2QVTc;
import org.eclipse.qvtd.pivot.qvtbase.Domain;
import org.eclipse.qvtd.pivot.qvtbase.Predicate;
import org.eclipse.qvtd.pivot.qvtbase.QVTbaseFactory;
import org.eclipse.qvtd.pivot.qvtbase.Transformation;
import org.eclipse.qvtd.pivot.qvtbase.TypedModel;
import org.eclipse.qvtd.pivot.qvtcore.Area;
import org.eclipse.qvtd.pivot.qvtcore.Assignment;
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.CorePattern;
import org.eclipse.qvtd.pivot.qvtcore.GuardPattern;
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.RealizedVariable;
import org.eclipse.qvtd.pivot.qvtcore.VariableAssignment;
import org.eclipse.qvtd.pivot.qvtcore.utilities.QVTcoreUtil;

/**
 * QVTc2QVTu transforms a QVTc transformation to impose the single direction defined by a QVTuConfiguration.
 * - the output domain is enforced
 * - other domains are not-enforced
 */
public class QVTc2QVTu extends AbstractQVTc2QVTc
{
	protected class CreateVisitor extends AbstractCreateVisitor<@NonNull QVTc2QVTu>
	{
		public CreateVisitor(@NonNull QVTc2QVTu context) {
			super(context);
		}

		private boolean allReferencedVariablesInInputDomain(@NonNull Element a) {
			VariableDeclaration referredVariable = getReferredMappingVariable(a);
			if ((referredVariable != null) && !isInputDomain(basicGetArea(referredVariable))) {
				return false;
			}
			for (TreeIterator<EObject> tit = a.eAllContents(); tit.hasNext(); ) {
				referredVariable = getReferredMappingVariable(tit.next());
				if ((referredVariable != null) && !isInputDomain(basicGetArea(referredVariable))) {
					return false;
				}
			}
			return true;
		}

		private boolean allReferencedVariablesInOutputDomain(@NonNull Element a) {
			VariableDeclaration referredVariable = getReferredMappingVariable(a);
			if ((referredVariable != null) && !isOutputDomain(basicGetArea(referredVariable))) {
				return false;
			}
			for (TreeIterator<EObject> tit = a.eAllContents(); tit.hasNext(); ) {
				referredVariable = getReferredMappingVariable(tit.next());
				if ((referredVariable != null) && !isOutputDomain(basicGetArea(referredVariable))) {
					return false;
				}
			}
			return true;
		}

		private boolean anyReferencedBottomMiddleDomainVariables(@NonNull OCLExpression value) {
			VariableDeclaration referredVariable = getReferredMappingVariable(value);
			if (isMiddleDomainVariable(referredVariable)) {
				return true;
			}
			for (TreeIterator<EObject> tit = value.eAllContents(); tit.hasNext(); ) {
				referredVariable = getReferredMappingVariable(tit.next());
				if (isMiddleDomainVariable(referredVariable)) {
					return true;
				}
			}
			return false;
		}

		private boolean anyReferencedMiddleDomainVariables(@NonNull OCLExpression value) {
			VariableDeclaration referredVariable = getReferredMappingVariable(value);
			if ((referredVariable != null) && isMiddleDomain(basicGetArea(referredVariable))) {
				return true;
			}
			for (TreeIterator<EObject> tit = value.eAllContents(); tit.hasNext(); ) {
				referredVariable = getReferredMappingVariable(tit.next());
				if ((referredVariable != null) && isMiddleDomain(basicGetArea(referredVariable))) {
					return true;
				}
			}
			return false;
		}

		private boolean anyReferencedRealizedVariables(@NonNull OCLExpression value) {
			VariableDeclaration referredVariable = getReferredMappingVariable(value);
			//			if ((referredVariable != null) && isMiddleDomain(basicGetArea(referredVariable))) {
			//				return true;
			//			}
			if (referredVariable instanceof RealizedVariable) {
				return true;
			}
			for (TreeIterator<EObject> tit = value.eAllContents(); tit.hasNext(); ) {
				referredVariable = getReferredMappingVariable(tit.next());
				//				if ((referredVariable != null) && isOutputDomain(basicGetArea(referredVariable))) {
				//					return true;
				//				}
				if (referredVariable instanceof RealizedVariable) {
					return true;
				}
			}
			return false;
		}

		/**
		 * Create an ocl expression from an assignment than can be used as the
		 * condition expression of a predicate.
		 *
		 * @param aIn the a in
		 * @param environmentFactory the environment factory
		 * @return the operation call exp
		 */
		private OperationCallExp assignmentToOclExp(@NonNull Assignment aIn) {
			OperationCallExp exp = PivotFactory.eINSTANCE.createOperationCallExp();
			for (Operation op : environmentFactory.getStandardLibrary().getOclAnyType().getOwnedOperations()) {
				if (op.getName().equals("=")) {
					exp.setReferredOperation(op);
					exp.setName(op.getName());
					exp.setType(op.getType());
					break;
				}
			}
			exp.getOwnedArguments().add(EcoreUtil.copy(aIn.getValue()));
			if (aIn instanceof PropertyAssignment) {
				PropertyCallExp sourceExp = PivotFactory.eINSTANCE.createPropertyCallExp();
				PropertyAssignment paIn = (PropertyAssignment) aIn;
				sourceExp.setReferredProperty(paIn.getTargetProperty());
				sourceExp.setType(paIn.getTargetProperty().getType());
				sourceExp.setOwnedSource(EcoreUtil.copy(paIn.getSlotExpression()));
				exp.setOwnedSource(sourceExp);
			} else if (aIn instanceof OppositePropertyAssignment) {
				OppositePropertyCallExp sourceExp = PivotFactory.eINSTANCE.createOppositePropertyCallExp();
				OppositePropertyAssignment opaIn = (OppositePropertyAssignment) aIn;
				sourceExp.setReferredProperty(opaIn.getTargetProperty());
				sourceExp.setType(opaIn.getTargetProperty().getType());
				sourceExp.setOwnedSource(EcoreUtil.copy(opaIn.getSlotExpression()));
				exp.setOwnedSource(sourceExp);
			} else { // aIn instanceof VariableAssignment
				VariableExp varExp = PivotFactory.eINSTANCE.createVariableExp();
				varExp.setIsImplicit(false);
				varExp.setReferredVariable(((VariableAssignment) aIn).getTargetVariable());
				exp.setOwnedSource(varExp);
			}
			return exp;
		}

		private @Nullable Area basicGetArea(@Nullable VariableDeclaration variable) {
			return QVTcoreUtil.getContainingArea(variable);
		}

		//
		//	Assignments may mutate to Predicates.
		//
		@Override
		protected void doAssignments(@NonNull BottomPattern bIn, @NonNull BottomPattern bOut) {
			GuardPattern gOut = context.equivalentTarget(bIn.getArea().getGuardPattern());
			assert gOut != null;
			for (@NonNull Assignment aIn : ClassUtil.nullFree(bIn.getAssignment())) {
				Element aOut = create(aIn);
				if (aOut instanceof Predicate) {
					bOut.getPredicate().add((Predicate) aOut);
				}
				else if (aOut instanceof Assignment) {
					bOut.getAssignment().add((Assignment) aOut);
				}
				else if (aOut != null) {
					throw new UnsupportedOperationException();
				}
			}
		}

		//
		//	Right-to-Middle and Local-to-Middle property assignments are discarded.
		//	Left-to-Left and Middle-to-Left property assignments change to predicates.
		//	Left defaults are non-defaults.
		//
		public @Nullable Element doNavigationAssignment(@NonNull NavigationAssignment paIn) {
			OCLExpression slotExpression = paIn.getSlotExpression();
			OCLExpression value = paIn.getValue();
			assert (slotExpression != null) && (value != null);
			//			Area sourceArea = getSourceVariableArea(value);
			Area targetArea = getSourceVariableArea(slotExpression);
			//
			// A backward "p.q := v" rewrites as a forward "v := p.q".
			//
			if (isInputDomain(targetArea) && (value instanceof VariableExp) && anyReferencedMiddleDomainVariables(value)) {		// isMtoL
				VariableAssignment vaOut = QVTcoreFactory.eINSTANCE.createVariableAssignment();
				context.addTrace(paIn, vaOut);
				return vaOut;
			}
			if (isNonOutputDomain(targetArea) &&								// is RtoM or MtoL or RtoL
					!(value instanceof VariableExp) &&			// why?
					!(value instanceof NullLiteralExp) &&		// why?
					allReferencedVariablesInOutputDomain(value)) {
				return null;
			}
			if (isInputDomain(targetArea) && (targetArea instanceof Mapping) && anyReferencedBottomMiddleDomainVariables(value)) {	// isMtoM
				return null;
			}
			/*			if (isInputDomain(sourceArea)) {
				VariableDeclaration referredVariable = getReferredMappingVariable(value);
				if (isMiddleDomainVariable(referredVariable)) {
//					return null;
				}
//				if (referredVariable != null) {
//					Area area = basicGetArea(referredVariable);
//					if (isMiddleDomain(area) && (area instanceof BottomPattern)) {		// FIXME are is never a BottomPattern
//						return null;
//					}
//				}
			}
			if (isMiddleDomain(sourceArea)) {								// isLocaltoM
				VariableDeclaration referredVariable = getReferredMappingVariable(value);
				if (isMiddleDomainVariable(referredVariable)) {
					return null;
				}
//				if (referredVariable != null) {
//					Area area = basicGetArea(referredVariable);
//					if (isMiddleDomain(area) && (area instanceof BottomPattern)) {		// FIXME are is never a BottomPattern
//						return null;
//					}
//				}
			} */

			if (isInputDomain(targetArea) && anyReferencedMiddleDomainVariables(value)) {		// isMtoL
				// Assignments to Predicates
				//				Predicate pOut = QVTbaseFactory.eINSTANCE.createPredicate();
				//				context.addTrace(paIn, pOut);
				//	            pOut.setConditionExpression(MtcUtil.assignmentToOclExp(paIn, environmentFactory));
				//	            return pOut;
				return null;
			}
			if (isInputDomain(targetArea) && allReferencedVariablesInInputDomain(paIn)) {
				// Assignments to Predicates
				Predicate pOut = QVTbaseFactory.eINSTANCE.createPredicate();
				context.addTrace(paIn, pOut);
				pOut.setConditionExpression(assignmentToOclExp(paIn));
				return pOut;
			}
			NavigationAssignment paOut = paIn instanceof OppositePropertyAssignment
					? (NavigationAssignment) super.visitOppositePropertyAssignment((@NonNull OppositePropertyAssignment) paIn)
						: (NavigationAssignment) super.visitPropertyAssignment((@NonNull PropertyAssignment) paIn);
					assert paOut != null;
					if (qvtuConfiguration.isCheckMode() && paIn.isIsDefault() && isOutputDomain(paIn.getBottomPattern().getArea())) {
						// Default assignments
						paOut.setIsDefault(false);
					}
					return paOut;
		}

		//
		//	RealizedVariables may mutate to Variables.
		//
		@Override
		protected void doRealizedVariables(@NonNull BottomPattern bIn, @NonNull BottomPattern bOut) {
			GuardPattern gOut = context.equivalentTarget(bIn.getArea().getGuardPattern());
			assert gOut != null;
			for (RealizedVariable rvIn : ClassUtil.nullFree(bIn.getRealizedVariable())) {
				Variable vOut = create(rvIn);
				if (vOut instanceof RealizedVariable) {
					bOut.getRealizedVariable().add((RealizedVariable) vOut);
				}
				else {
					gOut.getOwnedVariables().add(vOut);
				}
			}
		}

		private @NonNull Area getContainingArea(@NonNull VariableDeclaration variable) {
			Area targetArea = QVTcoreUtil.getContainingArea(variable);
			assert targetArea != null;
			return targetArea;
		}

		private @Nullable VariableDeclaration getReferredMappingVariable(@Nullable EObject value) {
			if (value instanceof VariableExp) {
				VariableDeclaration referredVariable = ((VariableExp)value).getReferredVariable();
				EObject eContainer = referredVariable.eContainer();
				if (eContainer instanceof Transformation) {			// "this" is not a mapping variable (has no domain)
					return null;
				}
				if (eContainer instanceof LoopExp) {				// iterators/accumulators are not mapping variables (has no domain)
					return null;
				}
				return referredVariable;
			}
			else {
				return null;
			}
		}

		private @Nullable Area getSourceVariableArea(@Nullable OCLExpression exp) {
			if (exp instanceof VariableExp) {
				Variable expV = (Variable) ((VariableExp)exp).getReferredVariable();
				return basicGetArea(expV);
			} else if (exp instanceof CallExp) {
				return getSourceVariableArea(((CallExp) exp).getOwnedSource());
			} else if (exp instanceof IfExp) {
				return getSourceVariableArea(((IfExp) exp).getOwnedCondition());
			} else if (exp instanceof LiteralExp) {
				return null;
			}
			return null;
		}

		private boolean isMiddleDomainVariable(@Nullable VariableDeclaration variable) {
			if (variable == null) {
				return false;
			}
			CorePattern pattern = QVTcoreUtil.getContainingPattern(variable);
			if (!(pattern instanceof BottomPattern)) {
				return false;
			}
			return pattern.getArea() instanceof Mapping;
		}

		//
		//	CoreDomains enforcement is aligned to the direction
		//
		@Override
		public @NonNull CoreDomain visitCoreDomain(@NonNull CoreDomain dIn) {
			CoreDomain dOut = super.visitCoreDomain(dIn);
			TypedModel typedModel = QVTcoreUtil.getTypedModel(dIn);
			String name = typedModel.getName();
			dOut.setName(name);			// Redundant replication of Epsilon prototype functionality
			if (qvtuConfiguration.isInput(typedModel)) {
				dOut.setIsEnforceable(false);
				dOut.setIsCheckable(true);
			} else {
				if (qvtuConfiguration.isCheckMode()) {
					dOut.setIsEnforceable(false);
				} else if (qvtuConfiguration.isEnforceMode()) {
					dOut.setIsCheckable(false);
				}
			}
			return dOut;
		}

		/*
		 * Override to redefine external URI.
		 */
		@Override
		public @NonNull CoreModel visitCoreModel(@NonNull CoreModel mIn) {
			CoreModel mOut = super.visitCoreModel(mIn);
			String externalURI = mIn.getExternalURI();
			if (externalURI.endsWith(".qvtcas")) {
				externalURI = externalURI.replace(".qvtcas", ".qvtu.qvtcas");
			}
			else if (externalURI.endsWith(".qvtc")) {
				externalURI = externalURI.replace(".qvtc", ".qvtu.qvtcas");
			}
			mOut.setExternalURI(externalURI);
			return mOut;
		}

		/*
		 * Override to suppresses nested scopes since QVTc references can be cross-domain and we convert mappings 1:1.
		 */
		@Override
		public @Nullable Element visitMapping(@NonNull Mapping mIn) {
			MappingMode mappingMode = getMappingMode(mIn);
			if (mappingMode == null) {
				return null;
			}
			@NonNull Mapping mOut = QVTcoreFactory.eINSTANCE.createMapping();
			doMapping(mIn, mOut);
			return mOut;
		}

		@Override
		public @Nullable Element visitOppositePropertyAssignment(@NonNull OppositePropertyAssignment paIn) {
			return doNavigationAssignment(paIn);
		}

		//
		//	Bottom pattern predicates involving output variables are discarded; they should be assignments.
		//
		@Override
		public @Nullable Element visitPredicate(@NonNull Predicate pIn) {
			//			boolean oldResult = true;
			//			if ((pIn.getPattern() instanceof BottomPattern) && allReferencedVariablesInOutputDomain(pIn)) {
			//				oldResult = false;
			//			}
			//			else if ((pIn.getPattern() instanceof BottomPattern) && anyReferencedVariableInMiddleOrOutputDomain(pIn)) {
			//				oldResult = false;
			//			}
			if ((pIn.getPattern() instanceof BottomPattern) && anyReferencedRealizedVariables(QVTcoreUtil.getOwnedConditionExpression(pIn))) {
				//				assert !oldResult;
				return null;
			}
			//			if (!oldResult) {
			//				anyReferencedNonInputDomainVariables2(pIn);
			//				allReferencedVariablesInOutputDomain(pIn);
			//				anyReferencedVariableInMiddleOrOutputDomain(pIn);
			//			}
			//			assert oldResult;
			/*			OCLExpression conditionExpression = pIn.getConditionExpression();
			if (conditionExpression instanceof OperationCallExp) {
				OperationCallExp callExp = (OperationCallExp)conditionExpression;
				if ("=".equals(callExp.getReferredOperation().getName()) && (callExp.getOwnedArguments().size() == 1)) {		// FIXME more accuracy
					OCLExpression leftExpression= callExp.getOwnedSource();
					OCLExpression rightExpression= callExp.getOwnedArguments().get(0);
					if ((leftExpression != null) && (rightExpression != null)) {
						PropertyCallExp middlePropertyAccess = isMiddleDomainPropertyAccess(leftExpression);
						if ((middlePropertyAccess != null) && isInputDomainExpression(rightExpression)) {
							return convertToPropertyAssignment(middlePropertyAccess, rightExpression);
						}
						middlePropertyAccess = isMiddleDomainPropertyAccess(rightExpression);
						if ((middlePropertyAccess != null) && isInputDomainExpression(leftExpression)) {
							return convertToPropertyAssignment(middlePropertyAccess, leftExpression);
						}
					}
				}
			} */
			return super.visitPredicate(pIn);
		}

		@Override
		public @Nullable Element visitPropertyAssignment(@NonNull PropertyAssignment paIn) {
			return doNavigationAssignment(paIn);
		}

		//
		//	Input domain RealizedVariables are changed to unrealized Variables.
		//
		@Override
		public @NonNull Variable visitRealizedVariable(@NonNull RealizedVariable rvIn) {
			Area aIn = getContainingArea(rvIn);
			if (isInputDomain(aIn)) {
				BottomVariable vOut = QVTcoreFactory.eINSTANCE.createBottomVariable();
				assert vOut != null;
				context.addTrace(rvIn, vOut);
				vOut.setName(rvIn.getName());
				vOut.setType(rvIn.getType());
				vOut.setIsRequired(rvIn.isIsRequired());
				return vOut;
			}
			else {
				return super.visitRealizedVariable(rvIn);
			}
		}

		//
		//	Right-to-Middle and Middle-to-Middle variable assignments are discarded.
		//	Middle-to-Left variable assignments change to predicates.
		//
		//	FIXME why different to PropertyAssignments
		//
		@Override
		public @Nullable Element visitVariableAssignment(@NonNull VariableAssignment vaIn) {
			VariableDeclaration targetVariable = vaIn.getTargetVariable();
			OCLExpression value = vaIn.getValue();
			assert (targetVariable != null) && (value != null);
			Area targetArea = getContainingArea(targetVariable);
			if (isInputDomain(targetArea) && !allReferencedVariablesInInputDomain(value)) {	// an output-to-input assignment
				return null;
			}
			//			if (isInputDomain1(targetArea) && anyReferencedMiddleDomainVariables(value)) {	// isMtoL
			//				return null;
			//			}
			//			if (isMiddleDomain(targetArea) /*&& !(value instanceof VariableExp)*/ && allMatchReferencedOutputDomainVariables(value)) {	// isRtoM
			//				return null;
			//			}
			//			if ((targetArea instanceof Mapping) && anyReferencedBottomMiddleDomainVariables(value)) {	// isMtoM
			//				return null;
			//			}
			return super.visitVariableAssignment(vaIn);
		}
	}

	protected class UpdateVisitor extends AbstractUpdateVisitor<@NonNull QVTc2QVTu>
	{
		public UpdateVisitor(@NonNull QVTc2QVTu context) {
			super(context);
		}

		/*
		 * Override to suppresses nested scopes since QVTc references can be cross-domain and we convert mappings 1:1.
		 */
		@Override
		public @NonNull Mapping visitMapping(@NonNull Mapping mOut) {
			return doMapping(mOut);
		}

		/*
		 * Override to handle the backward "p.q := v" rewrite as "v := p.q".
		 */
		@Override
		public @Nullable Object visitVariableAssignment(@NonNull VariableAssignment vaOut) {
			Element pIn = context.equivalentSource(vaOut);
			if (pIn instanceof PropertyAssignment) {
				return convertToVariableAssignment((PropertyAssignment)pIn, vaOut);
			}
			else {
				return super.visitVariableAssignment(vaOut);
			}
		}
	}

	private enum DomainMode {
		INPUT,
		MIDDLE,
		OUTPUT
	}

	private static final int IS_INPUT_MASK = 1;
	private static final int IS_OUTPUT_MASK = 2;

	private enum MappingMode {
		NULL(0),
		LEFT2MIDDLE(IS_INPUT_MASK),
		MIDDLE2RIGHT(IS_OUTPUT_MASK),
		LEFT2RIGHT(IS_INPUT_MASK | IS_OUTPUT_MASK);

		private int flags;

		private MappingMode(int flags) { this.flags = flags; }

		private @NonNull MappingMode get(int flagsUnion) {
			switch (flagsUnion) {
				case 1 : return LEFT2MIDDLE;
				case 2 : return MIDDLE2RIGHT;
				case 3 : return LEFT2RIGHT;
			}
			return NULL;
		}

		public @NonNull MappingMode asInput() {
			return get(flags | IS_INPUT_MASK);
		}

		public @NonNull MappingMode asOutput() {
			return get(flags | IS_OUTPUT_MASK);
		}

		public boolean hasInputDomain() { return (flags & IS_INPUT_MASK) != 0; }
		public boolean hasOutputDomain() { return (flags & IS_OUTPUT_MASK) != 0; }

		public @NonNull MappingMode union(@NonNull MappingMode anotherMappingMode) {
			return get(flags | anotherMappingMode.flags);
		}
	}

	private final @NonNull QVTuConfiguration qvtuConfiguration;

	/**
	 * Cached INPUT/MIDDLE/OUTPUT state of each Area, aggregating refined and/or local states.
	 */
	private final @NonNull Map<@NonNull Area, @NonNull DomainMode> domain2mode = new HashMap<@NonNull Area, @NonNull DomainMode>();

	/**
	 * Cached LEFT2MIDDLE/MIDDLE2RIGHT/LEFT2RIGHT state of each top or local Mapping aggregating refined states.
	 */
	private final @NonNull Map<@NonNull Mapping, @NonNull MappingMode> mapping2mode = new HashMap<@NonNull Mapping, @NonNull MappingMode>();

	public QVTc2QVTu(@NonNull EnvironmentFactory environmentFactory, @NonNull QVTuConfiguration qvtuConfiguration) {
		super(environmentFactory);
		this.qvtuConfiguration = qvtuConfiguration;
	}

	@Override
	protected @NonNull CreateVisitor createCreateVisitor() {
		return new CreateVisitor(this);
	}

	@Override
	protected @NonNull UpdateVisitor createUpdateVisitor() {
		return new UpdateVisitor(this);
	}

	private @Nullable MappingMode getComposedMappingMode(@NonNull Mapping mapping) {
		MappingMode mergedMode = MappingMode.NULL;
		for (@NonNull Domain domain: ClassUtil.nullFree(mapping.getDomain())) {
			TypedModel typedModel = QVTcoreUtil.getTypedModel(domain);
			//			String name = PivotUtil.getName(typedModel);
			if (qvtuConfiguration.isInput(typedModel)) {
				mergedMode = mergedMode.asInput();
				domain2mode.put((CoreDomain)domain, DomainMode.INPUT);
			}
			else if (qvtuConfiguration.isIntermediate(typedModel) || qvtuConfiguration.isOutput(typedModel)) {
				if (!domain.isIsEnforceable()) {
					return null;
				}
				mergedMode = mergedMode.asOutput();
				domain2mode.put((CoreDomain)domain, DomainMode.OUTPUT);
			}
		}
		for (@NonNull Mapping localMapping : ClassUtil.nullFree(mapping.getLocal())) {
			MappingMode mappingMode = getMappingMode(localMapping);
			if (mappingMode == null) {
				return null;
			}
			mergedMode = mergedMode.union(mappingMode);
		}
		return mergedMode;
	}

	private @Nullable MappingMode getMappingMode(@NonNull Mapping mapping) {
		MappingMode mergedMode = mapping2mode.get(mapping);
		if (mergedMode == null) {
			mergedMode = getComposedMappingMode(mapping);
			if (mergedMode == null) {
				return null;
			}
			for (@NonNull Mapping refinedMapping : ClassUtil.nullFree(mapping.getSpecification())) {
				MappingMode composedMappingMode = getComposedMappingMode(refinedMapping);
				if (composedMappingMode == null) {
					return null;
				}
				mergedMode = mergedMode.union(composedMappingMode);
			}
			mapping2mode.put(mapping, mergedMode);
			setMappingDomainModes(mapping, mergedMode);
		}
		return mergedMode;
	}

	private boolean isInputDomain(@Nullable Area area) {
		if (area == null) {
			return false;
		}
		DomainMode domainMode = domain2mode.get(area);
		assert domainMode != null;
		return domainMode == DomainMode.INPUT;
	}

	private boolean isMiddleDomain(@Nullable Area area) {
		if (area == null) {
			return false;
		}
		DomainMode domainMode = domain2mode.get(area);
		assert domainMode != null;
		return domainMode == DomainMode.MIDDLE;
	}

	private boolean isNonOutputDomain(@Nullable Area area) {
		if (area == null) {
			return false;
		}
		DomainMode domainMode = domain2mode.get(area);
		assert domainMode != null;
		return domainMode != DomainMode.OUTPUT;
	}

	private boolean isOutputDomain(@Nullable Area area) {
		if (area == null) {
			return false;
		}
		DomainMode domainMode = domain2mode.get(area);
		assert domainMode != null;
		return domainMode == DomainMode.OUTPUT;
	}

	private void setMappingDomainModes(@NonNull Mapping mapping, @NonNull MappingMode mode) {
		domain2mode.put(mapping, !mode.hasInputDomain() ? DomainMode.INPUT : !mode.hasOutputDomain() ? DomainMode.OUTPUT : DomainMode.MIDDLE);
		for (@NonNull Mapping localMapping : ClassUtil.nullFree(mapping.getLocal())) {
			setMappingDomainModes(localMapping, mode);
		}
	}
}
