/*******************************************************************************
 * Copyright (c) 2016, 2019 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
 *******************************************************************************/
package org.eclipse.qvtd.runtime.internal.evaluation;


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

import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.evaluation.Evaluator;
import org.eclipse.ocl.pivot.ids.ClassId;
import org.eclipse.ocl.pivot.ids.CollectionTypeId;
import org.eclipse.ocl.pivot.ids.IdManager;
import org.eclipse.ocl.pivot.ids.IdResolver;
import org.eclipse.ocl.pivot.ids.PackageId;
import org.eclipse.ocl.pivot.ids.PropertyId;
import org.eclipse.ocl.pivot.ids.TypeId;
import org.eclipse.ocl.pivot.internal.evaluation.EvaluationCache;
import org.eclipse.ocl.pivot.internal.values.SetValueImpl;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.ocl.pivot.utilities.NameUtil;
import org.eclipse.ocl.pivot.values.InvalidValueException;
import org.eclipse.ocl.pivot.values.SetValue;
import org.eclipse.qvtd.runtime.evaluation.AbstractObjectManager;
import org.eclipse.qvtd.runtime.evaluation.AbstractTransformer;
import org.eclipse.qvtd.runtime.evaluation.AbstractTypedModelInstance;
import org.eclipse.qvtd.runtime.evaluation.Connection;
import org.eclipse.qvtd.runtime.evaluation.DefaultInterval;
import org.eclipse.qvtd.runtime.evaluation.ExecutionVisitable;
import org.eclipse.qvtd.runtime.evaluation.ExecutionVisitor;
import org.eclipse.qvtd.runtime.evaluation.Interval;
import org.eclipse.qvtd.runtime.evaluation.InvalidEvaluationException;
import org.eclipse.qvtd.runtime.evaluation.InvocationFailedException;
import org.eclipse.qvtd.runtime.evaluation.InvocationManager;
import org.eclipse.qvtd.runtime.evaluation.ModeFactory;
import org.eclipse.qvtd.runtime.evaluation.ObjectManager;
import org.eclipse.qvtd.runtime.evaluation.TransformationExecutor;
import org.eclipse.qvtd.runtime.evaluation.Transformer;

/**
 * The abstract implementation of an auto-generated transformation provides the shared infrastructure for maintaining
 * models and deferring invocation of not-ready mapping invocations.
 */
public abstract class AbstractTransformerInternal /*extends AbstractModelManager*/ implements Transformer, ExecutionVisitable
{
	public static abstract class Incremental extends AbstractTransformerInternal
	{
		protected Incremental(@NonNull TransformationExecutor executor, @NonNull String @NonNull [] modelNames,
				@NonNull PropertyId @Nullable [] propertyIndex2propertyId, @NonNull ClassId @NonNull [] classIndex2classId, int @Nullable [] @NonNull [] classIndex2allClassIndexes) {
			super(executor, modelNames, propertyIndex2propertyId, classIndex2classId, classIndex2allClassIndexes) ;
		}

		@Override
		@Deprecated /* @deprecated pass interval */
		protected @NonNull Connection createConnection(@NonNull String name, @NonNull TypeId typeId, boolean isStrict) {
			return createConnection(invocationManager.getRootInterval(), name, typeId, isStrict, ModeFactory.NON_INCREMENTAL);
		}

		@Override
		protected @NonNull Connection createConnection(@NonNull Interval interval, @NonNull String name, @NonNull TypeId typeId, boolean isStrict, @NonNull ModeFactory modeFactory) {
			return interval.createConnection(name, typeId, isStrict, modeFactory);
		}

		@Override
		protected @NonNull InvocationManager createInvocationManager() {
			return new IncrementalInvocationManager(executor);
		}

		@Override
		@Deprecated /* @deprecated pass explit root interval */
		protected @NonNull Model createModel(@NonNull String modelName, @NonNull PropertyId @Nullable [] propertyIndex2propertyId,
				@NonNull ClassId @NonNull [] classIndex2classId, int @Nullable [] @NonNull [] classIndex2allClassIndexes) {
			return new Model.Incremental(this, modelName, propertyIndex2propertyId, classIndex2classId, classIndex2allClassIndexes, getInvocationManager().getRootInterval());
		}

		@Override
		protected @NonNull Model createModel(@NonNull String modelName, @NonNull PropertyId @Nullable [] propertyIndex2propertyId,
				@NonNull ClassId @NonNull [] classIndex2classId, int @Nullable [] @NonNull [] classIndex2allClassIndexes, @NonNull Interval rootInterval) {
			return new Model.Incremental(this, modelName, propertyIndex2propertyId, classIndex2classId, classIndex2allClassIndexes, rootInterval);
		}

		@Override
		protected @NonNull ObjectManager createObjectManager() {
			return new IncrementalObjectManager((IncrementalInvocationManager)invocationManager);
		}

		@Override
		@NonNull
		public ModeFactory getModeFactory() {
			return ModeFactory.INCREMENTAL;
		}
	}

	private static final @NonNull List<@NonNull Integer> EMPTY_INDEX_LIST = Collections.emptyList();
	private static final @NonNull List<@NonNull Object> EMPTY_EOBJECT_LIST = Collections.emptyList();

	public static class Model extends AbstractTypedModelInstance
	{
		public static class Incremental extends Model
		{
			public Incremental(@NonNull AbstractTransformerInternal transformer, @NonNull String name, @NonNull PropertyId @Nullable [] propertyIndex2propertyId,
					@NonNull ClassId @NonNull [] classIndex2classId, int @Nullable [] @NonNull [] classIndex2allClassIndexes, @NonNull Interval rootInterval) {
				super(transformer, name, propertyIndex2propertyId, classIndex2classId, classIndex2allClassIndexes, rootInterval);
			}

			public void remove(@NonNull EObject eObject) {
				rootObjects.remove(eObject);
				potentialOrphanObjects.remove(eObject);
				unaccumulateEObject(eClass2allClassIndexes, null, null, eObject);
			}

			/**
			 * Remove eObject from the caches.
			 * <p>
			 * If eClass2allClassIndexes is non-null, eObject is removed from the allInstances() caches potentially updating eClass2allClassIndexes with
			 * the state of a new EClass.
			 * <p>
			 * If eClass2allPropertyIndexes is non-null, eObject is removed fromun the unnavigable opposites caches potentially updating eClass2allPropertyIndexes with
			 * the state of a new EClass.
			 */
			private void unaccumulateEObject(@Nullable Map<@NonNull EClass, @NonNull Set<@NonNull Integer>> eClass2allClassIndexes,
					@Nullable Map<@NonNull EClass, @NonNull List<@NonNull Integer>> eClass2allPropertyIndexes, @Nullable Map<@NonNull EReference, @NonNull Integer> eReference2propertyIndex,
					@NonNull Object eObject) {
				EClass eClass = transformer.eClass(eObject);
				if (eClass2allClassIndexes != null) {
					Set<@NonNull Integer> allClassIndexes = eClass2allClassIndexes.get(eClass);
					if (allClassIndexes != null) {
						for (@NonNull Integer classIndex : allClassIndexes) {
							Connection.Incremental connection = (Connection.Incremental)classIndex2connection[classIndex];
							connection.removeElement(eObject);
						}
					}
				}
				if (eClass2allPropertyIndexes != null) {
					Map<@NonNull EReference, @NonNull Integer> eReference2propertyIndex2 = eReference2propertyIndex;
					assert eReference2propertyIndex2 != null;
					List<@NonNull Integer> allPropertyIndexes = eClass2allPropertyIndexes.get(eClass);
					if (allPropertyIndexes != null) {
						Map<@NonNull Object, @NonNull Object>[] object2oppositeObject2 = transformer.object2oppositeObject;
						assert object2oppositeObject2 != null;
						for (@NonNull Integer propertyIndex : allPropertyIndexes) {
							EReference @Nullable [] propertyIndex2eReference2 = transformer.propertyIndex2eReference;
							assert propertyIndex2eReference2 != null;
							EReference eReference = propertyIndex2eReference2[propertyIndex];
							if (eReference != null) {
								Object object = transformer.eGet(eObject, eReference);
								assert object != null;
								object2oppositeObject2[propertyIndex].remove(object);
							}
						}
					}
				}
			}
		}

		protected final @NonNull AbstractTransformerInternal transformer;
		protected final @NonNull String name;

		/**
		 * The (input) root objects added explicitly by addRootObjects.
		 */
		protected final @NonNull List<@NonNull Object> rootObjects = new ArrayList<>();

		/**
		 * The objects added by add filtered as defined by trackObjects.
		 */
		protected final @NonNull List<@NonNull Object> potentialOrphanObjects = new ArrayList<>();

		protected final @NonNull Map<@NonNull EClass, @NonNull Set<@NonNull Integer>> eClass2allClassIndexes = new HashMap<>();

		/**
		 * All possible allInstances() returns indexed by the ClassIndex of the ClassId for which allInstances() may be invoked.
		 */
		protected final @NonNull Connection [] classIndex2connection;
		private int isContainedCount = 0;
		private int isNotContainedCount = 0;

		/**
		 * true to add all EObjects to allEObjects unconditionally
		 * false to add no EObjects to allEObjects unconditionally
		 * null to add EObjects to allEObjects unless isContained
		 */
		private @Nullable Boolean trackAdditions = null;

		public Model(@NonNull AbstractTransformerInternal transformer, @NonNull String name, @NonNull PropertyId @Nullable [] propertyIndex2propertyId,
				@NonNull ClassId @NonNull [] classIndex2classId, int @Nullable [] @NonNull [] classIndex2allClassIndexes, @NonNull Interval rootInterval) { // FIXME Bug 540500 per-model classIndex2classId etc
			this.transformer = transformer;
			this.name = name;
			//
			//	Prepare the allInstances() fields
			//
			int classIds = classIndex2classId.length;
			this.classIndex2connection = new @NonNull Connection [classIds];
			for (int i = 0; i < classIds; i++) {
				@NonNull ClassId classId = classIndex2classId[i];
				String connectionName = name + "!" + classId.getName();
				classIndex2connection[i] = rootInterval.createConnection(connectionName, classId, false, transformer.getModeFactory());
			}
		}

		/**
		 * Add eObject to the the allInstances() caches potentially updating eClass2allClassIndexes with
		 * the state of a new EClass.
		 */
		private void accumulateEObject1(@NonNull Object eObject, @NonNull EClass eClass) {
			Set<@NonNull Integer> allClassIndexes = eClass2allClassIndexes.get(eClass);
			if (allClassIndexes == null) {
				allClassIndexes = transformer.getClassIndexes(eClass);
				eClass2allClassIndexes.put(eClass, allClassIndexes);
			}
			for (@NonNull Integer classIndex : allClassIndexes) {
				classIndex2connection[classIndex].appendElement(eObject);
			}
		}

		/**
		 * Add eObject to the caches.
		 * <p>
		 * If eClass2allPropertyIndexes is non-null, eObject is added to the unnavigable opposites caches potentially updating eClass2allPropertyIndexes with
		 * the state of a new EClass.
		 */
		private void accumulateEObject2(@NonNull Object eObject, @NonNull EClass eClass,
				@NonNull Map<@NonNull EClass, @NonNull List<@NonNull Integer>> eClass2allPropertyIndexes,
				@Nullable Map<@NonNull EReference, @NonNull Integer> eReference2propertyIndex) {
			Map<@NonNull EReference, @NonNull Integer> eReference2propertyIndex2 = eReference2propertyIndex;
			assert eReference2propertyIndex2 != null;
			List<@NonNull Integer> allPropertyIndexes = eClass2allPropertyIndexes.get(eClass);
			if (allPropertyIndexes == null) {
				allPropertyIndexes = transformer.getOppositePropertyIndexes(eReference2propertyIndex2, eClass);
				eClass2allPropertyIndexes.put(eClass, allPropertyIndexes);
			}
			Map<@NonNull Object, @NonNull Object>[] object2oppositeObject2 = transformer.object2oppositeObject;
			assert object2oppositeObject2 != null;
			for (@NonNull Integer propertyIndex : allPropertyIndexes) {
				EReference @Nullable [] propertyIndex2eReference2 = transformer.propertyIndex2eReference;
				assert propertyIndex2eReference2 != null;
				EReference eReference = propertyIndex2eReference2[propertyIndex];
				if (eReference == null) {
					PropertyId @Nullable [] propertyIndex2propertyId2 = transformer.propertyIndex2propertyId;
					assert propertyIndex2propertyId2 != null;
					PropertyId propertyId = propertyIndex2propertyId2[propertyIndex];
					assert propertyId != null;
					eReference = (EReference) NameUtil.getENamedElement(eClass.getEAllStructuralFeatures(), propertyId.getName());
					assert eReference != null;
				}
				Object object = transformer.eGet(eObject, eReference);
				assert object != null;
				object2oppositeObject2[propertyIndex].put(object, eObject);
			}
		}

		/**
		 * @deprecated provide isContained argument
		 */
		@Deprecated
		public void add(@NonNull EObject eObject) {
			add(eObject, false);
		}

		/**
		 * Add another eObject to the model, which must be distinct from all previously added eObjects.
		 * If isContained, the caller asserts that the caller will define the eObjects eContainer eliminating
		 * the need for the eObject to be tracked as a potential orphan to be assigned to the model root.
		 */
		public void add(@NonNull EObject eObject, boolean isContained) {
			if ((trackAdditions == Boolean.FALSE) || (isContained && (trackAdditions == null))) {
				isContainedCount++;
			}
			else {
				isNotContainedCount++;
				assert !potentialOrphanObjects.contains(eObject);
				potentialOrphanObjects.add(eObject);
			}
			EClass eClass = transformer.eClass(eObject);
			accumulateEObject1(eObject, eClass);
		}

		/**
		 * Add eRootObjects to the modelIndex model.
		 */
		public void addRootObjects(@NonNull Iterable<@NonNull ? extends Object> eRootObjects) {
			Map<@NonNull EClass, @NonNull List<@NonNull Integer>> eClass2allPropertyIndexes = null;
			Map<@NonNull EReference, @NonNull Integer> eReference2propertyIndex = null;
			if (transformer.propertyIndex2propertyId != null) {
				eClass2allPropertyIndexes = new HashMap<>();
				eReference2propertyIndex = new HashMap<>();
			}
			for (@NonNull Object eRootObject : eRootObjects) {
				//
				//	Accumulate the root object in the model extent
				//
				rootObjects.add(eRootObject);
				//
				//	Accumulate the root object and all its child objects in the allInstances() returns
				//
				EClass eRootClass = transformer.eClass(eRootObject);
				accumulateEObject1(eRootObject, eRootClass);
				if (eClass2allPropertyIndexes != null) {
					accumulateEObject2(eRootObject, eRootClass, eClass2allPropertyIndexes, eReference2propertyIndex);
				}
				for (TreeIterator<? extends Object> tit = transformer.eAllContents(eRootObject); tit.hasNext(); ) {
					Object eObject = tit.next();
					if (eObject != null) {
						EClass eClass = transformer.eClass(eObject);
						accumulateEObject1(eObject, eClass);
						if (eClass2allPropertyIndexes != null) {
							accumulateEObject2(eObject, eClass, eClass2allPropertyIndexes, eReference2propertyIndex);
						}
					}
				}
			}
		}

		//	protected @NonNull Connection createConnection(@NonNull Interval rootInterval, @NonNull ClassId classId, @NonNull String connectionName, boolean isStrict, boolean isIncremental) {
		//		return rootInterval.createConnection(connectionName, classId, isStrict, isIncremental);
		//	}

		/**
		 * This is solely used by the Model::allObjects Operation which is not needed by synthesized QVTr.
		 * @deprecated
		 */
		@Deprecated
		@Override
		public @NonNull Collection<@NonNull Object> getAllObjects() {
			/*			List<@NonNull Object> allEObjects2 = allEObjects;
			if (allEObjects2 == null) {
				allEObjects = allEObjects2 = new ArrayList<>();
				List<@NonNull Object> rootEObjects2 = rootEObjects;
				if (rootEObjects2 != null) {
					for (@NonNull Object eRootObject : rootEObjects2) {
						assert !allEObjects2.contains(eRootObject);
						allEObjects2.add(eRootObject);
						for (TreeIterator<? extends Object> tit = transformer.eAllContents(eRootObject); tit.hasNext(); ) {
							Object eObject = tit.next();
							if (eObject != null) {
								assert !allEObjects2.contains(eObject);
								allEObjects2.add(eObject);
							}
						}
					}
				}
			} */
			return potentialOrphanObjects;
		}

		public @NonNull Connection getConnection(int classIndex) {
			return classIndex2connection[classIndex];
		}

		/**
		 * This is solely used by the Model::objectsOfKind Operation which is not needed by synthesized QVTr.
		 */
		@Override
		public @NonNull Iterable<@NonNull Object> getObjectsOfKind(org.eclipse.ocl.pivot.@NonNull Class type) {
			TypeId classId = type.getTypeId();
			Integer classIndex = transformer.classId2classIndex.get(classId);
			if (classIndex != null) {
				Iterable<@NonNull Object> typedIterable = classIndex2connection[classIndex].typedIterable(Object.class);
				//				List<@NonNull Object> collection =  new ArrayList<>();
				//				for (@NonNull Object object : typedIterable) {
				//					collection.add(object);
				//				}
				return typedIterable;
			}
			return EMPTY_EOBJECT_LIST;
		}

		/**
		 * This is solely used by the Model::objectsOfType Operation which is not needed by synthesized QVTr.
		 * @deprecated
		 */
		@Deprecated
		@Override
		public @NonNull Collection<@NonNull Object> getObjectsOfType(org.eclipse.ocl.pivot.@NonNull Class type) {
			throw new UnsupportedOperationException();
		}

		/**
		 * Return all objects in the modelIndex model that conform to eClass.
		 *
	    protected @NonNull <T extends EObject> List<T> getObjectsByType(@NonNull EClass eClass) {
	    	List<T> selectedEObjects = new ArrayList<T>();
			if (rootEObjects != null) {
		    	for (EObject eRootObject : rootEObjects) {
		    		if (eClass.isInstance(eRootObject)) {
		    			@SuppressWarnings("unchecked") T eObject2 = (T)eRootObject;
		    			selectedEObjects.add(eObject2);
		    		}
		        	for (TreeIterator<EObject> tit = eRootObject.eAllContents(); tit.hasNext(); ) {
		        		@SuppressWarnings("null")@NonNull EObject eObject = tit.next();
			    		if (eClass.isInstance(eObject)) {
			    			@SuppressWarnings("unchecked") T eObject2 = (T)eObject;
			    			selectedEObjects.add(eObject2);
			    		}
		        	}
		    	}
			}
			return selectedEObjects;
		} */

		@Override
		public @NonNull Collection<@NonNull Object> getRootObjects() {
			if (rootObjects.size() > 0) {		// If we have explicit (input) roots
				return rootObjects;
			}
			List<@NonNull Object> rootObjects2 = new ArrayList<>();
			for (@NonNull Object eObject : potentialOrphanObjects) {
				if (transformer.eContainer(eObject) == null) {
					rootObjects2.add(eObject);
				}
			}
			if (AbstractTransformer.CONTAINMENTS.isActive()) {
				AbstractTransformer.CONTAINMENTS.println(name + " " + isContainedCount + "/" + (isContainedCount + isNotContainedCount));
			}
			return rootObjects2;
		}

		@Override
		public String toString() {
			return name + " " + rootObjects.size();
		}

		@Override
		public @NonNull String getName() {
			return name;
		}

		/**
		 * Set the behavior of add(eObject,isContained),
		 * true to add all EObjects to allEObjects unconditionally,
		 * false to add no EObjects to allEObjects unconditionally,
		 * null to add EObjects to allEObjects unless isContained
		 */
		public void setTrackAdditions(@Nullable Boolean trackAdditions) {
			this.trackAdditions = trackAdditions;
		}

		public <@NonNull T> Iterable<T> typedIterable(Class<T> javaClass, org.eclipse.ocl.pivot.@NonNull Class pivotType) {
			TypeId typeId = pivotType.getTypeId();
			Integer classIndex = transformer.classId2classIndex.get(typeId);
			if (classIndex != null) {
				Connection connection = classIndex2connection[classIndex];
				return connection.typedIterable(javaClass);
			}
			return null;
		}
	}

	@Deprecated // only used by exe2016/bugmde2016 tests
	private static class UnenforcedSetAccumulator extends SetValueImpl implements SetValue.Accumulator
	{
		public UnenforcedSetAccumulator(@NonNull CollectionTypeId typeId) {
			super(typeId, new ArrayList<Object>());
		}

		@Override
		@SuppressWarnings("unchecked")
		public boolean add(@Nullable Object value) {
			assert !((Collection<Object>)elements).contains(value);
			return ((Collection<Object>)elements).add(value);
		}
	}

	protected final @NonNull TransformationExecutor executor;
	/** deprecated use executor */
	@Deprecated
	protected final @NonNull Evaluator evaluator;
	protected final IdResolver.@NonNull IdResolverExtension idResolver;
	protected final @NonNull Model @NonNull [] models;
	protected final @NonNull Map<@NonNull String, @NonNull Integer> modelIndexes = new HashMap<>();
	protected final boolean debugAssignments = AbstractTransformer.ASSIGNMENTS.isActive();
	protected final boolean debugCreations = AbstractTransformer.CREATIONS.isActive();
	protected final boolean debugExceptions = AbstractTransformer.EXCEPTIONS.isActive();
	protected final boolean debugGettings = AbstractTransformer.GETTINGS.isActive();
	protected final boolean debugInvocations = AbstractTransformer.INVOCATIONS.isActive();

	/**
	 * Unchanging configured list PropertyId for which unnavigable opposite navigation may occur indexed by the PropertyIndex for that PropertyId.
	 */
	private final @NonNull PropertyId @Nullable [] propertyIndex2propertyId;

	/**
	 * Unchanging configured map from the PropertyId for which unnavigable opposite navigation may occur to the PropertyIndex for that PropertyId.
	 */
	private final @Nullable Map<PropertyId, Integer> propertyId2propertyIndex;

	/**
	 * Unchanging configured map from the PropertyIndex to the EReference for the opposite property navigation.
	 */
	private final @Nullable EReference @Nullable[] propertyIndex2eReference;

	/**
	 * Unchanging maps from an EObject to its opposite using the Property whose PropertyIndex indexes the map.
	 */
	private final @NonNull Map<@NonNull Object, @NonNull Object> @Nullable [] object2oppositeObject;

	/**
	 * Unchanging configured map from the ClassId for which allInstances() may be invoked to the ClassIndex for that ClassId.
	 */
	private final @NonNull Map<@NonNull ClassId, @NonNull Integer> classId2classIndex;

	/**
	 * Evolving map from the ClassId of some model object's class to all the ClassIndexes for which the model object
	 * might contribute to an allInstances() return. This is initially populated for the ClassIndexes of the ClassIds
	 * for which allInstances() may be invoked. It evolves lazily to include the ClassIds for all objects in the user
	 * models.
	 */
	private final @NonNull Map<@NonNull ClassId, @NonNull Set<@NonNull Integer>> classId2classIndexes;

	/**
	 * Manager for the blocked and unblocked invocations.
	 */
	protected final @NonNull InvocationManager invocationManager;

	/**
	 * Manager for the auxiliary object and property state.
	 */
	protected final @NonNull ObjectManager objectManager;

	/**
	 * Cache of operation evaluations.
	 */
	protected final @NonNull EvaluationCache evaluationCache;

	protected AbstractTransformerInternal(@NonNull TransformationExecutor executor, @NonNull String @NonNull [] modelNames,
			@NonNull PropertyId @Nullable [] propertyIndex2propertyId, @NonNull ClassId @NonNull [] classIndex2classId, int @Nullable [] @NonNull [] classIndex2allClassIndexes) {
		this.executor = executor;
		this.evaluator = executor;
		this.idResolver = (IdResolver.IdResolverExtension)executor.getIdResolver();
		this.invocationManager = createInvocationManager();
		this.objectManager = createObjectManager();
		this.evaluationCache = createEvaluationCache();
		this.models = new @NonNull Model @NonNull [modelNames.length];
		Interval rootInterval = lazyCreateInterval(0);
		for (int i = 0; i < modelNames.length; i++) {
			String modelName = modelNames[i];
			models[i] = createModel(modelName, propertyIndex2propertyId, classIndex2classId, classIndex2allClassIndexes, rootInterval);
			modelIndexes.put(modelName, i);
		}
		//
		//	Prepare the unnavigable opposite property fields
		//
		if (propertyIndex2propertyId != null) {
			int propertyIds = propertyIndex2propertyId.length;
			this.propertyIndex2propertyId = propertyIndex2propertyId;
			Map<@NonNull PropertyId, @NonNull Integer> propertyId2propertyIndex2 = new HashMap<>(propertyIds);
			this.propertyId2propertyIndex = propertyId2propertyIndex2;
			this.propertyIndex2eReference = new @Nullable EReference @NonNull [propertyIds];
			for (int propertyIndex = 0; propertyIndex < propertyIds; propertyIndex++) {
				PropertyId propertyId = propertyIndex2propertyId[propertyIndex];
				propertyId2propertyIndex2.put(propertyId, propertyIndex);
			}
			@SuppressWarnings("unchecked")@NonNull Map<@NonNull Object, @NonNull Object> @Nullable [] object2oppositeObject = (@NonNull Map<@NonNull Object, @NonNull Object> @NonNull []) new HashMap<?,?> @NonNull [propertyIds];
			this.object2oppositeObject = object2oppositeObject;
			for (int i = 0; i < propertyIds; i++) {
				object2oppositeObject[i] = new HashMap<>();
			}
		}
		else {
			this.propertyIndex2propertyId = null;
			this.propertyId2propertyIndex = null;
			this.propertyIndex2eReference = null;
			this.object2oppositeObject = null;
		}
		//
		//	Prepare the allInstances() fields
		//
		assert classIndex2allClassIndexes != null;
		int classIds = classIndex2classId.length;
		this.classId2classIndex = new HashMap<>(classIds);
		this.classId2classIndexes = new HashMap<>(classIds);
		for (int classIndex = 0; classIndex < classIds; classIndex++) {
			ClassId classId = classIndex2classId[classIndex];
			classId2classIndex.put(classId, classIndex);
			Set<@NonNull Integer> superClassIndexes = new HashSet<>();
			for (int allClassIndex : classIndex2allClassIndexes[classIndex]) {
				superClassIndexes.add(allClassIndex);
			}
			classId2classIndexes.put(classId, superClassIndexes);
		}
	}

	@Override
	public <R> R accept(@NonNull ExecutionVisitor<R> visitor) {
		return visitor.visitTransformer(this);
	}

	/**
	 * Add eRootObjects to the modelIndex model.
	 */
	@Override
	public void addRootObjects(@NonNull String modelName, @NonNull Iterable<@NonNull ? extends Object> eRootObjects) {
		getTypedModelInstance(modelName).addRootObjects(eRootObjects);
	}

	@Deprecated /* @deprecated pass interval */
	protected @NonNull Connection createConnection(@NonNull String name, @NonNull TypeId typeId, boolean isStrict) {
		return createConnection(invocationManager.getRootInterval(), name, typeId, isStrict, getModeFactory());
	}

	protected @NonNull Connection createConnection(@NonNull Interval interval, @NonNull String name, @NonNull TypeId typeId, boolean isStrict, @NonNull ModeFactory modeFactory) {
		return interval.createConnection(name, typeId, isStrict, modeFactory);
	}

	/**
	 * Create the evaluationCache. Creates a EvaluationCache by default.
	 */
	protected @NonNull EvaluationCache createEvaluationCache() {
		return new EvaluationCache(executor);
	}

	protected @NonNull Interval createInterval(int intervalIndex) {
		return new DefaultInterval(getInvocationManager(), intervalIndex);
	}

	/**
	 * Create the InvocationManager. Creates a LazyInvocationManager by default.
	 */
	protected @NonNull InvocationManager createInvocationManager() {
		return new LazyInvocationManager(executor);
	}

	@Deprecated /* @deprecated pass explicit root interval */
	protected @NonNull Model createModel(@NonNull String modelName, @NonNull PropertyId @Nullable [] propertyIndex2propertyId,
			@NonNull ClassId @NonNull [] classIndex2classId, int @Nullable [] @NonNull [] classIndex2allClassIndexes) {
		return new Model(this, modelName, propertyIndex2propertyId, classIndex2classId, classIndex2allClassIndexes, getInvocationManager().getRootInterval());
	}

	protected @NonNull Model createModel(@NonNull String modelName, @NonNull PropertyId @Nullable [] propertyIndex2propertyId,
			@NonNull ClassId @NonNull [] classIndex2classId, int @Nullable [] @NonNull [] classIndex2allClassIndexes, @NonNull Interval rootInterval) {
		return new Model(this, modelName, propertyIndex2propertyId, classIndex2classId, classIndex2allClassIndexes, rootInterval);
	}

	@Deprecated // Use createConnection
	protected SetValue.@NonNull Accumulator createUnenforcedSetAccumulatorValue(@NonNull CollectionTypeId typeId) {
		return new UnenforcedSetAccumulator(typeId);
	}

	/**
	 * Create the ObjectManager. Creates a LazyObjectManager by default.
	 */
	protected @NonNull ObjectManager createObjectManager() {
		return new LazyObjectManager((LazyInvocationManager)invocationManager);
	}

	@SuppressWarnings("null")
	protected @NonNull TreeIterator<? extends Object> eAllContents(@NonNull Object object) {
		return ((EObject)object).eAllContents();
	}

	@SuppressWarnings("null")
	protected @NonNull EClass eClass(@NonNull Object object) {
		return ((EObject)object).eClass();
	}

	protected @Nullable Object eContainer(@NonNull Object object) {
		return ((EObject)object).eContainer();
	}

	protected @Nullable Object eGet(@NonNull Object object, @NonNull EStructuralFeature eFeature) {
		return ((EObject)object).eGet(eFeature);
	}

	public @NonNull Iterable<@NonNull Object> get(org.eclipse.ocl.pivot.@NonNull Class type) {
		return models[0].getObjectsOfKind(type);
	}

	/**
	 * Return the Set of all ClassIndexes to which an EClass instance contributes to allInstances() returns.
	 */
	private @NonNull Set<@NonNull Integer> getClassIndexes(@NonNull EClass eClass) {
		//	ClassId classId = IdManager.getClassId(eClass);
		EPackage ePackage = ClassUtil.nonNullEMF(eClass.getEPackage());
		PackageId packageId = IdManager.getPackageId(ePackage);
		String className = ClassUtil.nonNullEMF(eClass.getName());		// FIXME Original name
		ClassId classId = packageId.getClassId(className, eClass.getETypeParameters().size());
		Map<@NonNull ClassId, @NonNull Set<@NonNull Integer>> classId2classIndexes2 = classId2classIndexes;
		assert classId2classIndexes2 != null;
		Set<@NonNull Integer> classIndexes = classId2classIndexes2.get(classId);
		if (classIndexes == null) {
			classIndexes = new HashSet<>();
			for (@NonNull EClass eSuperClass : ClassUtil.nullFree(eClass.getESuperTypes())) {
				Set<@NonNull Integer> partialResult = getClassIndexes(eSuperClass);
				classIndexes.addAll(partialResult);
			}
			classId2classIndexes2.put(classId, classIndexes);
		}
		return classIndexes;
	}

	@Override
	public @NonNull EvaluationCache getEvaluationCache() {
		return evaluationCache;
	}

	@Override
	public @NonNull TransformationExecutor getExecutor() {
		return executor;
	}

	@Override
	public @NonNull InvocationManager getInvocationManager() {
		return invocationManager;
	}

	public @NonNull ModeFactory getModeFactory() {
		return ModeFactory.NON_INCREMENTAL;
	}

	@Override
	public @NonNull ObjectManager getObjectManager() {
		return objectManager;
	}

	/**
	 * Return all objects in the modelIndex model that conform to eClass.
	 *
    protected @NonNull <T extends EObject> List<T> getObjectsByType(int modelIndex, @NonNull EClass eClass) {
		return models[modelIndex].getObjectsByType(eClass);
	} */

	/**
	 * Return the List of all PropertyIndexes for which an EClass instance could be the unnavigable opposite.
	 * eReference2propertyIndex contains known equivalences and may be updated if more are discovered
	 * using -1 as a propertyIndex for which no unnavigable opposite is appropriate.
	 */
	private @NonNull List<@NonNull Integer> getOppositePropertyIndexes(@NonNull Map<@NonNull EReference, @NonNull Integer> eReference2propertyIndex, @NonNull EClass eClass) {
		List<@NonNull Integer> propertyIndexes = null;
		for (EStructuralFeature eStructuralFeature : eClass.getEAllStructuralFeatures()) {
			if (eStructuralFeature instanceof EReference) {
				EReference eReference = (EReference)eStructuralFeature;
				Integer propertyIndex = eReference2propertyIndex.get(eReference);
				if (propertyIndex == null) {
					if ((eReference.getEOpposite() == null) && !eReference.isDerived() && !eReference.isTransient() && !eReference.isVolatile()) {
						//	PropertyId propertyId = IdManager.getPropertyId(eReference);
						EClass eContainingClass = eReference.getEContainingClass();
						EPackage ePackage = ClassUtil.nonNullEMF(eContainingClass.getEPackage());
						PackageId packageId = IdManager.getPackageId(ePackage);
						String className = ClassUtil.nonNullEMF(eContainingClass.getName());				// FIXME Original name
						ClassId classId = packageId.getClassId(className, eContainingClass.getETypeParameters().size());
						String propertyName = ClassUtil.nonNullEMF(eReference.getName());		// FIXME Original name
						PropertyId propertyId = classId.getPropertyId(propertyName);
						Map<PropertyId, Integer> propertyId2propertyIndex2 = propertyId2propertyIndex;
						assert propertyId2propertyIndex2 != null;
						propertyIndex = propertyId2propertyIndex2.get(propertyId);
					}
					if (propertyIndex == null) {
						propertyIndex = -1;
					}
					eReference2propertyIndex.put(eReference, propertyIndex);
				}
				if (propertyIndex >= 0) {
					if (propertyIndexes == null) {
						propertyIndexes = new ArrayList<>();
					}
					propertyIndexes.add(propertyIndex);
				}
			}
		}
		return propertyIndexes != null ? propertyIndexes : EMPTY_INDEX_LIST;
	}

	/**
	 * Return all the container-less objects in the modelName model.
	 */
	@Override
	public @NonNull Collection<@NonNull EObject> getRootEObjects(@NonNull String modelName) {
		Model model = getTypedModelInstance(modelName);
		List<@NonNull EObject> rootEObjects = new ArrayList<>();
		for (@NonNull Object rootObject : model.getRootObjects()) {
			if (rootObject instanceof EObject) {
				rootEObjects.add((EObject)rootObject);
			}
		}
		return rootEObjects;
	}

	/**
	 * Return all the container-less objects in the modelName model.
	 */
	@Override
	public @NonNull Collection<@NonNull Object> getRootObjects(@NonNull String modelName) {
		return getTypedModelInstance(modelName).getRootObjects();
	}

	@Override
	public @NonNull Model getTypedModelInstance(@NonNull String modelName) {
		Integer modelIndex = modelIndexes.get(modelName);
		if (modelIndex == null) {
			throw new IllegalStateException("Unknown model name '" + modelName + "'");
		}
		return models[modelIndex];
	}

	/**
	 * The default handler for an exception during mapping execution rethrows an InvocationFailedException so that the
	 * caller may organize a re-exection when the reqired memory access can succeed. Errors are rethrown and should
	 * propagate to the transformation invoker, except for AssertionError which is is absorbed if the user has configured
	 * AbstractTransformer.EXCEPTIONS to observe them on the console. All other exceptions are just absorbed since they
	 * may represent a predicate failure.
	 */
	protected boolean handleExecutionFailure(@NonNull String mappingName, @NonNull Throwable e) throws InvocationFailedException {
		if (e instanceof InvocationFailedException) {		// Normal case - premature access needs a retry later
			throw (InvocationFailedException)e;
		}
		else if (e instanceof InvalidEvaluationException) {	// Real errors are fatal
			if (debugExceptions) {
				AbstractTransformer.EXCEPTIONS.println("Execution failure in '" + mappingName + "' : " + e);
			}
			throw (InvalidEvaluationException)e;
		}
		else if (e instanceof AssertionError) {				// Debug case - assertion errors are diagnostic not catastrophic
			if (debugExceptions) {
				AbstractTransformer.EXCEPTIONS.println("Execution failure in '" + mappingName + "' : " + e);
			}
			else {
				throw (AssertionError)e;					// But if the user isn't watching them they are fatal
			}
		}
		else if (e instanceof Error) {						// Real errors are fatal
			if (debugExceptions) {
				AbstractTransformer.EXCEPTIONS.println("Execution failure in '" + mappingName + "' : " + e);
			}
			throw (Error)e;
		}
		else { 												// Other failures are just mappings whose predicates were not satisfied.
			if (e instanceof InvalidValueException) {		// Multiway branch to facilitate debugger breakpoints.
				if (debugExceptions) {
					AbstractTransformer.EXCEPTIONS.println("Execution failure in '" + mappingName + "' : " + e);
				}
			}
			else if (e instanceof NullPointerException) {
				if (debugExceptions) {
					AbstractTransformer.EXCEPTIONS.println("Execution failure in '" + mappingName + "' : " + e);
				}
			}
			else {
				if (debugExceptions) {
					AbstractTransformer.EXCEPTIONS.println("Execution failure in '" + mappingName + "' : " + e);
				}
			}
		}
		if (e instanceof Exception) {
			throw new InvalidEvaluationException((Exception)e);
		}
		throw new InvalidEvaluationException(new RuntimeException(e));
	}

	/*	protected void install(@NonNull InvocationConstructor constructor, int consumedConnections, @NonNull Connection @NonNull ... connections) {
		//		InvocationConstructor invoker = invocationManager.createInvoker(constructor, consumedConnections, interval, connections);
		for (int i = 0; i < consumedConnections; i++) {
			Connection consumedConnection = connections[i];
			consumedConnection.addConsumer(constructor);
			constructor.addConsumedConection(consumedConnection);
		}
		for (int i = consumedConnections; i < connections.length; i++) {
			Connection appendedConnection = connections[i];
			appendedConnection.addProducer(constructor);
			constructor.addAppendedConnection(appendedConnection);
		}
	} */

	protected @NonNull Interval lazyCreateInterval(int intervalIndex) {
		if (intervalIndex < 0) {
			return invocationManager.createInterval();		// Obsolete functionality
		}
		for (int i = invocationManager.getIntervalsSize(); i < intervalIndex; i++) {
			createInterval(i);
		}
		Interval interval = invocationManager.basicGetInterval(intervalIndex);
		return interval != null ? interval : createInterval(intervalIndex);
	}

	@Override
	public void setExternalURI(@NonNull String modelName, @NonNull URI modelURI) {
		Model model = getTypedModelInstance(modelName);
		for (Object object : model.getRootObjects()) {
			if (object instanceof org.eclipse.ocl.pivot.Model) {
				((org.eclipse.ocl.pivot.Model)object).setExternalURI(modelURI.toString());
			}
		}
	}

	public @NonNull Object throwInvalidEvaluationException(@NonNull String message, Object... bindings) {
		throw new InvalidEvaluationException(message, bindings);
	}

	/**
	 * Return the string rendering of object for use in debug messages. The default just invokes String.valueOf().
	 * Derived implementations may provide metamodel-specific content.
	 */
	protected @NonNull String toDebugString(@Nullable Object object) {
		return AbstractObjectManager.toDebugString(object);
	}
}
