/*******************************************************************************
 * Copyright (c) 2010, 2015 Willink Transformations and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     E.D.Willink - initial API and implementation
 *******************************************************************************/
package org.eclipse.ocl.pivot.uml.internal.es2as;

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

import org.apache.log4j.Logger;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EFactory;
import org.eclipse.emf.ecore.EGenericType;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.ETypeParameter;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.impl.DynamicEObjectImpl;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.URIConverter;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.xmi.XMIException;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.CompleteModel;
import org.eclipse.ocl.pivot.Element;
import org.eclipse.ocl.pivot.ExpressionInOCL;
import org.eclipse.ocl.pivot.Model;
import org.eclipse.ocl.pivot.NamedElement;
import org.eclipse.ocl.pivot.PivotFactory;
import org.eclipse.ocl.pivot.PivotPackage;
import org.eclipse.ocl.pivot.ProfileApplication;
import org.eclipse.ocl.pivot.Property;
import org.eclipse.ocl.pivot.Stereotype;
import org.eclipse.ocl.pivot.StereotypeExtender;
import org.eclipse.ocl.pivot.Type;
import org.eclipse.ocl.pivot.TypedElement;
import org.eclipse.ocl.pivot.ids.IdManager;
import org.eclipse.ocl.pivot.internal.ecore.es2as.AbstractExternal2AS;
import org.eclipse.ocl.pivot.internal.resource.StandaloneProjectMap;
import org.eclipse.ocl.pivot.internal.utilities.AliasAdapter;
import org.eclipse.ocl.pivot.internal.utilities.EnvironmentFactoryInternal;
import org.eclipse.ocl.pivot.internal.utilities.External2AS;
import org.eclipse.ocl.pivot.internal.utilities.PivotConstantsInternal;
import org.eclipse.ocl.pivot.internal.utilities.PivotObjectImpl;
import org.eclipse.ocl.pivot.internal.utilities.PivotUtilInternal;
import org.eclipse.ocl.pivot.resource.ASResource;
import org.eclipse.ocl.pivot.uml.UMLStandaloneSetup;
import org.eclipse.ocl.pivot.uml.internal.oclforuml.OCLforUMLPackage;
import org.eclipse.ocl.pivot.util.PivotPlugin;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.ocl.pivot.utilities.NameUtil;
import org.eclipse.ocl.pivot.utilities.ParserException;
import org.eclipse.ocl.pivot.utilities.PivotConstants;
import org.eclipse.ocl.pivot.utilities.PivotUtil;
import org.eclipse.ocl.pivot.utilities.TracingOption;
import org.eclipse.ocl.pivot.utilities.ValueUtil;
import org.eclipse.ocl.pivot.values.IntegerValue;
import org.eclipse.ocl.pivot.values.UnlimitedNaturalValue;
import org.eclipse.uml2.types.TypesPackage;
import org.eclipse.uml2.uml.OpaqueExpression;
import org.eclipse.uml2.uml.UMLPackage;
import org.eclipse.uml2.uml.resource.UMLResource;
import org.eclipse.uml2.uml.resources.util.UMLResourcesUtil;
import org.eclipse.uml2.uml.util.UMLUtil;

public abstract class UML2AS extends AbstractExternal2AS
{
	public static final @NonNull TracingOption ADD_ELEMENT_EXTENSION = new TracingOption(PivotPlugin.PLUGIN_ID, "uml2as/addElementExtension");
	public static final @NonNull TracingOption ADD_IMPORTED_RESOURCE = new TracingOption(PivotPlugin.PLUGIN_ID, "uml2as/addImportedResource");
	public static final @NonNull TracingOption ADD_PROFILE_APPLICATION = new TracingOption(PivotPlugin.PLUGIN_ID, "uml2as/addProfileApplication");
	public static final @NonNull TracingOption ADD_STEREOTYPE_APPLICATION = new TracingOption(PivotPlugin.PLUGIN_ID, "uml2as/addStereotypeApplication");
	public static final @NonNull TracingOption ADD_TYPE_EXTENSION = new TracingOption(PivotPlugin.PLUGIN_ID, "uml2as/addTypeExtension");
	public static final @NonNull TracingOption APPLICABLE_STEREOTYPES = new TracingOption(PivotPlugin.PLUGIN_ID, "uml2as/applicableStereotypes");
	public static final @NonNull TracingOption CONVERT_RESOURCE = new TracingOption(PivotPlugin.PLUGIN_ID, "uml2as/convertResource");
	public static final @NonNull TracingOption TYPE_EXTENSIONS = new TracingOption(PivotPlugin.PLUGIN_ID, "uml2as/typeExtensions");
	
	protected static final @NonNull String OCLforUML = ClassUtil.nonNullModel(NameUtil.getOriginalName(ClassUtil.nonNullModel(OCLforUMLPackage.eINSTANCE)));
	protected static final @NonNull String OCLforUML_COLLECTION = "OCLforUML::" + OCLforUMLPackage.Literals.COLLECTION.getName();
	protected static final @SuppressWarnings("null")@NonNull String OCLforUML_COLLECTION_IS_NULL_FREE_NAME = OCLforUMLPackage.Literals.COLLECTION__IS_NULL_FREE.getName();
	protected static final @NonNull String OCLforUML_COLLECTIONS = "OCLforUML::" + OCLforUMLPackage.Literals.COLLECTIONS.getName();
	protected static final @SuppressWarnings("null")@NonNull String OCLforUML_COLLECTIONS_IS_NULL_FREE_NAME = OCLforUMLPackage.Literals.COLLECTIONS__IS_NULL_FREE.getName();
	
	public static final @SuppressWarnings("null")@NonNull String STEREOTYPE_BASE_PREFIX = org.eclipse.uml2.uml.Extension.METACLASS_ROLE_PREFIX; //"base_";
	public static final @SuppressWarnings("null")@NonNull String STEREOTYPE_EXTENSION_PREFIX = org.eclipse.uml2.uml.Extension.STEREOTYPE_ROLE_PREFIX; //"extension_";

	private static final Logger logger = Logger.getLogger(UML2AS.class);

	public static @NonNull UML2AS getAdapter(@NonNull Resource resource, @NonNull EnvironmentFactoryInternal environmentFactory) {
		UMLStandaloneSetup.assertInitialized();
		UML2AS adapter = (UML2AS) findAdapter(resource, environmentFactory);
		if (adapter == null) {
			adapter = new Outer(resource, environmentFactory);
		}
		return adapter;
	}

	public static @Nullable String getBody(@NonNull OpaqueExpression opaqueExpression) {
		List<String> bodies = opaqueExpression.getBodies();
		List<String> languages = opaqueExpression.getLanguages();
		int bodiesSize = bodies.size();
		int languagesSize = languages.size();
		int i = 0;
		for ( ; i < languagesSize; i++) {
			if (PivotConstants.OCL_LANGUAGE.equals(languages.get(i))) {
				break;
			}
		}
		if (i < bodiesSize) {
			return bodies.get(i);
		}
		else {
			return null;
		}
	}

	/**
	 * Convert a UML resource to a Pivot Model.
	 * @param alias 
	 * 
	 * @param umlResource the UML resource
	 * 
	 * @return the Pivot root package
	 * @throws ParserException 
	 */
	public static Model importFromUML(@NonNull EnvironmentFactoryInternal environmentFactory, String alias, Resource umlResource) throws ParserException {
		if (umlResource == null) {
			return null;
		}
		UML2AS conversion = getAdapter(umlResource, environmentFactory);
		return conversion.getASModel();
	}

	/**
	 * Convert a UML object to a pivot element. 
	 * 
	 * @param eObject the UML object
	 * 
	 * @return the pivot element
	 * @throws ParserException 
	 */
	public static Element importFromUML(@NonNull EnvironmentFactoryInternal environmentFactory, String alias, EObject eObject) throws ParserException {
		if (eObject == null) {
			return null;
		}
		Resource umlResource = eObject.eResource();
		if (umlResource == null) {
			return null;
		}
		UML2AS conversion = getAdapter(umlResource, environmentFactory);
		@SuppressWarnings("unused")
		Model pivotModel = conversion.getASModel();
		return conversion.getCreated(Element.class, eObject);
	}

	public static void initialize() {
		IdManager.addMetamodelEPackage(ClassUtil.nonNullEMF(UMLPackage.eNS_URI), PivotConstants.UML_METAMODEL_NAME);
		IdManager.addMetamodelEPackage(ClassUtil.nonNullEMF(TypesPackage.eNS_URI), PivotConstants.TYPES_METAMODEL_NAME);
	}

	/**
	 * Initialize registries to support OCL and UML usage. This method is
	 * intended for initialization of standalone behaviors for which plugin extension
	 * registrations have not been applied.
	 *<p> 
	 * A null resourceSet may be provided to initialize the global package registry
	 * and global URI mapping registry.
	 *<p> 
	 * A non-null resourceSet may be provided to identify specific package
	 * and global URI mapping registries.
	 * <p>
	 * This method is used to configure the ResourceSet used to load the OCL Standard Library.

	 * @param resourceSet to be initialized or null for global initialization
	 * @return a failure reason, null if successful
	 */
	public static String initialize(@NonNull ResourceSet resourceSet) {
		UMLStandaloneSetup.init();
		UMLResourcesUtil.init(resourceSet);
		final String resourcesPluginId = "org.eclipse.uml2.uml.resources"; //$NON-NLS-1$
		String resourcesLocation = null;
		StandaloneProjectMap projectMap = StandaloneProjectMap.getAdapter(resourceSet);
		URI locationURI = projectMap.getLocation(resourcesPluginId);
		if (locationURI != null) {
			resourcesLocation = locationURI.toString();
			while (resourcesLocation.endsWith("/")) {
				resourcesLocation = resourcesLocation.substring(0, resourcesLocation.length()-1);
			}
		}
		if (resourcesLocation == null) {
			return "'" + resourcesPluginId + "' not found on class-path"; //$NON-NLS-1$
		}
		Map<URI, URI> uriMap = resourceSet.getURIConverter().getURIMap();		
		uriMap.put(URI.createURI(UMLResource.PROFILES_PATHMAP), URI.createURI(resourcesLocation + "/profiles/")); //$NON-NLS-1$
		uriMap.put(URI.createURI(UMLResource.METAMODELS_PATHMAP), URI.createURI(resourcesLocation + "/metamodels/")); //$NON-NLS-1$
		uriMap.put(URI.createURI(UMLResource.LIBRARIES_PATHMAP), URI.createURI(resourcesLocation + "/libraries/")); //$NON-NLS-1$
		return null;
	}
	public static String initialize(@NonNull StandaloneProjectMap projectMap) {
		UMLStandaloneSetup.init();
		UMLResourcesUtil.init(null);
		final String resourcesPluginId = "org.eclipse.uml2.uml.resources"; //$NON-NLS-1$
		String resourcesLocation = null;
		URI locationURI = projectMap.getLocation(resourcesPluginId);
		if (locationURI != null) {
			resourcesLocation = locationURI.toString();
			while (resourcesLocation.endsWith("/")) {
				resourcesLocation = resourcesLocation.substring(0, resourcesLocation.length()-1);
			}
		}
		if (resourcesLocation == null) {
			return "'" + resourcesPluginId + "' not found on class-path"; //$NON-NLS-1$
		}
		Map<URI, URI> uriMap = URIConverter.URI_MAP;		
		uriMap.put(URI.createURI(UMLResource.PROFILES_PATHMAP), URI.createURI(resourcesLocation + "/profiles/")); //$NON-NLS-1$
		uriMap.put(URI.createURI(UMLResource.METAMODELS_PATHMAP), URI.createURI(resourcesLocation + "/metamodels/")); //$NON-NLS-1$
		uriMap.put(URI.createURI(UMLResource.LIBRARIES_PATHMAP), URI.createURI(resourcesLocation + "/libraries/")); //$NON-NLS-1$
		return null;
	}

	public static boolean isUML(@NonNull Resource resource) {
		List<EObject> contents = resource.getContents();
		for (EObject content : contents) {
			if (content instanceof org.eclipse.uml2.uml.Package) {
				return true;
			}
		}
		return false;
	}

	public static UML2AS loadFromUML(@NonNull ASResource umlASResource, @NonNull URI umlURI) {
		EnvironmentFactoryInternal environmentFactory = PivotUtilInternal.getEnvironmentFactory(umlASResource);
		Resource umlResource = environmentFactory.getResourceSet().getResource(umlURI, true);
		if (umlResource == null) {
			return null;
		}
		UML2AS conversion = getAdapter(umlResource, environmentFactory);
		try {
			conversion.getASModel();
		} catch (ParserException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
/*		conversion.pivotModel = metamodelManager.createModel(umlURI.lastSegment(), umlResource.getURI().toString());
		conversion.update(umlASResource, umlResource.getContents());
		
		AliasAdapter ecoreAdapter = AliasAdapter.findAdapter(umlResource);
		if (ecoreAdapter != null) {
			Map<EObject, String> ecoreAliasMap = ecoreAdapter.getAliasMap();
			AliasAdapter pivotAdapter = AliasAdapter.getAdapter(umlASResource);
			Map<EObject, String> pivotAliasMap = pivotAdapter.getAliasMap();
			for (EObject eObject : ecoreAliasMap.keySet()) {
				String alias = ecoreAliasMap.get(eObject);
				Element element = conversion.newCreateMap.get(eObject);
				pivotAliasMap.put(element, alias);
			}
		}
		metamodelManager.installResource(umlASResource);
		conversion.installImports(); */
		return conversion;
	}
	
	/**
	 * A UML2AS$Inner adapts an unconverted UML resource that has been imported during
	 * the conversion of some other UML resource.
	 */
	public static class Inner extends UML2AS
	{		
		protected final @NonNull Outer root;
		
		protected Inner(@NonNull Resource umlResource, @NonNull Outer root) {
			super(umlResource, root.getEnvironmentFactory());
			this.root = root;
		}
		
		@Override
		public void addCreated(@NonNull EObject umlElement, @NonNull Element pivotElement) {
			root.addCreated(umlElement, pivotElement);
		}

		@Override
		public void addGenericType(@NonNull EGenericType eObject) {
			root.addGenericType(eObject);
		}

		@Override
		public void addImportedResource(@NonNull Resource importedResource) {
			root.addImportedResource(importedResource);
		}
		
		@Override
		public void addMapping(@NonNull EObject eObject, @NonNull Element pivotElement) {
			root.addMapping(eObject, pivotElement);
		}

		@Override
		public void addProfileApplication(@NonNull ProfileApplication asProfileApplication) {
			root.addProfileApplication(asProfileApplication);
		}

		@Override
		public void addProperty(org.eclipse.ocl.pivot.@NonNull Class asType, @NonNull Property asProperty) {
			root.addProperty(asType, asProperty);
		}

		@Override
		public void addStereotype(@NonNull Stereotype asStereotype) {
			root.addStereotype(asStereotype);
		}

		@Override
		public void addStereotypeApplication(@NonNull EObject stereotypeApplication) {
			root.addStereotypeApplication(stereotypeApplication);
		}

		@Override
		public void addTypeExtension(@NonNull StereotypeExtender asTypeExtension) {
			root.addTypeExtension(asTypeExtension);
		}

		@Override
		public void error(@NonNull String message) {
			root.error(message);
		}	

		@Override
		public <T extends Element> T getASElement(@NonNull Class<T> requiredClass, @NonNull EObject eObject) {
			return root.getASElement(requiredClass, eObject);
		}

		@Override
		public @NonNull Model getASModel() throws ParserException {
			Model pivotModel2 = pivotModel;
			if (pivotModel2 == null) {
				pivotModel2 = root.getASModel();
				Resource asResource = pivotModel.eResource();
				if (asResource == null) {
					throw new IllegalStateException("Missing containing resource");
				}
//				installAliases(asResource);
				metamodelManager.installResource(asResource);
			}
			return pivotModel2;
		}

		@Override
		public @Nullable Type getASType(@NonNull EObject eObject) {
			return root.getASType(eObject);
		}

		@Override
		public <T extends Element> @Nullable T getCreated(@NonNull Class<T> requiredClass, @NonNull EObject eObject) {
			return root.getCreated(requiredClass, eObject);
		}

		@Override
		public @Nullable Map<EObject, Element> getCreatedMap() {
			return root.getCreatedMap();
		}
		
		@Override
		public @NonNull UML2ASDeclarationSwitch getDeclarationPass() {
			return root.getDeclarationPass();
		}
		
		@Override
		public @NonNull Outer getRoot() {
			return root;
		}

		@Override
		public void queueReference(@NonNull EObject umlElement) {
			root.queueReference(umlElement);
		}

		@Override
		public void queueUse(@NonNull EObject umlElement) {
			root.queueUse(umlElement);
		}
		
		@Override
		public void resolveMultiplicity(@NonNull TypedElement pivotElement, org.eclipse.uml2.uml.@NonNull TypedElement umlTypedElement) {
			root.resolveMultiplicity(pivotElement, umlTypedElement);
		}
	}
	
	/**
	 * A UML2AS$Outer adapts an unconverted UML resource and hosts the additional conversions
	 * necessary for imported UML resources.
	 */
	public static class Outer extends UML2AS
	{		
		/**
		 * Mapping of source UML objects to their resulting pivot element.
		 */
		private @NonNull Map<EObject, Element> createMap = new HashMap<EObject, Element>();

		/**
		 * Set of all UML objects requiring further work during the reference pass.
		 */
		private @NonNull Set<EObject> referencers = new HashSet<EObject>();

		/**
		 * Set of all UML objects requiring further work after the reference pass.
		 */
		private @NonNull Set<EObject> users = new HashSet<EObject>();
		
		/**
		 * Set of all converters used during session.
		 */
		private @NonNull Set<UML2AS> allConverters = new HashSet<UML2AS>();
		
		private List<Resource.Diagnostic> errors = null;

		protected final @NonNull ProfileAnalysis profileAnalysis = new ProfileAnalysis(this);
		protected final @NonNull ModelAnalysis modelAnalysis = new ModelAnalysis(this, profileAnalysis);
		protected final @NonNull UML2ASDeclarationSwitch declarationPass = new UML2ASDeclarationSwitch(this);	
		protected final @NonNull UML2ASReferenceSwitch referencePass = new UML2ASReferenceSwitch(this);
		protected final @NonNull UML2ASUseSwitch usePass = new UML2ASUseSwitch(this);
		private @Nullable List<Resource> importedResources = null;

//		private @NonNull Set<org.eclipse.uml2.uml.Property> umlProperties = new HashSet<org.eclipse.uml2.uml.Property>();
		private @NonNull Map<org.eclipse.ocl.pivot.Class, List<Property>> type2properties = new HashMap<org.eclipse.ocl.pivot.Class, List<Property>>();
//		private @NonNull Map<Type, List<Property>> stereotypeProperties = new HashMap<Type, List<Property>>();
		private final @NonNull Map<org.eclipse.uml2.uml.NamedElement, Boolean> namedElement2isNullFree = new HashMap<org.eclipse.uml2.uml.NamedElement, Boolean>();;

		protected Outer(@NonNull Resource umlResource, @NonNull EnvironmentFactoryInternal environmentFactory) {
			super(umlResource, environmentFactory);
		}
		
		@Override
		public void addCreated(@NonNull EObject eObject, @NonNull Element pivotElement) {
//			if ((eObject instanceof ENamedElement) && "EnglishClass".equals(((ENamedElement)eObject).getName())) {
//				System.out.println("Define " + ClassUtil.debugSimpleName(eObject) + " => " + ClassUtil.debugSimpleName(pivotElement));
//			}
//			else if ((eObject instanceof org.eclipse.uml2.uml.NamedElement) && "EnglishClass".equals(((org.eclipse.uml2.uml.NamedElement)eObject).getName())) {
//				System.out.println("Define " + ClassUtil.debugSimpleName(eObject) + " => " + ClassUtil.debugSimpleName(pivotElement));
//			}
			@SuppressWarnings("unused")
			Element oldElement = createMap.put(eObject, pivotElement);
/*			if ((oldElement != null) && (oldElement != pivotElement)) {
				System.out.println("Reassigned : " + eObject);
			}
			else if (eObject instanceof EAnnotation) {
//				System.out.println("Assigned : " + eObject);
			}
			else {
//				System.out.println("Assigned : " + eObject);
			} */
		}

		@Override
		public void addGenericType(@NonNull EGenericType eObject) {
//			throw new UnsupportedOperationException();				// FIXME		
		}

		@Override
		public void addImportedResource(@NonNull Resource importedResource) {
			if (importedResource != umlResource) {
				List<Resource> importedResources2 = importedResources;
				if (importedResources2 == null) {
					importedResources = importedResources2 = new ArrayList<Resource>();
				}
				if (!importedResources2.contains(importedResource)) {
					URI uri = importedResource.getURI();
					if (ADD_IMPORTED_RESOURCE.isActive()) {
						ADD_IMPORTED_RESOURCE.println(String.valueOf(uri));
					}
//					if (UMLResource.UML_METAMODEL_URI.equals(uri.toString())) {
//						repairMetamodel(importedResource);
//					}
					importedResources2.add(importedResource);
				}
			}
		}
		
/*		private void repairMetamodel(Resource resource) {
			for (TreeIterator<EObject> tit = resource.getAllContents(); tit.hasNext(); ) {
				EObject eObject = tit.next();
				if (eObject instanceof org.eclipse.uml2.uml.OpaqueExpression) {
					org.eclipse.uml2.uml.OpaqueExpression opaqueExpression = (org.eclipse.uml2.uml.OpaqueExpression) eObject;
					EObject eContainer1 = opaqueExpression.eContainer();
					EObject eContainer2 = eContainer1 != null ? eContainer1.eContainer() : null;
//					String body = opaqueExpression.getBodies().size() > 0 ? opaqueExpression.getBodies().get(0) : null;
					String name1 = eContainer1 instanceof org.eclipse.uml2.uml.NamedElement ? ((org.eclipse.uml2.uml.NamedElement)eContainer1).getName() : "<null>";
					String name2 = eContainer2 instanceof org.eclipse.uml2.uml.NamedElement ? ((org.eclipse.uml2.uml.NamedElement)eContainer2).getName() : "<null>";
					String key = name2 + "::" + name1;
					if (!(eContainer2 instanceof org.eclipse.uml2.uml.Type)) {
						EObject eContainer3 = eContainer2 != null ? eContainer2.eContainer() : null;
						String name3 = eContainer3 instanceof org.eclipse.uml2.uml.NamedElement ? ((org.eclipse.uml2.uml.NamedElement)eContainer3).getName() : "<null>";
						key = name3 + "::" + key;
					}
//					System.out.println(key + " " + body);
				}
			}
		} */

		@Override
		public void addMapping(@NonNull EObject eObject, @NonNull Element pivotElement) {
			if (pivotElement instanceof PivotObjectImpl) {
				((PivotObjectImpl)pivotElement).setESObject(eObject);
			}
			addCreated(eObject, pivotElement);
		}

		@Override
		public void addProfileApplication(@NonNull ProfileApplication asProfileApplication) {
			modelAnalysis.addProfileApplication(asProfileApplication);
		}

		@Override
		public void addProperty(org.eclipse.ocl.pivot.@NonNull Class asType, @NonNull Property asProperty) {
			List<Property> asProperties = type2properties.get(asType);
			if (asProperties == null) {
				asProperties = new ArrayList<Property>();
				type2properties.put(asType, asProperties);
			}
			asProperties.add(asProperty);
		}

		@Override
		public void addStereotype(@NonNull Stereotype asStereotype) {
			profileAnalysis.addStereotype(asStereotype);
		}

		@Override
		public void addStereotypeApplication(@NonNull EObject stereotypeApplication) {
			modelAnalysis.addStereotypeApplication(stereotypeApplication);
		}

		@Override
		public void addTypeExtension(@NonNull StereotypeExtender asTypeExtension) {
			profileAnalysis.addTypeExtension(asTypeExtension);
		}

		@Override
		public void error(@NonNull String message) {
			if (errors == null) {
				errors = new ArrayList<Resource.Diagnostic>();
			}
			errors.add(new XMIException(message));
		}

/*		protected org.eclipse.uml2.uml.Property getOtherEnd(org.eclipse.uml2.uml.@NonNull Property umlProperty) {
			org.eclipse.uml2.uml.Property otherEnd = umlProperty.getOtherEnd();
			if (otherEnd != null) {
				return otherEnd;
			}
			// Workaround problem whereby UML has three ends two of them duplicates with distinct Class/Association ownership.
			org.eclipse.uml2.uml.Association association = umlProperty.getAssociation();
			if (association != null) {
				List<org.eclipse.uml2.uml.Property> memberEnds = new ArrayList<org.eclipse.uml2.uml.Property>(association.getMemberEnds());
				memberEnds.remove(umlProperty);
				for (org.eclipse.uml2.uml.Property aProperty : memberEnds) {
					if (!aProperty.getName().equals(umlProperty)) {
						return aProperty;
					}
				}
			}
			return otherEnd;
		} */

		@Override
		public <T extends Element> T getASElement(@NonNull Class<T> requiredClass, @NonNull EObject eObject) {
			Element pivotElement = createMap.get(eObject);
			if (pivotElement == null) {
				Resource resource = eObject.eResource();
				if ((resource != umlResource) && (resource != null)) {
					UML2AS converter = getAdapter(resource, environmentFactory);
					if (allConverters.add(converter)) {
						try {
							converter.getASModel();
						} catch (ParserException e) {
							@SuppressWarnings("null") @NonNull String message = e.getMessage();
							error(message);
						}
//						allEClassifiers.addAll(converter.allEClassifiers);
//						allNames.addAll(converter.allNames);
//						for (Map.Entry<EModelElement, Element> entry : converter.createMap.entrySet()) {
//							createMap.put(entry.getKey(), entry.getValue());
//						}
					}
				}
				pivotElement = createMap.get(eObject);
			}
			if (pivotElement == null) {
				error("Unresolved " + eObject);
			}
			else if (!requiredClass.isAssignableFrom(pivotElement.getClass())) {
				throw new ClassCastException(pivotElement.getClass().getName() + " is not assignable to " + requiredClass.getName());
			}
			@SuppressWarnings("unchecked")
			T castElement = (T) pivotElement;
			return castElement;
		}

		@Override
		public @NonNull Model getASModel() throws ParserException {
			Model pivotModel2 = pivotModel;
			if (pivotModel2 == null) {
				URI pivotURI = createPivotURI();
				ASResource asResource = metamodelManager.getResource(pivotURI, ASResource.UML_CONTENT_TYPE);
				try {
					pivotModel2 = installDeclarations(asResource);					
//					Map<String, Type> resolvedSpecializations = new HashMap<String, Type>();
//					for (EGenericType eGenericType : genericTypes) {
//						Type pivotType = resolveType(resolvedSpecializations, eGenericType);
//						createMap.put(eGenericType, pivotType);
//					}
//					for (List<TemplateableElement> pivotElements : specializations.values()) {
//						for (TemplateableElement pivotElement : pivotElements) {
//							metamodelManager.addOrphanType((Type)pivotElement);
//						}
//					}
					installImports();
					installReferencers();
					modelAnalysis.installStereotypes();
					installProperties();
					installUsers();
				}
				catch (Exception e) {
//					if (errors == null) {
//						errors = new ArrayList<Resource.Diagnostic>();
//					}
//					errors.add(new XMIException("Failed to load '" + pivotURI + "' : " + e.getMessage()));
					throw new ParserException(e, "Failed to load '" + pivotURI + "' : " + e.getMessage());
				}
				if (errors != null) {
					asResource.getErrors().addAll(errors);
				}
				installAliases(asResource);
				metamodelManager.installResource(asResource);
				ResourceSet resourceSet = umlResource.getResourceSet();
				if (resourceSet != null) {
					environmentFactory.addExternalResources(resourceSet);				// FIXME redundant ?? -- no updates URIResourceMap
				}
			}
			return pivotModel2;
		}

		@Override
		public Type getASType(@NonNull EObject eObject) {
			Element pivotElement = createMap.get(eObject);
			if (pivotElement == null) {
				Resource resource = eObject.eResource();
				if ((resource != umlResource) && (resource != null)) {
					UML2AS converter = getAdapter(resource, environmentFactory);
					if (allConverters.add(converter)) {
						try {
							converter.getASModel();
						} catch (ParserException e) {
							@SuppressWarnings("null") @NonNull String message = e.getMessage();
							error(message);
						}
//						allEClassifiers.addAll(converter.allEClassifiers);
//						allNames.addAll(converter.allNames);
//						for (Map.Entry<EModelElement, Element> entry : converter.createMap.entrySet()) {
//							createMap.put(entry.getKey(), entry.getValue());
//						}
					}
				}
				pivotElement = createMap.get(eObject);
			}
			if (pivotElement == null) {
				error("Unresolved " + eObject);
			}
			else if (!(pivotElement instanceof Type)) {
				error("Incompatible " + eObject);
			}
			else {
				return (Type) pivotElement;
			}
			return null;
		}

		@Override
		public <T extends Element> @Nullable T getCreated(@NonNull Class<T> requiredClass, @NonNull EObject eObject) {
			Element element = createMap.get(eObject);
			if (element == null) {
				Resource resource = eObject.eResource();
				if (resource == umlResource) {
					return null;
				}
				List<Resource> importedResources2 = importedResources;
				if ((importedResources2 != null) && importedResources2.contains(resource)) {
					return null;
				}
				try {
					return metamodelManager.getASOf(requiredClass, eObject);
				} catch (ParserException e) {
					return null;		// Never happens since UML element will never be a parsed one such as an OCLExpression 
				}
			}
			if (!requiredClass.isAssignableFrom(element.getClass())) {
				logger.error("UML " + element.getClass().getName() + "' element is not a '" + requiredClass.getName() + "'"); //$NON-NLS-1$
				return null;
			}
			@SuppressWarnings("unchecked")
			T castElement = (T) element;
			return castElement;
		}

		@Override
		public @Nullable Map<EObject, Element> getCreatedMap() {
			return createMap;
		}
		
		@Override
		public final @NonNull UML2ASDeclarationSwitch getDeclarationPass() {
			return declarationPass;
		}
		
		public @Nullable List<Resource> getImportedResources() {
			return importedResources;
		}

/*		protected org.eclipse.uml2.uml.Property getOtherEnd(org.eclipse.uml2.uml.@NonNull Property umlProperty) {
			org.eclipse.uml2.uml.Property otherEnd = umlProperty.getOtherEnd();
			if (otherEnd != null) {
				return otherEnd;
			}
			// Workaround problem whereby UML has three ends two of them duplicates with distinct Class/Association ownership.
			org.eclipse.uml2.uml.Association association = umlProperty.getAssociation();
			if (association != null) {
				List<org.eclipse.uml2.uml.Property> memberEnds = new ArrayList<org.eclipse.uml2.uml.Property>(association.getMemberEnds());
				memberEnds.remove(umlProperty);
				for (org.eclipse.uml2.uml.Property aProperty : memberEnds) {
					if (!aProperty.getName().equals(umlProperty)) {
						return aProperty;
					}
				}
			}
			return otherEnd;
		} */

		@Override
		public @NonNull Outer getRoot() {
			return this;
		}

		protected void installAliases(@NonNull Resource asResource) {
			AliasAdapter umlAdapter = AliasAdapter.findAdapter(umlResource);
			if (umlAdapter != null) {
				Map<EObject, String> umlAliasMap = umlAdapter.getAliasMap();
				AliasAdapter pivotAdapter = AliasAdapter.getAdapter(asResource);
				Map<EObject, String> pivotAliasMap = pivotAdapter.getAliasMap();
				for (EObject eObject : umlAliasMap.keySet()) {
					String alias = umlAliasMap.get(eObject);
					Element element = createMap.get(eObject);
					pivotAliasMap.put(element, alias);
				}
			}
		}

		protected void installImports() throws ParserException {
			List<Resource> importedResources2 = importedResources;
			if (importedResources2 != null) {
				for (int i = 0; i < importedResources2.size(); i++) {			// List may grow re-entrantly
					Resource importedResource = importedResources2.get(i);
					if (importedResource instanceof UMLResource) {
						External2AS adapter = UML2AS.findAdapter(importedResource, environmentFactory);
						if (adapter == null) {
							Inner importedAdapter = new Inner(importedResource, this);
							URI pivotURI = importedAdapter.createPivotURI();
							ASResource asResource = metamodelManager.getResource(pivotURI, ASResource.UML_CONTENT_TYPE);
							importedAdapter.installDeclarations(asResource);
							adapter = importedAdapter;
							metamodelManager.installResource(asResource);
						}
						else {
							Map<EObject, Element> importedCreatedMap = adapter.getCreatedMap();
							if (importedCreatedMap != null) {
								createMap.putAll(importedCreatedMap);
							}
						}
					}
					else if (importedResource != null) {
						environmentFactory.loadResource(importedResource, null);
					}
				}
			}
		}

		protected void installProperties() {
/*			Map<Type, List<org.eclipse.uml2.uml.Property>> typeProperties = new HashMap<Type, List<org.eclipse.uml2.uml.Property>>();
			List<org.eclipse.uml2.uml.Property> sortedList = new ArrayList<org.eclipse.uml2.uml.Property>(umlProperties);
			Collections.sort(sortedList, new Comparator<org.eclipse.uml2.uml.Property>() {

				public int compare(org.eclipse.uml2.uml.Property o1, org.eclipse.uml2.uml.Property o2) {
					String n1 = o1.getName();
					String n2 = o2.getName();
					return n1 == n2 ? 0 : (n1 != null) && (n2 != null) ? n1.compareTo(n2) : n2 == null ? 1 : -1;
				}
				
			});
			for (org.eclipse.uml2.uml.Property umlProperty : sortedList) {
				Property asProperty = getCreated(Property.class, umlProperty);
				Property asOppositeProperty = asProperty != null ? asProperty.getOpposite() : null;
//				if ("executionSpecification".equals(umlProperty.getName())) {
//					System.out.println("Install " + umlProperty);
//				}
				Type pivotType = null;
				EObject umlOwner = ClassUtil.nonNullEMF(umlProperty.eContainer());
				if (umlOwner instanceof org.eclipse.uml2.uml.Association) {
//					String name = ((org.eclipse.uml2.uml.NamedElement)umlProperty.eContainer()).getName();
//					if (name != null) {
//						System.out.println("Assoc Property " + name + "::" + umlProperty.getName());
//					}
//					else {
//						System.out.println("Anon Assoc Property " + name + "::" + umlProperty.getName());
//					}
					org.eclipse.uml2.uml.Property opposite = getOtherEnd(umlProperty);
					if (opposite != null) {
						pivotType = getCreated(Type.class, ClassUtil.nonNullModel(opposite.getType()));
					}
					else {
//						System.out.println("*****************Missing opposite");
					}
				}
				else {
					pivotType = getCreated(Type.class, umlOwner);
				}
				if (pivotType != null) {
					List<org.eclipse.uml2.uml.Property> someProperties = typeProperties.get(pivotType);
					if (someProperties == null) {
						someProperties = new ArrayList<org.eclipse.uml2.uml.Property>();
						typeProperties.put(pivotType, someProperties);
					}
					String name = umlProperty.getName();
					if (name == null) {
//						System.out.println("Unnamed " + pivotType.getName() + "::" + umlProperty.getName());
						name = umlProperty.getType().getName();
					}
					else {
/*						for (org.eclipse.uml2.uml.Property aProperty : someProperties) {
							String aName = aProperty.getName();
							if (name.equals(aName)) {
								System.out.println("Ambiguous " + pivotType.getName() + "::" + umlProperty.getName());
								org.eclipse.uml2.uml.Property opp1 = umlProperty.getOtherEnd();
								if (opp1 != null) {
									System.out.println("  opposite " + umlProperty.getType().getName() + "::" + opp1.getName() + " " + (umlProperty.getClass_() != null));
								}
								org.eclipse.uml2.uml.Property opp2 = aProperty.getOtherEnd();
								if (opp2 != null) {
									System.out.println("  opposite " + umlProperty.getType().getName() + "::" + opp2.getName() + " " + (aProperty.getClass_() != null));
								}
							}
						} * /
						someProperties.add(umlProperty);
					}
				}
				else {
					org.eclipse.uml2.uml.Property opposite = getOtherEnd(umlProperty);
					if (opposite != null) {
						org.eclipse.uml2.uml.Type oppositeType = ClassUtil.nonNullEMF(opposite.getType());
						pivotType = getCreated(Type.class, oppositeType);
					}
//					System.out.println("*****************Missing opposite type");
				}
			}
			Set<Type> allPropertiedTypes = new HashSet<Type>(typeProperties.keySet()); */
//			allPropertiedTypes.addAll(stereotypeProperties.keySet());
			for (org.eclipse.ocl.pivot.Class pivotType : type2properties.keySet()) {
				List<Property> asProperties = type2properties.get(pivotType);
				Collections.sort(asProperties, NameUtil.NAMEABLE_COMPARATOR);
				refreshList(ClassUtil.nonNullEMF(pivotType.getOwnedProperties()), asProperties);
			}
		}

		protected void installReferencers() {
			for (EObject eObject : referencers) {
				referencePass.doSwitch(eObject);
			}
		}

		protected void installUsers() {
			for (EObject eObject : users) {
				usePass.doSwitch(eObject);
			}
		}

		@Override
		public void queueReference(@NonNull EObject umlElement) {
			referencers.add(umlElement);
		}

		@Override
		public void queueUse(@NonNull EObject umlElement) {
			users.add(umlElement);
		}
		
		private @NonNull Boolean isNullFree(@Nullable EObject eObject) {
			if (eObject == null) {
				return ValueUtil.FALSE_VALUE;
			}
			else if ((eObject instanceof org.eclipse.uml2.uml.Class) || (eObject instanceof org.eclipse.uml2.uml.Package)) {
				org.eclipse.uml2.uml.NamedElement umlElement = (org.eclipse.uml2.uml.NamedElement)eObject;
				Boolean isNullFree = namedElement2isNullFree.get(umlElement);
				if (isNullFree == null) {
					org.eclipse.uml2.uml.Stereotype umlStereotype = umlElement.getAppliedStereotype(OCLforUML_COLLECTIONS);
					if (umlStereotype != null) {
						Object value = umlElement.getValue(umlStereotype, OCLforUML_COLLECTIONS_IS_NULL_FREE_NAME);
						if (value instanceof Boolean) {
							isNullFree = (Boolean)value;
						}
					}
					if (isNullFree == null) {
						isNullFree = isNullFree(umlElement.eContainer());
					}
					namedElement2isNullFree.put(umlElement, isNullFree);
				}
				return isNullFree;
			}
			else {
				return isNullFree(eObject.eContainer());
			}
		}

		@Override
		public void resolveMultiplicity(@NonNull TypedElement pivotElement, org.eclipse.uml2.uml.@NonNull TypedElement umlTypedElement) {
			boolean isRequired = false;
			org.eclipse.uml2.uml.Type umlType = umlTypedElement.getType();
			if (umlType != null) {
				Type pivotType = resolveType(umlType);
				if ((umlTypedElement instanceof org.eclipse.uml2.uml.MultiplicityElement) && (pivotType != null)) {
					org.eclipse.uml2.uml.MultiplicityElement umlMultiplicity = (org.eclipse.uml2.uml.MultiplicityElement)umlTypedElement;
					int lower = umlMultiplicity.getLower();
					int upper = umlMultiplicity.getUpper();
					if (upper == 1) {
						isRequired = lower == 1;
					}
					else {
						isRequired = true;
						boolean isOrdered = umlMultiplicity.isOrdered();
						boolean isUnique = umlMultiplicity.isUnique();
						Boolean isNullFree = null;
						org.eclipse.uml2.uml.Stereotype umlStereotype = umlMultiplicity.getAppliedStereotype(OCLforUML_COLLECTION);
						if (umlStereotype != null) {
							Object value = umlMultiplicity.getValue(umlStereotype, OCLforUML_COLLECTION_IS_NULL_FREE_NAME);
							if (value instanceof Boolean) {
								isNullFree = (Boolean)value;
							}
						}
						if (isNullFree == null) {
							isNullFree = isNullFree(umlMultiplicity.eContainer());
						}
						IntegerValue lowerValue = ValueUtil.integerValueOf(lower);
						UnlimitedNaturalValue upperValue = upper == -1 ? ValueUtil.UNLIMITED_VALUE : ValueUtil.unlimitedNaturalValueOf(upper);
						pivotType = environmentFactory.getMetamodelManager().getCollectionType(isOrdered, isUnique, pivotType, isNullFree == Boolean.TRUE, lowerValue, upperValue);
					}
				}
				pivotElement.setType(pivotType);
			}
			else {
				pivotElement.setType(standardLibrary.getOclVoidType());
			}
			pivotElement.setIsRequired(isRequired);
		}
	}
	
	protected final @NonNull Resource umlResource;	
	protected Model pivotModel = null;	// Set by installDeclarations
	private URI umlURI = null;;
	
	protected UML2AS(@NonNull Resource umlResource, @NonNull EnvironmentFactoryInternal environmentFactory) {
		super(environmentFactory);
		if (CONVERT_RESOURCE.isActive()) {
			CONVERT_RESOURCE.println(umlResource.getURI().toString());
		}
		this.umlResource = umlResource;
//		umlResource.eAdapters().add(this);
		environmentFactory.addExternal2AS(this);
//		metamodelManager.addListener(this);
		CompleteModel completeModel = environmentFactory.getCompleteModel();
		completeModel.addPackageURI2completeURI(ClassUtil.nonNullEMF(UMLPackage.eNS_URI), PivotConstants.UML_METAMODEL_NAME);
		completeModel.addPackageURI2completeURI(ClassUtil.nonNullEMF(TypesPackage.eNS_URI), PivotConstants.TYPES_METAMODEL_NAME);		// FIXME All known synonyms
		// FIXME All known synonyms
	}
	
	public abstract void addCreated(@NonNull EObject umlElement, @NonNull Element pivotElement);

	public void addImportedPackage(org.eclipse.uml2.uml.@NonNull Package importedPackage) {
		EObject rootContainer = EcoreUtil.getRootContainer(importedPackage);
		Resource importedResource = ClassUtil.nonNullEMF(rootContainer.eResource());
		addImportedResource(importedResource);
	}

	public void addImportedPackages(@NonNull List<? extends org.eclipse.uml2.uml.Package> importedPackages) {
		for (org.eclipse.uml2.uml.Package importedPackage : importedPackages) {
			if (importedPackage != null) {
				addImportedPackage(importedPackage);
			}
		}
	}

	public abstract void addImportedResource(@NonNull Resource importedResource);

	public abstract void addProfileApplication(@NonNull ProfileApplication asProfileApplication) ;

	public abstract void addProperty(org.eclipse.ocl.pivot.@NonNull Class asType, @NonNull Property asProperty);

	public abstract void addStereotype(@NonNull Stereotype asStereotype);

	public abstract void addStereotypeApplication(@NonNull EObject stereotypeApplication);

	public abstract void addTypeExtension(@NonNull StereotypeExtender asTypeExtension);

	@Override
	protected Model basicGetPivotModel() {
		return pivotModel;
	}

	public void copyModelElement(@NonNull Element pivotElement, org.eclipse.uml2.uml.@NonNull Element umlElement) {
		setOriginalMapping(pivotElement, umlElement);
	}

	public void copyNamedElement(@NonNull NamedElement pivotElement, org.eclipse.uml2.uml.@NonNull NamedElement umlNamedElement) {
		copyModelElement(pivotElement, umlNamedElement);
		String name = umlNamedElement.getName();
		pivotElement.setName(name);
//		copyAnnotatedElement(pivotElement, umlNamedElement, null);
//		copyComments(pivotElement, umlNamedElement);
	}

	protected @NonNull URI createPivotURI() {
		URI uri = umlResource.getURI();
		if (uri == null) {
			throw new IllegalStateException("Missing resource URI");
		}
		return PivotUtilInternal.getASURI(uri);
	}
	
	@Override
	public abstract void error(@NonNull String message);
	
	public abstract @Nullable Type getASType(@NonNull EObject eObject);

	public abstract @NonNull UML2ASDeclarationSwitch getDeclarationPass();
	
	@Override
	public @NonNull Resource getResource() {
		return umlResource;
	}
	
	public abstract @NonNull Outer getRoot();

	@Override
	public @NonNull URI getURI() {
		return ClassUtil.nonNullState(umlResource.getURI());
	}

	protected @NonNull Model installDeclarations(@NonNull Resource asResource) {
		URI pivotURI = asResource.getURI();
		Model pivotModel2 = pivotModel = PivotUtil.createModel(umlURI != null ? umlURI.toString() : pivotURI.toString());
		asResource.getContents().add(pivotModel2);
		UML2ASDeclarationSwitch declarationPass = getDeclarationPass();
		List<org.eclipse.ocl.pivot.Package> rootPackages = new ArrayList<org.eclipse.ocl.pivot.Package>();
		for (EObject eObject : umlResource.getContents()) {
			Object pivotElement = declarationPass.doSwitch(eObject);
			if (pivotElement instanceof org.eclipse.ocl.pivot.Package) {
				rootPackages.add((org.eclipse.ocl.pivot.Package) pivotElement);
			}
			else if (pivotElement != null) {			// Ignore stereotypes 
				error("Bad UML content : " + eObject.eClass().getName());
			}
		}
		PivotUtilInternal.refreshList(pivotModel2.getOwnedPackages(), rootPackages);
		return pivotModel2;
	}

	protected boolean isPivot(@NonNull Collection<EObject> umlContents) {
		if (umlContents.size() != 1) {
			return false;
		}
		EObject umlRoot = umlContents.iterator().next();
		if (!(umlRoot instanceof EPackage)) {
			return false;
		}
		EPackage umlPackage = (EPackage) umlRoot;
		if (umlPackage.getEClassifier(PivotPackage.Literals.ENUMERATION_LITERAL.getName()) == null) {
			return false;
		}
		if (umlPackage.getEClassifier(PivotPackage.Literals.EXPRESSION_IN_OCL.getName()) == null) {
			return false;
		}
		if (umlPackage.getEClassifier(PivotPackage.Literals.OPERATION_CALL_EXP.getName()) == null) {
			return false;
		}
		if (umlPackage.getEClassifier(PivotPackage.Literals.TEMPLATE_PARAMETER_SUBSTITUTION.getName()) == null) {
			return false;
		}
		return true;
	}

	public abstract void queueUse(@NonNull EObject eObject);

/*	protected void refreshAnnotation(NamedElement pivotElement, String key, String value) {
		String source = PIVOT_URI;
		Annotation pivotAnnotation = null;
		for (Annotation annotation : pivotElement.getOwnedAnnotation()) {
			if (annotation.getName().equals(source)) {
				pivotAnnotation = annotation;
				break;
			}
		}
		if (pivotAnnotation == null) {
			pivotAnnotation = PivotFactory.eINSTANCE.createAnnotation();
			pivotAnnotation.setName(source);
			pivotElement.getOwnedAnnotation().add(pivotAnnotation);
		}
		Detail pivotDetail = PivotFactory.eINSTANCE.createDetail();
		pivotDetail.setName(key);
		pivotDetail.getValue().add(value);
		pivotAnnotation.getOwnedDetail().add(pivotDetail);
	} */

	protected @NonNull <T extends Element> T refreshElement(@NonNull Class<T> pivotClass, /*@NonNull*/ EClass pivotEClass, @NonNull EObject umlElement) {
		assert pivotEClass != null;
		EFactory eFactoryInstance = pivotEClass.getEPackage().getEFactoryInstance();
		EObject pivotElement = eFactoryInstance.create(pivotEClass);
		if (!pivotClass.isAssignableFrom(pivotElement.getClass())) {
			throw new ClassCastException();
		}
		@SuppressWarnings("unchecked")
		T castElement = (T) pivotElement;
		return castElement;
	}

	protected @NonNull <T extends NamedElement> T refreshNamedElement(@NonNull Class<T> pivotClass,
			/*@NonNull*/ EClass pivotEClass, org.eclipse.uml2.uml.@NonNull NamedElement umlNamedElement) {
		assert pivotEClass != null;
		EFactory eFactoryInstance = pivotEClass.getEPackage().getEFactoryInstance();
		EObject pivotElement = eFactoryInstance.create(pivotEClass);
		if (!pivotClass.isAssignableFrom(pivotElement.getClass())) {
			throw new ClassCastException();
		}
		@SuppressWarnings("unchecked")
		T castElement = (T) pivotElement;
		castElement.setName(umlNamedElement.getName());
		return castElement;
	}

	public ExpressionInOCL refreshOpaqueExpression(org.eclipse.uml2.uml.@NonNull OpaqueExpression umlExpression) {
		ExpressionInOCL pivotElement = refreshNamedElement(ExpressionInOCL.class, PivotPackage.Literals.EXPRESSION_IN_OCL, umlExpression);
		pivotElement.setBody(null);
		List<String> umlBodies = umlExpression.getBodies();
		List<String> umlLanguages = umlExpression.getLanguages();
		for (int i = 0; i < umlBodies.size(); i++) {
			String asLanguage = PivotConstants.OCL_LANGUAGE;
			if (i < umlLanguages.size()) {		// languages are optional, with defaults implementation defined ==> OCL
				String umlLanguage = umlLanguages.get(i);
				if ((umlLanguage != null) && (umlLanguage.length() > 0)) {
					asLanguage = umlLanguage;
				}
			}
			String umlBody = umlBodies.get(i);
			if ((umlBody != null) && asLanguage.equals(PivotConstants.OCL_LANGUAGE)) {
				EObject eContainer = umlExpression.eContainer();
				if (eContainer instanceof org.eclipse.uml2.uml.Constraint) {
					EObject eContainerContainer = eContainer.eContainer();
					if (eContainerContainer instanceof org.eclipse.uml2.uml.Operation) {
						org.eclipse.uml2.uml.Operation umlOperation = (org.eclipse.uml2.uml.Operation)eContainerContainer;
						if (umlOperation.getBodyCondition() == eContainer) {
							umlBody = PivotUtilInternal.getBodyExpression(umlBody);
						}
					}
				}
			}
			pivotElement.setBody(umlBody);
		}
		copyNamedElement(pivotElement, umlExpression);
		return pivotElement;
	}
	
	public abstract void resolveMultiplicity(@NonNull TypedElement pivotElement, org.eclipse.uml2.uml.@NonNull TypedElement umlTypedElement);

	/**
	 * Return the UML Stereotype referenced by the UML stereotype application to some UML Stereotyped Elements.
	 *<p>
	 * Note that the reference in the UML Stereotype application is to a particular Ecore version of the Profile, rather than
	 * to the UML profile, so we have to locate the UML profile by URI and name.
	 */
	public @Nullable Stereotype resolveStereotype(@NonNull EObject umlStereotypeApplication, @NonNull List<org.eclipse.uml2.uml.Element> umlStereotypedElements) {
		ClassUtil.nonNullState(pivotModel);
		EClass umlStereotypeEClass = umlStereotypeApplication.eClass();
		if (!(umlStereotypeApplication instanceof DynamicEObjectImpl)) {					// If stereotyped element has been genmodelled
			Stereotype asStereotype = metamodelManager.getASOfEcore(Stereotype.class, umlStereotypeEClass);
			return asStereotype;		// then it is already a Type rather than a Stereotype
		}
		//
		//	Get the umlStereotypedPackage common to all the base_xxx elements
		//
		org.eclipse.uml2.uml.Package umlStereotypedPackage = null;
		for (org.eclipse.uml2.uml.Element umlStereotypedElement : umlStereotypedElements) {
			for (EObject eObject = umlStereotypedElement; eObject != null; eObject = eObject.eContainer()) {
				if (eObject instanceof org.eclipse.uml2.uml.Package) {
					if (umlStereotypedPackage == null) {
						umlStereotypedPackage = (org.eclipse.uml2.uml.Package)eObject;
					}
					else if (umlStereotypedPackage != (org.eclipse.uml2.uml.Package)eObject) {
						logger.error("Conflicting packages for stereotype application of " + umlStereotypeEClass.getName());
					}
					break;
				}
			}
		}
		//
		//	Get the pivot profile for which the profileNsURI is an application to the stereotypedPackage 
		//
		EPackage umlProfileEPackage = umlStereotypeEClass.getEPackage();
//			String profileNsURI = umlProfileEPackage.getNsURI();		// FIXME UML profiles have no URI.
		if (umlStereotypedPackage != null) {
//				for (org.eclipse.uml2.uml.ProfileApplication umlProfileApplication : umlStereotypedPackage.getProfileApplications()) {
//					org.eclipse.uml2.uml.Profile umlProfile = umlProfileApplication.getAppliedProfile();
//					if (profileNsURI.equals(umlProfile.getURI())) {
//						return umlProfile.getOwnedStereotype(umlStereotypeEClass.getName());
//					}
//				}
			String profileNsURI = umlProfileEPackage.getNsURI();
			for (org.eclipse.uml2.uml.Package umlPackage = umlStereotypedPackage; umlPackage != null; umlPackage = umlPackage.getNestingPackage()) {
				for (org.eclipse.uml2.uml.ProfileApplication umlProfileApplication : umlPackage.getProfileApplications()) {
					org.eclipse.uml2.uml.Profile umlProfile = umlProfileApplication.getAppliedProfile();
					if (profileNsURI.equals(umlProfile.getURI())) {
						org.eclipse.uml2.uml.Stereotype umlStereotype = umlProfile.getOwnedStereotype(umlStereotypeEClass.getName());
						return umlStereotype != null ? getCreated(Stereotype.class, umlStereotype) : null;
					}
				}
			}
			String profileName = umlProfileEPackage.getName();		// This is really only needed for a bad legacy test case
			for (org.eclipse.uml2.uml.Package umlPackage = umlStereotypedPackage; umlPackage != null; umlPackage = umlPackage.getNestingPackage()) {
				for (org.eclipse.uml2.uml.ProfileApplication umlProfileApplication : umlPackage.getProfileApplications()) {
					org.eclipse.uml2.uml.Profile umlProfile = umlProfileApplication.getAppliedProfile();
					if (profileName.equals(umlProfile.getName())) {
						org.eclipse.uml2.uml.Stereotype umlStereotype = umlProfile.getOwnedStereotype(umlStereotypeEClass.getName());
						return umlStereotype != null ? getCreated(Stereotype.class, umlStereotype) : null;
					}
				}
			}
		}
		logger.error("Missing package for stereotype application of " + umlStereotypeEClass.getName());
		return null;
	}

	protected @Nullable Type resolveType(org.eclipse.uml2.uml.@NonNull Type umlType) {
		Type pivotType = getCreated(Type.class, umlType);
		if (pivotType != null) {
			return pivotType;
		}
/*		EClassifier eClassifier = eGenericType.getEClassifier();
		ETypeParameter eTypeParameter = eGenericType.getETypeParameter();
		List<EGenericType> eTypeArguments = eGenericType.getETypeArguments();
		if (eTypeParameter != null) {
			pivotType = resolveTypeParameter(eGenericType);
		}
		else if (eClassifier == null) {
			pivotType = resolveWildcardType(eGenericType);
		}
		else if (!eTypeArguments.isEmpty()) {
			String ecoreMoniker = UML2Moniker.toString(eGenericType);
			pivotType = resolvedSpecializations.get(ecoreMoniker);
			if (pivotType == null) {
				pivotType = resolveGenericType(resolvedSpecializations, eGenericType);
				resolvedSpecializations.put(ecoreMoniker, pivotType);
			}
		}
		else if (eClassifier instanceof EDataType) {
			pivotType = resolveDataType(eGenericType);
		}
		else { 
			pivotType = resolveSimpleType(eGenericType);
		}
		createMap.put(eGenericType, pivotType); */
		if (umlType instanceof org.eclipse.uml2.uml.PrimitiveType) {
			if (UMLUtil.isBoolean(umlType)) {
				return standardLibrary.getBooleanType();
			}
			else if (UMLUtil.isInteger(umlType)) {
				return standardLibrary.getIntegerType();
			}
			else if (UMLUtil.isReal(umlType)) {
				return standardLibrary.getRealType();
			}
			else if (UMLUtil.isString(umlType)) {
				return standardLibrary.getStringType();
			}
			else if (UMLUtil.isUnlimitedNatural(umlType)) {
				return standardLibrary.getUnlimitedNaturalType();
			}
//			org.eclipse.uml2.uml.Package umlPackage = umlType.getPackage();
//			Resource umlResource = umlType.eResource();
//			if ((umlPackage instanceof org.eclipse.uml2.uml.Model) && "EcorePrimitiveTypes".equals(umlPackage.getName())			// No nsURI available
//					&& (umlResource != null) && UMLResource.ECORE_PRIMITIVE_TYPES_LIBRARY_URI.equals(umlResource.getURI())) {
//				
//			}
		}
		return pivotType;
	}

	protected @Nullable Type resolveTypeParameter(@NonNull EGenericType eGenericType) {
		EClassifier eClassifier = eGenericType.getEClassifier();
		ETypeParameter eTypeParameter = eGenericType.getETypeParameter();
		if (eTypeParameter != null) {
			List<EGenericType> eTypeArguments = eGenericType.getETypeArguments();
			assert eClassifier == null;
			assert eTypeArguments.isEmpty();
			Type pivotType = getCreated(Type.class, eTypeParameter);
			return pivotType;
		}
		else {
			return null;
		}
	}

	protected @Nullable Type resolveWildcardType(@NonNull EGenericType eGenericType) {
		assert eGenericType.getETypeArguments().isEmpty();
		assert eGenericType.getEClassifier() == null;
		EClassifier eClassifier = eGenericType.getERawType();
		assert eClassifier == EcorePackage.Literals.EJAVA_OBJECT;
/*			WildcardTypeRefCS csTypeRef = BaseCSFactory.eINSTANCE.createWildcardTypeRefCS();
			setOriginalMapping(csTypeRef, eObject);
//			csTypeRef.setExtends(doSwitchAll(eGenericType.getExtends()));
//			csTypeRef.setSuper(doSwitchAll(eGenericType.getSuper()));
			return csTypeRef; */
		org.eclipse.ocl.pivot.Class pivotElement = PivotFactory.eINSTANCE.createClass();
		String name = PivotConstantsInternal.WILDCARD_NAME;
		EStructuralFeature eFeature = eGenericType.eContainmentFeature();
		if ((eFeature != null) && eFeature.isMany()) {
			EObject eContainer = eGenericType.eContainer();
			List<?> list = (List<?>)eContainer.eGet(eGenericType.eContainingFeature());
			int index = list.indexOf(eGenericType);
			if (index != 0) {
				name += index;
			}
		}
		pivotElement.setName(name);		
		return pivotElement;
	}

	protected void setOriginalMapping(@NonNull Element pivotElement, @NonNull EObject umlElement) {
		((PivotObjectImpl)pivotElement).setESObject(umlElement);
		addCreated(umlElement, pivotElement);
	}

	public void setUMLURI(URI umlURI) {
		this.umlURI  = umlURI;
	}

	@Override
	public String toString() {
		return String.valueOf(umlResource.getURI());
	}
}
