[580363] Update for ASSaverNew, clearer TemplateParameterId
diff --git a/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/GenerateOCLCommon.java b/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/GenerateOCLCommon.java
index c3f1e80..65029b7 100644
--- a/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/GenerateOCLCommon.java
+++ b/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/GenerateOCLCommon.java
@@ -20,19 +20,21 @@
 import java.util.Map;
 import java.util.Set;
 
-import org.eclipse.emf.common.util.TreeIterator;
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.util.EcoreUtil;
 import org.eclipse.emf.mwe.utils.Mapping;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.ocl.examples.codegen.oclinecore.OCLinEcoreTablesUtils;
+import org.eclipse.ocl.pivot.Annotation;
 import org.eclipse.ocl.pivot.CollectionType;
 import org.eclipse.ocl.pivot.Comment;
 import org.eclipse.ocl.pivot.CompleteClass;
 import org.eclipse.ocl.pivot.Constraint;
+import org.eclipse.ocl.pivot.Detail;
 import org.eclipse.ocl.pivot.Element;
 import org.eclipse.ocl.pivot.Enumeration;
+import org.eclipse.ocl.pivot.EnumerationLiteral;
 import org.eclipse.ocl.pivot.Import;
 import org.eclipse.ocl.pivot.Iteration;
 import org.eclipse.ocl.pivot.LambdaType;
@@ -43,11 +45,11 @@
 import org.eclipse.ocl.pivot.NamedElement;
 import org.eclipse.ocl.pivot.Namespace;
 import org.eclipse.ocl.pivot.Operation;
-import org.eclipse.ocl.pivot.Package;
 import org.eclipse.ocl.pivot.Parameter;
 import org.eclipse.ocl.pivot.Precedence;
 import org.eclipse.ocl.pivot.PrimitiveType;
 import org.eclipse.ocl.pivot.Property;
+import org.eclipse.ocl.pivot.StandardLibrary;
 import org.eclipse.ocl.pivot.TemplateBinding;
 import org.eclipse.ocl.pivot.TemplateParameter;
 import org.eclipse.ocl.pivot.TemplateParameterSubstitution;
@@ -58,70 +60,521 @@
 import org.eclipse.ocl.pivot.TypedElement;
 import org.eclipse.ocl.pivot.ids.IdManager;
 import org.eclipse.ocl.pivot.ids.PackageId;
+import org.eclipse.ocl.pivot.ids.TypeId;
 import org.eclipse.ocl.pivot.internal.PackageImpl;
-import org.eclipse.ocl.pivot.internal.complete.StandardLibraryInternal;
+import org.eclipse.ocl.pivot.internal.complete.CompleteClassInternal;
+import org.eclipse.ocl.pivot.internal.manager.Orphanage;
 import org.eclipse.ocl.pivot.internal.manager.PivotMetamodelManager;
+import org.eclipse.ocl.pivot.internal.resource.ASSaverNew;
+import org.eclipse.ocl.pivot.internal.resource.ASSaverNew.ASSaverWithInverse;
 import org.eclipse.ocl.pivot.internal.utilities.AS2Moniker;
 import org.eclipse.ocl.pivot.internal.utilities.EnvironmentFactoryInternal;
-import org.eclipse.ocl.pivot.utilities.Nameable;
+import org.eclipse.ocl.pivot.util.AbstractExtendingVisitor;
+import org.eclipse.ocl.pivot.util.Visitable;
+import org.eclipse.ocl.pivot.utilities.NameUtil;
 import org.eclipse.ocl.pivot.utilities.PivotConstants;
 import org.eclipse.ocl.pivot.utilities.PivotUtil;
+import org.eclipse.ocl.pivot.utilities.TreeIterable;
+import org.eclipse.ocl.pivot.utilities.ValueUtil;
+import org.eclipse.ocl.pivot.values.IntegerValue;
+import org.eclipse.ocl.pivot.values.UnlimitedNaturalValue;
 import org.eclipse.xtext.util.Strings;
 
+import com.google.common.collect.Lists;
+
 @SuppressWarnings("all")
 public abstract class GenerateOCLCommon extends GenerateMetamodelWorkflowComponent
 {
-	private final @NonNull Map<Element, String> element2moniker = new HashMap<>();
-	private final @NonNull Map<NamedElement, @NonNull String> external2name = new HashMap<>();
-	protected final @NonNull Map<String, NamedElement> name2external = new HashMap<>();
-	protected final @NonNull Map<String, String> generatedClassNameMap = new HashMap<>();
-	protected EnvironmentFactoryInternal environmentFactory;
-	protected PivotMetamodelManager metamodelManager;
-	protected NameQueries nameQueries;
-
-	public static final @NonNull Comparator<@NonNull Property> classPropertyComparator = new Comparator<@NonNull Property>()
+	protected static class ContentAnalysis extends AbstractExtendingVisitor<@Nullable Object, @NonNull GenerateOCLCommon>
 	{
-		@Override
-		public int compare(@NonNull Property p1, @NonNull Property p2) {
-			String c1 = String.valueOf(p1.getOwningClass().getName());
-			String c2 = String.valueOf(p2.getOwningClass().getName());
-			int diff = c1.compareTo(c2);
-			if (diff != 0) {
-				return diff;
-			}
-			boolean b1 = p1.isIsImplicit();
-			boolean b2 = p2.isIsImplicit();
-			if (b1 != b2) {
-				return b1 ? 1 : -1;
-			}
-			String n1 = String.valueOf(p1.getName());
-			String n2 = String.valueOf(p2.getName());
-			diff = n1.compareTo(n2);
-			if (diff != 0) {
-				return diff;
-			}
-			Property o1 = p1.getOpposite();
-			Property o2 = p2.getOpposite();
-			if (o1 == null) {
-				if (o2 == null) {
-					return 0;
+		public static final @NonNull Comparator<@NonNull Property> classPropertyComparator = new Comparator<@NonNull Property>()
+		{
+			@Override
+			public int compare(@NonNull Property p1, @NonNull Property p2) {
+				String c1 = String.valueOf(p1.getOwningClass().getName());
+				String c2 = String.valueOf(p2.getOwningClass().getName());
+				int diff = c1.compareTo(c2);
+				if (diff != 0) {
+					return diff;
+				}
+				boolean b1 = p1.isIsImplicit();
+				boolean b2 = p2.isIsImplicit();
+				if (b1 != b2) {
+					return b1 ? 1 : -1;
+				}
+				String n1 = String.valueOf(p1.getName());
+				String n2 = String.valueOf(p2.getName());
+				diff = n1.compareTo(n2);
+				if (diff != 0) {
+					return diff;
+				}
+				Property o1 = p1.getOpposite();
+				Property o2 = p2.getOpposite();
+				if (o1 == null) {
+					if (o2 == null) {
+						return 0;
+					}
+					else {
+						return 1;
+					}
 				}
 				else {
-					return 1;
+					if (o2 == null) {
+						return -1;
+					}
+					else {
+						n1 = String.valueOf(o1.getName());
+						n2 = String.valueOf(o2.getName());
+						return n1.compareTo(n2);
+					}
 				}
 			}
-			else {
-				if (o2 == null) {
-					return -1;
+		};
+
+		protected final @NonNull Comparator<@NonNull CollectionType> collectionTypeComparator = new Comparator<@NonNull CollectionType>()
+		{
+			@Override
+			public int compare(@NonNull CollectionType o1, @NonNull CollectionType o2) {
+				TypeId m1 = o1.getTypeId();
+				TypeId m2 = o2.getTypeId();
+				int i = m1.toString().compareTo(m2.toString());
+				if (i != 0) {
+					return i;
 				}
-				else {
-					n1 = String.valueOf(o1.getName());
-					n2 = String.valueOf(o2.getName());
-					return n1.compareTo(n2);
+				String n1 = o1.getElementType().getName();
+				String n2 = o2.getElementType().getName();
+				i = n1.compareTo(n2);
+				if (i != 0) {
+					return i;
+				}
+				IntegerValue l1 = o1.getLowerValue();
+				IntegerValue l2 = o2.getLowerValue();
+				i = l1.compareTo(l2);
+				if (i != 0) {
+					return i;
+				}
+				UnlimitedNaturalValue u1 = o1.getUpperValue();
+				UnlimitedNaturalValue u2 = o2.getUpperValue();
+				return u1.compareTo(u2);
+			}
+		};
+
+		protected final @NonNull Comparator<@NonNull Element> monikerComparator = new Comparator<@NonNull Element>()
+		{
+			@Override
+			public int compare(@NonNull Element o1, @NonNull Element o2) {
+				String m1 = getMoniker(o1);
+				String m2 = getMoniker(o2);
+				return m1.compareTo(m2);
+			}
+		};
+
+		protected final @NonNull Comparator<org.eclipse.ocl.pivot.@NonNull Package> packageComparator = new Comparator<org.eclipse.ocl.pivot.@NonNull Package>()
+		{
+			@Override
+			public int compare(org.eclipse.ocl.pivot.@NonNull Package o1, org.eclipse.ocl.pivot.@NonNull Package o2) {
+				String m1 = o1.getName();
+				String m2 = o2.getName();
+				if (PivotConstants.ORPHANAGE_NAME.equals(m1)) {
+					if (PivotConstants.ORPHANAGE_NAME.equals(m2)) {
+						return 0;
+					}
+					else {
+						return 1;
+					}
+				}
+				else{
+					if (PivotConstants.ORPHANAGE_NAME.equals(m2)) {
+						return -1;
+					}
+					else {
+						return m1.compareTo(m2);
+					}
+				}
+			}
+		};
+
+		private final @NonNull Map<@NonNull Element, @NonNull String> element2moniker = new HashMap<>();
+		private final @NonNull Map<org.eclipse.ocl.pivot.@NonNull Package, @NonNull List<org.eclipse.ocl.pivot.@NonNull Class>> package2sortedClasses = new HashMap<>();
+		private final @NonNull Map<org.eclipse.ocl.pivot.@NonNull Package, @NonNull List<@NonNull CollectionType>> package2sortedCollectionTypes = new HashMap<>();
+		private final @NonNull Map<org.eclipse.ocl.pivot.@NonNull Package, @NonNull List<@NonNull Enumeration>> package2sortedEnumerations = new HashMap<>();
+		private final @NonNull Map<org.eclipse.ocl.pivot.@NonNull Package, @NonNull List<@NonNull Iteration>> package2sortedIterations = new HashMap<>();
+		private final @NonNull Map<org.eclipse.ocl.pivot.@NonNull Package, @NonNull List<@NonNull MapType>> package2sortedMapTypes = new HashMap<>();
+		private final @NonNull Map<org.eclipse.ocl.pivot.@NonNull Package, @NonNull List<@NonNull Operation>> package2sortedOperations = new HashMap<>();
+		private final @NonNull Map<org.eclipse.ocl.pivot.@NonNull Package, @NonNull List<@NonNull PrimitiveType>> package2sortedPrimitiveTypes = new HashMap<>();
+		private final @NonNull Map<org.eclipse.ocl.pivot.@NonNull Package, @NonNull List<@NonNull Property>> package2sortedProperties = new HashMap<>();
+		private final @NonNull List<@NonNull Operation> sortedCoercions = new ArrayList<>();
+		private final @NonNull List<@NonNull Element> sortedCommentedElements = new ArrayList<>();
+		private final @NonNull List<@NonNull LambdaType> sortedLambdaTypes = new ArrayList<>();
+		private final @NonNull List<@NonNull Library> sortedLibraries = new ArrayList<>();
+		private final @NonNull List<@NonNull Library> sortedLibrariesWithPrecedence = new ArrayList<>();
+		private final @NonNull List<@NonNull Operation> sortedOperationsWithPrecedence = new ArrayList<>();
+		private final @NonNull List<org.eclipse.ocl.pivot.@NonNull Package> sortedPackages = new ArrayList<>();
+		private final @NonNull List<org.eclipse.ocl.pivot.@NonNull Class> sortedParameterTypes = new ArrayList<>();
+		private final @NonNull List<@NonNull TemplateParameter> sortedTemplateParameters = new ArrayList<>();
+		private final @NonNull List<@NonNull TemplateSignature> sortedTemplateSignatures = new ArrayList<>();
+		private final @NonNull List<@NonNull TemplateableElement> sortedTemplateableElements = new ArrayList<>();
+		private final @NonNull List<@NonNull TupleType> sortedTupleTypes = new ArrayList<>();
+		private final @NonNull Set<org.eclipse.ocl.pivot.@NonNull Class> internalClasses = new HashSet<>();
+		private final @NonNull Set<org.eclipse.ocl.pivot.@NonNull Class> externalClasses = new HashSet<>();
+		private final @NonNull Set<@NonNull NamedElement> allReferences = new HashSet<>();
+
+		protected ContentAnalysis(@NonNull GenerateOCLCommon context) {
+			super(context);
+		}
+
+		protected void analyze(@NonNull Model thisModel) {
+			for (NamedElement asElement : context.external2name.keySet()) {
+				if (asElement instanceof org.eclipse.ocl.pivot.Class) {
+					CompleteClassInternal completeClass = context.metamodelManager.getCompleteClass((org.eclipse.ocl.pivot.Class)asElement);
+					for (org.eclipse.ocl.pivot.@NonNull Class  asPartialClass : completeClass.getPartialClasses()) {
+						externalClasses.add(asPartialClass);
+					}
+				}
+			}
+			for (@NonNull EObject eObject : new TreeIterable(thisModel, true)) {
+				((Element)eObject).accept(this);
+			}
+			Collections.sort(sortedCoercions, monikerComparator);
+			Collections.sort(sortedCommentedElements, monikerComparator);
+			Collections.sort(sortedLambdaTypes, monikerComparator);
+			Collections.sort(sortedLibraries, monikerComparator);
+			Collections.sort(sortedLibrariesWithPrecedence, monikerComparator);
+			Collections.sort(sortedOperationsWithPrecedence, monikerComparator);
+			Collections.sort(sortedPackages, packageComparator);
+			Collections.sort(sortedParameterTypes, monikerComparator);
+			Collections.sort(sortedTupleTypes, monikerComparator);
+			Collections.sort(sortedTemplateParameters, monikerComparator);
+			Collections.sort(sortedTemplateSignatures, monikerComparator);
+			Collections.sort(sortedTemplateableElements, monikerComparator);
+
+			for (org.eclipse.ocl.pivot.@NonNull Package asPackage : PivotUtil.getOwnedPackages(thisModel)) {
+				List<org.eclipse.ocl.pivot.@NonNull Class> sortedClasses = package2sortedClasses.get(asPackage);
+				if (sortedClasses != null) {
+					Collections.sort(sortedClasses, NameUtil.NAMEABLE_COMPARATOR);
+				}
+				List<@NonNull CollectionType> sortedCollectionTypes = package2sortedCollectionTypes.get(asPackage);
+				if (sortedCollectionTypes != null) {
+					Collections.sort(sortedCollectionTypes, collectionTypeComparator);
+				}
+				List<@NonNull Enumeration> sortedEnumerations = package2sortedEnumerations.get(asPackage);
+				if (sortedEnumerations != null) {
+					Collections.sort(sortedEnumerations, NameUtil.NAMEABLE_COMPARATOR);
+				}
+				List<@NonNull Iteration> sortedIterations = package2sortedIterations.get(asPackage);
+				if (sortedIterations != null) {
+					Collections.sort(sortedIterations, monikerComparator);
+				}
+				List<@NonNull MapType> sortedMapTypes = package2sortedMapTypes.get(asPackage);
+				if (sortedMapTypes != null) {
+					Collections.sort(sortedMapTypes, monikerComparator);
+				}
+				List<@NonNull Operation> sortedOperations = package2sortedOperations.get(asPackage);
+				if (sortedOperations != null) {
+					Collections.sort(sortedOperations, monikerComparator);
+				}
+				List<@NonNull PrimitiveType> sortedPrimitiveTypes = package2sortedPrimitiveTypes.get(asPackage);
+				if (sortedPrimitiveTypes != null) {
+					Collections.sort(sortedPrimitiveTypes, NameUtil.NAMEABLE_COMPARATOR);
+				}
+				List<@NonNull Property> sortedProperties = package2sortedProperties.get(asPackage);
+				if (sortedProperties != null) {
+					Collections.sort(sortedProperties, classPropertyComparator);
+				}
+			}
+			if (allReferences.size() > 0) {
+				StandardLibrary standardLibrary = context.environmentFactory.getStandardLibrary();
+				allReferences.add(standardLibrary.getOclAnyType());
+				allReferences.add(standardLibrary.getOclElementType());
+			}
+			for (@NonNull NamedElement asNamedElement : allReferences) {
+				if (!internalClasses.contains(asNamedElement)) {
+					context.addExternalReference(asNamedElement, thisModel);
 				}
 			}
 		}
-	};
+
+		protected void doSuperClasses(org.eclipse.ocl.pivot.@NonNull Class asClass) {
+			for (org.eclipse.ocl.pivot.Class superClass : PivotUtil.getSuperClasses(asClass)) {
+				allReferences.add(superClass);
+			}
+		}
+
+		protected void doTemplateableElement(@NonNull TemplateableElement asTemplateableElement) {
+			if (asTemplateableElement.getOwnedBindings().size() > 0) {
+				sortedTemplateableElements.add(asTemplateableElement);
+			}
+			TemplateSignature asTemplateSignature = asTemplateableElement.getOwnedSignature();
+			if (asTemplateSignature != null) {
+				sortedTemplateParameters.addAll(asTemplateSignature.getOwnedParameters());
+			}
+			TemplateableElement unspecializedElement = asTemplateableElement.getUnspecializedElement();
+			if (unspecializedElement instanceof NamedElement) {
+				allReferences.add((NamedElement)unspecializedElement);
+			}
+		}
+
+		protected @NonNull String getMoniker(@NonNull Element elem) {
+			String moniker = element2moniker.get(elem);
+			if (moniker == null) {
+				moniker = AS2Moniker.toString(elem);
+				element2moniker.put(elem, moniker);
+			}
+			return moniker;
+		}
+
+		@Override
+		public @Nullable Object visiting(@NonNull Visitable visitable) {
+			System.out.println("Unsupported " + visitable.eClass().getName() + " for " + getClass().getSimpleName());
+			return null;
+		}
+
+		@Override
+		public @Nullable Object visitAnnotation(@NonNull Annotation asAnnotation) {
+			return null;
+		}
+
+		@Override
+		public @Nullable Object visitClass(org.eclipse.ocl.pivot.@NonNull Class asClass) {
+			org.eclipse.ocl.pivot.Package asPackage = asClass.getOwningPackage();
+			List<org.eclipse.ocl.pivot.@NonNull Class> sortedClasses = package2sortedClasses.get(asPackage);
+			if (sortedClasses == null) {
+				sortedClasses = new ArrayList<>();
+				package2sortedClasses.put(asPackage, sortedClasses);
+			}
+			sortedClasses.add(asClass);
+			if (asClass.isTemplateParameter() != null) {			// FIXME can never happen
+				sortedParameterTypes.add(asClass);
+			}
+			else if (!externalClasses.contains(asClass)){
+				CompleteClassInternal completeClass = context.metamodelManager.getCompleteClass(asClass);
+				for (org.eclipse.ocl.pivot.@NonNull Class  asPartialClass : completeClass.getPartialClasses()) {
+					internalClasses.add(asPartialClass);
+				}
+			}
+			doSuperClasses(asClass);
+			doTemplateableElement(asClass);
+			return null;
+		}
+
+		@Override
+		public @Nullable Object visitCollectionType(@NonNull CollectionType asCollectionType) {
+			org.eclipse.ocl.pivot.Package asPackage = asCollectionType.getOwningPackage();
+			List<@NonNull CollectionType> sortedCollectionTypes = package2sortedCollectionTypes.get(asPackage);
+			if (sortedCollectionTypes == null) {
+				sortedCollectionTypes = new ArrayList<>();
+				package2sortedCollectionTypes.put(asPackage, sortedCollectionTypes);
+			}
+			sortedCollectionTypes.add(asCollectionType);
+			doSuperClasses(asCollectionType);
+			doTemplateableElement(asCollectionType);
+			return null;
+		}
+
+		@Override
+		public @Nullable Object visitComment(@NonNull Comment asComment) {
+			Element owningElement = asComment.getOwningElement();
+			if (!externalClasses.contains(owningElement)) {
+				sortedCommentedElements.add(owningElement);
+			}
+			return null;
+		}
+
+		@Override
+		public @Nullable Object visitConstraint(@NonNull Constraint asConstraint) {
+			return null;
+		}
+
+		@Override
+		public @Nullable Object visitDetail(@NonNull Detail asDetail) {
+			return null;
+		}
+
+		@Override
+		public @Nullable Object visitEnumeration(@NonNull Enumeration asEnumeration) {
+			org.eclipse.ocl.pivot.Package asPackage = asEnumeration.getOwningPackage();
+			List<@NonNull Enumeration> sortedEnumerations = package2sortedEnumerations.get(asPackage);
+			if (sortedEnumerations == null) {
+				sortedEnumerations = new ArrayList<>();
+				package2sortedEnumerations.put(asPackage, sortedEnumerations);
+			}
+			sortedEnumerations.add(asEnumeration);
+			doSuperClasses(asEnumeration);
+			return null;
+		}
+
+		@Override
+		public @Nullable Object visitEnumerationLiteral(@NonNull EnumerationLiteral asEnumerationLiteral) {
+			return null;
+		}
+
+		@Override
+		public @Nullable Object visitImport(@NonNull Import asImport) {
+			allReferences.add(asImport.getImportedNamespace());
+			return null;
+		}
+
+		@Override
+		public @Nullable Object visitIteration(@NonNull Iteration asIteration) {
+			org.eclipse.ocl.pivot.Class asClass = asIteration.getOwningClass();
+			org.eclipse.ocl.pivot.Package asPackage = asClass.getOwningPackage();
+			List<@NonNull Iteration> sortedIterations = package2sortedIterations.get(asPackage);
+			if (sortedIterations == null) {
+				sortedIterations = new ArrayList<>();
+				package2sortedIterations.put(asPackage, sortedIterations);
+			}
+			sortedIterations.add(asIteration);
+			doTemplateableElement(asIteration);
+			return super.visitIteration(asIteration);
+		}
+
+		@Override
+		public @Nullable Object visitLambdaType(@NonNull LambdaType asLambdaType) {
+			sortedLambdaTypes.add(asLambdaType);
+			doSuperClasses(asLambdaType);
+			return null;
+		}
+
+		@Override
+		public @Nullable Object visitLibrary(@NonNull Library asLibrary) {
+			sortedLibraries.add(asLibrary);
+			if (asLibrary.getOwnedPrecedences().size() > 0) {
+				sortedLibrariesWithPrecedence.add(asLibrary);
+			}
+			return super.visitLibrary(asLibrary);
+		}
+
+		@Override
+		public @Nullable Object visitMapType(@NonNull MapType asMapType) {
+			org.eclipse.ocl.pivot.Package asPackage = asMapType.getOwningPackage();
+			List<@NonNull MapType> sortedMapTypes = package2sortedMapTypes.get(asPackage);
+			if (sortedMapTypes == null) {
+				sortedMapTypes = new ArrayList<>();
+				package2sortedMapTypes.put(asPackage, sortedMapTypes);
+			}
+			sortedMapTypes.add(asMapType);
+			doTemplateableElement(asMapType);
+			doSuperClasses(asMapType);
+			return null;
+		}
+
+		@Override
+		public @Nullable Object visitModel(@NonNull Model asModel) {
+			return null;
+		}
+
+		@Override
+		public @Nullable Object visitOperation(@NonNull Operation asOperation) {
+			if (!(asOperation instanceof Iteration)) {
+				org.eclipse.ocl.pivot.Class asClass = asOperation.getOwningClass();
+				org.eclipse.ocl.pivot.Package asPackage = asClass.getOwningPackage();
+				List<@NonNull Operation> sortedOperations = package2sortedOperations.get(asPackage);
+				if (sortedOperations == null) {
+					sortedOperations = new ArrayList<>();
+					package2sortedOperations.put(asPackage, sortedOperations);
+				}
+				sortedOperations.add(asOperation);
+				if (/*!context.isEcoreConstraint(asOperation) &&*/ (asOperation.getPrecedence() != null)) {
+					sortedOperationsWithPrecedence.add(asOperation);
+				}
+				doTemplateableElement(asOperation);
+			}
+			return super.visitOperation(asOperation);
+		}
+
+		@Override
+		public @Nullable Object visitPackage(org.eclipse.ocl.pivot.@NonNull Package asPackage) {
+			sortedPackages.add(asPackage);
+			return null;
+		}
+
+		@Override
+		public @Nullable Object visitPrecedence(@NonNull Precedence asPrecedence) {
+			return null;
+		}
+
+		@Override
+		public @Nullable Object visitPrimitiveType(final @NonNull PrimitiveType asPrimitiveType) {
+			org.eclipse.ocl.pivot.Package asPackage = asPrimitiveType.getOwningPackage();
+			List<@NonNull PrimitiveType> sortedPrimitiveTypes = package2sortedPrimitiveTypes.get(asPackage);
+			if (sortedPrimitiveTypes == null) {
+				sortedPrimitiveTypes = new ArrayList<>();
+				package2sortedPrimitiveTypes.put(asPackage, sortedPrimitiveTypes);
+			}
+			sortedPrimitiveTypes.add(asPrimitiveType);
+			sortedCoercions.addAll(asPrimitiveType.getCoercions());
+			doSuperClasses(asPrimitiveType);
+			return null;
+		}
+
+		@Override
+		public @Nullable Object visitProperty(@NonNull Property asProperty) {
+			org.eclipse.ocl.pivot.Class asClass = asProperty.getOwningClass();
+			if (!(asClass instanceof TupleType)) {
+				org.eclipse.ocl.pivot.Package asPackage = asClass.getOwningPackage();
+				List<@NonNull Property> sortedProperties = package2sortedProperties.get(asPackage);
+				if (sortedProperties == null) {
+					sortedProperties = new ArrayList<>();
+					package2sortedProperties.put(asPackage, sortedProperties);
+				}
+				sortedProperties.add(asProperty);
+				Property asOpposite = asProperty.getOpposite();
+				if (asOpposite != null) {
+					if (PivotUtil.getContainingModel(asOpposite) == PivotUtil.getContainingModel(asProperty)) {
+						allReferences.add(asOpposite);
+					}
+					allReferences.add(asOpposite.getType());
+				}
+			}
+			return super.visitProperty(asProperty);
+		}
+
+		@Override
+		public @Nullable Object visitTemplateBinding(@NonNull TemplateBinding asTemplateBinding) {
+			return null;
+		}
+
+		@Override
+		public @Nullable Object visitTemplateParameter(@NonNull TemplateParameter asTemplateParameter) {
+			return null;
+		}
+
+		@Override
+		public @Nullable Object visitTemplateParameterSubstitution(@NonNull TemplateParameterSubstitution asTemplateParameterSubstitution) {
+			allReferences.add(asTemplateParameterSubstitution.getActual());
+			allReferences.add(asTemplateParameterSubstitution.getFormal());
+			return null;
+		}
+
+		@Override
+		public @Nullable Object visitTemplateSignature(@NonNull TemplateSignature asTemplateSignature) {
+			sortedTemplateSignatures.add(asTemplateSignature);
+			return null;
+		}
+
+		@Override
+		public @Nullable Object visitTupleType(@NonNull TupleType asTupleType) {
+			sortedTupleTypes.add(asTupleType);
+			doSuperClasses(asTupleType);
+			return null;
+		}
+
+		@Override
+		public @Nullable Object visitTypedElement(@NonNull TypedElement asTypedElement) {
+			allReferences.add(asTypedElement.getType());
+			return null;
+		}
+	}
+
+	private final @NonNull Map<@NonNull NamedElement, @NonNull String> external2name = new HashMap<>();
+	protected final @NonNull Map<@NonNull String, @NonNull NamedElement> name2external = new HashMap<>();
+	protected final @NonNull Map<@NonNull String, @NonNull String> generatedClassNameMap = new HashMap<>();
+	protected EnvironmentFactoryInternal environmentFactory;
+	protected PivotMetamodelManager metamodelManager;
+	protected NameQueries nameQueries;
+	protected Model thisModel;
+	private List<@NonNull Element> orphans;
+	protected final @NonNull ContentAnalysis contentAnalysis = createContentAnalysis();
 
 	protected final @NonNull Comparator<@NonNull Comment> commentComparator = new Comparator<@NonNull Comment>()
 	{
@@ -158,51 +611,6 @@
 		}
 	};
 
-	protected final @NonNull Comparator<@NonNull Element> monikerComparator = new Comparator<@NonNull Element>()
-	{
-		@Override
-		public int compare(@NonNull Element o1, @NonNull Element o2) {
-			String m1 = getMoniker(o1);
-			String m2 = getMoniker(o2);
-			return m1.compareTo(m2);
-		}
-	};
-
-	protected final @NonNull Comparator<@NonNull Nameable> nameableComparator = new Comparator<@NonNull Nameable>()
-	{
-		@Override
-		public int compare(@NonNull Nameable o1, @NonNull Nameable o2) {
-			String m1 = o1.getName();
-			String m2 = o2.getName();
-			return m1.compareTo(m2);
-		}
-	};
-
-	protected final @NonNull Comparator<@NonNull Package> packageComparator = new Comparator<@NonNull Package>()
-	{
-		@Override
-		public int compare(@NonNull Package o1, @NonNull Package o2) {
-			String m1 = o1.getName();
-			String m2 = o2.getName();
-			if (PivotConstants.ORPHANAGE_NAME.equals(m1)) {
-				if (PivotConstants.ORPHANAGE_NAME.equals(m2)) {
-					return 0;
-				}
-				else {
-					return 1;
-				}
-			}
-			else{
-				if (PivotConstants.ORPHANAGE_NAME.equals(m2)) {
-					return -1;
-				}
-				else {
-					return m1.compareTo(m2);
-				}
-			}
-		}
-	};
-
 	protected final @NonNull Comparator<@NonNull EObject> symbolNameComparator = new Comparator<@NonNull EObject>()
 	{
 		@Override
@@ -218,14 +626,18 @@
 			return;
 		}
 		Model containingModel = PivotUtil.getContainingModel(reference);
-		if ((containingModel == root) || external2name.containsKey(reference)) {
+		if ((containingModel == root) || external2name.containsKey(reference) || Orphanage.isOrphanage(containingModel)) {
 			return;
 		}
 		if (reference instanceof Model) {
 			return;
 		}
+		if (contentAnalysis.internalClasses.contains(reference)) {
+			return;
+		}
 		//		boolean hasComplements = false;
 		if (reference instanceof Type) {
+			assert !"Annotation".equals(reference.getName());
 			//			hasComplements = hasComplements((Type) reference);
 		/*	The following now loads existing classes when we are generating new ones for GeneratePivotModel.
 		 * EnvironmentFactoryInternal environmentFactory = PivotUtilInternal.findEnvironmentFactory(reference);
@@ -297,7 +709,11 @@
 		generatedClassNameMap.put(mapping.getFrom(), mapping.getTo());
 	}
 
-	protected String declarePackageImport(@NonNull Package elem) {
+	protected @NonNull ContentAnalysis createContentAnalysis() {
+		return new ContentAnalysis(this);
+	}
+
+	protected String declarePackageImport(org.eclipse.ocl.pivot.@NonNull Package elem) {
 		//		String generatedClassName = getGeneratedClassName(elem);
 		//		if (generatedClassName != null) {
 		//			return null;//"import " + generatedClassName + ";";
@@ -311,198 +727,13 @@
 
 	protected org.eclipse.ocl.pivot.Package findPackage(Iterable<org.eclipse.ocl.pivot.Package> packages) {
 		for (org.eclipse.ocl.pivot.Package pkg : packages) {
-			if (!"$$".equals(pkg.getName())) {
+			if (!PivotConstants.ORPHANAGE_NAME.equals(pkg.getName())) {
 				return pkg;
 			}
 		}
 		return null;
 	}
 
-	protected @NonNull Set<CollectionType> getAllCollectionTypes(@NonNull Model root) {
-		Set<CollectionType> allElements = new HashSet<>();
-		TreeIterator<EObject> tit = root.eAllContents();
-		while (tit.hasNext()) {
-			EObject eObject = tit.next();
-			if (eObject instanceof CollectionType) {
-				allElements.add((CollectionType)eObject);
-			}
-		}
-		return allElements;
-	}
-
-	protected @NonNull Set<Enumeration> getAllEnumerations(@NonNull Model root) {
-		Set<Enumeration> allElements = new HashSet<>();
-		TreeIterator<EObject> tit = root.eAllContents();
-		while (tit.hasNext()) {
-			EObject eObject = tit.next();
-			if (eObject instanceof Enumeration) {
-				allElements.add((Enumeration)eObject);
-			}
-		}
-		return allElements;
-	}
-
-	protected @NonNull Set<LambdaType> getAllLambdaTypes(@NonNull Model root) {
-		Set<LambdaType> allElements = new HashSet<>();
-		TreeIterator<EObject> tit = root.eAllContents();
-		while (tit.hasNext()) {
-			EObject eObject = tit.next();
-			if (eObject instanceof LambdaType) {
-				allElements.add((LambdaType)eObject);
-			}
-		}
-		return allElements;
-	}
-
-	protected @NonNull Set<MapType> getAllMapTypes(@NonNull Model root) {
-		Set<MapType> allElements = new HashSet<>();
-		TreeIterator<EObject> tit = root.eAllContents();
-		while (tit.hasNext()) {
-			EObject eObject = tit.next();
-			if (eObject instanceof MapType) {
-				allElements.add((MapType)eObject);
-			}
-		}
-		return allElements;
-	}
-
-	protected @NonNull List<org.eclipse.ocl.pivot.Package> getAllPackages(@NonNull Model root) {
-		Set<org.eclipse.ocl.pivot.Package> allElements = new HashSet<>();
-		TreeIterator<EObject> tit = root.eAllContents();
-		while (tit.hasNext()) {
-			EObject eObject = tit.next();
-			if (eObject instanceof org.eclipse.ocl.pivot.Package) {
-				allElements.add((org.eclipse.ocl.pivot.Package)eObject);
-			}
-		}
-		List<org.eclipse.ocl.pivot.Package> sortedElements = new ArrayList<>(allElements);
-		Collections.sort(sortedElements, monikerComparator);
-		return sortedElements;
-	}
-
-	protected @NonNull Set<Precedence> getAllPrecedences(@NonNull Model root) {
-		Set<Precedence> allElements = new HashSet<>();
-		TreeIterator<EObject> tit = root.eAllContents();
-		while (tit.hasNext()) {
-			EObject eObject = tit.next();
-			if (eObject instanceof Precedence) {
-				allElements.add((Precedence)eObject);
-			}
-		}
-		return allElements;
-	}
-
-	protected @NonNull Set<PrimitiveType> getAllPrimitiveTypes(@NonNull Model root) {
-		Set<PrimitiveType> allElements = new HashSet<>();
-		TreeIterator<EObject> tit = root.eAllContents();
-		while (tit.hasNext()) {
-			EObject eObject = tit.next();
-			if (eObject instanceof PrimitiveType) {
-				allElements.add((PrimitiveType)eObject);
-			}
-		}
-		return allElements;
-	}
-
-	protected @NonNull List<Property> getAllProperties(@NonNull Model root) {
-		List<Property> allElements = new ArrayList<>();
-		TreeIterator<EObject> tit = root.eAllContents();
-		while (tit.hasNext()) {
-			EObject eObject = tit.next();
-			if ((eObject instanceof Property) && !(eObject.eContainer() instanceof TupleType) &&
-					(((Property)eObject).getOwningClass() != null)) {
-				allElements.add((Property)eObject);
-			}
-		}
-		return allElements;
-	}
-
-	protected @NonNull Set<TemplateBinding> getAllTemplateBindings(@NonNull Model root) {
-		Set<TemplateBinding> allElements = new HashSet<>();
-		TreeIterator<EObject> tit = root.eAllContents();
-		while (tit.hasNext()) {
-			EObject eObject = tit.next();
-			if (eObject instanceof TemplateBinding) {
-				allElements.add((TemplateBinding)eObject);
-			}
-		}
-		return allElements;
-	}
-
-	protected @NonNull Set<TemplateSignature> getAllTemplateSignatures(@NonNull Model root) {
-		Set<TemplateSignature> allElements = new HashSet<>();
-		TreeIterator<EObject> tit = root.eAllContents();
-		while (tit.hasNext()) {
-			EObject eObject = tit.next();
-			if (eObject instanceof TemplateSignature) {
-				allElements.add((TemplateSignature)eObject);
-			}
-		}
-		return allElements;
-	}
-
-	protected @NonNull Set<TupleType> getAllTupleTypes(@NonNull Model root) {
-		Set<TupleType> allElements = new HashSet<>();
-		TreeIterator<EObject> tit = root.eAllContents();
-		while (tit.hasNext()) {
-			EObject eObject = tit.next();
-			if (eObject instanceof TupleType) {
-				allElements.add((TupleType)eObject);
-			}
-		}
-		return allElements;
-	}
-
-	protected @NonNull Set<org.eclipse.ocl.pivot.Class> getAllTypes(@NonNull Model root) {
-		Set<org.eclipse.ocl.pivot.Class> allElements = new HashSet<>();
-		TreeIterator<EObject> tit = root.eAllContents();
-		while (tit.hasNext()) {
-			EObject eObject = tit.next();
-			if (eObject instanceof org.eclipse.ocl.pivot.Class) {
-				allElements.add((org.eclipse.ocl.pivot.Class)eObject);
-			}
-		}
-		return allElements;
-	}
-
-	protected @Nullable List<org.eclipse.ocl.pivot.Class> getClassTypes(@NonNull Package pkge) {
-		List<org.eclipse.ocl.pivot.Class> classTypes = null;
-		for (org.eclipse.ocl.pivot.Class type : pkge.getOwnedClasses()) {
-			boolean useIt = false;
-			if (type instanceof CollectionType) {
-				useIt = false;
-			}
-			else if (type instanceof Enumeration) {
-				useIt = false;
-			}
-			else if (type instanceof LambdaType) {
-				useIt = false;
-			}
-			else if (type instanceof MapType) {
-				useIt = false;
-			}
-			else if (type instanceof PrimitiveType) {
-				useIt = false;
-			}
-			else if (type instanceof TupleType) {
-				useIt = false;
-			}
-			else if (type.isTemplateParameter() != null) {
-				useIt = false;
-			}
-			else {
-				useIt = true;
-			}
-			if (useIt) {
-				if (classTypes == null) {
-					classTypes = new ArrayList<>();
-				}
-				classTypes.add(type);
-			}
-		}
-		return classTypes;
-	}
-
 	protected String getEcoreLiteral(org.eclipse.ocl.pivot.@NonNull Class elem) {
 		return nameQueries.getEcoreLiteral(elem);
 	}
@@ -545,86 +776,16 @@
 		return "\"" + EcoreUtil.getURI(element).toString() + "\"";
 	}
 
-	protected void getExternals(@NonNull Model root) {
-		Set<org.eclipse.ocl.pivot.Class> internalTypes = new HashSet<>();
-		for (org.eclipse.ocl.pivot.Package pkge : root.getOwnedPackages()) {
-			List<org.eclipse.ocl.pivot.Class> classTypes = getClassTypes(pkge);
-			if (classTypes != null) {
-				for (org.eclipse.ocl.pivot.Class classType : classTypes) {
-					for (org.eclipse.ocl.pivot.Class  partialClass : metamodelManager.getCompleteClass(classType).getPartialClasses()) {
-						internalTypes.add(partialClass);
-					}
-				}
-			}
-		}
-		Set<Element> allReferences = new HashSet<>();
-		TreeIterator<EObject> tit = root.eAllContents();
-		while (tit.hasNext()) {
-			EObject eObject = tit.next();
-			if (eObject instanceof CollectionType) {
-				CollectionType collectionType = (CollectionType)eObject;
-				addExternalReference(collectionType, root);
-				TemplateableElement unspecializedElement = collectionType.getUnspecializedElement();
-				if (unspecializedElement instanceof NamedElement) {
-					addExternalReference((NamedElement) unspecializedElement, root);
-				}
-			}
-			else if (eObject instanceof TemplateParameterSubstitution) {
-				TemplateParameterSubstitution templateParameterSubstitution = (TemplateParameterSubstitution)eObject;
-				addExternalReference(templateParameterSubstitution.getActual(), root);
-				addExternalReference(templateParameterSubstitution.getFormal(), root);
-			}
-			else if (eObject instanceof Import) {
-				Import asImport = (Import)eObject;
-				addExternalReference(asImport.getImportedNamespace(), root);
-			}
-			else if (eObject instanceof TypedElement) {
-				TypedElement typedElement = (TypedElement)eObject;
-				Type type = typedElement.getType();
-				if (!internalTypes.contains(type)) {
-					addExternalReference(type, root);
-				}
-				if (eObject instanceof Property) {
-					Property property = (Property)eObject;
-					Property opposite = property.getOpposite();
-					if (opposite != null) {
-						if (PivotUtil.getContainingModel(opposite) == PivotUtil.getContainingModel(property)) {
-							addExternalReference(opposite, root);
-						}
-						Type oppositeType = opposite.getType();
-						if (!internalTypes.contains(oppositeType)) {
-							addExternalReference(oppositeType, root);
-						}
-					}
-				}
-			}
-		}
-		if (name2external.size() > 0) {
-			StandardLibraryInternal standardLibrary = environmentFactory.getStandardLibrary();
-			addExternalReference(standardLibrary.getOclAnyType(), root);
-			addExternalReference(standardLibrary.getOclElementType(), root);
-		}
-	}
-
 	protected @Nullable String getGeneratedClassName(EObject eObject) {
-		return (eObject instanceof Package) ? generatedClassNameMap.get(((Package)eObject).getURI()) : null;
+		return (eObject instanceof org.eclipse.ocl.pivot.Package) ? generatedClassNameMap.get(((org.eclipse.ocl.pivot.Package)eObject).getURI()) : null;
 	}
 
-	protected @NonNull String getGeneratedPackageId(@NonNull Package pkge) {
+	protected @NonNull String getGeneratedPackageId(org.eclipse.ocl.pivot.@NonNull Package pkge) {
 		PackageId basicPackageId = ((PackageImpl)pkge).basicGetPackageId();
 		return basicPackageId == IdManager.METAMODEL ? "IdManager.METAMODEL" : "null";
 	}
 
 
-	protected @NonNull String getMoniker(@NonNull Element elem) {
-		String moniker = element2moniker.get(elem);
-		if (moniker == null) {
-			moniker = AS2Moniker.toString(elem);
-			element2moniker.put(elem, moniker);
-		}
-		return moniker;
-	}
-
 	protected @NonNull String getNameLiteral(@NonNull Operation operation) {
 		return '"' + operation.getName() + '"';
 	}
@@ -637,13 +798,13 @@
 		return getOrphanPackage(getRootPackage(elem));
 	}
 
-	protected org.eclipse.ocl.pivot.@Nullable Package getOrphanPackage(@NonNull Model elem) {
-		for (org.eclipse.ocl.pivot.Package pkg : getAllPackages(elem)) {
+	protected org.eclipse.ocl.pivot.@NonNull Package getOrphanPackage(@NonNull Model elem) {
+		for (org.eclipse.ocl.pivot.@NonNull Package pkg : PivotUtil.getOwnedPackages(elem)) {
 			if (PivotConstants.ORPHANAGE_NAME.equals(pkg.getName())) {
 				return pkg;
 			}
 		}
-		return null;
+		throw new IllegalStateException();
 	}
 
 	protected @NonNull String getPartialName(@NonNull Property property) {
@@ -664,20 +825,11 @@
 		}
 	}
 
-	protected String getPrefixedSymbolName(@NonNull EObject elem, @NonNull String prefix) {
-		if (!(elem instanceof org.eclipse.ocl.pivot.Package)) {
-			if (!((elem instanceof Type) && hasComplements((Type)elem))) {
-				elem = metamodelManager.getPrimaryElement(elem);
-			}
-		}
-		String prefixedSymbolName = nameQueries.getPrefixedSymbolName(prefix.replace(".",  "_"), elem);
-		if (prefixedSymbolName.startsWith("_Variable")) {
-			getClass();
-		}
-		return prefixedSymbolName;
+	protected @NonNull String getPrefixedSymbolName(@NonNull EObject elem, @NonNull String prefix) {
+		return nameQueries.getPrefixedSymbolName(prefix.replace(".",  "_"), elem);
 	}
 
-	protected String getPrefixedSymbolNameWithoutNormalization(org.eclipse.ocl.pivot.@NonNull Class type, @NonNull String prefix) {
+	protected @NonNull String getPrefixedSymbolNameWithoutNormalization(org.eclipse.ocl.pivot.@NonNull Class type, @NonNull String prefix) {
 		CompleteClass completeClass = metamodelManager.getCompleteClass(type);
 		org.eclipse.ocl.pivot.@NonNull Class primaryType = completeClass.getPrimaryClass();
 		String normalizedSymbol = nameQueries.basicGetSymbolName(completeClass);
@@ -711,7 +863,7 @@
 		}
 	}
 
-	protected String getSignature(@NonNull Operation elem) {
+	protected @NonNull String getSignature(@NonNull Operation elem) {
 		EObject parent = elem.eContainer();
 		if (parent != null) {
 			return getSignature((NamedElement)parent) + "::" + elem.getName() + "()";
@@ -720,153 +872,51 @@
 		}
 	}
 
-	protected @NonNull List<Operation> getSortedCoercions(@NonNull Model root) {
-		Set<Operation> allElements = new HashSet<>();
-		TreeIterator<EObject> tit = root.eAllContents();
-		while (tit.hasNext()) {
-			EObject eObject = tit.next();
-			if (eObject instanceof PrimitiveType) {
-				allElements.addAll(((PrimitiveType)eObject).getCoercions());
-			}
-		}
-		List<Operation> sortedElements = new ArrayList<>(allElements);
-		Collections.sort(sortedElements, monikerComparator);
-		return sortedElements;
+	protected @NonNull List<@NonNull Operation> getSortedCoercions(@NonNull Model root) {
+		return contentAnalysis.sortedCoercions;
 	}
 
-	protected @NonNull List<Operation> getSortedCoercions(@NonNull PrimitiveType type, @NonNull List<Operation> allCoercions) {
-		Set<Operation> allElements = new HashSet<>();
+	protected @NonNull List<@NonNull Operation> getSortedCoercions(@NonNull PrimitiveType type, @NonNull List<@NonNull Operation> allCoercions) {
+		Set<@NonNull Operation> allElements = new HashSet<>();
 		for (Operation coercion : type.getCoercions()) {
 			if (allCoercions.contains(coercion)) {
 				allElements.add(coercion);
 			}
 		}
-		List<Operation> sortedElements = new ArrayList<Operation>(allElements);
-		Collections.sort(sortedElements, monikerComparator);
+		List<@NonNull Operation> sortedElements = new ArrayList<>(allElements);
+		Collections.sort(sortedElements, contentAnalysis.monikerComparator);
 		return sortedElements;
 	}
 
-	protected @NonNull Map<org.eclipse.ocl.pivot.Package, List<org.eclipse.ocl.pivot.Class>> getSortedClassTypes(@NonNull Model root) {
-		Map<org.eclipse.ocl.pivot.Package, List<org.eclipse.ocl.pivot.Class>> pkge2classTypes = new HashMap<>();
-		for (org.eclipse.ocl.pivot.Package pkge : root.getOwnedPackages()) {
-			List<org.eclipse.ocl.pivot.Class> classTypes = getClassTypes(pkge);
-			if (classTypes != null) {
-				pkge2classTypes.put(pkge, classTypes);
-				Collections.sort(classTypes, monikerComparator);
-			}
-		}
-		return pkge2classTypes;
+	protected @NonNull Map<org.eclipse.ocl.pivot.@NonNull Package, @NonNull List<org.eclipse.ocl.pivot.@NonNull Class>> getSortedClassTypes(@NonNull Model root) {
+		return contentAnalysis.package2sortedClasses;
 	}
 
-	protected abstract @NonNull Map<org.eclipse.ocl.pivot.Package, List<CollectionType>> getSortedCollectionTypes(@NonNull Model root);
+	protected abstract @NonNull Map<org.eclipse.ocl.pivot.@NonNull Package, @NonNull List<@NonNull CollectionType>> getSortedCollectionTypes(@NonNull Model root);
 
-	protected @NonNull Map<org.eclipse.ocl.pivot.Package, List<CollectionType>> getSortedCollectionTypes(@NonNull Model root, Comparator<? super CollectionType> comparator) {
-		Map<org.eclipse.ocl.pivot.Package, List<CollectionType>> pkge2collectionTypes = new HashMap<>();
-		for (org.eclipse.ocl.pivot.Package pkge : root.getOwnedPackages()) {
-			List<CollectionType> collectionTypes = null;
-			for (Type type : pkge.getOwnedClasses()) {
-				if (type instanceof CollectionType) {
-					if (collectionTypes == null) {
-						collectionTypes = new ArrayList<>();
-						pkge2collectionTypes.put(pkge, collectionTypes);
-					}
-					collectionTypes.add((CollectionType)type);
-				}
-				/*				else if (type instanceof org.eclipse.ocl.pivot.Class) {		// FIXME fails because Orphanage has no Model
-					for (Property property : ((org.eclipse.ocl.pivot.Class)type).getOwnedProperties()) {
-						Property opposite = property.getOpposite();
-						if (opposite != null) {
-							Type oppositeType = opposite.getType();
-							if (oppositeType instanceof CollectionType) {
-								if (collectionTypes == null) {
-									collectionTypes = new ArrayList<>();
-									pkge2collectionTypes.put(pkge, collectionTypes);
-								}
-								collectionTypes.add((CollectionType)oppositeType);
-							}
-						}
-					}
-				} */
-			}
-			if (collectionTypes != null) {
-				Collections.sort(collectionTypes, comparator);
-			}
-		}
-		return pkge2collectionTypes;
+	protected @NonNull Map<org.eclipse.ocl.pivot.@NonNull Package, @NonNull List<@NonNull CollectionType>> getSortedCollectionTypes(@NonNull Model root, Comparator<@NonNull ? super CollectionType> comparator) {
+		return contentAnalysis.package2sortedCollectionTypes;
 	}
 
-	/*	protected @NonNull List<Element> getSortedCommentedElements(@NonNull Model root) {
-		List<Element> allClassTypes = new ArrayList<>();
-		for (org.eclipse.ocl.pivot.Package pkge : root.getOwnedPackages()) {
-			List<org.eclipse.ocl.pivot.Class> classTypes = getClassTypes(pkge);
-			if (classTypes != null) {
-				allClassTypes.addAll(classTypes);
-			}
-		}
-		Collections.sort(allClassTypes, monikerComparator);
-		return allClassTypes;
-	}*/
-	protected @NonNull List<Element> getSortedCommentedElements(@NonNull Model root) {
-		List<org.eclipse.ocl.pivot.Class> allClassTypes = new ArrayList<>();
-		for (org.eclipse.ocl.pivot.Package pkge : root.getOwnedPackages()) {
-			List<org.eclipse.ocl.pivot.Class> classTypes = getClassTypes(pkge);
-			if (classTypes != null) {
-				allClassTypes.addAll(classTypes);
-			}
-		}
-		Collection<org.eclipse.ocl.pivot.Class> oclTypes = allClassTypes;
-		Set<Element> allElements = new HashSet<>();
-		TreeIterator<EObject> tit = root.eAllContents();
-		while (tit.hasNext()) {
-			EObject eObject = tit.next();
-			if ((eObject instanceof Element) && !(eObject instanceof Constraint) &&
-					!((eObject instanceof Property) && (((Property)eObject).getOwningClass() == null)) &&
-					!((eObject instanceof org.eclipse.ocl.pivot.Class) && !oclTypes.contains(eObject))) {
-				Element t = (Element)eObject;
-				if (t.getOwnedComments().size() > 0) {
-					allElements.add(t);
-				}
-			}
-		}
-		List<Element> sortedElements = new ArrayList<>(allElements);
-		Collections.sort(sortedElements, monikerComparator);
-		return sortedElements;
+	protected @NonNull List<@NonNull Element> getSortedCommentedElements(@NonNull Model root) {
+		return contentAnalysis.sortedCommentedElements;
 	}
 
-	protected @NonNull List<Comment> getSortedComments(@NonNull Element element) {
+	protected @NonNull List<@NonNull Comment> getSortedComments(@NonNull Element element) {
 		List<Comment> sortedElements = new ArrayList<>(element.getOwnedComments());
 		Collections.sort(sortedElements, commentComparator);
 		return sortedElements;
 	}
 
-	protected @NonNull Map<org.eclipse.ocl.pivot.Package, List<Enumeration>> getSortedEnumerations(@NonNull Model root) {
-		Map<org.eclipse.ocl.pivot.Package, List<Enumeration>> pkge2enumerations = new HashMap<>();
-		for (org.eclipse.ocl.pivot.Package pkge : root.getOwnedPackages()) {
-			List<Enumeration> enumerations = null;
-			for (Type type : pkge.getOwnedClasses()) {
-				if (type instanceof Enumeration) {
-					if (enumerations == null) {
-						enumerations = new ArrayList<>();
-						pkge2enumerations.put(pkge, enumerations);
-					}
-					enumerations.add((Enumeration)type);
-				}
-			}
-			if (enumerations != null) {
-				Collections.sort(enumerations, nameableComparator);
-			}
-		}
-		return pkge2enumerations;
+	protected @NonNull Map<org.eclipse.ocl.pivot.@NonNull Package, @NonNull List<@NonNull Enumeration>> getSortedEnumerations(@NonNull Model root) {
+		return contentAnalysis.package2sortedEnumerations;
 	}
 
-	protected @NonNull List<Package> getSortedExternalPackages(@NonNull Model root) {
-		if (name2external.size() <= 0) {
-			getExternals(root);
-		}
-		List<Package> externalPackages = new ArrayList<>(root.getOwnedPackages());
+	protected @NonNull List<org.eclipse.ocl.pivot.@NonNull Package> getSortedExternalPackages(@NonNull Model root) {
+		List<org.eclipse.ocl.pivot.@NonNull Package> externalPackages = new ArrayList<>(root.getOwnedPackages());
 		for (Import asImport : root.getOwnedImports()) {
 			Namespace importedNamespace = asImport.getImportedNamespace();
-			Package externalPackage = PivotUtil.getContainingPackage(importedNamespace);
+			org.eclipse.ocl.pivot.Package externalPackage = PivotUtil.getContainingPackage(importedNamespace);
 			if (externalPackage != null) {
 				if (!externalPackages.contains(externalPackage)) {
 					externalPackages.add(externalPackage);
@@ -874,7 +924,7 @@
 			}
 		}
 		for (Element element : name2external.values()) {
-			Package externalPackage = PivotUtil.getContainingPackage(element);
+			org.eclipse.ocl.pivot.Package externalPackage = PivotUtil.getContainingPackage(element);
 			if (externalPackage != null) {
 				if (!externalPackages.contains(externalPackage)) {
 					externalPackages.add(externalPackage);
@@ -882,15 +932,12 @@
 			}
 		}
 		if (externalPackages.size() > 1) {
-			Collections.sort(externalPackages, packageComparator);
+			Collections.sort(externalPackages, contentAnalysis.packageComparator);
 		}
 		return externalPackages;
 	}
 
 	protected @NonNull List<String> getSortedExternals(@NonNull Model root) {
-		if (name2external.size() <= 0) {
-			getExternals(root);
-		}
 		List<NamedElement> sortedExternals = new ArrayList<>(name2external.values());
 		Collections.sort(sortedExternals, externalComparator);
 		List<String> sortedExternalNames = new ArrayList<>(sortedExternals.size());
@@ -900,18 +947,15 @@
 		return sortedExternalNames;
 	}
 
-	protected @NonNull Map<Package,String> getSortedImports(@NonNull Model model) {
-		if (name2external.size() <= 0) {
-			getExternals(model);
-		}
-		Map<Package,String> import2alias = new HashMap<>();
+	protected @NonNull Map<org.eclipse.ocl.pivot.@NonNull Package,String> getSortedImports(@NonNull Model model) {
+		Map<org.eclipse.ocl.pivot.@NonNull Package,String> import2alias = new HashMap<>();
 		for (Import asImport : model.getOwnedImports()) {
 			Namespace importedNamespace = asImport.getImportedNamespace();
-			if (importedNamespace instanceof Package) {
-				import2alias.put((Package)importedNamespace, asImport.getName());
+			if (importedNamespace instanceof org.eclipse.ocl.pivot.Package) {
+				import2alias.put((org.eclipse.ocl.pivot.Package)importedNamespace, asImport.getName());
 			}
 		}
-		for (Map.Entry<String, NamedElement> entry : name2external.entrySet()) {
+		for (Map.Entry<@NonNull String, @NonNull NamedElement> entry : name2external.entrySet()) {
 			NamedElement value = entry.getValue();
 			if ((value instanceof Library) && !import2alias.containsKey(value)) {
 				import2alias.put((Library)value, null);
@@ -920,421 +964,126 @@
 		return import2alias;
 	}
 
-
-	/*	protected @NonNull List<Iteration> getSortedIterations(@NonNull Model root) {
-		Set<Iteration> allElements = new HashSet<>();
-		TreeIterator<EObject> tit = root.eAllContents();
-		while (tit.hasNext()) {
-			EObject eObject = tit.next();
-			if (eObject instanceof Iteration) {
-				allElements.add((Iteration)eObject);
-			}
-		}
-		List<Iteration> sortedElements = new ArrayList<>(allElements);
-		Collections.sort(sortedElements, monikerComparator);
-		return sortedElements;
-	} */
-
-	protected @NonNull Map<org.eclipse.ocl.pivot.Package, List<Iteration>> getSortedIterations(@NonNull Model root) {
-		Map<org.eclipse.ocl.pivot.Package, List<Iteration>> pkge2iterations = new HashMap<>();
-		for (org.eclipse.ocl.pivot.Package pkge : root.getOwnedPackages()) {
-			List<Iteration> iterations = null;
-			for (org.eclipse.ocl.pivot.Class type : pkge.getOwnedClasses()) {
-				for (Operation operation : type.getOwnedOperations()) {
-					if (operation instanceof Iteration) {
-						if (iterations == null) {
-							iterations = new ArrayList<>();
-							pkge2iterations.put(pkge, iterations);
-						}
-						iterations.add((Iteration) operation);
-					}
-				}
-			}
-			if (iterations != null) {
-				Collections.sort(iterations, monikerComparator);
-			}
-		}
-		return pkge2iterations;
+	protected @NonNull Map<org.eclipse.ocl.pivot.@NonNull Package, @NonNull List<@NonNull Iteration>> getSortedIterations(@NonNull Model root) {
+		return contentAnalysis.package2sortedIterations;
 	}
 
-	/*	protected @NonNull List<Iteration> getSortedIterations(org.eclipse.ocl.pivot.@NonNull Class type, @NonNull List<Iteration> allIterations) {
-		Set<Iteration> allElements = new HashSet<>();
-		for (Operation operation : type.getOwnedOperations()) {
-			if (allIterations.contains(operation)) {
-				allElements.add((Iteration)operation);
-			}
-		}
-		List<Iteration> sortedElements = new ArrayList<>(allElements);
-		Collections.sort(sortedElements, monikerComparator);
-		return sortedElements;
-	} */
-
-	protected @NonNull List<LambdaType> getSortedLambdaTypes(@NonNull Model root) {
-		Set<LambdaType> allElements = new HashSet<>();
-		TreeIterator<EObject> tit = root.eAllContents();
-		while (tit.hasNext()) {
-			EObject eObject = tit.next();
-			if (eObject instanceof LambdaType) {
-				allElements.add((LambdaType)eObject);
-			}
-		}
-		List<LambdaType> sortedElements = new ArrayList<>(allElements);
-		Collections.sort(sortedElements, monikerComparator);
-		return sortedElements;
+	protected @NonNull List<@NonNull LambdaType> getSortedLambdaTypes(@NonNull Model root) {
+		return contentAnalysis.sortedLambdaTypes;
 	}
 
-	protected @NonNull List<Library> getSortedLibraries(@NonNull Model root) {
-		Set<Library> allElements = new HashSet<>();
-		TreeIterator<EObject> tit = root.eAllContents();
-		while (tit.hasNext()) {
-			EObject eObject = tit.next();
-			if (eObject instanceof Library) {
-				allElements.add((Library)eObject);
-			}
-		}
-		List<Library> sortedElements = new ArrayList<>(allElements);
-		Collections.sort(sortedElements, monikerComparator);
-		return sortedElements;
+	protected @NonNull List<@NonNull Library> getSortedLibraries(@NonNull Model root) {
+		return contentAnalysis.sortedLibraries;
 	}
 
-	protected @NonNull List<Library> getSortedLibrariesWithPrecedence(@NonNull Model root) {
-		Set<Library> allElements = new HashSet<>();
-		TreeIterator<EObject> tit = root.eAllContents();
-		while (tit.hasNext()) {
-			EObject eObject = tit.next();
-			if ((eObject instanceof Library) && (((Library)eObject).getOwnedPrecedences().size() > 0)) {
-				allElements.add((Library)eObject);
-			}
-		}
-		List<Library> sortedElements = new ArrayList<>(allElements);
-		Collections.sort(sortedElements, monikerComparator);
-		return sortedElements;
+	protected @NonNull List<@NonNull Library> getSortedLibrariesWithPrecedence(@NonNull Model root) {
+		return contentAnalysis.sortedLibrariesWithPrecedence;
 	}
 
-	protected @NonNull <T extends Nameable> List<T> getSortedList(@NonNull Collection<? extends T> packages) {
-		List<T> sortedElements = new ArrayList<>(packages);
-		Collections.sort(sortedElements, nameableComparator);
-		return sortedElements;
+	protected @NonNull Map<org.eclipse.ocl.pivot.@NonNull Package, @NonNull List<@NonNull MapType>> getSortedMapTypes(@NonNull Model root) {
+		return contentAnalysis.package2sortedMapTypes;
 	}
 
-	protected @NonNull Map<org.eclipse.ocl.pivot.Package, List<MapType>> getSortedMapTypes(@NonNull Model root) {
-		Map<org.eclipse.ocl.pivot.Package, List<MapType>> pkge2mapTypes = new HashMap<>();
-		for (org.eclipse.ocl.pivot.Package pkge : root.getOwnedPackages()) {
-			List<MapType> mapTypes = null;
-			for (Type type : pkge.getOwnedClasses()) {
-				if (type instanceof MapType) {
-					if (mapTypes == null) {
-						mapTypes = new ArrayList<>();
-						pkge2mapTypes.put(pkge, mapTypes);
-					}
-					mapTypes.add((MapType)type);
-				}
-			}
-			if (mapTypes != null) {
-				Collections.sort(mapTypes, monikerComparator);
-			}
-		}
-		return pkge2mapTypes;
+	protected @NonNull Map<org.eclipse.ocl.pivot.@NonNull Package, @NonNull List<@NonNull Operation>> getSortedOperations(@NonNull Model root) {
+		return contentAnalysis.package2sortedOperations;
 	}
 
-	/*	protected @NonNull List<Operation> getSortedOperations(@NonNull Model root) {
-		Set<Operation> allElements = new HashSet<>();
-		TreeIterator<EObject> tit = root.eAllContents();
-		while (tit.hasNext()) {
-			EObject eObject = tit.next();
-			if ((eObject instanceof Operation) && !(eObject instanceof Iteration) &&
-				!isEcoreConstraint((Operation)eObject)) {
-				allElements.add((Operation)eObject);
-			}
-		}
-		List<Operation> sortedElements = new ArrayList<>(allElements);
-		Collections.sort(sortedElements, monikerComparator);
-		return sortedElements;
-	} */
-
-	protected @NonNull Map<org.eclipse.ocl.pivot.Package, List<Operation>> getSortedOperations(@NonNull Model root) {
-		Map<org.eclipse.ocl.pivot.Package, List<Operation>> pkge2operations = new HashMap<>();
-		for (org.eclipse.ocl.pivot.Package pkge : root.getOwnedPackages()) {
-			List<Operation> operations = null;
-			for (org.eclipse.ocl.pivot.Class type : pkge.getOwnedClasses()) {
-				for (Operation operation : type.getOwnedOperations()) {
-					if (!(operation instanceof Iteration)) {
-						if (operations == null) {
-							operations = new ArrayList<>();
-							pkge2operations.put(pkge, operations);
-						}
-						operations.add(operation);
-					}
-				}
-			}
-			if (operations != null) {
-				Collections.sort(operations, monikerComparator);
-			}
-		}
-		return pkge2operations;
+	protected @NonNull List<@NonNull Operation> getSortedOperationsWithPrecedence(@NonNull Model root) {
+		return contentAnalysis.sortedOperationsWithPrecedence;
 	}
 
-	/*	protected @NonNull List<Operation> getSortedOperations(org.eclipse.ocl.pivot.@NonNull Class type, @NonNull List<Operation> allOperations) {
-		Set<Operation> allElements = new HashSet<>();
-		for (Operation operation : type.getOwnedOperations()) {
-			if (allOperations.contains(operation)) {
-				allElements.add(operation);
-			}
-		}
-		List<Operation> sortedElements = new ArrayList<Opration>(allElements);
-		Collections.sort(sortedElements, monikerComparator);
-		return sortedElements;
-	} */
-
-	protected @NonNull List<Operation> getSortedOperationsWithPrecedence(@NonNull Model root) {
-		Set<Operation> allElements = new HashSet<>();
-		TreeIterator<EObject> tit = root.eAllContents();
-		while (tit.hasNext()) {
-			EObject eObject = tit.next();
-			if ((eObject instanceof Operation) && !(eObject instanceof Iteration) &&
-					!isEcoreConstraint((Operation)eObject)) {
-				Operation operation = (Operation)eObject;
-				if (!(operation instanceof Iteration) && !isEcoreConstraint(operation) &&
-						(operation.getPrecedence() != null)) {
-					allElements.add(operation);
-				}
-			}
-		}
-		List<Operation> sortedElements = new ArrayList<>(allElements);
-		Collections.sort(sortedElements, monikerComparator);
-		return sortedElements;
-	}
-
-	protected @NonNull List<org.eclipse.ocl.pivot.Class> getSortedOwningTypes(@NonNull List<@NonNull ? extends Operation> operations) {
-		Set<org.eclipse.ocl.pivot.Class> allElements = new HashSet<>();
+	protected @NonNull List<org.eclipse.ocl.pivot.@NonNull Class> getSortedOwningTypes(@NonNull List<@NonNull ? extends Operation> operations) {
+		Set<org.eclipse.ocl.pivot.@NonNull Class> allElements = new HashSet<>();
 		for (@NonNull Operation operation : operations) {
 			if (operation.getOwningClass() != null) {
 				allElements.add(operation.getOwningClass());
 			}
 		}
-		List<org.eclipse.ocl.pivot.Class> sortedElements = new ArrayList<>(allElements);
-		Collections.sort(sortedElements, monikerComparator);
+		List<org.eclipse.ocl.pivot.@NonNull Class> sortedElements = new ArrayList<>(allElements);
+		Collections.sort(sortedElements, contentAnalysis.monikerComparator);
 		return sortedElements;
 	}
 
-	protected @NonNull List<org.eclipse.ocl.pivot.Class> getSortedOwningTypes2(@NonNull List<@NonNull ? extends Property> properties) {
-		Set<org.eclipse.ocl.pivot.Class> allElements = new HashSet<>();
-		for (@NonNull Property property : properties) {
-			if (property.getOwningClass() != null) {
-				allElements.add(property.getOwningClass());
-			}
-		}
-		List<org.eclipse.ocl.pivot.Class> sortedElements = new ArrayList<>(allElements);
-		Collections.sort(sortedElements, monikerComparator);
+	protected @NonNull List<org.eclipse.ocl.pivot.@NonNull Package> getSortedPackages(@NonNull Model root, @NonNull Collection<? extends org.eclipse.ocl.pivot.Package> packages) {
+		List<org.eclipse.ocl.pivot.@NonNull Package> sortedElements = new ArrayList<>(packages);
+		Collections.sort(sortedElements, contentAnalysis.packageComparator);
 		return sortedElements;
 	}
 
-	protected @NonNull List<org.eclipse.ocl.pivot.Package> getSortedPackages(@NonNull Model root, @NonNull Collection<? extends org.eclipse.ocl.pivot.Package> packages) {
-		//		Package orphanPackage = getOrphanPackage(root);
-		List<org.eclipse.ocl.pivot.Package> sortedElements = new ArrayList<>(packages);
-		Collections.sort(sortedElements, packageComparator);
-		return sortedElements;
+	protected @NonNull List<org.eclipse.ocl.pivot.@NonNull Package> getSortedPackages(@NonNull Model root) {
+		return contentAnalysis.sortedPackages;
 	}
 
-	protected @NonNull List<org.eclipse.ocl.pivot.Package> getSortedPackages(@NonNull Model root) {
-		//		Set<org.eclipse.ocl.pivot.Package> allElements = new HashSet<>();
-		//		TreeIterator<EObject> tit = root.eAllContents();
-		//		while (tit.hasNext()) {
-		//			EObject eObject = tit.next();
-		//			if (eObject instanceof org.eclipse.ocl.pivot.Package) {
-		//				allElements.add((org.eclipse.ocl.pivot.Package)eObject);
-		//			}
-		//		}
-		List<org.eclipse.ocl.pivot.Package> sortedElements = new ArrayList<>(root.getOwnedPackages());
-		Collections.sort(sortedElements, packageComparator);
-		return sortedElements;
-	}
-
-	protected @NonNull List<org.eclipse.ocl.pivot.Package> getSortedPackages(org.eclipse.ocl.pivot.@NonNull Package pkg) {
+	protected @NonNull List<org.eclipse.ocl.pivot.@NonNull Package> getSortedPackages(org.eclipse.ocl.pivot.@NonNull Package pkg) {
 		List<org.eclipse.ocl.pivot.Package> sortedElements = new ArrayList<>(pkg.getOwnedPackages());
-		Collections.sort(sortedElements, nameableComparator);
+		Collections.sort(sortedElements, NameUtil.NAMEABLE_COMPARATOR);
 		return sortedElements;
 	}
 
-	protected @NonNull List<org.eclipse.ocl.pivot.Class> getSortedParameterTypes(@NonNull Model root) {
-		Set<org.eclipse.ocl.pivot.Class> allElements = new HashSet<>();
-		TreeIterator<EObject> tit = root.eAllContents();
-		while (tit.hasNext()) {
-			EObject eObject = tit.next();
-			if (eObject instanceof org.eclipse.ocl.pivot.Class) {
-				org.eclipse.ocl.pivot.Class t = (org.eclipse.ocl.pivot.Class)eObject;
-				if (t.isTemplateParameter() != null) {			// FIXME can never happen
-					allElements.add(t);
-				}
-			}
-		}
-		List<org.eclipse.ocl.pivot.Class> sortedElements = new ArrayList<>(allElements);
-		Collections.sort(sortedElements, monikerComparator);
+	protected @NonNull List<org.eclipse.ocl.pivot.@NonNull Class> getSortedParameterTypes(@NonNull Model root) {
+		return contentAnalysis.sortedParameterTypes;
+	}
+
+	protected @NonNull List<@NonNull Precedence> getSortedPrecedences(@NonNull Library library) {
+		List<@NonNull Precedence> sortedElements = new ArrayList<>(library.getOwnedPrecedences());
+		Collections.sort(sortedElements, NameUtil.NAMEABLE_COMPARATOR);
 		return sortedElements;
 	}
 
-	protected @NonNull List<Precedence> getSortedPrecedences(@NonNull Library library) {
-		List<Precedence> sortedElements = new ArrayList<>(library.getOwnedPrecedences());
-		Collections.sort(sortedElements, nameableComparator);
-		return sortedElements;
+	protected @NonNull Map<org.eclipse.ocl.pivot.@NonNull Package, @NonNull List<@NonNull PrimitiveType>> getSortedPrimitiveTypes(@NonNull Model root) {
+		return contentAnalysis.package2sortedPrimitiveTypes;
 	}
 
-	protected @NonNull Map<org.eclipse.ocl.pivot.Package, List<PrimitiveType>> getSortedPrimitiveTypes(@NonNull Model root) {
-		Map<org.eclipse.ocl.pivot.Package, List<PrimitiveType>> pkge2primitiveTypes = new HashMap<>();
-		for (org.eclipse.ocl.pivot.Package pkge : root.getOwnedPackages()) {
-			List<PrimitiveType> primitiveTypes = null;
-			for (Type type : pkge.getOwnedClasses()) {
-				if (type instanceof PrimitiveType) {
-					boolean isDefinedPrimitive = false;
-					Type primaryType = metamodelManager.getPrimaryElement(type);
-					if (type == primaryType)  {
-						isDefinedPrimitive = true;
-					}
-					else if (!hasComplements(type)) {
-						type = primaryType;
-					}
-					if (type != primaryType) {
-						String externalName = external2name.get(type);
-						if (externalName == null) {
-							isDefinedPrimitive = true;
-						}
-					}
-					if (isDefinedPrimitive) {
-						if (primitiveTypes == null) {
-							primitiveTypes = new ArrayList<>();
-							pkge2primitiveTypes.put(pkge, primitiveTypes);
-						}
-						primitiveTypes.add((PrimitiveType)type);
-					}
-				}
-			}
-			if (primitiveTypes != null) {
-				Collections.sort(primitiveTypes, monikerComparator);
-			}
-		}
-		return pkge2primitiveTypes;
+	protected @NonNull Map<org.eclipse.ocl.pivot.@NonNull Package, @NonNull List<@NonNull Property>> getSortedProperties(@NonNull Model root) {
+		return contentAnalysis.package2sortedProperties;
 	}
 
-	protected @NonNull Map<org.eclipse.ocl.pivot.Package, List<Property>> getSortedProperties(@NonNull Model root) {
-		Map<org.eclipse.ocl.pivot.Package, List<Property>> pkge2properties = new HashMap<>();
-		for (org.eclipse.ocl.pivot.Package pkge : root.getOwnedPackages()) {
-			List<Property> properties = null;
-			for (org.eclipse.ocl.pivot.Class type : pkge.getOwnedClasses()) {
-				if (!(type instanceof TupleType)) {
-					for (Property property : type.getOwnedProperties()) {
-						if (properties == null) {
-							properties = new ArrayList<>();
-							pkge2properties.put(pkge, properties);
-						}
-						properties.add(property);
-					}
-				}
-			}
-			if (properties != null) {
-				Collections.sort(properties, classPropertyComparator);
-			}
-		}
-		return pkge2properties;
-	}
-
-	protected @NonNull List<Property> getSortedProperties(org.eclipse.ocl.pivot.@NonNull Class type) {
-		List<Property> sortedElements = new ArrayList<>(type.getOwnedProperties());
+	protected @NonNull List<@NonNull Property> getSortedProperties(org.eclipse.ocl.pivot.@NonNull Class type) {
+		List<@NonNull Property> sortedElements = new ArrayList<>(type.getOwnedProperties());
 		Collections.sort(sortedElements, OCLinEcoreTablesUtils.propertyComparator);
 		return sortedElements;
 	}
 
-	/*	protected @NonNull List<Property> getSortedProperties(org.eclipse.ocl.pivot.@NonNull Class type, @NonNull List<Property> allProperties) {
-		Set<Property> allElements = new HashSet<>();
-		for (Property property : type.getOwnedProperties()) {
-			if (allProperties.contains(property)) {
-				allElements.add(property);
-			}
-		}
-		List<Property> sortedElements = new ArrayList<>(allElements);
-		Collections.sort(sortedElements, OCLinEcoreTablesUtils.propertyComparator);
-		if ("OCLExpression".equals(type.getName())) {
-			Collections.sort(sortedElements, OCLinEcoreTablesUtils.propertyComparator);
-		}
-		return sortedElements;
-	} */
+	protected @NonNull List<@NonNull TemplateParameter> getSortedTemplateParameters(@NonNull Model root) {
+		return contentAnalysis.sortedTemplateParameters;
+	}
 
-	protected @NonNull List<TemplateParameter> getSortedTemplateParameters(@NonNull Model root) {
-		Set<TemplateParameter> allElements = new HashSet<>();
-		TreeIterator<EObject> tit = root.eAllContents();
-		while (tit.hasNext()) {
-			EObject eObject = tit.next();
-			if (eObject instanceof TemplateParameter) {
-				allElements.add((TemplateParameter)eObject);
-			}
-		}
-		List<TemplateParameter> sortedElements = new ArrayList<>(allElements);
-		Collections.sort(sortedElements, monikerComparator);
+	protected @NonNull List<@NonNull TemplateSignature> getSortedTemplateSignatures(@NonNull Model root) {
+		return contentAnalysis.sortedTemplateSignatures;
+	}
+
+	protected @NonNull List<@NonNull TemplateableElement> getSortedTemplateableElements(@NonNull Model root) {
+		return contentAnalysis.sortedTemplateableElements;
+	}
+
+	protected @NonNull List<@NonNull TemplateableElement> getSortedTemplateableElements(@NonNull Model root, @NonNull Comparator<EObject> nameComparator) {
+		List<@NonNull TemplateableElement> sortedElements = Lists.newArrayList(contentAnalysis.sortedTemplateableElements);
+		Collections.sort(sortedElements, nameComparator);
 		return sortedElements;
 	}
 
-	protected @NonNull List<TemplateSignature> getSortedTemplateSignatures(@NonNull Model root) {
-		Set<TemplateSignature> allElements = new HashSet<>();
-		TreeIterator<EObject> tit = root.eAllContents();
-		while (tit.hasNext()) {
-			EObject eObject = tit.next();
-			if (eObject instanceof TemplateSignature) {
-				allElements.add((TemplateSignature)eObject);
-			}
-		}
-		List<TemplateSignature> sortedElements = new ArrayList<>(allElements);
-		Collections.sort(sortedElements, monikerComparator);
-		return sortedElements;
-	}
-
-	protected List<TemplateableElement> getSortedTemplateableElements(@NonNull Model root, @Nullable Comparator<EObject> nameComparator) {
-		Set<TemplateableElement> allElements = new HashSet<>();
-		TreeIterator<EObject> tit = root.eAllContents();
-		while (tit.hasNext()) {
-			EObject eObject = tit.next();
-			if (eObject instanceof TemplateableElement) {
-				TemplateableElement asTemplateableElement = (TemplateableElement)eObject;
-				if (asTemplateableElement.getOwnedBindings().size() > 0) {
-					allElements.add(asTemplateableElement);
-				}
-			}
-		}
-		List<TemplateableElement> sortedElements = new ArrayList<>(allElements);
-		Collections.sort(sortedElements, nameComparator != null ? nameComparator : monikerComparator);
-		return sortedElements;
-	}
-
-	protected @NonNull List<Property> getSortedTupleParts(@NonNull TupleType tupleType) {
-		List<Property> sortedElements = new ArrayList<>(tupleType.getOwnedProperties());
-		Collections.sort(sortedElements, nameableComparator);
+	protected @NonNull List<@NonNull Property> getSortedTupleParts(@NonNull TupleType tupleType) {
+		List<@NonNull Property> sortedElements = Lists.newArrayList(PivotUtil.getOwnedProperties(tupleType));
+		Collections.sort(sortedElements, NameUtil.NAMEABLE_COMPARATOR);
 		return sortedElements;
 	}
 
 	protected @NonNull List<TupleType> getSortedTupleTypes(@NonNull Model root) {
-		Set<TupleType> allElements = new HashSet<>();
-		TreeIterator<EObject> tit = root.eAllContents();
-		while (tit.hasNext()) {
-			EObject eObject = tit.next();
-			if (eObject instanceof TupleType) {
-				allElements.add((TupleType)eObject);
-			}
-		}
-		List<TupleType> sortedElements = new ArrayList<>(allElements);
-		Collections.sort(sortedElements, monikerComparator);
-		return sortedElements;
+		return contentAnalysis.sortedTupleTypes;
 	}
 
-	protected @NonNull List<org.eclipse.ocl.pivot.Class> getSuperclassesInPackage(org.eclipse.ocl.pivot.@NonNull Class type) {
-		List<org.eclipse.ocl.pivot.Class> allElements = new ArrayList<>();
-		for (org.eclipse.ocl.pivot.Class superclass : type.getSuperClasses()) {
-			if (getRootPackage(superclass.getOwningPackage()) == getRootPackage(type.getOwningPackage())) {
+	protected @NonNull List<org.eclipse.ocl.pivot.@NonNull Class> getSuperclassesInPackage(org.eclipse.ocl.pivot.@NonNull Class asClass) {		// Redundant filter
+		List<org.eclipse.ocl.pivot.@NonNull Class> allElements = new ArrayList<>();
+		for (org.eclipse.ocl.pivot.@NonNull Class superclass : asClass.getSuperClasses()) {
+		//	if (getRootPackage(superclass.getOwningPackage()) == getRootPackage(type.getOwningPackage())) {
 				allElements.add(superclass);
-			}
+		//	}
 		}
 		return allElements;
 	}
 
-	protected @NonNull List<TemplateParameterSubstitution> getTemplateParameterSubstitutions(@NonNull TemplateableElement element) {
-		List<TemplateParameterSubstitution> allElements = new ArrayList<>();
+	protected @NonNull List<@NonNull TemplateParameterSubstitution> getTemplateParameterSubstitutions(@NonNull TemplateableElement element) {
+		List<@NonNull TemplateParameterSubstitution> allElements = new ArrayList<>();
 		for (TemplateBinding templateBinding : element.getOwnedBindings()) {
 			allElements.addAll(templateBinding.getOwnedSubstitutions());
 		}
@@ -1378,7 +1127,7 @@
 		//		throw new IllegalStateException("No external name defined for " + EcoreUtil.getURI(elem));
 	}
 
-	protected abstract Model getThisModel();
+	protected abstract @NonNull Model getThisModel();
 
 	protected boolean hasComplements(@NonNull Type type) {
 		if (type instanceof org.eclipse.ocl.pivot.Class) {
@@ -1391,6 +1140,95 @@
 		return false;
 	}
 
+	protected void initLocalTypes() {
+		contentAnalysis.analyze(thisModel);
+	}
+
+	public void initModel(@NonNull Model thisModel, ASSaverNew.@NonNull ASSaverWithInverse asSaver) {
+		this.thisModel = thisModel;
+		initLocalTypes();
+		initOrphanSymbolNames(asSaver);
+	}
+
+	/**
+	 * Assign a unique symbol name for each localized orphan and assign the same symbol name to the shared orphan#
+	 * from which the local was cloned so that synthesis of references to the shared element are serialized as if the
+	 * local copy had been corrupted to point at the local.
+	 */
+	protected void initOrphanSymbolNames(@NonNull ASSaverWithInverse asSaver) {
+		org.eclipse.ocl.pivot.Package localOrphanage = getOrphanPackage(thisModel);
+		for (EObject localOrphan : new TreeIterable(localOrphanage, true)) {
+			StringBuilder s = new StringBuilder();
+			if (localOrphan instanceof CollectionType) {
+				CollectionType type = (CollectionType)localOrphan;
+				s.append("_" + type.getName());
+				s.append("_" + partialName(type.getElementType()));
+				s.append("_" + (type.isIsNullFree() ? "T" : "F"));
+				if (type.getLowerValue() != ValueUtil.ZERO_VALUE) {
+					s.append("_L" + type.getLowerValue());
+				}
+				if (type.getUpperValue() != ValueUtil.UNLIMITED_VALUE) {
+					s.append("_U" + type.getUpperValue());
+				}
+			}
+			else if (localOrphan instanceof LambdaType) {
+				LambdaType type = (LambdaType)localOrphan;
+				s.append("_" + type.getName());
+				s.append("_" + partialName(type.getContextType()));
+				for (Type parameterType : type.getParameterTypes()) {
+					s.append("_" + partialName(parameterType));
+				}
+				s.append("_" + partialName(type.getResultType()));
+			}
+			else if (localOrphan instanceof MapType) {
+				MapType type = (MapType)localOrphan;
+				s.append("_" + type.getName());
+				s.append("_" + partialName(type.getKeyType()));
+				s.append("_" + (type.isKeysAreNullFree() ? "T" : "F"));
+				s.append("_" + partialName(type.getValueType()));
+				s.append("_" + (type.isValuesAreNullFree() ? "T" : "F"));
+			}
+			else if (localOrphan instanceof Property) {
+				s.append("_" + partialName(localOrphan));
+			}
+		//	else if (localOrphan instanceof TemplateParameter) {
+		//		TemplateParameter type = (TemplateParameter)localOrphan;
+		//		s.append("tp_" + type.getTemplateParameterId().getIndex());
+		//	}
+			else if (localOrphan instanceof TupleType) {
+				s.append("_" + partialName(localOrphan));
+			}
+			else if (localOrphan instanceof TemplateBinding) {
+			}
+			else if (localOrphan instanceof TemplateParameterSubstitution) {
+			}
+			else if ((localOrphan instanceof org.eclipse.ocl.pivot.Class) && Orphanage.isOrphan((org.eclipse.ocl.pivot.Class)localOrphan)) {
+				s.append("orphanClass");
+			}
+			else if ((localOrphan instanceof org.eclipse.ocl.pivot.Package) && Orphanage.isOrphan((org.eclipse.ocl.pivot.Package)localOrphan)) {
+				s.append("orphanPackage");
+			}
+			else {
+				System.out.println("Unexpected localOrphan: " + NameUtil.debugSimpleName(localOrphan));
+				s.append("_" + partialName(localOrphan));
+			}
+			if (s.length() > 0) {
+				String symbolName = getPrefixedSymbolName(localOrphan, s.toString());
+				EObject sharedOrphan = asSaver.basicGetSource(localOrphan);
+				if (sharedOrphan != null) {
+					nameQueries.putSymbolName(sharedOrphan, symbolName);
+				}
+				else if (localOrphan == localOrphanage) {
+					Orphanage sharedOrphanage = Orphanage.getOrphanage(environmentFactory.getCompleteModel().getOrphanage());
+					nameQueries.putSymbolName(sharedOrphanage, symbolName);
+				}
+				else {
+					System.out.println("Missing orphan mapping for " + NameUtil.debugSimpleName(localOrphan) + " : " + localOrphan);
+				}
+			}
+		}
+	}
+
 	protected Boolean isEcoreConstraint(@NonNull Operation operation) {
 		for (Parameter p : operation.getOwnedParameters()) {
 			if (p.getName().equals("diagnostics") && p.getType().getName().equals("EDiagnosticChain")) {
diff --git a/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/GenerateOCLCommonXtend.xtend b/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/GenerateOCLCommonXtend.xtend
index d1c490c..3fb56a9 100644
--- a/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/GenerateOCLCommonXtend.xtend
+++ b/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/GenerateOCLCommonXtend.xtend
@@ -11,6 +11,7 @@
 package org.eclipse.ocl.examples.build.xtend
 
 import java.util.ArrayList
+import java.util.Collection
 import java.util.Collections
 import org.eclipse.emf.ecore.EObject
 import org.eclipse.ocl.pivot.AnyType
@@ -32,8 +33,10 @@
 import org.eclipse.ocl.pivot.TemplateParameterSubstitution
 import org.eclipse.ocl.pivot.TemplateSignature
 import org.eclipse.ocl.pivot.utilities.ClassUtil
-import java.util.Collection
 import org.eclipse.ocl.pivot.values.Unlimited
+import org.eclipse.ocl.pivot.utilities.PivotConstants
+import org.eclipse.ocl.pivot.ids.TypeId
+import org.eclipse.ocl.pivot.utilities.NameUtil
 
 abstract class GenerateOCLCommonXtend extends GenerateOCLCommon
 {
@@ -61,7 +64,7 @@
 
 			«FOR type : ClassUtil.nullFree(pkge2collectionTypes.get(pkge))»«var typeName = type.getPrefixedSymbolName("_" + type.getName() + "_" + type.getElementType().partialName() + (if (type.isIsNullFree()) "_NullFree" else "") )»
 			«IF type.getOwnedSignature() !== null»
-			private final @NonNull «type.eClass.name» «typeName» = create«type.eClass.name»("«type.name»"/*«type.elementType.name»*/, "«type.lower.toString()»", "«type.upper.toString()»"«IF type.getOwnedSignature() !== null»«FOR templateParameter : type.getOwnedSignature().getOwnedParameters()», «templateParameter.getSymbolName()»«ENDFOR»«ENDIF»);
+			private final @NonNull «type.eClass.name» «typeName» = create«type.eClass.name»(«getEcoreLiteral(type)»«IF type.getOwnedSignature() !== null»«FOR templateParameter : type.getOwnedSignature().getOwnedParameters()», «templateParameter.getSymbolName()»«ENDFOR»«ENDIF»);
 			«ENDIF»
 			«ENDFOR»
 			«FOR type : ClassUtil.nullFree(pkge2collectionTypes.get(pkge))»«var typeName = type.getPrefixedSymbolName("_" + type.getName() + "_" + type.getElementType().partialName() + (if (type.isIsNullFree()) "_NullFree" else "") )»
@@ -102,7 +105,7 @@
 			«FOR type : ClassUtil.nullFree(pkge2mapTypes.get(pkge))»
 				«IF type.getOwnedSignature() !== null»
 					private final @NonNull «type.eClass.name» «type.getPrefixedSymbolName("_" + type.getName() + "_" + type.getKeyType().partialName() + "_" + type.getValueType().partialName())» = create«type.
-					eClass.name»("«type.name»"/*«type.keyType.name» «type.valueType.name»*/«IF type.getOwnedSignature() !== null»«FOR templateParameter : type.getOwnedSignature().getOwnedParameters()», «templateParameter.getSymbolName()»«ENDFOR»«ENDIF»);
+					eClass.name»(«getEcoreLiteral(type)»«IF type.getOwnedSignature() !== null»«FOR templateParameter : type.getOwnedSignature().getOwnedParameters()», «templateParameter.getSymbolName()»«ENDFOR»«ENDIF»);
 				«ENDIF»
 			«ENDFOR»
 			«FOR type : ClassUtil.nullFree(pkge2mapTypes.get(pkge))»
@@ -175,17 +178,21 @@
 				Class type;
 				«FOR pkge : sortedPackages»
 
-					ownedClasses = «pkge.getSymbolName()».getOwnedClasses();
-					«FOR type : ClassUtil.nullFree(pkge2classTypes.get(pkge))»
-						type = «type.getSymbolName()»;
-						«IF type.isAbstract»

-						type.setIsAbstract(true);

-						«ENDIF»
-						«IF !(type instanceof AnyType)»
-							«type.emitSuperClasses("type")»
-						«ENDIF»
-						ownedClasses.add(type);
-					«ENDFOR»
+				ownedClasses = «pkge.getSymbolName()».getOwnedClasses();
+				«FOR type : ClassUtil.nullFree(pkge2classTypes.get(pkge))»«var templateSignature = type.getOwnedSignature()»
+				type = «type.getSymbolName()»;
+				«IF type.isAbstract»
+				type.setIsAbstract(true);
+				«ENDIF»
+				«IF !(type instanceof AnyType)»
+					«type.emitSuperClasses("type")»
+				«ENDIF»
+				«IF templateSignature !== null»«IF templateSignature.getOwnedParameters().size() > 0»
+					createTemplateSignature(type, «FOR templateParameter : templateSignature.getOwnedParameters() SEPARATOR(", ")»«templateParameter.getSymbolName()»«ENDFOR»);
+				«ENDIF»
+				«ENDIF»
+				ownedClasses.add(type);
+				«ENDFOR»
 				«ENDFOR»
 			}
 		'''
@@ -475,7 +482,7 @@
 		var allPackages = root.getSortedPackages();
 		var import2alias = root.getSortedImports();
 		var importKeys = new ArrayList<Package>(import2alias.keySet());
-		Collections.sort(importKeys, nameableComparator);
+		Collections.sort(importKeys, NameUtil.NAMEABLE_COMPARATOR);
 		if (allPackages.isEmpty()) return "";
 		'''
 
@@ -719,7 +726,8 @@
 				superClasses = «typeName».getSuperClasses();
 				superClasses.add(_OclAny);
 			«ELSEIF (type instanceof AnyType)»
-			«ELSEIF "OclElement".equals(type.getName())»
+			«ELSEIF TypeId.OCL_ELEMENT_NAME.equals(type.getName())»
+			«ELSEIF PivotConstants.ORPHANAGE_NAME.equals(type.getName())»
 			«ELSE»
 				superClasses = «typeName».getSuperClasses();
 				superClasses.add(_OclElement);
@@ -727,18 +735,18 @@
 		'''
 	}
 
-	protected def String installCoercions(/*@NonNull*/ Model root) {
-		var allCoercions = root.getSortedCoercions();
-		if (allCoercions.isEmpty()) return "";
-		'''installCoercions();'''
-	}
-
 	protected def String installClassTypes(/*@NonNull*/ Model root) {
 		var pkge2classTypes = root.getSortedClassTypes();
 		if (pkge2classTypes.isEmpty()) return "";
 		'''installClassTypes();'''
 	}
 
+	protected def String installCoercions(/*@NonNull*/ Model root) {
+		var allCoercions = root.getSortedCoercions();
+		if (allCoercions.isEmpty()) return "";
+		'''installCoercions();'''
+	}
+
 	protected def String installCollectionTypes(/*@NonNull*/ Model root) {
 		var pkge2collectionTypes = root.getSortedCollectionTypes();
 		if (pkge2collectionTypes.isEmpty()) return "";
@@ -805,7 +813,7 @@
 	}
 	
 	protected def String installTemplateBindings(/*@NonNull*/ Model root) {
-		var allTemplateableElements = root.getSortedTemplateableElements(null);
+		var allTemplateableElements = root.getSortedTemplateableElements();
 		if (allTemplateableElements.isEmpty()) return "";
 		'''installTemplateBindings();'''
 	}
diff --git a/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/GenerateOCLmetamodel.java b/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/GenerateOCLmetamodel.java
index a738c65..970e54d 100644
--- a/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/GenerateOCLmetamodel.java
+++ b/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/GenerateOCLmetamodel.java
@@ -17,7 +17,6 @@
 import java.util.HashMap;
 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;
@@ -44,7 +43,7 @@
 import org.eclipse.ocl.pivot.internal.complete.StandardLibraryInternal;
 import org.eclipse.ocl.pivot.internal.ecore.es2as.Ecore2AS;
 import org.eclipse.ocl.pivot.internal.resource.AS2ID;
-import org.eclipse.ocl.pivot.internal.resource.ASSaver;
+import org.eclipse.ocl.pivot.internal.resource.ASSaverNew.ASSaverWithInverse;
 import org.eclipse.ocl.pivot.internal.resource.StandaloneProjectMap;
 import org.eclipse.ocl.pivot.internal.utilities.OCLInternal;
 import org.eclipse.ocl.pivot.model.OCLstdlib;
@@ -85,8 +84,6 @@
 		}
 	};
 
-	protected Model thisModel;
-
 	protected CollectionType findCollectionType(Iterable<org.eclipse.ocl.pivot.Class> types, String name) {
 		CollectionType collType = null;
 		for (org.eclipse.ocl.pivot.Class type : types) {
@@ -130,7 +127,7 @@
 		return super.getExternalReference(element);
 	}
 
-	protected abstract String generateMetamodel(/*@NonNull*/ Model pivotModel, /*@NonNull*/ Collection</*@NonNull*/ String> excludedEClassifierNames);
+	protected abstract String generateMetamodel(/*@NonNull*/ Collection</*@NonNull*/ String> excludedEClassifierNames);
 
 	protected String getEcoreLiteral(@NonNull EnumerationLiteral elem) {
 		return nameQueries.getEcoreLiteral(elem);
@@ -142,12 +139,6 @@
 	}
 
 	@Override
-	protected @NonNull Set<PrimitiveType> getAllPrimitiveTypes(@NonNull Model root) {
-		@NonNull Set<PrimitiveType> emptySet = Collections.emptySet();
-		return emptySet;
-	}
-
-	@Override
 	protected @NonNull String getNameLiteral(@NonNull Operation operation) {
 		return nameQueries.getEcoreLiteral(operation);
 	}
@@ -158,19 +149,19 @@
 	}
 
 	@Override
-	protected @NonNull Map<org.eclipse.ocl.pivot.Package, List<CollectionType>> getSortedCollectionTypes(@NonNull Model root) {
+	protected @NonNull Map<org.eclipse.ocl.pivot.@NonNull Package, @NonNull List<@NonNull CollectionType>> getSortedCollectionTypes(@NonNull Model root) {
 		return super.getSortedCollectionTypes(root, collectionTypeComparator);
 	}
 
 	@Override
-	protected @NonNull Map<org.eclipse.ocl.pivot.Package, List<PrimitiveType>> getSortedPrimitiveTypes(@NonNull Model root) {
-		Map<org.eclipse.ocl.pivot.Package, List<PrimitiveType>> pkge2primitiveTypes = new HashMap<org.eclipse.ocl.pivot.Package, List<PrimitiveType>>();
+	protected @NonNull Map<org.eclipse.ocl.pivot.@NonNull Package, @NonNull List<@NonNull PrimitiveType>> getSortedPrimitiveTypes(@NonNull Model root) {
+		Map<org.eclipse.ocl.pivot.@NonNull Package, @NonNull List<@NonNull PrimitiveType>> pkge2primitiveTypes = new HashMap<>();
 		return pkge2primitiveTypes;
 	}
 
 	@Override
-	protected Model getThisModel() {
-		return thisModel;
+	protected @NonNull Model getThisModel() {
+		return ClassUtil.nonNullState(thisModel);
 	}
 
 	@Override
@@ -209,26 +200,26 @@
 			}
 			sourceFile = "/" + projectName + "/" + modelFile;
 			EObject asRoot = asResource.getContents().get(0);
-			ASSaver saver = new ASSaver(asResource);
-			/*Package orphanage =*/ saver.localizeSpecializations();
+			ASSaverWithInverse saver = new ASSaverWithInverse(asResource);
+			/*Package orphanage =*/ saver.localizeOrphans();
 			//			if ((orphanage != null) && (pivotModel instanceof Root)) {
 			//				(pivotModel as Root).getOwnedPackages().add(orphanage);
 			//			}
 			String fileName = outputFolder + "/" + javaClassName + ".java";
 			log.info("Generating '" + fileName + "'");
 			assert asRoot instanceof Model;
-			Model asRoot2 = (Model)asRoot;
+			Model asModel = (Model)asRoot;
 			StandardLibraryInternal standardLibrary = ocl.getStandardLibrary();
-			getExternals(asRoot2);
-			addExternalReference(standardLibrary.getBooleanType(), asRoot2);
-			addExternalReference(standardLibrary.getIntegerType(), asRoot2);
-			addExternalReference(standardLibrary.getOclAnyType(), asRoot2);
-			addExternalReference(standardLibrary.getOclElementType(), asRoot2);
-			addExternalReference(standardLibrary.getOclEnumerationType(), asRoot2);
-			addExternalReference(standardLibrary.getRealType(), asRoot2);
-			addExternalReference(standardLibrary.getStringType(), asRoot2);
-			addExternalReference(standardLibrary.getUnlimitedNaturalType(), asRoot2);
-			String metamodel = generateMetamodel(asRoot2, Collections.emptyList());
+			addExternalReference(standardLibrary.getBooleanType(), asModel);
+			addExternalReference(standardLibrary.getIntegerType(), asModel);
+			addExternalReference(standardLibrary.getOclAnyType(), asModel);
+			addExternalReference(standardLibrary.getOclElementType(), asModel);
+			addExternalReference(standardLibrary.getOclEnumerationType(), asModel);
+			addExternalReference(standardLibrary.getRealType(), asModel);
+			addExternalReference(standardLibrary.getStringType(), asModel);
+			addExternalReference(standardLibrary.getUnlimitedNaturalType(), asModel);
+			initModel(asModel, saver);
+			String metamodel = generateMetamodel(Collections.emptyList());
 			MergeWriter fw = new MergeWriter(fileName);
 			if (metamodel != null) {
 				fw.append(metamodel);
diff --git a/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/GenerateOCLmetamodelXtend.xtend b/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/GenerateOCLmetamodelXtend.xtend
index 7e37cdb..cfec03c 100644
--- a/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/GenerateOCLmetamodelXtend.xtend
+++ b/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/GenerateOCLmetamodelXtend.xtend
@@ -57,8 +57,8 @@
 		'''
 	}
 
-	protected override String generateMetamodel(Model root, /*@NonNull*/ Collection</*@NonNull*/ String> excludedEClassifierNames) {
-		thisModel = root;
+	protected override String generateMetamodel(/*@NonNull*/ Collection</*@NonNull*/ String> excludedEClassifierNames) {
+		var Model root = thisModel;
 		var Package pkg = root.ownedPackages.findPackage();
 		if (pkg === null) {
 			return null;
diff --git a/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/GenerateOCLstdlib.java b/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/GenerateOCLstdlib.java
index a627d73..ab88adc 100644
--- a/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/GenerateOCLstdlib.java
+++ b/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/GenerateOCLstdlib.java
@@ -45,7 +45,7 @@
 import org.eclipse.ocl.pivot.internal.ecore.as2es.AS2Ecore;
 import org.eclipse.ocl.pivot.internal.library.StandardLibraryContribution;
 import org.eclipse.ocl.pivot.internal.resource.AS2ID;
-import org.eclipse.ocl.pivot.internal.resource.ASSaver;
+import org.eclipse.ocl.pivot.internal.resource.ASSaverNew.ASSaverWithInverse;
 import org.eclipse.ocl.pivot.internal.utilities.OCLInternal;
 import org.eclipse.ocl.pivot.internal.utilities.PivotDiagnostician;
 import org.eclipse.ocl.pivot.model.OCLstdlib;
@@ -62,7 +62,6 @@
 
 public abstract class GenerateOCLstdlib extends GenerateOCLCommonXtend
 {
-	protected Model thisModel;
 	protected String ecoreFile;
 	protected String libraryName;
 	protected String libraryNsPrefix;
@@ -70,7 +69,7 @@
 	protected boolean useOCLstdlib = false;
 	protected @NonNull List<@NonNull String> excludedEClassifierNames = new ArrayList<>();
 
-	protected abstract /*@NonNull*/ String generateMetamodel(/*@NonNull*/ Model pivotModel, @NonNull Collection<@NonNull String> excludedEClassifierNames);
+	protected abstract /*@NonNull*/ String generateMetamodel(@NonNull Collection<@NonNull String> excludedEClassifierNames);
 
 	public void addExcludedEClassifierName(String excludedEClassifierName) {
 		assert excludedEClassifierName != null;
@@ -98,13 +97,13 @@
 	}
 
 	@Override
-	protected @NonNull Map<org.eclipse.ocl.pivot.Package, List<CollectionType>> getSortedCollectionTypes(@NonNull Model root) {
-		return super.getSortedCollectionTypes(root, monikerComparator);
+	protected @NonNull Map<org.eclipse.ocl.pivot.@NonNull Package, @NonNull List<@NonNull CollectionType>> getSortedCollectionTypes(@NonNull Model root) {
+		return super.getSortedCollectionTypes(root, contentAnalysis.monikerComparator);
 	}
 
 	@Override
-	protected Model getThisModel() {
-		return thisModel;
+	protected @NonNull Model getThisModel() {
+		return ClassUtil.nonNullState(thisModel);
 	}
 
 	@Override
@@ -144,12 +143,14 @@
 			//			if (asResource == null) {
 			//				return;
 			//			}
-			EObject pivotModel = ClassUtil.nonNullState(asResource.getContents().get(0));
-			ASSaver saver = new ASSaver(asResource);
-			saver.localizeSpecializations();
+			Model pivotModel = (Model)ClassUtil.nonNullState(asResource.getContents().get(0));
+		//	assert pivotModel.getOwnedPackages().size() == 1;				// No orphanage, but may have an implicit package, so 100% to synthesize
+			ASSaverWithInverse saver = new ASSaverWithInverse(asResource);
+			saver.localizeOrphans();
 			String fileName = folder + "/" + javaClassName + ".java";
 		//	log.info("Generating '" + fileName + "'");
-			@SuppressWarnings("null")@NonNull String metamodel = generateMetamodel((Model)pivotModel, excludedEClassifierNames);
+			initModel(pivotModel, saver);
+			@SuppressWarnings("null")@NonNull String metamodel = generateMetamodel(excludedEClassifierNames);
 			MergeWriter fw = new MergeWriter(fileName);
 			fw.append(metamodel);
 			fw.close();
diff --git a/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/GenerateOCLstdlibXtend.xtend b/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/GenerateOCLstdlibXtend.xtend
index 8780ec7..4b795ee 100644
--- a/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/GenerateOCLstdlibXtend.xtend
+++ b/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/GenerateOCLstdlibXtend.xtend
@@ -38,50 +38,6 @@
 		'''
 	}
 
-	protected override String declareCollectionTypes(Model root) {
-		var pkge2collectionTypes = root.getSortedCollectionTypes();
-		if (pkge2collectionTypes.isEmpty()) return "";
-		var sortedPackages = root.getSortedPackages(pkge2collectionTypes.keySet());
-		'''
-		«FOR pkge : sortedPackages»
-
-			«FOR type : ClassUtil.nullFree(pkge2collectionTypes.get(pkge))»«var typeName = type.getPrefixedSymbolName("_" + type.getName() + "_" + type.getElementType().partialName() + (if (type.isIsNullFree()) "_NullFree" else "") )»
-			«IF type.getOwnedSignature() !== null»
-			private final @NonNull «type.eClass.name» «typeName» = create«type.eClass.name»(«getEcoreLiteral(type)»«IF type.getOwnedSignature() !== null»«FOR templateParameter : type.getOwnedSignature().getOwnedParameters()», «templateParameter.getSymbolName()»«ENDFOR»«ENDIF»);
-			«ENDIF»
-			«ENDFOR»
-			«FOR type : ClassUtil.nullFree(pkge2collectionTypes.get(pkge))»«var typeName = type.getPrefixedSymbolName("_" + type.getName() + "_" + type.getElementType().partialName() + (if (type.isIsNullFree()) "_NullFree" else "") )»
-			«IF type.getOwnedSignature() === null»
-			private final @NonNull «type.eClass.name» «typeName» = create«type.eClass.name»(«type.getUnspecializedElement().getSymbolName()»);
-			«ENDIF»
-			«ENDFOR»
-		«ENDFOR»
-		'''
-	}
-
-	protected override String declareMapTypes(/*@NonNull*/ Model root) {
-		var pkge2mapTypes = root.getSortedMapTypes();
-		if (pkge2mapTypes.isEmpty()) return "";
-		var sortedPackages = root.getSortedPackages(pkge2mapTypes.keySet());
-		'''
-
-		«FOR pkge : sortedPackages»
-			«FOR type : ClassUtil.nullFree(pkge2mapTypes.get(pkge))»
-				«IF type.getOwnedSignature() !== null»
-					private final @NonNull «type.eClass.name» «type.getPrefixedSymbolName("_" + type.getName() + "_" + type.getKeyType().partialName() + "_" + type.getValueType().partialName())» = create«type.
-					eClass.name»(«getEcoreLiteral(type)»«IF type.getOwnedSignature() !== null»«FOR templateParameter : type.getOwnedSignature().getOwnedParameters()», «templateParameter.getSymbolName()»«ENDFOR»«ENDIF»);
-				«ENDIF»
-			«ENDFOR»
-			«FOR type : ClassUtil.nullFree(pkge2mapTypes.get(pkge))»
-				«IF type.getOwnedSignature() === null»
-					private final @NonNull «type.eClass.name» «type.getPrefixedSymbolName("_" + type.getName() + "_" + type.getKeyType().partialName() + "_" + type.getValueType().partialName())» = create«type.
-					eClass.name»(«type.getUnspecializedElement().getSymbolName()»);
-				«ENDIF»
-			«ENDFOR»
-		«ENDFOR»
-		'''
-	}
-
 	protected override String declarePrimitiveTypes(/*@NonNull*/ Model root) {
 		var pkge2primitiveTypes = root.getSortedPrimitiveTypes();
 		if (pkge2primitiveTypes.isEmpty()) return "";
@@ -112,10 +68,10 @@
 			private void DataType «type.getPrefixedSymbolName("_"+type.partialName())» = createDataType("«type.name»");«ENDIF»
 	'''}
 
-	/*@NonNull*/ protected override String generateMetamodel(/*@NonNull*/ Model root, /*@NonNull*/ Collection</*@NonNull*/ String> excludedEClassifierNames) {
-		thisModel = root;
-		var lib = ClassUtil.nonNullState(root.getLibrary());
-		var externalPackages = root.getSortedExternalPackages();
+	/*@NonNull*/ protected override String generateMetamodel(/*@NonNull*/ Collection</*@NonNull*/ String> excludedEClassifierNames) {
+		// initModel(root); in caller
+		var lib = ClassUtil.nonNullState(thisModel.getLibrary());
+		var externalPackages = thisModel.getSortedExternalPackages();
 		var year = new GregorianCalendar().get(GregorianCalendar.YEAR);
 		'''
 			/*******************************************************************************
@@ -401,60 +357,60 @@
 			
 				private static class Contents extends AbstractContents
 				{
-					private final @NonNull Model «root.getPrefixedSymbolName("model")»;
-					«FOR pkge : root.getSortedPackages()»
-					private final @NonNull «pkge.eClass().getName()» «pkge.getPrefixedSymbolName(if (pkge == root.getOrphanPackage()) "orphanage" else pkge.getName())»;
+					private final @NonNull Model «thisModel.getPrefixedSymbolName("model")»;
+					«FOR pkge : thisModel.getSortedPackages()»
+					private final @NonNull «pkge.eClass().getName()» «pkge.getPrefixedSymbolName(if (pkge == thisModel.getOrphanPackage()) "orphanage" else pkge.getName())»;
 					«ENDFOR»
 			
 					private Contents(@NonNull String asURI)
 					{
-						«root.getSymbolName()» = createModel(asURI);
-						«FOR pkge : root.getSortedPackages()»
+						«thisModel.getSymbolName()» = createModel(asURI);
+						«FOR pkge : thisModel.getSortedPackages()»
 						«pkge.getSymbolName()» = create«pkge.eClass().getName()»("«pkge.getName()»", "«pkge.getNsPrefix()»", "«pkge.getURI()»", «pkge.getGeneratedPackageId()», «getEcoreLiteral(pkge)»);
 						«ENDFOR»
-						«root.installPackages()»
-						«root.installClassTypes()»
-						«root.installPrimitiveTypes()»
-						«root.installEnumerations()»
-						«root.installCollectionTypes()»
-						«root.installMapTypes()»
-						«root.installLambdaTypes()»
-						«root.installTupleTypes()»
-						«root.installOperations()»
-						«root.installIterations()»
-						«root.installCoercions()»
-						«root.installProperties()»
-						«root.installTemplateBindings()»
-						«root.installPrecedences()»
-						«root.installComments()»
+						«thisModel.installPackages()»
+						«thisModel.installClassTypes()»
+						«thisModel.installPrimitiveTypes()»
+						«thisModel.installEnumerations()»
+						«thisModel.installCollectionTypes()»
+						«thisModel.installMapTypes()»
+						«thisModel.installLambdaTypes()»
+						«thisModel.installTupleTypes()»
+						«thisModel.installOperations()»
+						«thisModel.installIterations()»
+						«thisModel.installCoercions()»
+						«thisModel.installProperties()»
+						«thisModel.installTemplateBindings()»
+						«thisModel.installPrecedences()»
+						«thisModel.installComments()»
 					}
 			
 					public @NonNull Model getModel() {
-						return «root.getSymbolName()»;
+						return «thisModel.getSymbolName()»;
 					}
-					«root.defineExternals()»
-					«root.definePackages()»
-					«root.declareClassTypes(excludedEClassifierNames)»
-					«root.declarePrimitiveTypes()»
-					«root.declareEnumerations()»
-					«root.defineTemplateParameters()»
-					«root.declareTupleTypes()»
-					«root.declareCollectionTypes()»
-					«root.declareMapTypes()»
-					«root.defineClassTypes()»
-					«root.definePrimitiveTypes()»
-					«root.defineEnumerations()»
-					«root.defineCollectionTypes()»
-					«root.defineMapTypes()»
-					«root.defineTupleTypes()»
-					«root.defineLambdaTypes()»
-					«root.defineOperations()»
-					«root.defineIterations()»
-					«root.defineCoercions()»
-					«root.defineProperties()»
-					«root.defineTemplateBindings()»
-					«root.definePrecedences()»
-					«root.defineComments()»
+					«thisModel.defineExternals()»
+					«thisModel.definePackages()»
+					«thisModel.declareClassTypes(excludedEClassifierNames)»
+					«thisModel.declarePrimitiveTypes()»
+					«thisModel.declareEnumerations()»
+					«thisModel.defineTemplateParameters()»
+					«thisModel.declareTupleTypes()»
+					«thisModel.declareCollectionTypes()»
+					«thisModel.declareMapTypes()»
+					«thisModel.defineClassTypes()»
+					«thisModel.definePrimitiveTypes()»
+					«thisModel.defineEnumerations()»
+					«thisModel.defineCollectionTypes()»
+					«thisModel.defineMapTypes()»
+					«thisModel.defineTupleTypes()»
+					«thisModel.defineLambdaTypes()»
+					«thisModel.defineOperations()»
+					«thisModel.defineIterations()»
+					«thisModel.defineCoercions()»
+					«thisModel.defineProperties()»
+					«thisModel.defineTemplateBindings()»
+					«thisModel.definePrecedences()»
+					«thisModel.defineComments()»
 				}
 			}
 		'''
diff --git a/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/NameQueries.java b/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/NameQueries.java
index 4557f43..7061d62 100644
--- a/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/NameQueries.java
+++ b/examples/org.eclipse.ocl.examples.build/src/org/eclipse/ocl/examples/build/xtend/NameQueries.java
@@ -65,14 +65,14 @@
 		//		if (elem == null) {
 		//			logger.error("getPrefixedSymbolName for '" + prefix + "'and null");
 		//		}
-		/*		if ((elem instanceof CollectionType) && (((CollectionType)elem).getUnspecializedElement() != null)) {
+				if ((elem instanceof CollectionType) && (((CollectionType)elem).getUnspecializedElement() != null)) {
 		}
 		else if ((elem instanceof MapType) && (((MapType)elem).getUnspecializedElement() != null)) {
 		}
 		else if (elem instanceof org.eclipse.ocl.pivot.Class) {
 			//	elem = metamodelManager.getCompleteModel().getCompleteClass((Type)elem);
 			elem = metamodelManager.getPrimaryClass((org.eclipse.ocl.pivot.Class)elem);
-		} */
+		}
 		return definedSymbols.get(elem);
 	}
 
@@ -241,6 +241,15 @@
 	}
 
 	public void putSymbolName(@NonNull Object elem, @NonNull String symbolName) {
+		if (symbolName.startsWith("Model")) {
+			getClass();			// FIXME Debugging
+		}
+		if (symbolName.startsWith("symbol_")) {
+			getClass();			// FIXME Debugging
+		}
+		if (symbolName.startsWith("_OclElement")) {
+			getClass();			// FIXME Debugging
+		}
 		String oldSymbolName = definedSymbols.put(elem, symbolName);
 		assert oldSymbolName == null;
 	}
diff --git a/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/analyzer/BoxingAnalyzer.java b/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/analyzer/BoxingAnalyzer.java
index 255381b..23d9553 100644
--- a/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/analyzer/BoxingAnalyzer.java
+++ b/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/analyzer/BoxingAnalyzer.java
@@ -224,26 +224,29 @@
 	}
 
 	/**
-	 * Insert a CGCastExp around cgChild.
+	 * Insert a CGCastExp around cgChild if required.
 	 */
-	protected CGValuedElement rewriteAsCast(@Nullable CGValuedElement/*CGVariableExp*/ cgChild) {
-		if (cgChild == null) {
+	protected CGValuedElement rewriteAsCast(@NonNull CGVariableExp cgChild) {
+		CGVariable cgVariable = cgChild.getReferredVariable();
+		CGTypeId cgRequiredTypeId = cgChild.getTypeId();
+		CGTypeId cgActualTypeId = cgVariable.getTypeId();
+		if (cgRequiredTypeId == cgActualTypeId) {
 			return cgChild;
 		}
 		TypeDescriptor typeDescriptor = codeGenerator.getTypeDescriptor(cgChild);
 		if (typeDescriptor.getJavaClass() == Object.class) {
 			return cgChild;
 		}
-		TypedElement pivot = (TypedElement) cgChild.getAst();
-		Type asType = pivot.getType();
+		TypedElement asChild = (TypedElement) cgChild.getAst();
+		Type asType = asChild.getType();
 		CGCastExp cgCastExp = CGModelFactory.eINSTANCE.createCGCastExp();
 		CGUtil.wrap(cgCastExp, cgChild);
-		cgCastExp.setAst(pivot);
+		cgCastExp.setAst(asChild);
 		if (asType != null) {
 			CGExecutorType cgExecutorType = context.createExecutorType(asType);
 			cgCastExp.setExecutorType(cgExecutorType);
 		}
-		cgCastExp.setTypeId(codeGenerator.getAnalyzer().getTypeId(pivot.getTypeId()));
+		cgCastExp.setTypeId(codeGenerator.getAnalyzer().getTypeId(asChild.getTypeId()));
 		return cgCastExp;
 	}
 
@@ -602,7 +605,8 @@
 	@Override
 	public @Nullable Object visitCGTypeExp(@NonNull CGTypeExp cgTypeExp) {
 		super.visitCGTypeExp(cgTypeExp);
-		rewriteAsCast(cgTypeExp);
+	//	CGExecutorType executorType = cgTypeExp.getExecutorType();
+	//	rewriteAsCast(cgTypeExp);
 		return null;
 	}
 
diff --git a/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/analyzer/NameManager.java b/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/analyzer/NameManager.java
index 7876e28..7a9f7b5 100644
--- a/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/analyzer/NameManager.java
+++ b/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/analyzer/NameManager.java
@@ -24,17 +24,20 @@
 import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.ocl.examples.codegen.cgmodel.CGBoxExp;
 import org.eclipse.ocl.examples.codegen.cgmodel.CGCallExp;
+import org.eclipse.ocl.examples.codegen.cgmodel.CGCastExp;
 import org.eclipse.ocl.examples.codegen.cgmodel.CGCatchExp;
 import org.eclipse.ocl.examples.codegen.cgmodel.CGCollectionExp;
 import org.eclipse.ocl.examples.codegen.cgmodel.CGCollectionPart;
 import org.eclipse.ocl.examples.codegen.cgmodel.CGEcoreExp;
 import org.eclipse.ocl.examples.codegen.cgmodel.CGGuardExp;
+import org.eclipse.ocl.examples.codegen.cgmodel.CGIfExp;
 import org.eclipse.ocl.examples.codegen.cgmodel.CGIterationCallExp;
 import org.eclipse.ocl.examples.codegen.cgmodel.CGOperationCallExp;
 import org.eclipse.ocl.examples.codegen.cgmodel.CGOppositePropertyCallExp;
 import org.eclipse.ocl.examples.codegen.cgmodel.CGPropertyCallExp;
 import org.eclipse.ocl.examples.codegen.cgmodel.CGString;
 import org.eclipse.ocl.examples.codegen.cgmodel.CGThrowExp;
+import org.eclipse.ocl.examples.codegen.cgmodel.CGTupleExp;
 import org.eclipse.ocl.examples.codegen.cgmodel.CGTypeId;
 import org.eclipse.ocl.examples.codegen.cgmodel.CGUnboxExp;
 import org.eclipse.ocl.examples.codegen.cgmodel.CGValuedElement;
@@ -92,6 +95,7 @@
 import org.eclipse.ocl.pivot.ids.UnspecifiedId;
 import org.eclipse.ocl.pivot.ids.WildcardId;
 import org.eclipse.ocl.pivot.utilities.ClassUtil;
+import org.eclipse.ocl.pivot.utilities.NameUtil;
 import org.eclipse.ocl.pivot.utilities.Nameable;
 import org.eclipse.ocl.pivot.utilities.PivotConstants;
 import org.eclipse.ocl.pivot.values.CollectionValue;
@@ -545,34 +549,43 @@
 			}
 			String lastResort = null;
 			if (nameHints != null) {
-				for (String nameHint : nameHints) {
-					if (nameHint != null)  {
-						String validHint = getValidJavaIdentifier(nameHint, false, anObject);
-						if (!reservedJavaNames.contains(validHint) || ((anObject instanceof CGValuedElement) && isNative((CGValuedElement)anObject))) {
-							if (anObject != null) {
-								Object oldElement = name2object.get(validHint);
-								if (oldElement == anObject) {
-									return validHint;
-								}
-								if ((oldElement == null) && !name2object.containsKey(validHint)) {
-									install(validHint, anObject);
-									return validHint;
+				boolean isNative = (anObject instanceof CGValuedElement) && isNative((CGValuedElement)anObject);
+				boolean hasRawNameHint = false;
+				for (int hintSuffix = 0; lastResort == null; hintSuffix++) {
+					for (String rawNameHint : nameHints) {
+						if (rawNameHint != null)  {
+							hasRawNameHint = true;
+							String nameHint = hintSuffix > 0 ? rawNameHint + hintSuffix : rawNameHint;
+							String validHint = getValidJavaIdentifier(nameHint, false, anObject);
+							if (!reservedJavaNames.contains(validHint) || isNative) {
+								if (anObject != null) {
+									Object oldElement = name2object.get(validHint);
+									if (oldElement == anObject) {
+										return validHint;
+									}
+									if ((oldElement == null) && !name2object.containsKey(validHint)) {
+										install(validHint, anObject);
+										return validHint;
+									}
+									else {
+										nameHint.toString();
+									}
 								}
 								else {
-									nameHint.toString();
+									if (!name2object.containsKey(validHint)) {
+										install(validHint, anObject);
+										return validHint;
+									}
 								}
-							}
-							else {
-								if (!name2object.containsKey(validHint)) {
-									install(validHint, anObject);
-									return validHint;
+								if (lastResort == null) {
+									lastResort = validHint;
 								}
 							}
-							if (lastResort == null) {
-								lastResort = validHint;
-							}
 						}
 					}
+					if (!hasRawNameHint) {
+						break;
+					}
 				}
 			}
 			if (lastResort == null) {
@@ -793,6 +806,9 @@
 			else if (anObject instanceof CGBoxExp) {
 				return "BOXED_" + ((CGBoxExp)anObject).getSourceValue().getValueName();
 			}
+			else if (anObject instanceof CGCastExp) {
+				return "CAST_" + ((CGCastExp)anObject).getSourceValue().getValueName();
+			}
 			else if (anObject instanceof CGEcoreExp) {
 				return "ECORE_" + ((CGEcoreExp)anObject).getSourceValue().getValueName();
 			}
@@ -812,6 +828,9 @@
 				return null;
 			}
 		}
+		else if (anObject instanceof CGIfExp) {
+			return "IF_" + ((CGIfExp)anObject).getCondition().getValueName();
+		}
 		else if (anObject instanceof RealLiteralExp) {
 			Number numberSymbol = ((RealLiteralExp)anObject).getRealSymbol();
 			return numberSymbol != null ? getNumericNameHint(numberSymbol) : null;
@@ -831,6 +850,9 @@
 			String stringSymbol = ((StringLiteralExp)anObject).getStringSymbol();
 			return stringSymbol != null ? getStringNameHint(stringSymbol) : null;
 		}
+		else if (anObject instanceof CGTupleExp) {
+			return TUPLE_NAME_HINT_PREFIX;
+		}
 		else if (anObject instanceof Type) {
 			return getTypeNameHint((Type)anObject);
 		}
@@ -862,6 +884,7 @@
 			return name != null ? getValidJavaIdentifier(name, false, anObject) : null;
 		}
 		else {
+			System.out.println("Missing nameHint for " + NameUtil.debugSimpleName(anObject));
 			return null;
 		}
 	}
diff --git a/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/generator/AbstractGenModelHelper.java b/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/generator/AbstractGenModelHelper.java
index 2e4d391..3335a56 100644
--- a/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/generator/AbstractGenModelHelper.java
+++ b/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/generator/AbstractGenModelHelper.java
@@ -53,8 +53,18 @@
 
 public abstract class AbstractGenModelHelper implements GenModelHelper
 {
+	public static final @NonNull String ENUMERATION_LITERALS_PACKAGE_NAME = "EnumerationLiterals";
+	public static final @NonNull String FRAGMENT_OPERATIONS_PACKAGE_NAME = "FragmentOperations";
+	public static final @NonNull String FRAGMENTS_PACKAGE_NAME = "Fragments";
+	public static final @NonNull String FRAGMENT_PROPERTIES_PACKAGE_NAME = "FragmentProperties";
+	public static final @NonNull String OPERATIONS_PACKAGE_NAME = "Operations";
+	public static final @NonNull String PARAMETERS_PACKAGE_NAME = "Parameters";
+	public static final @NonNull String PROPERTIES_PACKAGE_NAME = "Properties";
 	public static final @NonNull String TABLES_CLASS_SUFFIX = "Tables";
 	public static final @NonNull String TABLES_PACKAGE_NAME = "";
+	public static final @NonNull String TYPE_FRAGMENTS_PACKAGE_NAME = "TypeFragments";
+	public static final @NonNull String TYPE_PARAMETERS_PACKAGE_NAME = "TypeParameters";
+	public static final @NonNull String TYPES_PACKAGE_NAME = "Types";
 
 	public static @NonNull GenModelHelper create(@NonNull PivotMetamodelManager metamodelManager, @Nullable GenModel genModel) {
 		if (genModel instanceof org.eclipse.uml2.codegen.ecore.genmodel.GenModel) {
diff --git a/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/java/CG2JavaVisitor.java b/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/java/CG2JavaVisitor.java
index 84eed81..61a659a 100644
--- a/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/java/CG2JavaVisitor.java
+++ b/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/java/CG2JavaVisitor.java
@@ -1916,7 +1916,7 @@
 				js.append(", null)");
 			}
 		};
-		js.appendClassCast(cgExecutorType, castBody1);
+		js.appendClassCast(cgExecutorType, Boolean.TRUE, org.eclipse.ocl.pivot.Class.class, castBody1);
 		js.append(";\n");
 		return true;
 	}
diff --git a/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/java/JavaStream.java b/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/java/JavaStream.java
index 6f334ba..93e45ae 100644
--- a/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/java/JavaStream.java
+++ b/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/java/JavaStream.java
@@ -443,6 +443,7 @@
 		}
 	}
 
+	@Deprecated /* @deprecated pass actualJavaClass so that redundant casts are suppressed */
 	public void appendClassCast(@Nullable CGValuedElement cgValue, @NonNull SubStream subStream) {
 		if (cgValue == null) {
 			append("<<null-appendClassCast>>");
@@ -974,7 +975,7 @@
 				String qualifiedPackageName = genPackage.getQualifiedPackageName() + AbstractGenModelHelper.TABLES_PACKAGE_NAME;
 				String tablesClassName = genPackage.getPrefix() + AbstractGenModelHelper.TABLES_CLASS_SUFFIX;
 				appendClassReference(null, qualifiedPackageName + "." + tablesClassName);
-				append(".Operations._" + type.getName() + "__" + AbstractGenModelHelper.encodeName(anOperation));
+				append("." + AbstractGenModelHelper.OPERATIONS_PACKAGE_NAME + "._" + type.getName() + "__" + AbstractGenModelHelper.encodeName(anOperation));
 			}
 		}
 	}
diff --git a/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/oclinecore/OCLinEcoreTables.java b/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/oclinecore/OCLinEcoreTables.java
index e3e1fe4..1ff59ca 100644
--- a/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/oclinecore/OCLinEcoreTables.java
+++ b/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/oclinecore/OCLinEcoreTables.java
@@ -31,6 +31,7 @@
 import org.eclipse.emf.ecore.EStructuralFeature;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.ocl.examples.codegen.generator.AbstractGenModelHelper;
 import org.eclipse.ocl.examples.codegen.genmodel.OCLGenModelUtil;
 import org.eclipse.ocl.pivot.AnyType;
 import org.eclipse.ocl.pivot.BagType;
@@ -40,6 +41,7 @@
 import org.eclipse.ocl.pivot.Enumeration;
 import org.eclipse.ocl.pivot.EnumerationLiteral;
 import org.eclipse.ocl.pivot.InvalidType;
+import org.eclipse.ocl.pivot.LambdaType;
 import org.eclipse.ocl.pivot.Model;
 import org.eclipse.ocl.pivot.Operation;
 import org.eclipse.ocl.pivot.OrderedSetType;
@@ -51,10 +53,10 @@
 import org.eclipse.ocl.pivot.TemplateParameter;
 import org.eclipse.ocl.pivot.TemplateParameters;
 import org.eclipse.ocl.pivot.TemplateSignature;
+import org.eclipse.ocl.pivot.TemplateableElement;
 import org.eclipse.ocl.pivot.Type;
 import org.eclipse.ocl.pivot.VoidType;
 import org.eclipse.ocl.pivot.ids.IdManager;
-import org.eclipse.ocl.pivot.ids.TemplateParameterId;
 import org.eclipse.ocl.pivot.ids.TypeId;
 import org.eclipse.ocl.pivot.internal.library.ecore.EcoreExecutorAnyType;
 import org.eclipse.ocl.pivot.internal.library.ecore.EcoreExecutorBagType;
@@ -403,8 +405,8 @@
 		s.append("	/**\n");
 		s.append("	 *	The lists of enumeration literals for each enumeration.\n");
 		s.append("	 */\n");
-		s.append("	public static class EnumerationLiterals {\n");
-		appendInitializationStart("EnumerationLiterals");
+		s.append("	public static class " + AbstractGenModelHelper.ENUMERATION_LITERALS_PACKAGE_NAME + " {\n");
+		appendInitializationStart(AbstractGenModelHelper.ENUMERATION_LITERALS_PACKAGE_NAME);
 		for (org.eclipse.ocl.pivot.@NonNull Class asClass : activeClassesSortedByName) {
 			EClassifier eClassifier = ClassUtil.nonNullState((EClassifier)asClass.getESObject());
 			if (asClass instanceof Enumeration) {
@@ -467,8 +469,8 @@
 		s.append("	/**\n");
 		s.append("	 *	The fragment descriptors for the local elements of each type and its supertypes.\n");
 		s.append("	 */\n");
-		s.append("	public static class Fragments {\n");
-		appendInitializationStart("Fragments");
+		s.append("	public static class " + AbstractGenModelHelper.FRAGMENTS_PACKAGE_NAME + " {\n");
+		appendInitializationStart(AbstractGenModelHelper.FRAGMENTS_PACKAGE_NAME);
 		for (org.eclipse.ocl.pivot.@NonNull Class asClass : activeClassesSortedByName) {
 			s.append("\n");
 			List<org.eclipse.ocl.pivot.@NonNull Class> allSupertypesSortedByName = getAllSupertypesSortedByName(asClass);
@@ -497,7 +499,7 @@
 		int page = 1;
 		int pageMax = paginatedFragmentOperations.size();
 		for (@NonNull LinkedHashMap<org.eclipse.ocl.pivot.@NonNull Class, @NonNull LinkedHashMap<org.eclipse.ocl.pivot.@NonNull Class, @NonNull List<@NonNull Operation>>> fragmentOperations : paginatedFragmentOperations) {
-			String pagedName = getPagedName("FragmentOperations", page, pageMax);
+			String pagedName = getPagedName(AbstractGenModelHelper.FRAGMENT_OPERATIONS_PACKAGE_NAME, page, pageMax);
 			s.append("	public static class " + pagedName);
 			s.append(" {\n");
 			appendInitializationStart(pagedName);
@@ -544,7 +546,7 @@
 			s.append("		static {\n");
 			for (org.eclipse.ocl.pivot.@NonNull Class pClass : fragmentOperations.keySet()) {
 				for (org.eclipse.ocl.pivot.@NonNull Class pSuperClass : getAllSupertypesSortedByName(pClass)) {
-					s.append("			Fragments.");
+					s.append("			" + AbstractGenModelHelper.FRAGMENTS_PACKAGE_NAME + ".");
 					appendClassSuperClassName(pClass, pSuperClass);
 					s.append(".initOperations(");
 					appendClassSuperClassName(pClass, pSuperClass);
@@ -566,7 +568,7 @@
 		int page = 1;
 		int pageMax = paginatedFragmentProperties.size();
 		for (@NonNull LinkedHashMap<org.eclipse.ocl.pivot.@NonNull Class, @NonNull List<@NonNull Property>> fragmentProperties : paginatedFragmentProperties) {
-			String pagedName = getPagedName("FragmentProperties", page, pageMax);
+			String pagedName = getPagedName(AbstractGenModelHelper.FRAGMENT_PROPERTIES_PACKAGE_NAME, page, pageMax);
 			s.append("	public static class " + pagedName);
 			s.append(" {\n");
 			appendInitializationStart(pagedName);
@@ -606,7 +608,7 @@
 			//		s.append("\n");
 			s.append("		static {\n");
 			for (org.eclipse.ocl.pivot.@NonNull Class asClass : fragmentProperties.keySet()) {
-				s.append("			Fragments.");
+				s.append("			" + AbstractGenModelHelper.FRAGMENTS_PACKAGE_NAME + ".");
 				appendClassSuperClassName(asClass, asClass);
 				s.append(".initProperties(");
 				asClass.accept(emitLiteralVisitor);
@@ -706,8 +708,8 @@
 		s.append("	 * @noinstantiate This class is not intended to be instantiated by clients.\n");
 		s.append("	 * @noreference This class is not intended to be referenced by clients.\n");
 		s.append("	 */\n");
-		s.append("	public static class Operations {\n");
-		appendInitializationStart("Operations");
+		s.append("	public static class " + AbstractGenModelHelper.OPERATIONS_PACKAGE_NAME + " {\n");
+		appendInitializationStart(AbstractGenModelHelper.OPERATIONS_PACKAGE_NAME);
 		for (org.eclipse.ocl.pivot.@NonNull Class pClass : activeClassesSortedByName) {
 			List<@NonNull Operation> sortedOperations = new ArrayList<>(getOperations(pClass));
 			Collections.sort(sortedOperations, signatureComparator);
@@ -759,10 +761,16 @@
 	}
 
 	protected void declareParameterLists() {
+		Map<@NonNull String, @NonNull ParameterTypes> name2list = new HashMap<>();
 		Set<@NonNull ParameterTypes> allLists = new HashSet<>();
 		for (org.eclipse.ocl.pivot.@NonNull Class pClass : activeClassesSortedByName) {
 			for (Operation operation : getOperations(pClass)) {
-				allLists.add(operation.getParameterTypes());
+				ParameterTypes parameterTypes = operation.getParameterTypes();
+				allLists.add(parameterTypes);
+				if (parameterTypes.size() > 0) {
+					String name = getTemplateBindingsName(parameterTypes);
+					name2list.put(name, parameterTypes);
+				}
 			}
 		}
 		s.append("	/**\n");
@@ -772,28 +780,53 @@
 		s.append("	 * @noinstantiate This class is not intended to be instantiated by clients.\n");
 		s.append("	 * @noreference This class is not intended to be referenced by clients.\n");
 		s.append("	 */\n");
-		s.append("	public static class Parameters {\n");
-		appendInitializationStart("Parameters");
-		s.append("\n");
-		List<@NonNull ParameterTypes> sortedLists = new ArrayList<>(allLists);
-		Collections.sort(sortedLists, templateBindingNameComparator);
-		for (@NonNull ParameterTypes types : sortedLists) {
-			if (types.size() > 0) {				// Bug 471118 avoid deprecated _ identifier
-				s.append("		public static final ");
-				s.appendClassReference(true, ParameterTypes.class);
-				s.append(" ");
-				s.append(getTemplateBindingsName(types));
-				s.append(" = ");
-				s.appendClassReference(null, TypeUtil.class);
-				s.append(".createParameterTypes(");
-				for (int i = 0; i < types.size(); i++) {
-					if (i > 0) {
-						s.append(", ");
+		s.append("	public static class " + AbstractGenModelHelper.PARAMETERS_PACKAGE_NAME + " {\n");
+		appendInitializationStart(AbstractGenModelHelper.PARAMETERS_PACKAGE_NAME);
+		if (name2list.size() > 0) {
+			s.append("\n");
+			List<@NonNull String> sortedNames = new ArrayList<>(name2list.keySet());
+			Collections.sort(sortedNames);
+			for (@NonNull String name : sortedNames) {
+				ParameterTypes types = name2list.get(name);
+				assert types != null;
+				if (types.size() > 0) {				// Bug 471118 avoid deprecated _ identifier
+					s.append("		public static final ");
+					s.appendClassReference(true, ParameterTypes.class);
+					s.append(" ");
+					s.append(name);
+					s.append(" = ");
+					s.appendClassReference(null, TypeUtil.class);
+					s.append(".createParameterTypes(");
+					for (int i = 0; i < types.size(); i++) {
+						if (i > 0) {
+							s.append(", ");
+						}
+						Type type = types.get(i);
+						type.accept(declareParameterTypeVisitor);
 					}
-					Type type = types.get(i);
-					type.accept(declareParameterTypeVisitor);
+					s.append(");\n");
 				}
-				s.append(");\n");
+			}
+		}
+		if (allLists.size() > 0) {
+		//	s.append("\n");
+			List<@NonNull ParameterTypes> sortedLists = new ArrayList<>(allLists);
+			Collections.sort(sortedLists, leegacyTemplateBindingNameComparator);
+			for (@NonNull ParameterTypes types : sortedLists) {
+				if (types.size() > 0) {				// Bug 471118 avoid deprecated _ identifier
+					String legacyTemplateBindingsName = getLegacyTemplateBindingsName(types);
+					String templateBindingsName = getTemplateBindingsName(types);
+					if (!legacyTemplateBindingsName.equals(templateBindingsName) && !(types.get(0) instanceof LambdaType)) {		// legacy never defined LambdaType
+						s.append("		@Deprecated /* @deprecated use normalized name */\n");
+						s.append("		public static final ");
+						s.appendClassReference(true, ParameterTypes.class);
+						s.append(" ");
+						s.append(legacyTemplateBindingsName);
+						s.append(" = ");
+						s.append(templateBindingsName);
+						s.append(";\n");
+					}
+				}
 			}
 		}
 		appendInitializationEnd(false);
@@ -808,8 +841,8 @@
 		s.append("	 * @noinstantiate This class is not intended to be instantiated by clients.\n");
 		s.append("	 * @noreference This class is not intended to be referenced by clients.\n");
 		s.append("	 */\n");
-		s.append("	public static class Properties {\n");
-		appendInitializationStart("Properties");
+		s.append("	public static class " + AbstractGenModelHelper.PROPERTIES_PACKAGE_NAME + " {\n");
+		appendInitializationStart(AbstractGenModelHelper.PROPERTIES_PACKAGE_NAME);
 		boolean isFirst = false;
 		for (org.eclipse.ocl.pivot.@NonNull Class pClass : activeClassesSortedByName) {
 			List<@NonNull Property> sortedProperties = getLocalPropertiesSortedByName(pClass);
@@ -913,6 +946,9 @@
 				if (asTemplateParameter != null) {
 					s.append(", ");
 					asTemplateParameter.accept(emitScopedLiteralVisitor);
+				//	s.append(AbstractGenModelHelper.TYPE_PARAMETERS_PACKAGE_NAME);
+				//	s.append(".");
+				//	s.append(getTemplateParameterName(asTemplateParameter));
 				}
 			}
 		}
@@ -923,8 +959,8 @@
 		s.append("	/**\n");
 		s.append("	 *	The type descriptors for each type.\n");
 		s.append("	 */\n");
-		s.append("	public static class Types {\n");
-		appendInitializationStart("Types");
+		s.append("	public static class " + AbstractGenModelHelper.TYPES_PACKAGE_NAME + " {\n");
+		appendInitializationStart(AbstractGenModelHelper.TYPES_PACKAGE_NAME);
 		s.append("\n");
 		for (org.eclipse.ocl.pivot.@NonNull Class pClass : activeClassesSortedByName) {
 			declareType(pClass);
@@ -965,8 +1001,8 @@
 		s.append("	/**\n");
 		s.append("	 *	The fragments for all base types in depth order: OclAny first, OclSelf last.\n");
 		s.append("	 */\n");
-		s.append("	public static class TypeFragments {\n");
-		appendInitializationStart("TypeFragments");
+		s.append("	public static class " + AbstractGenModelHelper.TYPE_FRAGMENTS_PACKAGE_NAME + " {\n");
+		appendInitializationStart(AbstractGenModelHelper.TYPE_FRAGMENTS_PACKAGE_NAME);
 		for (org.eclipse.ocl.pivot.@NonNull Class asClass : activeClassesSortedByName) {
 			final Map<org.eclipse.ocl.pivot.@NonNull Class, @NonNull Integer> allSuperTypes = new HashMap<>();
 			int myDepth = getAllSuperClasses(allSuperTypes, asClass);
@@ -1007,7 +1043,7 @@
 					s.append(",");
 				}
 				s.append("\n");
-				s.append("				Fragments.");
+				s.append("				" + AbstractGenModelHelper.FRAGMENTS_PACKAGE_NAME + ".");
 				asClass.accept(emitLiteralVisitor);
 				s.append("__");
 				s.appendUnscopedTypeName(asSuperClass);
@@ -1047,69 +1083,53 @@
 	}
 
 	protected void declareTypeParameters() {
+		Map<@NonNull String, @NonNull TemplateParameter> name2templateParameter = new HashMap<>();
+		for (org.eclipse.ocl.pivot.@NonNull Class asClass : activeClassesSortedByName) {
+			TemplateSignature asTemplateSignature = asClass.getOwnedSignature();
+			if (asTemplateSignature != null) {
+				declareTypeParameters(name2templateParameter, asTemplateSignature);
+			}
+			for (@NonNull Operation operation : getLocalOperationsSortedBySignature(asClass)) {
+				asTemplateSignature = operation.getOwnedSignature();
+				if (asTemplateSignature != null) {
+					declareTypeParameters(name2templateParameter, asTemplateSignature);
+				}
+			}
+		}
+		List<@NonNull String> names = new ArrayList<>(name2templateParameter.keySet());
+		Collections.sort(names);
 		s.append("	/**\n");
 		s.append("	 *	The type parameters for templated types and operations.\n");
 		s.append("	 */\n");
-		s.append("	public static class TypeParameters {\n");
-		appendInitializationStart("TypeParameters");
-		for (org.eclipse.ocl.pivot.@NonNull Class pClass : activeClassesSortedByName) {
-			TemplateSignature templateSignature = pClass.getOwnedSignature();
-			if (templateSignature != null) {
-				s.append("\n");
-				for (TemplateParameter asTemplateParameter : templateSignature.getOwnedParameters()) {
-					if (asTemplateParameter != null) {
-						s.append("		public static final ");
-						s.appendClassReference(true, ExecutorTypeParameter.class);
-						s.append(" ");
-						asTemplateParameter.accept(emitLiteralVisitor);
-						s.append(" = new ");
-						s.appendClassReference(null, ExecutorTypeParameter.class);
-						s.append("(");
-						TemplateParameterId elementId = asTemplateParameter.getTemplateParameterId();
-						String idName = elementId.getLiteralName();
-						if (idName != null) {
-							s.appendClassReference(null, TypeId.class);
-							s.append(".");
-							s.append(idName);
-						}
-						else {
-							s.appendClassReference(null, IdManager.class);
-							s.append(".getTemplateParameterId(" + elementId.getIndex() + ")");
-						}
-						s.append(", ");
-						s.appendString(ClassUtil.nonNullModel(asTemplateParameter.getName()));
-						s.append(");\n");
-					}
-				}
+		s.append("	public static class " + AbstractGenModelHelper.TYPE_PARAMETERS_PACKAGE_NAME + " {\n");
+		appendInitializationStart(AbstractGenModelHelper.TYPE_PARAMETERS_PACKAGE_NAME);
+		if (names.size() > 0) {
+			s.append("\n");
+			for (@NonNull String name : names) {
+				TemplateParameter asTemplateParameter = name2templateParameter.get(name);
+				assert asTemplateParameter != null;
+				s.append("		public static final ");
+				s.appendClassReference(true, ExecutorTypeParameter.class);
+				s.append(" ");
+				s.append(name);
+				s.append(" = new ");
+				s.appendClassReference(null, ExecutorTypeParameter.class);
+				s.append("(");
+				s.append(Integer.toString(asTemplateParameter.getTemplateParameterId().getIndex()));
+				s.append(", ");
+				s.appendString(ClassUtil.nonNullModel(asTemplateParameter.getName()));
+				s.append(");\n");
 			}
-			for (@NonNull Operation operation : getLocalOperationsSortedBySignature(pClass)) {
+		}
+		for (org.eclipse.ocl.pivot.@NonNull Class asClass : activeClassesSortedByName) {
+			TemplateSignature templateSignature = asClass.getOwnedSignature();
+			if (templateSignature != null) {
+				declareTypeParameters(templateSignature);
+			}
+			for (@NonNull Operation operation : getLocalOperationsSortedBySignature(asClass)) {
 				templateSignature = operation.getOwnedSignature();
 				if (templateSignature != null) {
-					for (/*@NonNull*/ TemplateParameter asTemplateParameter : templateSignature.getOwnedParameters()) {
-						if (asTemplateParameter != null) {
-							s.append("		public static final ");
-							s.appendClassReference(true, ExecutorTypeParameter.class);
-							s.append(" ");
-							asTemplateParameter.accept(emitLiteralVisitor);
-							s.append(" = new ");
-							s.appendClassReference(null, ExecutorTypeParameter.class);
-							s.append("(");
-							TemplateParameterId elementId = asTemplateParameter.getTemplateParameterId();
-							String idName = elementId.getLiteralName();
-							if (idName != null) {
-								s.appendClassReference(null, TypeId.class);
-								s.append(".");
-								s.append(idName);
-							}
-							else {
-								s.appendClassReference(null, IdManager.class);
-								s.append(".getTemplateParameterId(" + elementId.getIndex() + ")");
-							}
-							s.append(", ");
-							s.appendString(ClassUtil.nonNullModel(asTemplateParameter.getName()));
-							s.append(");\n");
-						}
-					}
+					declareTypeParameters(templateSignature);
 				}
 			}
 		}
@@ -1117,6 +1137,48 @@
 		s.append("	}\n");
 	}
 
+	protected void declareTypeParameters(@NonNull Map<@NonNull String, @NonNull TemplateParameter> name2templateParameter, @NonNull TemplateSignature templateSignature) {
+		for (@NonNull TemplateParameter asTemplateParameter : PivotUtil.getOwnedParameters(templateSignature)) {
+			String name = getTemplateParameterName(asTemplateParameter);
+			if (!name2templateParameter.containsKey(name)) {
+				name2templateParameter.put(name, asTemplateParameter);
+			}
+		}
+	}
+
+	protected void declareTypeParameters(@NonNull TemplateSignature templateSignature) {
+		for (@NonNull TemplateParameter asTemplateParameter : PivotUtil.getOwnedParameters(templateSignature)) {
+			s.append("		@Deprecated /* @deprecated use normalized name */\n");
+			s.append("		public static final ");
+			s.appendClassReference(true, ExecutorTypeParameter.class);
+			s.append(" ");
+			TemplateSignature asTemplateSignature = asTemplateParameter.getOwningSignature();
+			TemplateableElement asTemplateableElement = asTemplateSignature.getOwningElement();
+			org.eclipse.ocl.pivot.Class asClass = null;
+			if (asTemplateableElement instanceof Operation) {
+				Operation asOperation = (Operation)asTemplateableElement;
+				asClass = PivotUtil.getOwningClass(asOperation);
+			}
+			else if (asTemplateableElement instanceof org.eclipse.ocl.pivot.Class) {
+				asClass = (org.eclipse.ocl.pivot.Class)asTemplateableElement;
+			}
+			if (asClass != null) {
+				if (asTemplateableElement instanceof Operation) {
+					s.append("_");
+				}
+				asTemplateableElement.accept(emitLiteralVisitor);
+				s.append("_");
+				s.appendAndEncodeName(asTemplateParameter);
+			}
+			else {
+				s.append("null");
+			}
+			s.append(" = ");
+			asTemplateParameter.accept(emitLiteralVisitor);
+			s.append(";\n");
+		}
+	}
+
 	protected String deresolveFileName(@Nullable String uri) {
 		if (uri != null) {
 			String modelProjectDirectory = genPackage.getGenModel().getModelProjectDirectory();
@@ -1129,9 +1191,6 @@
 	}
 
 	public @NonNull String generateTablesClass(@Nullable String constants) {
-		//		if (constants != null) {
-		//			constants = s.rewriteManagedImports(constants);
-		//		}
 		String tablesClassName = getTablesClassName();
 		LinkedHashMap<org.eclipse.ocl.pivot.@NonNull Class, @NonNull LinkedHashMap<org.eclipse.ocl.pivot.@NonNull Class, @NonNull List<@NonNull Operation>>> fragmentOperations = computeFragmentOperations();
 		LinkedHashMap<org.eclipse.ocl.pivot.@NonNull Class, @NonNull List<@NonNull Property>> fragmentProperties = computeFragmentProperties();
diff --git a/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/oclinecore/OCLinEcoreTablesUtils.java b/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/oclinecore/OCLinEcoreTablesUtils.java
index 886c4a2..66f8106 100644
--- a/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/oclinecore/OCLinEcoreTablesUtils.java
+++ b/examples/org.eclipse.ocl.examples.codegen/src/org/eclipse/ocl/examples/codegen/oclinecore/OCLinEcoreTablesUtils.java
@@ -57,7 +57,6 @@
 import org.eclipse.ocl.pivot.TemplateBinding;
 import org.eclipse.ocl.pivot.TemplateParameter;
 import org.eclipse.ocl.pivot.TemplateParameterSubstitution;
-import org.eclipse.ocl.pivot.TemplateSignature;
 import org.eclipse.ocl.pivot.TemplateableElement;
 import org.eclipse.ocl.pivot.TupleType;
 import org.eclipse.ocl.pivot.Type;
@@ -65,6 +64,7 @@
 import org.eclipse.ocl.pivot.ids.BuiltInTypeId;
 import org.eclipse.ocl.pivot.ids.LambdaTypeId;
 import org.eclipse.ocl.pivot.ids.ParametersId;
+import org.eclipse.ocl.pivot.ids.TemplateParameterId;
 import org.eclipse.ocl.pivot.ids.TypeId;
 import org.eclipse.ocl.pivot.internal.complete.StandardLibraryInternal;
 import org.eclipse.ocl.pivot.internal.ecore.es2as.Ecore2AS;
@@ -87,6 +87,19 @@
 
 public class OCLinEcoreTablesUtils
 {
+	private static int SHOW_TABLES_PACKAGE = 1;
+	private static int SHOW_TABLES_SUBPACKAGE = 2;
+
+	public Comparator<@NonNull ParameterTypes> leegacyTemplateBindingNameComparator = new Comparator<@NonNull ParameterTypes>()
+	{
+		@Override
+		public int compare(@NonNull ParameterTypes o1, @NonNull ParameterTypes o2) {
+			String n1 = getLegacyTemplateBindingsName(o1);
+			String n2 = getLegacyTemplateBindingsName(o2);
+			return n1.compareTo(n2);
+		}
+	};
+
 	public Comparator<@NonNull ParameterTypes> templateBindingNameComparator = new Comparator<@NonNull ParameterTypes>()
 	{
 		@Override
@@ -599,14 +612,11 @@
 		@Override
 		public @Nullable Object visitTemplateParameter(@NonNull TemplateParameter asTemplateParameter) {
 			asTemplateParameter.accept(emitQualifiedLiteralVisitor);
+		//	s.append(Integer.toString(asTemplateParameter.getTemplateParameterId().getIndex()));
 			return null;
 		}
 	}
 
-	private static int SHOW_TABLES_PACKAGE = 1;
-	private static int SHOW_TABLES_SUBPACKAGE = 2;
-
-
 	public class EmitLiteralVisitor extends AbstractExtendingVisitor<Object, Object>
 	{
 		protected final @NonNull CodeGenString s;
@@ -642,7 +652,7 @@
 		@Override
 		public @Nullable Object visitClass(org.eclipse.ocl.pivot.@NonNull Class asClass) {
 			appendTablesPackageQualification(asClass);
-			appendTablesSubackageQualification("Types");
+			appendTablesSubackageQualification(AbstractGenModelHelper.TYPES_PACKAGE_NAME);
 			s.append("_");
 			s.appendAndEncodeName(asClass);
 			return null;
@@ -652,7 +662,7 @@
 		public @Nullable Object visitCollectionType(@NonNull CollectionType type) {
 			CollectionType unspecializedType = PivotUtil.getUnspecializedTemplateableElement(type);
 			appendTablesPackageQualification(type);
-			appendTablesSubackageQualification("Types");
+			appendTablesSubackageQualification(AbstractGenModelHelper.TYPES_PACKAGE_NAME);
 			s.append("_");
 			s.appendAndEncodeName(unspecializedType);
 			return null;
@@ -672,7 +682,7 @@
 		public @Nullable Object visitEnumerationLiteral(@NonNull EnumerationLiteral asEnumerationLiteral) {
 			Enumeration asEnumeration = PivotUtil.getOwningEnumeration(asEnumerationLiteral);
 			appendTablesPackageQualification(asEnumeration);
-			appendTablesSubackageQualification("EnumerationLiterals");
+			appendTablesSubackageQualification(AbstractGenModelHelper.ENUMERATION_LITERALS_PACKAGE_NAME);
 			s.append("_");
 			s.appendAndEncodeName(asEnumeration);
 			s.append("__");
@@ -694,7 +704,7 @@
 		public @Nullable Object visitOperation(@NonNull Operation asOperation) {
 			org.eclipse.ocl.pivot.Class asClass = PivotUtil.getOwningClass(asOperation);
 			appendTablesPackageQualification(asClass);
-			appendTablesSubackageQualification("Operations");
+			appendTablesSubackageQualification(AbstractGenModelHelper.OPERATIONS_PACKAGE_NAME);
 			s.append("_");
 			s.appendAndEncodeName(asClass);
 			s.append("__");
@@ -713,7 +723,7 @@
 		public @Nullable Object visitProperty(@NonNull Property asProperty) {
 			org.eclipse.ocl.pivot.Class asClass = PivotUtil.getOwningClass(asProperty);
 			appendTablesPackageQualification(asClass);
-			appendTablesSubackageQualification("Properties");
+			appendTablesSubackageQualification(AbstractGenModelHelper.PROPERTIES_PACKAGE_NAME);
 			s.append("_");
 			s.appendAndEncodeName(asClass);
 			s.append("__");
@@ -730,29 +740,10 @@
 
 		@Override
 		public @Nullable Object visitTemplateParameter(@NonNull TemplateParameter asTemplateParameter) {
-			TemplateSignature asTemplateSignature = asTemplateParameter.getOwningSignature();
-			TemplateableElement asTemplateableElement = asTemplateSignature.getOwningElement();
-			org.eclipse.ocl.pivot.Class asClass = null;
-			if (asTemplateableElement instanceof Operation) {
-				Operation asOperation = (Operation)asTemplateableElement;
-				asClass = PivotUtil.getOwningClass(asOperation);
-			}
-			else if (asTemplateableElement instanceof org.eclipse.ocl.pivot.Class) {
-				asClass = (org.eclipse.ocl.pivot.Class)asTemplateableElement;
-			}
-			if (asClass != null) {
-				appendTablesPackageQualification(asClass);
-				appendTablesSubackageQualification("TypeParameters");
-				if (asTemplateableElement instanceof Operation) {
-					s.append("_");
-				}
-				asTemplateableElement.accept(emitLiteralVisitor);
-				s.append("_");
-				s.appendAndEncodeName(asTemplateParameter);
-			}
-			else {
-				s.append("null");
-			}
+		//	appendLegacyTemplateParameterName(asTemplateParameter);
+		//	appendTablesPackageQualification(asClass);
+			appendTablesSubackageQualification(AbstractGenModelHelper.TYPE_PARAMETERS_PACKAGE_NAME);
+			s.append(getTemplateParameterName(asTemplateParameter));
 			return null;
 		}
 
@@ -785,6 +776,7 @@
 	protected final @NonNull EmitLiteralVisitor emitScopedLiteralVisitor;		// emit YYY._ZZZ
 	protected final @NonNull EmitLiteralVisitor emitQualifiedLiteralVisitor;	// emit XXXTables.YYY._ZZZ
 	protected final @NonNull Iterable<org.eclipse.ocl.pivot.@NonNull Class> activeClassesSortedByName;
+	protected final @NonNull Map<@NonNull ParameterTypes, String> legacyTemplateBindingsNames = new HashMap<>();
 	protected final @NonNull Map<@NonNull ParameterTypes, String> templateBindingsNames = new HashMap<>();
 	protected final @NonNull GenModelHelper genModelHelper;
 
@@ -1034,6 +1026,64 @@
 		}
 	}
 
+	protected @NonNull String getLegacyTemplateBindingsName(@NonNull ParameterTypes templateBindings) {
+		String name2 = legacyTemplateBindingsNames.get(templateBindings);
+		if (name2 == null) {
+			StringBuilder s = new StringBuilder();
+			s.append("_");
+			if (templateBindings.size() > 0 ) {
+				for (int i = 0; i < templateBindings.size(); i++) {
+					if (i > 0) {
+						s.append("___");
+					}
+					Type element = templateBindings.get(i);
+					getLegacyTemplateBindingsName(s, element);
+				}
+			}
+			name2 = s.toString();
+			legacyTemplateBindingsNames.put(templateBindings, name2);
+		}
+		return name2;
+	}
+	private void getLegacyTemplateBindingsName(@NonNull StringBuilder s, @NonNull Type element) {
+		TemplateParameter templateParameter = element.isTemplateParameter();
+		if (templateParameter != null) {
+			TemplateableElement template = templateParameter.getOwningSignature().getOwningElement();
+			if (template instanceof Operation) {
+				s.append(AbstractGenModelHelper.encodeName(ClassUtil.nonNullModel(((Operation) template).getOwningClass())));
+				s.append("_");
+			}
+			s.append(AbstractGenModelHelper.encodeName(ClassUtil.nonNullModel((NamedElement) template)));
+			s.append("_");
+		}
+		s.append(AbstractGenModelHelper.encodeName(element));
+		if (element instanceof TemplateableElement) {
+			List<TemplateBinding> templateBindings = ((TemplateableElement)element).getOwnedBindings();
+			if (templateBindings.size() > 0) {
+				s.append("_");
+				for (TemplateBinding templateBinding : templateBindings) {
+					for (TemplateParameterSubstitution templateParameterSubstitution : templateBinding.getOwnedSubstitutions()) {
+						s.append("_");
+						getLegacyTemplateBindingsName(s, ClassUtil.nonNullModel(templateParameterSubstitution.getActual()));
+					}
+				}
+				s.append("__");
+			}
+		}
+		if (element instanceof LambdaType) {
+			LambdaType lambdaType = (LambdaType)element;
+			s.append("_");
+			getLegacyTemplateBindingsName(s, ClassUtil.nonNullModel(lambdaType.getContextType()));
+			for (/*@NonNull*/ Type type : lambdaType.getParameterType()) {
+				assert type != null;
+				s.append("_");
+				getLegacyTemplateBindingsName(s, type);
+			}
+			s.append("_");
+			getLegacyTemplateBindingsName(s, ClassUtil.nonNullModel(lambdaType.getResultType()));
+		}
+	}
+
 	protected @NonNull Iterable<@NonNull Operation> getLocalOperationsSortedBySignature(org.eclipse.ocl.pivot.@NonNull Class pClass) {
 		// cls.getOperations()->sortedBy(op2 : Operation | op2.getSignature())
 		List<@NonNull Operation> sortedOperations = new ArrayList<>(getOperations(pClass));
@@ -1197,12 +1247,7 @@
 	private void getTemplateBindingsName(@NonNull StringBuilder s, @NonNull Type element) {
 		TemplateParameter templateParameter = element.isTemplateParameter();
 		if (templateParameter != null) {
-			TemplateableElement template = templateParameter.getOwningSignature().getOwningElement();
-			if (template instanceof Operation) {
-				s.append(AbstractGenModelHelper.encodeName(ClassUtil.nonNullModel(((Operation) template).getOwningClass())));
-				s.append("_");
-			}
-			s.append(AbstractGenModelHelper.encodeName(ClassUtil.nonNullModel((NamedElement) template)));
+			s.append(Integer.toString(templateParameter.getTemplateParameterId().getIndex()));
 			s.append("_");
 		}
 		s.append(AbstractGenModelHelper.encodeName(element));
@@ -1233,6 +1278,11 @@
 		}
 	}
 
+	protected @NonNull String getTemplateParameterName(@NonNull TemplateParameter asTemplateParameter) {
+		TemplateParameterId asTemplateParameterId = asTemplateParameter.getTemplateParameterId();
+		return "_" + asTemplateParameterId.getIndex() + "_" + asTemplateParameter.getName();
+	}
+
 	/**
 	 * Return  true if property has an Ecore counterpart. Non-navigable opposites may have a Property
 	 * but no Ecore EReference.
diff --git a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/utilities/ParserContext.java b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/utilities/ParserContext.java
index 2bfe8a9..3cd594e 100644
--- a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/utilities/ParserContext.java
+++ b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/utilities/ParserContext.java
@@ -59,7 +59,7 @@
 	@Nullable Type getClassContext();
 
 	/**
-	 * Return the element that hsts an expression that may reference the self variable.
+	 * Return the element that hosts an expression that may reference the self variable.
 	 * This may be an Operation rather than a Type.
 	 *
 	 * @since 1.7
diff --git a/plugins/org.eclipse.ocl.xtext.base/src/org/eclipse/ocl/xtext/base/cs2as/CS2AS.java b/plugins/org.eclipse.ocl.xtext.base/src/org/eclipse/ocl/xtext/base/cs2as/CS2AS.java
index ac2decf..d6da91e 100644
--- a/plugins/org.eclipse.ocl.xtext.base/src/org/eclipse/ocl/xtext/base/cs2as/CS2AS.java
+++ b/plugins/org.eclipse.ocl.xtext.base/src/org/eclipse/ocl/xtext/base/cs2as/CS2AS.java
@@ -484,7 +484,7 @@
 		return helper2;
 	}
 
-	public Element getPivotElement(@NonNull ModelElementCS csElement) {
+	public @Nullable Element getPivotElement(@NonNull ModelElementCS csElement) {
 		return csi2asMapping.get(csElement);
 	}