/*******************************************************************************
 * 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;
import org.eclipse.qvtd.runtime.qvtruntimelibrary.Extent;
import org.eclipse.qvtd.runtime.qvtruntimelibrary.QVTruntimeLibraryFactory;

import com.google.common.collect.Iterables;

/**
 * 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) ;
		}

		protected Incremental(@NonNull TransformationExecutor executor, int models) {
			super(executor, models);
		}

		@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);
		//		}

		@Override
		protected @NonNull Model createModel(@NonNull String modelName) {
			return new Model.Incremental(this, modelName);
		}

		@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) {
				super(transformer, name);
			}

			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) {
				assert classIndex2connection != null;
				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<>();

		/**
		 * Unchanging list, in class index order, of the ClassId for which allInstances() may be invoked.
		 */
		protected @NonNull ClassId @Nullable [] classIndex2classId = null;

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

		/**
		 * 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.
		 */
		protected @Nullable Map<@NonNull ClassId, @NonNull Set<@NonNull Integer>> classId2classIndexes = null;

		/**
		 * All possible allInstances() returns indexed by the ClassIndex of the ClassId for which allInstances() may be invoked.
		 *
		 * Must be sert non-null by initConnections() before transformation execution starts.
		 */
		protected @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;

		//	@Deprecated /* @deprecated omit redundant argument */
		public Model(@NonNull AbstractTransformerInternal transformer, @NonNull String name) { // FIXME Bug 540500 per-model classIndex2classId etc
			this.transformer = transformer;
			this.name = name;
		}

		/**
		 * 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) {
			assert classIndex2connection != null;
			Set<@NonNull Integer> allClassIndexes = eClass2allClassIndexes.get(eClass);
			if (allClassIndexes == null) {
				allClassIndexes = 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);
						}
					}
				}
			}
			ClassId extentClassId = IdManager.getNsURIPackageId("http://www.eclipse.org/qvt/2019/QVTruntimeLibrary", null, null).getClassId("Extent", 0);
			Integer extentClassIndex = classId2classIndex != null ? classId2classIndex.get(extentClassId) : null;
			if (extentClassIndex != null) {
				Extent extent = QVTruntimeLibraryFactory.eINSTANCE.createExtent();
				Iterables.addAll(extent.getElements(), eRootObjects);
				accumulateEObject1(extent, extent.eClass());
			}
		}

		//	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;
		}

		/**
		 * 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;
		}

		public @NonNull Connection getConnection(int classIndex) {
			assert classIndex2connection != null;
			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) {
			assert classIndex2connection != null;
			TypeId classId = type.getTypeId();
			Integer classIndex = classId2classIndex != null ? classId2classIndex.get(classId) : null;
			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;
		}

		public @NonNull Model initClassIds(@NonNull ClassId @NonNull [] classIndex2classId, int @Nullable [] @NonNull [] classIndex2allClassIndexes) {
			this.classIndex2classId = classIndex2classId;
			//
			//	Prepare the allInstances() fields
			//
			assert classIndex2allClassIndexes != null;
			int classIds = classIndex2classId.length;
			Map<@NonNull ClassId, @NonNull Integer> classId2classIndex = this.classId2classIndex = new HashMap<>(classIds);
			Map<@NonNull ClassId, @NonNull Set<@NonNull Integer>> classId2classIndexes = 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);
			}
			return this;
		}

		void initConnections(@NonNull Interval rootInterval) {
			//
			//	Prepare the allInstances() fields
			//
			@NonNull ClassId[] classIndex2classId2 = classIndex2classId;
			assert classIndex2classId2 != null;
			@NonNull Connection [] classIndex2connection = this.classIndex2connection = new @NonNull Connection[classIndex2classId2.length];
			int classIndex = 0;
			for (@NonNull ClassId classId : classIndex2classId2) {
				String connectionName = name + "!" + classId.getName();
				classIndex2connection[classIndex] = rootInterval.createConnection(connectionName, classId, false, transformer.getModeFactory());
				classIndex++;
			}
		}

		@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) {
			assert classIndex2connection != null;
			TypeId typeId = pivotType.getTypeId();
			Integer classIndex = classId2classIndex != null ? classId2classIndex.get(typeId) : null;
			if (classIndex != null) {
				Connection connection = classIndex2connection[classIndex];
				return connection.typedIterable(javaClass);
			}
			return null;
		}
	}

	@Deprecated // only used by exe2016/bigmde2016 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 @NonNull PropertyId @Nullable [] propertyIndex2propertyId;

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

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

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

	/**
	 * 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, modelNames.length) ;
		if (propertyIndex2propertyId != null) {
			initOpposites(propertyIndex2propertyId);
		}
		for (int i = 0; i < modelNames.length; i++) {
			Model model = initModel(i, modelNames[i]);
			model.initClassIds(classIndex2classId, classIndex2allClassIndexes);
		}
		initConnections();
	}

	protected AbstractTransformerInternal(@NonNull TransformationExecutor executor, int models) {
		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 [models];
	}

	@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);
	//	}

	protected @NonNull Model createModel(@NonNull String modelName) {
		return new Model(this, modelName);
	}

	@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);
	}

	@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) {
		boolean hasExtent = false;
		Model model = getTypedModelInstance(modelName);
		List<@NonNull EObject> rootEObjects = new ArrayList<>();
		for (@NonNull Object rootObject : model.getRootObjects()) {
			if (rootObject instanceof Extent) {
				hasExtent = true;
				for (Object object : ((Extent)rootObject).getElements()) {
					if (object != null) {
						rootEObjects.add((EObject)object);
					}
				}
			}
		}
		if (!hasExtent) {
			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 initConnections() {
		Interval rootInterval = lazyCreateInterval(0);
		for (@NonNull Model model : models) {
			model.initConnections(rootInterval);
		}
	}

	protected @NonNull Model initModel(int i, @NonNull String modelName, @NonNull PropertyId @Nullable [] propertyIndex2propertyId,
			@NonNull ClassId @NonNull [] classIndex2classId, int @Nullable [] @NonNull [] classIndex2allClassIndexes, @NonNull Interval rootInterval) {
		Model model = createModel(modelName); //, propertyIndex2propertyId, classIndex2classId, classIndex2allClassIndexes);
		models[i] = model;
		modelIndexes.put(modelName, i);
		return model;
	}

	protected @NonNull Model initModel(int i, @NonNull String modelName) {
		Model model = createModel(modelName);
		models[i] = model;
		modelIndexes.put(modelName, i);
		return model;
	}

	protected void initOpposites(@NonNull PropertyId @NonNull [] propertyIndex2propertyId) {
		//
		//	Prepare the unnavigable opposite property fields
		//
		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<>();
		}
	}

	/*	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);
	}
}
