/*******************************************************************************
 * Copyright (c) 2015 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:
 *   E.D.Willink - Initial API and implementation
 *******************************************************************************/
package org.eclipse.qvtd.compiler.internal.qvts2qvti;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.emf.common.util.ECollections;
import org.eclipse.emf.common.util.EList;
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.AnyType;
import org.eclipse.ocl.pivot.CollectionItem;
import org.eclipse.ocl.pivot.CollectionLiteralExp;
import org.eclipse.ocl.pivot.CollectionLiteralPart;
import org.eclipse.ocl.pivot.CollectionRange;
import org.eclipse.ocl.pivot.CollectionType;
import org.eclipse.ocl.pivot.DataType;
import org.eclipse.ocl.pivot.IfExp;
import org.eclipse.ocl.pivot.InvalidType;
import org.eclipse.ocl.pivot.IterateExp;
import org.eclipse.ocl.pivot.Iteration;
import org.eclipse.ocl.pivot.IteratorExp;
import org.eclipse.ocl.pivot.MapLiteralExp;
import org.eclipse.ocl.pivot.MapLiteralPart;
import org.eclipse.ocl.pivot.MapType;
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.PrimitiveLiteralExp;
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.StandardLibrary;
import org.eclipse.ocl.pivot.TupleLiteralExp;
import org.eclipse.ocl.pivot.TupleLiteralPart;
import org.eclipse.ocl.pivot.TupleType;
import org.eclipse.ocl.pivot.Type;
import org.eclipse.ocl.pivot.TypeExp;
import org.eclipse.ocl.pivot.TypedElement;
import org.eclipse.ocl.pivot.Variable;
import org.eclipse.ocl.pivot.VariableDeclaration;
import org.eclipse.ocl.pivot.VariableExp;
import org.eclipse.ocl.pivot.VoidType;
import org.eclipse.ocl.pivot.internal.manager.PivotMetamodelManager;
import org.eclipse.ocl.pivot.util.Visitable;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.ocl.pivot.utilities.NameUtil;
import org.eclipse.ocl.pivot.utilities.PivotUtil;
import org.eclipse.qvtd.compiler.internal.qvtp2qvts.ClassDatumAnalysis;
import org.eclipse.qvtd.compiler.internal.qvtp2qvts.Edge;
import org.eclipse.qvtd.compiler.internal.qvtp2qvts.EdgeRole;
import org.eclipse.qvtd.compiler.internal.qvtp2qvts.NavigationEdge;
import org.eclipse.qvtd.compiler.internal.qvtp2qvts.Node;
import org.eclipse.qvtd.compiler.internal.qvtp2qvts.NodeConnection;
import org.eclipse.qvtd.compiler.internal.qvtp2qvts.Region;
import org.eclipse.qvtd.compiler.internal.qvtp2qvts.RegionUtil;
import org.eclipse.qvtd.compiler.internal.qvtp2qvts.SchedulerConstants;
import org.eclipse.qvtd.pivot.qvtbase.Domain;
import org.eclipse.qvtd.pivot.qvtbase.Function;
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.qvtbase.utilities.QVTbaseUtil;
import org.eclipse.qvtd.pivot.qvtcorebase.Area;
import org.eclipse.qvtd.pivot.qvtcorebase.Assignment;
import org.eclipse.qvtd.pivot.qvtcorebase.BottomPattern;
import org.eclipse.qvtd.pivot.qvtcorebase.GuardPattern;
import org.eclipse.qvtd.pivot.qvtcorebase.PropertyAssignment;
import org.eclipse.qvtd.pivot.qvtcorebase.RealizedVariable;
import org.eclipse.qvtd.pivot.qvtcorebase.VariableAssignment;
import org.eclipse.qvtd.pivot.qvtcorebase.analysis.DomainUsage;
import org.eclipse.qvtd.pivot.qvtcorebase.utilities.AssignmentComparator;
import org.eclipse.qvtd.pivot.qvtimperative.ConnectionVariable;
import org.eclipse.qvtd.pivot.qvtimperative.ImperativeArea;
import org.eclipse.qvtd.pivot.qvtimperative.ImperativeBottomPattern;
import org.eclipse.qvtd.pivot.qvtimperative.ImperativeDomain;
import org.eclipse.qvtd.pivot.qvtimperative.MappingCallBinding;
import org.eclipse.qvtd.pivot.qvtimperative.MappingStatement;
import org.eclipse.qvtd.pivot.qvtimperative.util.AbstractExtendingQVTimperativeVisitor;
import org.eclipse.qvtd.pivot.qvtimperative.utilities.QVTimperativeUtil;

import com.google.common.collect.Iterables;

public class BasicRegion2Mapping extends AbstractRegion2Mapping
{		
	private static final class DomainNameComparator implements Comparator<@NonNull Domain>
	{
		public static final @NonNull DomainNameComparator INSTANCE = new DomainNameComparator();

		@Override
		public int compare(@NonNull Domain o1, @NonNull Domain o2) {
			TypedModel t1 = o1.getTypedModel();
			TypedModel t2 = o2.getTypedModel();
			String n1 = t1 != null ? t1.getName() : null;
			String n2 = t2 != null ? t2.getName() : null;
			return ClassUtil.safeCompareTo(n1, n2);
		}
	}

	private class ExpressionCreator extends AbstractExtendingQVTimperativeVisitor<@NonNull OCLExpression, @NonNull BasicRegion2Mapping>
	{
		protected final @NonNull Set<@NonNull Node> multiAccessedNodes = new HashSet<@NonNull Node>();
		protected final @NonNull Set<@NonNull Node> conditionalNodes = new HashSet<@NonNull Node>();

		public ExpressionCreator() {
			super(BasicRegion2Mapping.this);
			analyzeExpressions(multiAccessedNodes, conditionalNodes);
		}

		/**
		 * Compute the nodes that are only evaluated if a run-time if-condition is satisfied, and the nodes that are always accessed more than once.
		 */
		private void analyzeExpressions(@NonNull Set<Node> multiAccessedNodes, @NonNull Set<Node> conditionalNodes) {
			Set<@NonNull Node> unconditionalNodes = new HashSet<@NonNull Node>();
			for (@NonNull Edge edge : region.getRealizedEdges()) {
				analyzeIncomingPath(edge.getTarget(), unconditionalNodes, conditionalNodes, false);
			}
			conditionalNodes.removeAll(unconditionalNodes);
//			if (conditionalNodes.size() > 0) {
//				System.out.println("Conditional nodes for " + this);
//				for (Node conditionalNode : conditionalNodes) {
//					System.out.println("  " + conditionalNode);
//				}
//			}
			for (@NonNull Node node : unconditionalNodes) {
				int accesses = 0;
				for (@NonNull Edge outgoingEdge : node.getOutgoingEdges()) {
					if (outgoingEdge.isNavigation() || outgoingEdge.isComputation()) {
						accesses++;
					}
				}
				if (accesses > 1) {
					multiAccessedNodes.add(node);
				}
			}
//			if (multiAccessedNodes.size() > 0) {
//				System.out.println("multi-accessed nodes for " + this);
//				for (Node multiAccessedNode : multiAccessedNodes) {
//					System.out.println("  " + multiAccessedNode);
//				}
//			}
		}

		private void analyzeIncomingPath(@NonNull Node node, @NonNull Set<Node> unconditionalNodes, @NonNull Set<Node> conditionalNodes, boolean isConditional) {
			if ((isConditional ? conditionalNodes : unconditionalNodes).add(node)) {
				boolean isIf = isIfExp(node);
				for (@NonNull Edge edge : node.getIncomingEdges()) {
					if (edge.isComputation()) {
						boolean isIfThenOrElse = isIf && ("then".equals(edge.getName()) || "else".equals(edge.getName()));
						analyzeIncomingPath(edge.getSource(), unconditionalNodes, conditionalNodes, isConditional || isIfThenOrElse);
					}
					else if (edge.isNavigation()) {
						analyzeIncomingPath(edge.getSource(), unconditionalNodes, conditionalNodes, isConditional);
					}
				}
				return;
			}
		}
		
		protected @NonNull OCLExpression create(/*@NonNull*/ Node node) {
			if (node.isNull()) {
				return helper.createNullLiteralExp();
			}
			Variable theVariable = node2variable.get(node);
			if (theVariable == null) {
				TypedElement oldTypedElement = node.getTypedElements().iterator().next();
				assert oldTypedElement != null;
				OCLExpression initExpression = oldTypedElement.accept(this);
				assert initExpression != null;
//				Type type = newExpression.getType();
//				assert type != null;
//				theVariable = PivotUtil.createVariable(getSafeName(node), type, true, newExpression);
//				mapping.getBottomPattern().getVariable().add(theVariable);
//				node2variable.put(node, theVariable);
				if ((initExpression instanceof PrimitiveLiteralExp) || hasRealizedVariableReference(initExpression) || conditionalNodes.contains(node)) {
					return initExpression;
				}
				theVariable = createBottomVariable(node, initExpression);
			}
			return PivotUtil.createVariableExp(theVariable);
		}

		private @Nullable OCLExpression create(@Nullable OCLExpression oldTypedElement) {
			if (oldTypedElement == null) {
				return null;
			}
			Node node = context.getNode(oldTypedElement);
			if (node == null) {
				node = context.getNode(oldTypedElement);		// FIXME debugging
			}
			if (node != null) {
				return create(node);
			}
			else {
				return oldTypedElement.accept(this);
			}
		}

		private @NonNull List<@NonNull OCLExpression> createAll(@NonNull List<@NonNull OCLExpression> oldTypedElements) {
			List<@NonNull OCLExpression> newTypedElements = new ArrayList<@NonNull OCLExpression>(oldTypedElements.size());
			for (@NonNull OCLExpression oldTypedElement : oldTypedElements) {
				OCLExpression newTypedElement = create(oldTypedElement);
				assert newTypedElement != null;
				newTypedElements.add(newTypedElement);
			}
			return newTypedElements;
		}

		private @NonNull OCLExpression createNonNull(@Nullable OCLExpression oldTypedElement) {
			assert oldTypedElement != null;
			Node node = context.getNode(oldTypedElement);
			if (node == null) {
				node = context.getNode(oldTypedElement);		// FIXME debugging
			}
			return create(node);
		}

		private @NonNull List<@NonNull Variable> createVariables(@NonNull List<@NonNull Variable> oldVariables) {
			List<@NonNull Variable> newVariables = new ArrayList<@NonNull Variable>(oldVariables.size());
			for (@NonNull Variable oldVariable : oldVariables) {
				Variable newVariable = createVariable(oldVariable);
				newVariables.add(newVariable);
			}
			return newVariables;
		}

		private @NonNull Variable createVariable(@NonNull Variable oldVariable) {
			String name = oldVariable.getName();
			assert name != null;
			Type type = oldVariable.getType();
			assert type != null;
			Variable newVariable = PivotUtil.createVariable(name, type, oldVariable.isIsRequired(), create(oldVariable.getOwnedInit()));
			Node variableNode = getNode(oldVariable);
			if (variableNode != null) {
				node2variable.put(variableNode, newVariable);
			}
			return newVariable;
		}

		@Override
		public String toString() {
			return getClass().getSimpleName() + " " + region;
		}

		@Override
		public @NonNull OCLExpression visiting(@NonNull Visitable visitable) {
			throw new UnsupportedOperationException(getClass().getSimpleName() + ": " + visitable.getClass().getSimpleName());
		}

		public @Nullable OCLExpression getExpression(@NonNull Node node) {		
			if (node.isNull()) {
				return helper.createNullLiteralExp();
			}
			Variable variable = node2variable.get(node);
			if (variable != null) {
				return PivotUtil.createVariableExp(variable);
			}
			for (@NonNull Edge edge : node.getArgumentEdges()) {
				Node expNode = edge.getSource();
//				TypedElement oldTypedElement = expNode.getTypedElements().iterator().next();
//				assert oldTypedElement != null;
				OCLExpression clonedElement = create(expNode);
//				assert clonedNode != null;
//				TypedElement typedElement = clonedNode.getTypedElements().iterator().next();
				if (clonedElement instanceof VariableExp) {
					VariableDeclaration referredVariable = ((VariableExp)clonedElement).getReferredVariable();
					if (referredVariable instanceof Variable) {
						node2variable.put(node, (Variable) referredVariable);
					}
				}
				return clonedElement;
			}
			for (@NonNull Edge edge : node.getIncomingEdges()) {
				EdgeRole edgeRole = edge.getEdgeRole();
				if (edgeRole.isNavigation()) {
					if (edgeRole.isLoaded()) {
						OCLExpression source = getExpression(edge.getSource());
						if (source != null) {
							return PivotUtil.createNavigationCallExp(source, ((NavigationEdge)edge).getProperty());
						}
					}
					else if (edgeRole.isPredicated()) {
						OCLExpression source = create(edge.getSource());
						return PivotUtil.createNavigationCallExp(source, ((NavigationEdge)edge).getProperty());
					}
				}
			}
			return null;
		}

		private boolean hasRealizedVariableReference(@NonNull OCLExpression oclExpression) {
			for (TreeIterator<EObject> tit = oclExpression.eAllContents(); tit.hasNext(); ) {
				EObject eObject = tit.next();
				if (eObject instanceof VariableExp) {
					if (((VariableExp)eObject).getReferredVariable() instanceof RealizedVariable) {
						return true;
					}
				}
			}
			return false;
		}

//		public boolean isConditional(@NonNull Node node) {
//			return conditionalNodes.contains(node);
//		}

		@Override
		public @NonNull OCLExpression visitCollectionLiteralExp(@NonNull CollectionLiteralExp pCollectionLiteralExp) {
			List<@NonNull CollectionLiteralPart> clonedParts = new ArrayList<@NonNull CollectionLiteralPart>();
			for (@NonNull CollectionLiteralPart pPart : ClassUtil.nullFree(pCollectionLiteralExp.getOwnedParts())) {
				if (pPart instanceof CollectionItem) {
					OCLExpression item = createNonNull(((CollectionItem)pPart).getOwnedItem());
					clonedParts.add(helper.createCollectionItem(item));
				}
				else {
					CollectionRange pCollectionRange = (CollectionRange)pPart;
					OCLExpression first = createNonNull(pCollectionRange.getOwnedFirst());
					OCLExpression last = createNonNull(pCollectionRange.getOwnedLast());
					clonedParts.add(helper.createCollectionRange(first, last));
				}
			}
			CollectionType collectionType = (CollectionType)pCollectionLiteralExp.getType();
			assert collectionType != null;
			return helper.createCollectionLiteralExp(collectionType, clonedParts);
		}

		@Override
		public @NonNull OCLExpression visitIfExp(@NonNull IfExp pIfExp) {
			PivotMetamodelManager metamodelManager = (PivotMetamodelManager)visitor.getMetamodelManager();
			return metamodelManager.createIfExp(createNonNull(pIfExp.getOwnedCondition()),
				inlineExpressionCreator.createNonNull(pIfExp.getOwnedThen()),
				inlineExpressionCreator.createNonNull(pIfExp.getOwnedElse()));
		}

		@Override
		public @NonNull OCLExpression visitIterateExp(@NonNull IterateExp pIterateExp) {
			OCLExpression iSource = create(pIterateExp.getOwnedSource());
			assert iSource != null;
			List<@NonNull ? extends Variable> iIterators = createVariables(ClassUtil.nullFree(pIterateExp.getOwnedIterators()));
			Variable result = createVariable(ClassUtil.nonNull(pIterateExp.getOwnedResult()));
			Iteration referredIteration = (Iteration) visitor.create(pIterateExp.getReferredIteration());
			assert referredIteration != null;
			OCLExpression iBody = inlineExpressionCreator.create(pIterateExp.getOwnedBody());
			assert iBody != null;
			return helper.createIterateExp(iSource, referredIteration, iIterators, result, iBody);
		}

		@Override
		public @NonNull OCLExpression visitIteratorExp(@NonNull IteratorExp pIteratorExp) {
			OCLExpression iSource = create(pIteratorExp.getOwnedSource());
			assert iSource != null;
			List<@NonNull ? extends Variable> iIterators = createVariables(ClassUtil.nullFree(pIteratorExp.getOwnedIterators()));
			Iteration referredIteration = (Iteration) visitor.create(pIteratorExp.getReferredIteration());
			assert referredIteration != null;
			OCLExpression iBody = inlineExpressionCreator.create(pIteratorExp.getOwnedBody());
			assert iBody != null;
			return helper.createIteratorExp(iSource, referredIteration, iIterators, iBody);
		}

		@Override
		public @NonNull OCLExpression visitMapLiteralExp(@NonNull MapLiteralExp pMapLiteralExp) {
			List<@NonNull MapLiteralPart> clonedParts = new ArrayList<@NonNull MapLiteralPart>();
			for (@NonNull MapLiteralPart pPart : ClassUtil.nullFree(pMapLiteralExp.getOwnedParts())) {
				OCLExpression key = createNonNull(pPart.getOwnedKey());
				OCLExpression value = createNonNull(pPart.getOwnedValue());
				clonedParts.add(helper.createMapLiteralPart(key, value));
			}
			MapType mapType = (MapType)pMapLiteralExp.getType();
			assert mapType != null;
			return helper.createMapLiteralExp(mapType, clonedParts);
		}

		@Override
		public @NonNull OCLExpression visitOperationCallExp(@NonNull OperationCallExp pOperationCallExp) {
			OCLExpression iSource = create(pOperationCallExp.getOwnedSource());
			List<@NonNull OCLExpression> iArguments = createAll(ClassUtil.nullFree(pOperationCallExp.getOwnedArguments()));
			Operation referredOperation = visitor.create(pOperationCallExp.getReferredOperation());
			assert referredOperation != null;
			if ((iSource == null) && (referredOperation instanceof Function)) {
				SchedulerConstants scheduler = getRegion().getSuperRegion().getSchedulerConstants();
				StandardLibrary standardLibrary = scheduler.getStandardLibrary();
				Variable thisVariable = QVTbaseUtil.getContextVariable(standardLibrary, visitor.getTransformation());
				iSource = PivotUtil.createVariableExp(thisVariable);
			}
			return helper.createOperationCallExp(iSource, referredOperation, iArguments);
		}

		@Override
		public @NonNull OCLExpression visitOppositePropertyCallExp(@NonNull OppositePropertyCallExp pOppositePropertyCallExp) {
			OCLExpression iSource = createNonNull(pOppositePropertyCallExp.getOwnedSource());
			Property referredProperty = pOppositePropertyCallExp.getReferredProperty();
			assert referredProperty != null;
			return PivotUtil.createNavigationCallExp(iSource, referredProperty);
		}

		@Override
		public @NonNull OCLExpression visitPrimitiveLiteralExp(@NonNull PrimitiveLiteralExp pPrimitiveLiteralExp) {
			return EcoreUtil.copy(pPrimitiveLiteralExp);
		}

		@Override
		public @NonNull OCLExpression visitPropertyCallExp(@NonNull PropertyCallExp pPropertyCallExp) {
			OCLExpression iSource = createNonNull(pPropertyCallExp.getOwnedSource());
			Property referredProperty = pPropertyCallExp.getReferredProperty();
			assert referredProperty != null;
			assert referredProperty.eContainer() != null;
			return helper.createNavigationCallExp(iSource, referredProperty);
		}

		@Override
		public @NonNull OCLExpression visitShadowExp(@NonNull ShadowExp pShadowExp) {
			List<@NonNull ShadowPart> clonedParts = new ArrayList<@NonNull ShadowPart>();
			for (@NonNull ShadowPart pPart : ClassUtil.nullFree(pShadowExp.getOwnedParts())) {
				OCLExpression init = createNonNull(pPart.getOwnedInit());
				String name = pPart.getName();
				Type type = pPart.getType();
				assert (name != null) && (type != null);
				Property referredProperty = pPart.getReferredProperty();
				assert referredProperty != null;
				clonedParts.add(helper.createShadowPart(referredProperty, init));
			}
			org.eclipse.ocl.pivot.Class shadowType = pShadowExp.getType();
			assert shadowType != null;
			return helper.createShadowExp(shadowType, clonedParts);
		}

		@Override
		public @NonNull OCLExpression visitTupleLiteralExp(@NonNull TupleLiteralExp pTupleLiteralExp) {
			List<@NonNull TupleLiteralPart> clonedParts = new ArrayList<@NonNull TupleLiteralPart>();
			for (@NonNull TupleLiteralPart pPart : ClassUtil.nullFree(pTupleLiteralExp.getOwnedParts())) {
				OCLExpression init = createNonNull(pPart.getOwnedInit());
				String name = pPart.getName();
				Type type = pPart.getType();
				assert (name != null) && (type != null);
				clonedParts.add(helper.createTupleLiteralPart(name, type, pPart.isIsRequired(), init));
			}
			TupleType tupleType = (TupleType)pTupleLiteralExp.getType();
			assert tupleType != null;
			return helper.createTupleLiteralExp(tupleType, clonedParts);
		}

		@Override
		public @NonNull OCLExpression visitTypeExp(@NonNull TypeExp pTypeExp) {
			Type referredType = pTypeExp.getReferredType();
			assert referredType != null;
			return helper.createTypeExp(referredType);
		}

		@Override
		public @NonNull OCLExpression visitVariableExp(@NonNull VariableExp pVariableExp) {
			VariableDeclaration pVariable = pVariableExp.getReferredVariable();
			Node node = getNode(pVariable);
			if (node == null) {
				SchedulerConstants scheduler = getRegion().getSuperRegion().getSchedulerConstants();
				StandardLibrary standardLibrary = scheduler.getStandardLibrary();
				Transformation pTransformation = QVTbaseUtil.getContainingTransformation(pVariableExp);
				if (pTransformation != null) {
					Variable pThisVariable = QVTbaseUtil.getContextVariable(standardLibrary, pTransformation);
					if (pVariableExp.getReferredVariable() == pThisVariable) {
						Variable iThisVariable = QVTbaseUtil.getContextVariable(standardLibrary, visitor.getTransformation());
						return PivotUtil.createVariableExp(iThisVariable);
					}
				}
			}
			if (node != null) {
				Variable iVariable = getVariable(node);
				assert iVariable != null;
				return PivotUtil.createVariableExp(iVariable);
			}
			else {
				System.err.println("Creating unexpected variable for " + pVariable + " in " + region);
				BottomPattern bottomPattern = mapping.getBottomPattern();
				assert bottomPattern != null;
				Type variableType = pVariable.getType();
				assert variableType != null;
				String safeName = getSafeName(ClassUtil.nonNullState(pVariable.getName()));
				Variable iVariable = PivotUtil.createVariable(safeName, variableType, pVariable.isIsRequired(), null);
				bottomPattern.getVariable().add(iVariable);
//				Variable oldVariable = node2variable.put(node, iVariable);
//				assert oldVariable == null;
				return PivotUtil.createVariableExp(iVariable);
			}
		}
	}
	
	private class InlineExpressionCreator extends ExpressionCreator
	{
		@Override
		public @NonNull OCLExpression create(/*@NonNull*/ Node node) {
			if (node.isNull()) {
				return helper.createNullLiteralExp();
			}
			Variable theVariable = node2variable.get(node);
			if (theVariable == null) {
				TypedElement oldTypedElement = node.getTypedElements().iterator().next();
				assert oldTypedElement != null;
				if ((oldTypedElement instanceof Variable) && (((Variable)oldTypedElement).getOwnedInit() == null)) {
//					for (@NonNull Edge edge : node.getIncomingEdges()) {
//						if (edge.isArgument() || edge.isCast()) {
							theVariable = createBottomVariable(node, null);
//							break;
//						}
//					}
				}
				else {
					return oldTypedElement.accept(this);
				}
				assert theVariable != null;
			}
			return PivotUtil.createVariableExp(theVariable);
		}
	}
	
	/**
	 * The selected head from each head group that is actually passed. Other heads are computed.
	 */
	private final @NonNull List<@NonNull Node> headNodes = new ArrayList<@NonNull Node>();

	/**
	 * The subset of possible guard nodes that all callers can pass..
	 */
	private final @NonNull List<@NonNull Node> guardNodes = new ArrayList<@NonNull Node>();

	/**
	 * Mapping from the scheduled Nodes to their QVTi variables.
	 */
	private final @NonNull Map<@NonNull Node, @NonNull Variable> node2variable = new HashMap<@NonNull Node, @NonNull Variable>();

	/**
	 * Mapping from the TypedModel to its ImperativeDomain.
	 */
	private final @NonNull Map<@NonNull TypedModel, @NonNull ImperativeDomain> typedModel2domain = new HashMap<@NonNull TypedModel, @NonNull ImperativeDomain>();
	
	/**
	 * Mapping from QVTi expression to Schedule Node.
	 */
//	private final @NonNull Map<TypedElement, Node> qvti2node = new HashMap<TypedElement, Node>();

	private final @NonNull ExpressionCreator expressionCreator;
	private final @NonNull ExpressionCreator inlineExpressionCreator = new InlineExpressionCreator();

	public BasicRegion2Mapping(@NonNull QVTs2QVTiVisitor visitor, @NonNull Region region) {
		super(visitor, region);
		this.expressionCreator = new ExpressionCreator();
		@SuppressWarnings("unused")String name = region.getName();
		createEmptyDomainsAndPatterns();
		createHeadAndGuardNodeVariables();
		createNavigablePredicates();
		createExternalPredicates();
		createRealizedVariables();
		createPropertyAssignments();
		createConnectionAssignments();
		createPollingDependencies();
	}

	/**
	 * Add asPredicate to the bottom pattern if any bottom variable is referenced, otherwise add to the guard pattern.
	 */
	protected void addPredicate(@NonNull Predicate asPredicate) {
		boolean isBottom = false;
		for (TreeIterator<EObject> tit = asPredicate.eAllContents(); tit.hasNext(); ) {
			EObject eObject = tit.next();
			if (eObject instanceof VariableExp) {
				VariableDeclaration variable = ((VariableExp)eObject).getReferredVariable();
				if ((variable != null) && (variable.eContainer() instanceof BottomPattern)) {
					isBottom = true;
					break;
				}
			}
		}
		if (isBottom) {
			mapping.getBottomPattern().getPredicate().add(asPredicate);
		}
		else {
			mapping.getGuardPattern().getPredicate().add(asPredicate);
		}
	}

/*	@Override
	public void checkAndEnforceRealizations(@NonNull Map<TypedModel, Map<Property, List<NavigationEdge>>> typedModel2property2realizedEdges) {
		boolean doDebug = QVTs2QVTiVisitor.POLLED_PROPERTIES.isActive();
		for (NavigationEdge predicatedEdge : region.getPredicatedNavigationEdges()) {
			Node laterNode = predicatedEdge.getTarget();
			ClassDatumAnalysis classDatumAnalysis = laterNode.getClassDatumAnalysis();
			TypedModel typedModel = classDatumAnalysis.getTypedModel();
			Property property = predicatedEdge.getProperty();
			Map<Property, List<NavigationEdge>> property2realizedEdges = typedModel2property2realizedEdges.get(typedModel);
			assert property2realizedEdges != null;
			List<NavigationEdge> realizedEdges = property2realizedEdges.get(property);
			assert realizedEdges != null;
			for (NavigationEdge realizedEdge : realizedEdges) {
				Node earlierNode = realizedEdge.getTarget();
				Region earlierRegion = earlierNode.getRegion();
				boolean isAfter = isAfter(earlierRegion, region);
				if (!isAfter) {
					Area laterArea = QVTimperativeUtil.getArea(mapping, typedModel);
					if (laterArea instanceof ImperativeArea) {
						if (((ImperativeArea)laterArea).getCheckedProperties().add(property)) {
							if (doDebug) {
								QVTs2QVTiVisitor.POLLED_PROPERTIES.println("    checks " + property +
									" at " + region.getEarliestIndex() + ".." + region.getLatestIndex() + " in " + typedModel + " for " + region);
							}
						}
					}
					AbstractRegion2Mapping earlierRegion2Mapping = visitor.getRegion2Mapping(earlierRegion);
					Mapping earlierMapping = earlierRegion2Mapping.getMapping();
					Area earlierArea = QVTimperativeUtil.getArea(earlierMapping, typedModel);
					if (earlierArea instanceof ImperativeArea) {
						if (((ImperativeArea)earlierArea).getEnforcedProperties().add(property)) {
							if (doDebug) {
								QVTs2QVTiVisitor.POLLED_PROPERTIES.println("    enforces " + property +
									" at " + earlierRegion.getEarliestIndex() + ".." + earlierRegion.getLatestIndex() + " in " + typedModel + " for " + earlierRegion);
							}
						}
					}
				}
				else if (doDebug) {
					QVTs2QVTiVisitor.POLLED_PROPERTIES.println("  " + region + "::" + laterNode.getName() + "(" + region.getEarliestIndex() + ".." + region.getLatestIndex() + ")" + 
						" isAfter (" + earlierRegion.getEarliestIndex() + ".." + earlierRegion.getLatestIndex() + ")" + earlierRegion + "::" + earlierNode.getName());
				}
			}
		}
	}  */

/*	@Override
	public void computeCheckedProperties() {
		boolean doDebug = QVTs2QVTiVisitor.POLLED_PROPERTIES.isActive();
		if (doDebug) {
			QVTs2QVTiVisitor.POLLED_PROPERTIES.println("Computing polled properties for " + this);
		}
		for (NavigationEdge laterEdge : region.getNavigationEdges()) {
			Node laterNode = laterEdge.getTarget();
//			Region laterRegion = laterNode.getRegion();
			for (@SuppressWarnings("null")@NonNull Node earlierNode : laterNode.getUsedBindingSources()) {
				Region earlierRegion = earlierNode.getRegion();
				boolean isAfter = isAfter(earlierRegion, region);
				if (!isAfter) {
					ClassDatumAnalysis classDatumAnalysis = laterNode.getClassDatumAnalysis();
					TypedModel typedModel = classDatumAnalysis.getTypedModel();
					Property property = laterEdge.getProperty();
					Area laterArea = QVTimperativeUtil.getArea(mapping, typedModel);
					if (laterArea instanceof ImperativeArea) {
						if (((ImperativeArea)laterArea).getCheckedProperties().add(property)) {
							if (doDebug) {
								QVTs2QVTiVisitor.POLLED_PROPERTIES.println("    checks " + property +
									" at " + region.getEarliestIndex() + ".." + region.getLatestIndex() + " in " + typedModel + " for " + region);
							}
						}
					}
					AbstractRegion2Mapping earlierRegion2Mapping = visitor.getRegion2Mapping(earlierRegion);
					Mapping earlierMapping = earlierRegion2Mapping.getMapping();
					Area earlierArea = QVTimperativeUtil.getArea(earlierMapping, typedModel);
					if (earlierArea instanceof ImperativeArea) {
						if (((ImperativeArea)earlierArea).getEnforcedProperties().add(property)) {
							if (doDebug) {
								QVTs2QVTiVisitor.POLLED_PROPERTIES.println("    enforces " + property +
									" at " + earlierRegion.getEarliestIndex() + ".." + earlierRegion.getLatestIndex() + " in " + typedModel + " for " + earlierRegion);
							}
						}
					}
				}
				else if (doDebug) {
					QVTs2QVTiVisitor.POLLED_PROPERTIES.println("  " + region + "::" + laterNode.getName() + "(" + region.getEarliestIndex() + ".." + region.getLatestIndex() + ")" + 
						" isAfter (" + earlierRegion.getEarliestIndex() + ".." + earlierRegion.getLatestIndex() + ")" + earlierRegion + "::" + earlierNode.getName());
				}
			}
		}
	} */
	
	private @NonNull Variable createBottomVariable(@NonNull Node node, @Nullable OCLExpression initExpression) {
		Area area = getArea(node.getClassDatumAnalysis());
		Type variableType = node.getCompleteClass().getPrimaryClass();
		assert variableType != null;
		boolean isRequired = true;
		for (@NonNull TypedElement typedElement : node.getTypedElements()) {
			if (!typedElement.isIsRequired()) {
				isRequired = false;
			}
		}
		if ((initExpression != null) && initExpression.isIsRequired()) {
			isRequired = true;
		}
		Variable variable = PivotUtil.createVariable(getSafeName(node), variableType, isRequired, null);
		
		
		BottomPattern bottomPattern = area.getBottomPattern();
		bottomPattern.getVariable().add(variable);
		if (initExpression != null) {
			VariableAssignment variableAssignment = helper.createVariableAssignment(variable, initExpression);
			mapping.getBottomPattern().getAssignment().add(variableAssignment);
		}
		Variable oldVariable = node2variable.put(node, variable);
		assert oldVariable == null;
		return variable;
	}

	private void createClassPropertyAssignments(@NonNull Iterable<@NonNull List<@NonNull NavigationEdge>> classAssignments) {
		for (@NonNull List<@NonNull NavigationEdge> edges : classAssignments) {
			for (@NonNull NavigationEdge edge : edges) {
				Node sourceNode = edge.getSource();
				Node targetNode = edge.getTarget();
				OCLExpression slotVariableExp = createVariableExp(sourceNode);
				Property property = edge.getProperty();
				OCLExpression targetVariableExp = createVariableExp(targetNode);
				PropertyAssignment propertyAssignment = QVTimperativeUtil.createPropertyAssignment(slotVariableExp, property, targetVariableExp);
				mapping.getBottomPattern().getAssignment().add(propertyAssignment);
			}
		}
	}

	/**
	 *	Create accumulation assignments for connections.
	 */
	private void createConnectionAssignments() {
		if (connection2variable != null) {
			for (@NonNull NodeConnection connection : connection2variable.keySet()) {
				Node sourceNode = connection.getSource(region);
				OCLExpression variableExpression = createVariableExp(sourceNode);
				ConnectionVariable connectionVariable = (ConnectionVariable)connection2variable.get(connection);
				assert connectionVariable != null;
				createConnectionAssignment(connectionVariable, variableExpression);
			}
		}
	}

	/**
	 * Create the domains and guard/bottom patterns.
	 */
	private void createEmptyDomainsAndPatterns() {
		Set<@NonNull TypedModel> checkableTypedModels = new HashSet<@NonNull TypedModel>();
		Set<@NonNull TypedModel> enforceableTypedModels = new HashSet<@NonNull TypedModel>();
		for (@NonNull Node node : region.getNodes()) {
			ClassDatumAnalysis classDatumAnalysis = node.getClassDatumAnalysis();
			Type type = classDatumAnalysis.getClassDatum().getType();
			if (!(type instanceof DataType) && !(type instanceof AnyType) && !(type instanceof VoidType) && !(type instanceof InvalidType)) {
				DomainUsage domainUsage = classDatumAnalysis.getDomainUsage();
				if (domainUsage.isInput()) {		// EObject is $primitive$
					for (@NonNull TypedModel typedModel : domainUsage.getTypedModels()) {
						TypedModel qvtiTypedModel = visitor.getQVTiTypedModel(typedModel);
						assert qvtiTypedModel != null;
						checkableTypedModels.add(qvtiTypedModel);
					}
				}
				if (domainUsage.isOutput()) {		// EObject is $primitive$
					for (@NonNull TypedModel typedModel : domainUsage.getTypedModels()) {
						TypedModel qvtiTypedModel = visitor.getQVTiTypedModel(typedModel);
						assert qvtiTypedModel != null;
						enforceableTypedModels.add(qvtiTypedModel);
					}
				}
			}
		}
		checkableTypedModels.removeAll(enforceableTypedModels);
		for (@NonNull TypedModel qvtiTypedModel : checkableTypedModels) {
			ImperativeDomain domain = QVTimperativeUtil.createImperativeDomain(qvtiTypedModel);
			domain.setIsCheckable(true);
			mapping.getDomain().add(domain);
			ImperativeDomain oldDomain = typedModel2domain.put(qvtiTypedModel, domain);
			assert oldDomain == null;
		}
		for (@NonNull TypedModel qvtiTypedModel : enforceableTypedModels) {
			ImperativeDomain domain = QVTimperativeUtil.createImperativeDomain(qvtiTypedModel);
			domain.setIsEnforceable(true);
			mapping.getDomain().add(domain);
			ImperativeDomain oldDomain = typedModel2domain.put(qvtiTypedModel, domain);
			assert oldDomain == null;
		}
		ECollections.sort(ClassUtil.nullFree(mapping.getDomain()), DomainNameComparator.INSTANCE);
	}

	/**
	 * Create a predicate expression for each TRUE 'head'.
	 */
	private void createExternalPredicates() {
		for (@NonNull Node node : region.getNodes()) {
			if (node.isTrue()) {
				for (@NonNull Edge edge : node.getArgumentEdges()) {
					Node predicateNode = edge.getSource();
					for (@NonNull TypedElement typedElement : predicateNode.getTypedElements()) {
						OCLExpression conditionExpression = typedElement.accept(inlineExpressionCreator);
						Predicate asPredicate = QVTbaseFactory.eINSTANCE.createPredicate();
						asPredicate.setConditionExpression(conditionExpression);
						addPredicate(asPredicate);
					}
				}
			}
		}
	}

	private @NonNull Variable createGuardVariable(@NonNull Node guardNode) {
		Area area = getArea(guardNode.getClassDatumAnalysis());
		GuardPattern guardPattern = area.getGuardPattern();
		assert guardPattern != null;
		Type variableType = guardNode.getCompleteClass().getPrimaryClass();
		Variable guardVariable = PivotUtil.createVariable(getSafeName(guardNode), variableType, true, null);
		guardPattern.getVariable().add(guardVariable);
		Variable oldVariable = node2variable.put(guardNode, guardVariable);
		assert oldVariable == null;
		return guardVariable;
	}

	/**
	 * Identify the headNodes/guardNodes and create a guard variable for each guard node.
	 */
	private void createHeadAndGuardNodeVariables() {
		Set<@NonNull Region> headCallingRegions = new HashSet<@NonNull Region>();
		Iterable<@NonNull Edge> recursionEdges = region.getRecursionEdges();
		if (Iterables.size(recursionEdges) > 0) {
			headCallingRegions.add(region);
		}
		for (@NonNull Node headNode : region.getHeadNodes()) {
			Node bestHeadNode = null;
			boolean isExtraGuard = false;
			Iterable<@NonNull Node> callingSources = headNode.getPassedBindingSources();
			if (!Iterables.isEmpty(callingSources)) {
				bestHeadNode = headNode;
			}
			else if (headNode.getNodeRole().isExtraGuardVariable()) {
				isExtraGuard = true;
			}
			for (@NonNull Node callingSource : callingSources) {
				headCallingRegions.add(callingSource.getRegion());
			}
			if (bestHeadNode != null) {
				headNodes.add(bestHeadNode);
			}
			else if (!isExtraGuard) {
				System.err.println("No best head for " + region);
			}
		}
		guardNodes.addAll(headNodes);
		for (@NonNull Node guardNode : region.getGuardNodes()) {
			if (!guardNodes.contains(guardNode)) {
				NodeConnection connection = guardNode.getIncomingUsedConnection();
				if (connection != null) {				// null for LOADED
					Set<Region> guardCallingRegions = new HashSet<Region>();
					boolean canBeGuard = true;
					for (@NonNull Node callingSource : guardNode.getUsedBindingSources()) {
						if (callingSource.getNodeRole().isComposed()) {
							canBeGuard = false;
							break;
						}
						guardCallingRegions.add(callingSource.getRegion());
					}
					for (@NonNull Node recursionSource : guardNode.getRecursionSources()) {
						guardCallingRegions.add(recursionSource.getRegion());
					}
					if (canBeGuard && guardCallingRegions.containsAll(headCallingRegions) && guardCallingRegions.contains(connection.getCommonRegion())) {
						if (!guardNodes.contains(guardNode)) {
							guardNodes.add(guardNode);
						}
					}
				}
			}
		}
		Collections.sort(guardNodes, NameUtil.NAMEABLE_COMPARATOR);
		for (@NonNull Node guardNode : guardNodes) {
			createGuardVariable(guardNode);
		}
		//
		//	Create any connectionVariable guards
		//
		createConnectionGuardVariables();
	}

	private void createMappingStatements(@NonNull Map<@NonNull Region, @NonNull Map<@NonNull Node, @NonNull Node>> calls) {
		MappingStatement mappingStatement = null;
		Map<@NonNull Variable, @NonNull OCLExpression> loopVariables = null;
		for (Map.Entry<@NonNull Region, @NonNull Map<@NonNull Node, @NonNull Node>> entry : calls.entrySet()) {
			@NonNull Region calledRegion = entry.getKey();
			AbstractRegion2Mapping calledRegion2Mapping = visitor.getRegion2Mapping(calledRegion);
			List<@NonNull MappingCallBinding> mappingCallBindings = new ArrayList<@NonNull MappingCallBinding>();
			for (Map.Entry<@NonNull Node, @NonNull Node> entry2 : entry.getValue().entrySet()) {
				@NonNull Node sourceNode = entry2.getKey();
				@NonNull Node targetNode = entry2.getValue();
				OCLExpression sourceExpression = getSourceExpression(sourceNode);
				Type type = sourceExpression.getType();
				if (type instanceof CollectionType) {
					if (loopVariables == null) {
						loopVariables = new HashMap<@NonNull Variable, @NonNull OCLExpression>();
					}
					Type elementType = ((CollectionType)type).getElementType();
					assert elementType != null;
					Variable loopVariable = PivotUtil.createVariable("loop" + loopVariables.size(), elementType, true, sourceExpression);
					loopVariables.put(loopVariable, sourceExpression);
					sourceExpression = PivotUtil.createVariableExp(loopVariable);
				}
				Variable guardVariable = calledRegion2Mapping.getGuardVariable(targetNode);
				mappingCallBindings.add(QVTimperativeUtil.createMappingCallBinding(guardVariable, sourceExpression));
//					mappingCallBindings.add(QVTimperativeUtil.createMappingLoop(source, iterator, mappingStatement);
			}
/*			Mapping calledMapping = calledRegion2Mapping.getMapping();
			for (Node node : calledRegion2Mapping.getRegion().getPredicatedNodes()) {
				for (Edge edge : node.getIncomingUsedBindingEdges()) {
					Node sourceNode = edge.getSource();
					if (sourceNode.getRegion() == region) {
						OCLExpression sourceExpression = createVariableExp(sourceNode);
						Variable guardVariable = calledRegion2Mapping.getGuardVariable(edge.getTarget());
						MappingCallBinding mappingCallBinding = QVTimperativeUtil.createMappingCallBinding(guardVariable, sourceExpression);
						if (calledMapping.getPolledClasses().size() > 0) {
							mappingCallBinding.setIsPolled(true);		// FIXME temporary backward compatibility
						}
						mappingCallBindings.add(mappingCallBinding);
					}
					else {
						// FIXME find source
					}
				}
			} */
			Collections.sort(mappingCallBindings, QVTimperativeUtil.MappingCallBindingComparator.INSTANCE);
			MappingStatement mappingCallStatement = calledRegion2Mapping.createMappingCall(mappingCallBindings);
			if (loopVariables != null) {
				for (Map.Entry<@NonNull Variable, @NonNull OCLExpression> loopEntry : loopVariables.entrySet()) {
					@NonNull Variable loopVariable = loopEntry.getKey();
					@NonNull OCLExpression loopSource = loopEntry.getValue();
					mappingCallStatement = QVTimperativeUtil.createMappingLoop(loopSource, loopVariable, mappingCallStatement);
				}				
			}
			mappingStatement = QVTimperativeUtil.addMappingStatement(mappingStatement, mappingCallStatement);
		}
		mapping.setMappingStatement(mappingStatement);
	}

	/**
	 * Recurse over the guard nodes and loaded/predicates region and convert the edges to predicates and non-guard nodes to unrealized variables.
	 */
	private void createNavigablePredicates() {
		@SuppressWarnings("unused")String name = region.getName();
		//
		//	Categorize the relevant navigation edges
		//
		Set<@NonNull NavigationEdge> backwardEdges = new HashSet<@NonNull NavigationEdge>();
		Set<@NonNull NavigationEdge> forwardEdges = new HashSet<@NonNull NavigationEdge>();
//		Set<@NonNull NavigationEdge> attributeEdges = new HashSet<@NonNull NavigationEdge>();
		/*
		 * The nodes that form the traversal forest.
		 */
		Set<@NonNull Node> navigableNodes = new HashSet<@NonNull Node>();
		/*
		 * The edges that are not traversed while locating each node.
		 */
		Set<@NonNull NavigationEdge> untraversedEdges = new HashSet<@NonNull NavigationEdge>();
		for (@NonNull NavigationEdge edge : region.getNavigationEdges()) {
			if (edge.isRealized()) {}
			else if (!edge.isNavigable()) {}
			else if (edge.isCast()) {}
			else {
				assert !edge.isArgument();
				assert !edge.isComputation();
				Node sourceNode = edge.getSource();
				navigableNodes.add(sourceNode);
				Node targetNode = edge.getTarget();
				if (targetNode.isNull()) {
					untraversedEdges.add(edge);
				}
				else {
					targetNode = RegionUtil.getCastTarget(targetNode);
					Property property = edge.getProperty();
					if (property.isIsImplicit()) {
						backwardEdges.add(edge);
						navigableNodes.add(targetNode);
					}
	//				else if (targetNode.isAttributeNode()) {
	//					attributeEdges.add(edge);
	//				}
					else {
						forwardEdges.add(edge);
						navigableNodes.add(targetNode);
					}
				}
			}
		}
		//
		//	Identify the edges that need traversal to reach as all nodes preferring forwardEdges.
		//
		/*
		 * The edges that are traversed while locating each node and their depth in the traversal forest.
		 */
		Map<@NonNull NavigationEdge, @NonNull Integer> traversedEdge2depth = new HashMap<@NonNull NavigationEdge, @NonNull Integer>();
		/*
		 * The incoming edge for each node in the traversal forest, null at a root.
		 */
		Map<@NonNull Node, @Nullable NavigationEdge> traversedNode2incomingEdge = new HashMap<@NonNull Node, @Nullable NavigationEdge>();
		for (@NonNull Node guardNode : guardNodes) {
			traversedNode2incomingEdge.put(guardNode, null);
		}
		Set<@NonNull Node> moreNodes = new HashSet<@NonNull Node>(guardNodes);
		int depth = 0;
		while (moreNodes.size() > 0) {
			//
			//	Select the forward edges that make progress.
			//
			Set<@NonNull Node> moreMoreNodes = new HashSet<@NonNull Node>();
			for (@NonNull Node sourceNode : moreNodes) {
				for (@NonNull NavigationEdge edge : sourceNode.getNavigationEdges()) {
					if (forwardEdges.contains(edge)) {
						Node targetNode = RegionUtil.getCastTarget(edge.getTarget());
						if (!traversedNode2incomingEdge.containsKey(targetNode)) {
							traversedNode2incomingEdge.put(targetNode, edge);
							moreMoreNodes.add(targetNode);
							traversedEdge2depth.put(edge, depth);
						}
						else {
							untraversedEdges.add(edge);
						}
					}
				}
			}
			if (moreMoreNodes.isEmpty() && (traversedNode2incomingEdge.size() < navigableNodes.size())) {
				//
				//	Unblock an incomplete traversal by choosing a backward edge.
				//
				for (@NonNull NavigationEdge edge : backwardEdges) {		// FIXME maintain reducing list of possibles
					Node sourceNode = edge.getSource();
					if (traversedNode2incomingEdge.containsKey(sourceNode)) {
						Node targetNode = edge.getTarget();
						if (!traversedNode2incomingEdge.containsKey(targetNode)) {
							traversedNode2incomingEdge.put(targetNode, edge);
							moreMoreNodes.add(targetNode);
							traversedEdge2depth.put(edge, depth);
							break;
						}
					}
				}
			}
			moreNodes = moreMoreNodes;
			depth++;
		}
		//
		//	Traverse the attributes too.
		//
/*		for (@NonNull NavigationEdge edge : attributeEdges) {
			Node targetNode = edge.getTarget();
			if (!traversedNode2incomingEdge.containsKey(targetNode)) {
				traversedNode2incomingEdge.put(targetNode, edge);
			}
			else {
				untraversedEdges.add(edge);
			}
		} */
		//
		//	Identify the remaining untraversed edges that are not used to reach nodes and so must be reified as predicates to check nodes.
		//
		for (@NonNull NavigationEdge edge : forwardEdges) {
			if (!traversedEdge2depth.containsKey(edge)) {
				NavigationEdge oppositeEdge = getOppositeEdge(edge);
				if ((oppositeEdge == null) || !traversedEdge2depth.containsKey(oppositeEdge)) {
					untraversedEdges.add(edge);
				}
			}
		}
		for (@NonNull NavigationEdge edge : backwardEdges) {
			if (!traversedEdge2depth.containsKey(edge) && !untraversedEdges.contains(edge)) {
				NavigationEdge oppositeEdge = getOppositeEdge(edge);
				if ((oppositeEdge == null) || (!traversedEdge2depth.containsKey(oppositeEdge) && !untraversedEdges.contains(edge))) {
					untraversedEdges.add(edge);
				}
			}
		}
		//
		//	Order the traversal edges shallowest first then alphabetically.
		//
		List<@NonNull NavigationEdge> traversedEdges = new ArrayList<@NonNull NavigationEdge>(traversedEdge2depth.keySet());
		Collections.sort(traversedEdges, new Comparator<@NonNull NavigationEdge>() {
			@Override
			public int compare(@NonNull NavigationEdge o1, @NonNull NavigationEdge o2) {
				Integer d1 = traversedEdge2depth.get(o1);
				Integer d2 = traversedEdge2depth.get(o2);
				assert (d1 != null) && (d2 != null);
				if (d1 != d2) {
					return d1 - d2;
				}
				String n1 = o1.getDisplayName();
				String n2 = o2.getDisplayName();
				return n1.compareTo(n2);
			}
		});
		//
		//	Convert the traversed edges to unrealized variables and initializers.
		//
		for (@NonNull NavigationEdge traversedEdge : traversedEdges) {
			Node sourceNode = traversedEdge.getSource();
			Node targetNode = traversedEdge.getTarget();
			Property property = traversedEdge.getProperty();
			OCLExpression sourceExp = createVariableExp(sourceNode);
			OCLExpression source2targetExp = createCallExp(sourceExp, property);
			if (targetNode.isAttributeNode()) {
				Variable attributeVariable = node2variable.get(targetNode);
				assert attributeVariable == null;
				createBottomVariable(targetNode, source2targetExp);
			}
			else {
				Variable classVariable = node2variable.get(targetNode);
				assert classVariable == null;
				createBottomVariable(targetNode, source2targetExp);
/*				}
				else {
					OCLExpression ownedInit = classVariable.getOwnedInit();
					assert ownedInit == null;
					if (source2targetExp != null) {
						Type variableType = classVariable.getType();
						Type initType = source2targetExp.getType();
						assert variableType != null;
						if (!initType.conformsTo(visitor.getStandardLibrary(), variableType)) {
							source2targetExp = createOclAsTypeCallExp(source2targetExp, variableType);
						}
					}
					classVariable.setOwnedInit(source2targetExp);
				} */
			}
		}
		//
		//	Convert the untraversed edges to predicates.
		//
		for (@NonNull NavigationEdge untraversedEdge : untraversedEdges) {
			Node sourceNode = untraversedEdge.getSource();
			Node targetNode = untraversedEdge.getTarget();
			Property property = untraversedEdge.getProperty();
			OCLExpression sourceExp = createVariableExp(sourceNode);
			OCLExpression targetExp = createVariableExp(targetNode);
			OCLExpression source2targetExp = createCallExp(sourceExp, property);
			OCLExpression matchesExp = targetNode.isNull()
					? helper.createOperationCallExp(source2targetExp, "=", targetExp)
					: helper.createOperationCallExp(targetExp, "=", source2targetExp);
			Predicate asPredicate = QVTbaseFactory.eINSTANCE.createPredicate();
			asPredicate.setConditionExpression(matchesExp);
			addPredicate(asPredicate);
		}
/*		Set<@NonNull Node> reachableNodes = new HashSet<@NonNull Node>(guardNodes);
		List<@NonNull Node> sourcesList = new ArrayList<@NonNull Node>(guardNodes);
		for (int i = 0; i < sourcesList.size(); i++) {
			@NonNull Node sourceNode = sourcesList.get(i);
			for (@NonNull NavigationEdge edge : sourceNode.getNavigationEdges()) {		// if !edge.getEdgeRole().isRealized() && !targetNode.isNull()
				EdgeRole edgeRole = edge.getEdgeRole();
				if (!edgeRole.isRealized()) {
					Node targetNode = edge.getTarget();
					if (targetNode.isNull()) {
						// FIXME check in caller
					}
					else if (targetNode.isIterator()) {
						// Process in LoopExp
					}
					else {
						Property property = edge.getProperty();
						if (reachableNodes.add(targetNode)) {
							if (targetNode.isAttributeNode()) {
								if (targetNode.getCompleteClass().getPrimaryClass() instanceof CollectionType) {
									sourcesList.add(targetNode);
								}
								OCLExpression sourceExp = createVariableExp(sourceNode);
								OCLExpression source2targetExp = createCallExp(sourceExp, property);
//								qvti2node.put(source2targetExp, targetNode);
								Variable attributeVariable = node2variable.get(targetNode);
								if (attributeVariable == null) {
									createUnrealizedVariable(bottomPattern, targetNode, source2targetExp);
								}
		/*							else {
										OCLExpression targetExp = PivotUtil.createVariableExp(attributeVariable);
										OCLExpression matchesExp = createOperationCallExp(targetExp, visitor.getEqualsOperation(), source2targetExp);
										Predicate asPredicate = QVTbaseFactory.eINSTANCE.createPredicate();
										asPredicate.setConditionExpression(matchesExp);
										mapping.getBottomPattern().getPredicate().add(asPredicate);
									} * /
							}
							else if (expressionCreator.isConditional(targetNode)) {
								
							}
							else if (!guardNodes.contains(targetNode)) {
								sourcesList.add(targetNode);
								OCLExpression sourceExp = createVariableExp(sourceNode);
								OCLExpression source2targetExp = createCallExp(sourceExp, property);
								Variable classVariable = node2variable.get(targetNode);
								if (classVariable == null) {
									classVariable = createUnrealizedVariable(bottomPattern, targetNode, source2targetExp);
								}
								else {
									OCLExpression ownedInit = classVariable.getOwnedInit();
									assert ownedInit == null;
									if (source2targetExp != null) {
										Type variableType = classVariable.getType();
										Type initType = source2targetExp.getType();
										assert variableType != null;
										if (!initType.conformsTo(visitor.getStandardLibrary(), variableType)) {
											source2targetExp = createOclAsTypeCallExp(source2targetExp, variableType);
										}
									}
									classVariable.setOwnedInit(source2targetExp);
								}
								
		/*							else {
										OCLExpression targetExp = PivotUtil.createVariableExp(attributeVariable);
										OCLExpression matchesExp = createOperationCallExp(targetExp, visitor.getEqualsOperation(), source2targetExp);
										Predicate asPredicate = QVTbaseFactory.eINSTANCE.createPredicate();
										asPredicate.setConditionExpression(matchesExp);
										mapping.getBottomPattern().getPredicate().add(asPredicate);
									} * /
							}
							else {
								sourcesList.add(targetNode);
								Iterable<@NonNull Node> callingSources = targetNode.getPassedBindingSources();		// Used
								if (Iterables.size(callingSources) <= 0) {			// FIXME check predicate in source etc
									OCLExpression sourceExp = createVariableExp(sourceNode);
									OCLExpression targetExp = createVariableExp(targetNode);
									OCLExpression source2targetExp = createCallExp(sourceExp, property);
									OCLExpression matchesExp = createOperationCallExp(targetExp, visitor.getEqualsOperation(), source2targetExp);
									Predicate asPredicate = QVTbaseFactory.eINSTANCE.createPredicate();
									asPredicate.setConditionExpression(matchesExp);
									addPredicate(asPredicate);
								}
							}
						}
					}
				}
			}
		} */
	}

	private void createPollingDependencies() {
		DomainUsage anyUsage = region.getSchedulerConstants().getDomainAnalysis().getAnyUsage();
		for (@NonNull TypedModel qvtpTypedModel : anyUsage.getTypedModels()) {
			TypedModel qvtiTypedModel = visitor.getQVTiTypedModel(qvtpTypedModel);
			ImperativeDomain domain = typedModel2domain.get(qvtiTypedModel);
			ImperativeArea imperativeArea = domain != null ? (ImperativeArea)domain : mapping;
			Iterable<@NonNull NavigationEdge> checkedEdges = region.getCheckedEdges(qvtpTypedModel);
			if (checkedEdges != null) {
				List<Property> checkedProperties = imperativeArea.getCheckedProperties();
				for (NavigationEdge checkedEdge : checkedEdges) {
					checkedProperties.add(checkedEdge.getProperty());
				}
			}
			Iterable<@NonNull NavigationEdge> enforcedEdges = region.getEnforcedEdges(qvtpTypedModel);
			if (enforcedEdges != null) {
				List<@NonNull Property> enforcedProperties = ClassUtil.nullFree(imperativeArea.getEnforcedProperties());
				for (@NonNull NavigationEdge enforcedEdge : enforcedEdges) {
					enforcedProperties.add(enforcedEdge.getProperty());
				}
			}
		}
	}

	private void createPropertyAssignments() {
		Map<@NonNull Node, @NonNull List<@NonNull NavigationEdge>> classAssignments = null;
		ImperativeBottomPattern bottomPattern = (ImperativeBottomPattern) mapping.getBottomPattern();
		for (@NonNull NavigationEdge edge : region.getRealizedNavigationEdges()) {
			Node sourceNode = edge.getSource();
			Node targetNode = edge.getTarget();
			if (targetNode.isAttributeNode()) {
				OCLExpression slotVariableExp = createVariableExp(sourceNode);
				Property property = edge.getProperty();
				OCLExpression valueExp = expressionCreator.getExpression(targetNode);
				if (valueExp == null) {
					valueExp = expressionCreator.getExpression(targetNode);		// FIXME debugging
				}
				if (valueExp != null) {
					PropertyAssignment propertyAssignment = QVTimperativeUtil.createPropertyAssignment(slotVariableExp, property, valueExp);
					bottomPattern.getAssignment().add(propertyAssignment);
				}
				else {
					System.err.println("No assignment in " + this + " to " + slotVariableExp);
				}
			}
			else {
				if (classAssignments == null) {
					classAssignments = new HashMap<@NonNull Node, @NonNull List<@NonNull NavigationEdge>>();
				}
				List<@NonNull NavigationEdge> edges = classAssignments.get(sourceNode);
				if (edges == null) {
					edges = new ArrayList<@NonNull NavigationEdge>();
					classAssignments.put(sourceNode, edges);
				}
				edges.add(edge);
			}
		}
		if (classAssignments != null) {
			pruneClassAssignments(classAssignments);
			Collection<@NonNull List<@NonNull NavigationEdge>> values = classAssignments.values();
			createClassPropertyAssignments(values);
		}
		@SuppressWarnings("null")
		@NonNull EList<@NonNull Assignment> bottomAssignments = bottomPattern.getOrderedAssignment();
		ECollections.sort(bottomAssignments, new AssignmentComparator(bottomAssignments));
	}

	private void createRealizedVariables() {
		for (@NonNull Node node : region.getRealizedVariableNodes()) {
			OCLExpression constructor = null;
			for (Edge edge : node.getIncomingEdges()) {
				if (edge.isResult()) {
					Node sourceNode = edge.getSource();
					if (sourceNode.isOperation()) {
						constructor = ((OperationCallExp)sourceNode.getTypedElements().iterator().next()).accept(expressionCreator);
					}
				}
			}
			ClassDatumAnalysis classDatumAnalysis = node.getClassDatumAnalysis();
			BottomPattern bottomPattern = getArea(classDatumAnalysis).getBottomPattern();
			RealizedVariable realizedVariable = QVTimperativeUtil.createRealizedVariable(getSafeName(node), classDatumAnalysis.getCompleteClass().getPrimaryClass());
			realizedVariable.setOwnedInit(constructor);
			bottomPattern.getRealizedVariable().add(realizedVariable);
			Variable oldVariable = node2variable.put(node, realizedVariable);
			assert oldVariable == null;
		}
	}

	@Override
	public void createStatements() {
		Map<@NonNull Region, @NonNull Map<@NonNull Node, @NonNull Node>> calls = null;
//		for (@SuppressWarnings("null")@NonNull Region calledRegion : getEarliestFirstCalledRegions()) {
		for (@NonNull Region calledRegion : region.getCallableChildren()) {
			if (calls == null) {
				calls = new HashMap<@NonNull Region, @NonNull Map<@NonNull Node, @NonNull Node>>();
			}
			Map<@NonNull Node, @NonNull Node> source2target = calls.get(calledRegion);
			if (source2target == null) {
				source2target = new HashMap<@NonNull Node, @NonNull Node>();
				calls.put(calledRegion, source2target);
			}
			AbstractRegion2Mapping calledRegion2Mapping = visitor.getRegion2Mapping(calledRegion);
			for (@NonNull Node calledGuardNode : calledRegion2Mapping.getGuardNodes()) {
				for (@NonNull Node callingNode : calledGuardNode.getPassedBindingSources()) {
					if (callingNode.getRegion() == region) {
						Node oldNode = source2target.put(callingNode, calledGuardNode);
						assert oldNode == null;
					}
				}
				for (@NonNull Node callingNode : calledGuardNode.getUsedBindingSources()) {
					if (callingNode.getRegion() == region) {
						Node oldNode = source2target.put(callingNode, calledGuardNode);
						assert oldNode == null;
					}
				}
			}
		}
		if (calls != null) {
			createMappingStatements(calls);
		}
	}

	private @NonNull OCLExpression createVariableExp(@NonNull Node node) {
		if (node.isNull()) {
			return helper.createNullLiteralExp();
		}
		else {
			Variable variable = node2variable.get(node);
			if (variable == null) {
				for (@NonNull Edge edge : node.getIncomingEdges()) {
					if (edge.isArgument() || edge.isCast()) {
						OCLExpression initExpression = edge.getSource().getTypedElements().iterator().next().accept(expressionCreator);
						variable = createBottomVariable(node, initExpression);
						break;
					}
				}
			}
			if (variable == null) {
				for (@NonNull Edge edge : node.getIncomingEdges()) {
					boolean isPredicated = edge.isPredicated();
					boolean isNavigable = edge.isNavigable();
					boolean isNavigation = edge.isNavigation();
					if (isPredicated && !isNavigable && isNavigation) {
						OCLExpression initExpression = edge.getSource().getTypedElements().iterator().next().accept(expressionCreator);
						variable = createBottomVariable(node, initExpression);
						break;
					}
				}
			}
			if (variable == null) {
				System.err.println("Creating dummy variable for " + node + " in " + region);
				BottomPattern bottomPattern = mapping.getBottomPattern();
				assert bottomPattern != null;
				Type variableType = node.getCompleteClass().getPrimaryClass();
				assert variableType != null;
				variable = PivotUtil.createVariable(getSafeName(node), variableType, false, null);
				bottomPattern.getVariable().add(variable);
				Variable oldVariable = node2variable.put(node, variable);
				assert oldVariable == null;
			}
			return PivotUtil.createVariableExp(variable);
		}
	}
	
/*	private @Nullable Integer depthRecursion(@NonNull Node node, @NonNull Map<Node, Integer> node2pathDepth,
			@NonNull Map<Node, Integer> node2acyclicDepth, @NonNull Map<Node, Integer> node2cyclicDepth) {
		Integer pathDepth = node2pathDepth.get(node);
		if (pathDepth != null) {
			return pathDepth;
		}
		Integer recursiveDepth = null;
		pathDepth = node2pathDepth.size();
		node2pathDepth.put(node, pathDepth);
		for (Edge edge : node.getOutgoingEdges()) {
			if (edge.isNavigation() || edge.isComputation()) {
				Node nextNode = edge.getTarget();
				Integer nextDepth = depthRecursion(nextNode, node2pathDepth, node2acyclicDepth, node2cyclicDepth);
				if (nextDepth == null) {
					Integer acyclicDepth = node2acyclicDepth.get(node);
					if ((acyclicDepth == null) || (acyclicDepth < pathDepth)) {
						node2acyclicDepth.put(node, pathDepth);
					}
				}
				else {
					Integer cyclicDepth = node2cyclicDepth.get(node);
					if ((cyclicDepth == null) || (pathDepth < cyclicDepth)) {
						node2cyclicDepth.put(node, pathDepth);
					}
					if ((recursiveDepth == null) || (nextDepth < recursiveDepth)) {
						recursiveDepth = nextDepth;
					}
				}
			}
		}
		node2pathDepth.remove(node);
		return recursiveDepth;
	} */

	private @NonNull Area getArea(@NonNull ClassDatumAnalysis classDatumAnalysis) {	
		TypedModel qvtpTypedModel = classDatumAnalysis.getTypedModel();
		ImperativeDomain coreDomain = typedModel2domain.get(qvtpTypedModel);
		if (coreDomain != null) {
			return coreDomain;
		}
		TypedModel qvtiTypedModel = visitor.qvtpTypedModel2qvtiTypedModel.get(qvtpTypedModel);		// FIXME shouldn't happen
		coreDomain = typedModel2domain.get(qvtiTypedModel);
		if (coreDomain != null) {
			return coreDomain;
		}
//		for (Domain domain : mapping.getDomain()) {
//			if (domain.getTypedModel() == qvtiTypedModel) {
//				return (ImperativeDomain)domain;
//			}
//		}
		return mapping;
	}

	@Override
	public @NonNull List<@NonNull Node> getGuardNodes() {
		return guardNodes;
	}

	@Override
	public @NonNull Variable getGuardVariable(@NonNull Node node) {
//		Area area = getArea(mapping, node.getClassDatumAnalysis().getDomainUsage());
//		String name = getName(node);
//		Variable variable = NameUtil.getNameable(area.getGuardPattern().getVariable(),name);
		Variable variable = node2variable.get(node);
		assert variable != null;
		return variable;
	}

/*	@Override
	public @Nullable Node getNode(@Nullable TypedElement typedElement) {
		Node node = qvti2node.get(typedElement);
		if (node != null) {
			return node;
		}
		else {
			return super.getNode(typedElement);
		}
	} */

	private @Nullable NavigationEdge getOppositeEdge(@NonNull NavigationEdge edge) {
		Node targetNode = edge.getTarget();
		Property property = edge.getProperty();
		Property oppositeProperty = property.getOpposite();
		if (oppositeProperty == null) {
			return null;
		}
		NavigationEdge oppositeEdge = targetNode.getNavigationEdge(oppositeProperty);
		if (oppositeEdge == null) {
			return null;
		}
		assert oppositeEdge.getTarget() == edge.getSource();
		return oppositeEdge;
	}

	private @NonNull OCLExpression getSourceExpression(@NonNull Node sourceNode) {
		return createVariableExp(sourceNode);
	}
	
	public @Nullable Variable getVariable(@NonNull Node node) {
		return node2variable.get(node);
	}

	private boolean isIfExp(@NonNull Node node) {
		if (node.isExpression()) {
			for (TypedElement typedElement : node.getTypedElements()) {
				if (typedElement instanceof IfExp) {
					return true;
				}
			}
		}
		return false;
	}

	@Override
	public boolean isInfinite() {
		if (region.getRecursionEdges().iterator().hasNext()) {		// FIXME unduly pessimistic
			return true;
		}	
		return false;
	}

	/**
	 * Filter classAssignments to retain only one of each opposite-property assignment pair.
	 */
	private void pruneClassAssignments(@NonNull Map<@NonNull Node, @NonNull List<@NonNull NavigationEdge>> classAssignments) {
		for (@NonNull Node sourceNode : new ArrayList<@NonNull Node>(classAssignments.keySet())) {
			List<@NonNull NavigationEdge> forwardEdges = classAssignments.get(sourceNode);
			assert forwardEdges != null;
			for (int iForward = forwardEdges.size()-1; iForward >= 0; iForward--) {
				NavigationEdge forwardEdge = forwardEdges.get(iForward);
				Node targetNode = forwardEdge.getTarget();
				List<@NonNull NavigationEdge> reverseEdges = classAssignments.get(targetNode);
				if (reverseEdges != null) {
					for (int iReverse = reverseEdges.size()-1; iReverse >= 0; iReverse--) {
						NavigationEdge reverseEdge = reverseEdges.get(iReverse);
						if (sourceNode == reverseEdge.getTarget()) {
							Property forwardProperty = forwardEdge.getProperty();
							Property reverseProperty = reverseEdge.getProperty();
							if (forwardProperty.getOpposite() == reverseProperty) {
								if (forwardProperty.isIsImplicit()) {
									forwardEdges.remove(forwardEdge);
								}
								else if (reverseProperty.isIsImplicit()) {
									reverseEdges.remove(reverseEdge);
								}
								else if (sourceNode.isInternal()) {
									forwardEdges.remove(forwardEdge);
								}
								else if (targetNode.isInternal()) {
									reverseEdges.remove(reverseEdge);
								}
								else {		// FIXME do we prefer either direction ?
									reverseEdges.remove(reverseEdge);
								}
							}
						}
					}
				}
			}
		}
	}
}