/*******************************************************************************
 * Copyright (c) 2006, 2018 IBM Corporation and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v20.html
 *
 * Contributors:
 *   IBM - Initial API and implementation
 *   Zeligsoft - Bug 245897
 *	 E.D.Willink Bug 298128
 *******************************************************************************/

package org.eclipse.ocl.uml.internal;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.ocl.types.BagType;
import org.eclipse.ocl.types.CollectionType;
import org.eclipse.ocl.types.OrderedSetType;
import org.eclipse.ocl.types.PrimitiveType;
import org.eclipse.ocl.types.SequenceType;
import org.eclipse.ocl.types.SetType;
import org.eclipse.ocl.uml.UMLEnvironment;
import org.eclipse.ocl.uml.options.UMLParsingOptions;
import org.eclipse.ocl.uml.util.OCLUMLUtil;
import org.eclipse.ocl.util.ObjectUtil;
import org.eclipse.ocl.utilities.ExpressionInOCL;
import org.eclipse.ocl.utilities.OCLFactory;
import org.eclipse.ocl.utilities.UMLReflection;
import org.eclipse.uml2.uml.Association;
import org.eclipse.uml2.uml.BehavioredClassifier;
import org.eclipse.uml2.uml.CallOperationAction;
import org.eclipse.uml2.uml.Class;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.Constraint;
import org.eclipse.uml2.uml.DataType;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Enumeration;
import org.eclipse.uml2.uml.EnumerationLiteral;
import org.eclipse.uml2.uml.Feature;
import org.eclipse.uml2.uml.Interface;
import org.eclipse.uml2.uml.MultiplicityElement;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.Operation;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.Parameter;
import org.eclipse.uml2.uml.ParameterDirectionKind;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Reception;
import org.eclipse.uml2.uml.SendSignalAction;
import org.eclipse.uml2.uml.Signal;
import org.eclipse.uml2.uml.State;
import org.eclipse.uml2.uml.Stereotype;
import org.eclipse.uml2.uml.Type;
import org.eclipse.uml2.uml.TypedElement;
import org.eclipse.uml2.uml.UMLFactory;

/**
 * Implementation of the UML reflection service for the UML environment.
 * 
 * @author Christian W. Damus (cdamus)
 */
public class UMLReflectionImpl
    implements
    UMLReflection<Package, Classifier, Operation, Property, EnumerationLiteral, Parameter, State, CallOperationAction, SendSignalAction, Constraint> {

	private static Set<String> ECORE_INTEGER_TYPES = new java.util.HashSet<String>(
		Arrays.asList(EcorePackage.Literals.EINT.getName(),
			EcorePackage.Literals.EINTEGER_OBJECT.getName(),
			EcorePackage.Literals.ELONG.getName(),
			EcorePackage.Literals.ELONG_OBJECT.getName(),
			EcorePackage.Literals.ESHORT.getName(),
			EcorePackage.Literals.ESHORT_OBJECT.getName(),
			EcorePackage.Literals.EBIG_INTEGER.getName()));

	private static Set<String> ECORE_REAL_TYPES = new java.util.HashSet<String>(
		Arrays.asList(EcorePackage.Literals.EFLOAT.getName(),
			EcorePackage.Literals.EFLOAT_OBJECT.getName(),
			EcorePackage.Literals.EDOUBLE.getName(),
			EcorePackage.Literals.EDOUBLE_OBJECT.getName(),
			EcorePackage.Literals.EBIG_DECIMAL.getName()));

	private static Set<String> ECORE_BOOLEAN_TYPES = new java.util.HashSet<String>(
		Arrays.asList(EcorePackage.Literals.EBOOLEAN.getName(),
			EcorePackage.Literals.EBOOLEAN_OBJECT.getName()));
	
    private final UMLEnvironment env;
    
    public UMLReflectionImpl(UMLEnvironment env) {
        this.env = env;
    }
    
    final java.lang.Class<? extends Association> getAssociationClassType() {
        return env.getValue(UMLParsingOptions.ASSOCIATION_CLASS_TYPE);
    }
    
    /**
     * Default implementation just gets the name of the named element's
     * {@link org.eclipse.emf.ecore.EObject#eClass() metaclass} or, if it is a
     * {@link TypedElement}, the name of its type.
     */
    public String getDescription(Object namedElement) {
        if (namedElement instanceof TypedElement) {
            Type type = ((TypedElement) namedElement).getType();
            return (type == null) ? OCLStandardLibraryImpl.INSTANCE
                .getOclVoid().getName()
                : type.getName();
        } else if (namedElement instanceof EnumerationLiteral) {
            return ((EnumerationLiteral) namedElement).getEnumeration()
                .getName();
        } else if (namedElement == null) {
            return null;
        }

        return ((EObject) namedElement).eClass().getName();
    }
    
    public String getName(Object namedElement) {
        return (namedElement instanceof NamedElement)?
            ((NamedElement) namedElement).getName() : null;
    }
    
    public String getQualifiedName(Object namedElement) {
        return (namedElement instanceof NamedElement)?
            ((NamedElement) namedElement).getQualifiedName() : null;
    }
    
    public Classifier getOCLType(Object metaElement) {
        Classifier result = null;
        
        if (metaElement instanceof TypedElement) {
            TypedElement typedElement = (TypedElement) metaElement;
            result = (Classifier) typedElement.getType();
            
            if (result == null) {
                // absence of a type in UML indicates void type
                result = OCLStandardLibraryImpl.INSTANCE.getOclVoid();
            }
            
            if (isMany(typedElement)) {
                result = getOCLCollectionType(
                        result,
                        isOrdered(typedElement),
                        isUnique(typedElement));
            } else {
                result = getOCLType(result);
            }
        } else if (metaElement instanceof Operation) {
            // Operations are not TypedElements!
            Operation operation = (Operation) metaElement;
            result = (Classifier) operation.getType();
            
            if (result == null) {
                // absence of a type in UML indicates void type
                result = OCLStandardLibraryImpl.INSTANCE.getOclVoid();
            }
            
            if (isMany(operation)) {
                result = getOCLCollectionType(
                        result,
                        isOrdered(operation),
                        isUnique(operation));
            } else {
                result = getOCLType(result);
            }
        } else if (metaElement instanceof Classifier) {
            result = getOCLType((Classifier) metaElement);
        }
        
        return result;
    }
    
    public boolean isMany(Object metaElement) {
        if (metaElement instanceof MultiplicityElement) {
            return ((MultiplicityElement) metaElement).isMultivalued();
        } else if (metaElement instanceof Operation) {
            int upper = ((Operation) metaElement).getUpper();
            return (upper > 1) || (upper < 0);
        }
        
        return false;
    }
    
    /**
     * Queries whether the specified {@link MultiplicityElement} or
     * {@link Operation} is unique.
     * 
     * @param metaElement a multiplicity-element or operation
     * @return whether it is unique
     */
    protected boolean isUnique(Object metaElement) {
        if (metaElement instanceof MultiplicityElement) {
            return ((MultiplicityElement) metaElement).isUnique();
        } else if (metaElement instanceof Operation) {
            return ((Operation) metaElement).isUnique();
        }
        
        return false;
    }
    
    /**
     * Queries whether the specified {@link MultiplicityElement} or
     * {@link Operation} is ordered.
     * 
     * @param metaElement a multiplicity-element or operation
     * @return whether it is ordered
     */
    protected boolean isOrdered(Object metaElement) {
        if (metaElement instanceof MultiplicityElement) {
            return ((MultiplicityElement) metaElement).isOrdered();
        } else if (metaElement instanceof Operation) {
            return ((Operation) metaElement).isOrdered();
        }
        
        return false;
    }
    
    public Classifier asOCLType(Classifier modelType) {
        return getOCLType(modelType);
    }
    
    public Package getNestingPackage(Package pkg) {
        return pkg.getNestingPackage();
    }
    
    public List<Package> getNestedPackages(Package pkg) {
        return pkg.getNestedPackages();
    }
    
    public Package getPackage(Classifier classifier) {
        return classifier.getNearestPackage();
    }
    
    public List<Classifier> getClassifiers(Package pkg) {
        EList<Type> types = pkg.getOwnedTypes();
        List<Classifier> result = new java.util.ArrayList<Classifier>(types.size());
        
        for (Type t : types) {
            if (t instanceof Classifier) {
                result.add((Classifier) t);
            }
        }
        
        return result;
    }
    
    public Classifier getOwningClassifier(Object feature) {
        Classifier result = null;
        
        if (feature instanceof Feature) {
            result = (Classifier) ((Feature) feature).getOwner();
        }
        
        if (result instanceof Class) {
            Classifier shadowed = OCLStandardLibraryImpl.getRealClassifier(
                (Class) result);
            
            if (shadowed != null) {
                result = shadowed;
            }
        }
        
        return result;
    }
    
    public List<Parameter> getParameters(Operation operation) {
        List<Parameter> result = new java.util.ArrayList<Parameter>(
                operation.getOwnedParameters().size());
        
        for (Parameter p : operation.getOwnedParameters()) {
            if (p.getDirection() != ParameterDirectionKind.RETURN_LITERAL) {
                result.add(p);
            }
        }
        
        return result;
    }
    
    public Operation createOperation(String name, Classifier resultType,
            List<String> paramNames, List<Classifier> paramTypes) {
        
        Operation result = UMLFactory.eINSTANCE.createOperation();
        result.setName(name);
        
        // OCL can only define query operations
        result.setIsQuery(true);
        
        if (resultType != null) {
            result.setType(resultType);
        }
        
        int i = 0;
        for (String pname : paramNames) {
            result.createOwnedParameter(pname, paramTypes.get(i++));
        }
        
        return result;
    }
    
    public List<Operation> getOperations(Classifier classifier) {
        return OCLUMLUtil.getAllOperations(classifier);
    }
    
    public Property createProperty(String name, Classifier resultType) {
        Property result = UMLFactory.eINSTANCE.createProperty();
        
        result.setName(name);
        result.setType(resultType);
        
        return result;
    }
    
    public List<Property> getAttributes(Classifier classifier) {
        return OCLUMLUtil.getAllAttributes(classifier);
    }
    
    public Collection<? extends Classifier> getAllSupertypes(
            Classifier classifier) {
        
        return classifier.allParents();
    }
    
    public boolean isQuery(Operation operation) {
        return operation.isQuery();
    }
    
    public boolean isStatic(Object feature) {
        return (feature instanceof Feature) && ((Feature) feature).isStatic();
    }
    
    public boolean setIsStatic(Object feature, boolean isStatic) {
        if (!(feature instanceof Feature))
        	return false;
        ((Feature) feature).setIsStatic(isStatic);
        return true;
    }

    public boolean isAssociationClass(Classifier classifier) {
        return getAssociationClassType().isInstance(classifier);
    }
    
    public Classifier getAssociationClass(Property property) {
        return getAssociationClassType().isInstance(property.getAssociation())?
                property.getAssociation() : null;
    }
    
    public List<Property> getMemberEnds(Classifier associationClass) {
        if (getAssociationClassType().isInstance(associationClass)) {
            return ((Association) associationClass).getMemberEnds();
        }
        
        return Collections.emptyList();
    }

    public boolean isOperation(Object metaElement) {
        return metaElement instanceof Operation;
    }

	public boolean isPackage(Object metaElement) {
        return metaElement instanceof Package;
	}
    
    public boolean isProperty(Object metaElement) {
        return metaElement instanceof Property;
    }
    
    public boolean isClassifier(Object metaElement) {
        return metaElement instanceof Classifier;
    }
    
    public boolean isClass(Object metaElement) {
        return metaElement instanceof Class;
    }

	public boolean isConstraint(Object metaElement) {
        return metaElement instanceof Constraint;
	}
    
    public boolean isDataType(Object metaElement) {
        return metaElement instanceof DataType;
    }
    
    public boolean isStereotype(Classifier type) {
        return type instanceof Stereotype;
    }
    
    public Object getStereotypeApplication(Object baseElement,
            Classifier stereotype) {
        Object result = null;
        
        if (baseElement instanceof Element) {
            Element element = (Element) baseElement;
            Stereotype stereo = (Stereotype) stereotype;
            
            if (element.isStereotypeApplied(stereo)) {
                result = element.getStereotypeApplication(stereo);
            }
 
    		if (result == null) {
    			// maybe some specializing stereotype is applied?

				List<Stereotype> applied = element
					.getAppliedSubstereotypes(stereo);
				if (!applied.isEmpty()) {
					return element.getStereotypeApplication(applied.get(0));
				}
    		}
       }
        
        return result;
    }
    
    public boolean isEnumeration(Classifier type) {
        return type instanceof Enumeration;
    }

    public Classifier getEnumeration(EnumerationLiteral enumerationLiteral) {
        return enumerationLiteral.getEnumeration();
    }

    public List<EnumerationLiteral> getEnumerationLiterals(Classifier enumerationType) {
        return ((Enumeration) enumerationType).getOwnedLiterals();
    }
    
    public EnumerationLiteral getEnumerationLiteral(Classifier enumerationType,
            String literalName) {
        return ((Enumeration) enumerationType).getOwnedLiteral(literalName);
    }
    
    public boolean isComparable(Classifier type) {
        if ((type instanceof PrimitiveType<?>)
            || (type.getOperation("<", null, null) != null)) { //$NON-NLS-1$
            
            return true;
        }
        
        EClassifier eclassifier = env.getEClassifier(type, null);
        
        return (eclassifier != null)
            && Comparable.class.isAssignableFrom(eclassifier.getInstanceClass());
    }
    
    public Operation getOperation(CallOperationAction callOperationAction) {
        return callOperationAction.getOperation();
    }
    
    public Classifier getSignal(SendSignalAction sendSignalAction) {
        return sendSignalAction.getSignal();
    }
    
    public String getStereotype(Constraint constraint) {
        EList<String> keywords = constraint.getKeywords();
        return keywords.isEmpty()? null : keywords.get(0);
    }
    
    public void setStereotype(Constraint constraint, String stereotype) {
        // first, clear existing keywords (there wouldn't usually be any)
        for (String keyword : constraint.getKeywords()) {
            constraint.removeKeyword(keyword);
        }
        
        constraint.addKeyword(stereotype);
    }
    
    public String getConstraintName(Constraint constraint) {
        return constraint.getName();
    }
    
    public void setConstraintName(Constraint constraint, String name) {
        constraint.setName(name);
    }
    
    public ExpressionInOCL<Classifier, Parameter>
    getSpecification(Constraint constraint) {
        
        if (constraint.getSpecification() instanceof ExpressionInOCL<?, ?>) {
            return (org.eclipse.ocl.uml.ExpressionInOCL) constraint.getSpecification();
        }
        
        return null;
    }
    
    public void setSpecification(
            Constraint constraint,
            org.eclipse.ocl.utilities.ExpressionInOCL<Classifier, Parameter> specification) {
        
        constraint.setSpecification(
            (org.eclipse.ocl.uml.ExpressionInOCL) specification);
    }
    
    public Constraint getConstraint(
            ExpressionInOCL<Classifier, Parameter> specification) {
        EObject container = specification.eContainer();
        
        if (container instanceof Constraint) {
            return (Constraint) container;
        }
        
        return null;
    }
    
    public List<Element> getConstrainedElements(Constraint constraint) {
        return constraint.getConstrainedElements();
    }

	public void addConstrainedElement(Constraint constraint, EObject constrainedElement) {
		constraint.getConstrainedElements().add((Element) constrainedElement);
	}
    
    public List<Property> getQualifiers(Property property) {
        return property.getQualifiers();
    }

    public Classifier getCommonSuperType(Classifier type1, Classifier type2) {
    
        if (ObjectUtil.equal(type1, type2)) {
            return type2;
        }
        
        if (type1.conformsTo(type2)) {
            return type2;
        }
        if (type2.conformsTo(type1)) {
            return type1;
        }
        List<Classifier> type1Ancestors = new ArrayList<Classifier>(
                type1.allParents());
        
        List<Classifier> type2Ancestors = new ArrayList<Classifier>(
                type2.allParents());
        
        type1Ancestors.retainAll(type2Ancestors);
        if (!type1Ancestors.isEmpty()) {
            // the least common ancestor type will be the first, because UML
            //   computes the ancestors starting with the immediate parents
            return type1Ancestors.get(0);
        }
    
        return null;
    }

    public int getRelationship(Classifier type1, Classifier type2) {
        if (ObjectUtil.equal(type1, type2)) {
            return SAME_TYPE;
        }
        
        if (type2.conformsTo(type1)) {
            return STRICT_SUPERTYPE;
        } else if (type1.conformsTo(type2)) {
            return STRICT_SUBTYPE;
        } else if ((type2 instanceof BehavioredClassifier) && (type1 instanceof Interface)) {
            for (Interface i : ((BehavioredClassifier) type2).getAllImplementedInterfaces()) {
                if (i.conformsTo(type1)) {
                    return STRICT_SUPERTYPE;
                }
            }
        } else if ((type1 instanceof BehavioredClassifier) && (type2 instanceof Interface)) {
            for (Interface i : ((BehavioredClassifier) type1).getAllImplementedInterfaces()) {
                if (i.conformsTo(type2)) {
                    return STRICT_SUBTYPE;
                }
            }
        }
    
        return UNRELATED_TYPE;
    }

    /**
     * Translator from primitive UML types to OCL types
     * 
     * @param dataType a data type in the UML metamodel
     * @return the corresponding OCL classifier
     */
    private Classifier getOCLTypeFor(DataType dataType) {
    
        // First check if it is already an OCL data type (Enumerations represent
        //    themselves)
        if (dataType instanceof Enumeration) {
            return dataType;
        }
        if (dataType instanceof CollectionType<?, ?>) {
            return dataType;
        }
        if (dataType instanceof PrimitiveType<?>) {
            return dataType;
        }
    
        if (dataType instanceof org.eclipse.uml2.uml.PrimitiveType) {
            // Boolean -> OCL_BOOLEAN
            if (PrimitiveType.BOOLEAN_NAME.equals(dataType.getName())) {
                return OCLStandardLibraryImpl.INSTANCE.getBoolean();
            } else if (PrimitiveType.REAL_NAME.equals(dataType.getName())) {
                return OCLStandardLibraryImpl.INSTANCE.getReal();
            } else if (PrimitiveType.STRING_NAME.equals(dataType.getName())) {
                return OCLStandardLibraryImpl.INSTANCE.getString();
            } else if (PrimitiveType.INTEGER_NAME.equals(dataType.getName())) {
                return OCLStandardLibraryImpl.INSTANCE.getInteger();
            } else if (PrimitiveType.UNLIMITED_NATURAL_NAME.equals(dataType.getName())) {
                return OCLStandardLibraryImpl.INSTANCE.getUnlimitedNatural();
            } else if (SequenceType.SINGLETON_NAME.equals(dataType.getName())) {
                return OCLStandardLibraryImpl.INSTANCE.getSequence();
            } else if (SetType.SINGLETON_NAME.equals(dataType.getName())) {
                return OCLStandardLibraryImpl.INSTANCE.getSet();
            } else if (BagType.SINGLETON_NAME.equals(dataType.getName())) {
                return OCLStandardLibraryImpl.INSTANCE.getBag();
            } else if (OrderedSetType.SINGLETON_NAME.equals(dataType.getName())) {
                return OCLStandardLibraryImpl.INSTANCE.getOrderedSet();
            } else if (CollectionType.SINGLETON_NAME.equals(dataType.getName())) {
                return OCLStandardLibraryImpl.INSTANCE.getCollection();
            } else if ("Object".equals(dataType.getName())) { //$NON-NLS-1$
                return OCLStandardLibraryImpl.INSTANCE.getOclAny();
            } else if (ECORE_INTEGER_TYPES.contains(dataType.getName())) {
                return OCLStandardLibraryImpl.INSTANCE.getInteger();
            } else if (ECORE_REAL_TYPES.contains(dataType.getName())) {
                return OCLStandardLibraryImpl.INSTANCE.getReal();
            } else if (ECORE_BOOLEAN_TYPES.contains(dataType.getName())) {
                return OCLStandardLibraryImpl.INSTANCE.getBoolean();
            } else if ("EString".equals(dataType.getName())) { //$NON-NLS-1$
                return OCLStandardLibraryImpl.INSTANCE.getString();
            }
        }
        
        // All other data types map to themselves
        return dataType;
    }

    /**
     * Obtains the appropriate OCL type for a {@link Classifier}, if it
     * corresponds to an OCL primitive type.
     * 
     * @param type the type to convert to an OCL type
     * @return the corresponding OCL type
     */ 
    Classifier getOCLType(Classifier type) {
        Classifier resultType = type;
    
        if (resultType instanceof DataType) {
            resultType = getOCLTypeFor((DataType) resultType);
        }
        
        return resultType;
    }

    /**
     * Obtains the appropriate OCL collection type for a {@link Classifier}, 
     * according to the collection's orderedness and uniqueness.  The mapping is
     * as follows:
     * <ul>
     *   <li>ordered, unique: ordered set type</li>
     *   <li>ordered, non-unique: sequence type</li>
     *   <li>non-ordered, unique: set type</li>
     *   <li>non-ordered, non-unique: bag type</li>
     * </ul>
     * <p>
     * Note that the collection's element <code>type</code> is mapped to an
     * OCL primitive type where possible.
     * </p>
     * 
     * @param type the type to get the corresponding OCL collection type for
     * @param isOrdered whether the OCL type should be ordered
     * @param isUnique whether the OCL type should be unique
     * 
     * @return the corresponding OCL type
     * 
     * @see #getOCLType(Classifier)
     */ 
    Classifier getOCLCollectionType(Classifier type,
            boolean isOrdered, boolean isUnique) {
        Classifier resultType = type;
    
        if (resultType instanceof DataType) {
            resultType = getOCLTypeFor((DataType) resultType);
        }
        
        OCLFactory oclFactory = OCLFactoryImpl.INSTANCE;
        
        if (isOrdered) {
            if (isUnique) {
                resultType = (Classifier) oclFactory.createOrderedSetType(resultType);
            } else {
                resultType = (Classifier) oclFactory.createSequenceType(resultType);
            }
        } else {
            if (isUnique) {
                resultType = (Classifier) oclFactory.createSetType(resultType);
            } else {
                resultType = (Classifier) oclFactory.createBagType(resultType);
            }
        }
        
        return resultType;
    }

    public List<Classifier> getSignals(Classifier owner) {
        if (owner instanceof Class) {
            List<Reception> receptions = OCLUMLUtil.getAllReceptions((Class) owner);
            
            if (!receptions.isEmpty()) {
                List<Classifier> result = new java.util.ArrayList<Classifier>(
                        receptions.size());
                
                for (Reception r : receptions) {
                    if (r.getSignal() != null) {
                        result.add(r.getSignal());
                    }
                }
                
                return result;
            }
        }
        
        return Collections.emptyList();
    }

    public CallOperationAction createCallOperationAction(Operation operation) {
        CallOperationAction result = UMLFactory.eINSTANCE.createCallOperationAction();
        result.setOperation(operation);
        return result;
    }

    public SendSignalAction createSendSignalAction(Classifier signal) {
        SendSignalAction result = UMLFactory.eINSTANCE.createSendSignalAction();
        result.setSignal((Signal) signal);
        return result;
    }

    public Constraint createConstraint() {
        return UMLFactory.eINSTANCE.createConstraint();
    }

    public ExpressionInOCL<Classifier, Parameter> createExpressionInOCL() {
        return org.eclipse.ocl.uml.UMLFactory.eINSTANCE.createExpressionInOCL();
    }
    
    public void setName(
    		org.eclipse.ocl.utilities.TypedElement<Classifier> element,
    		String name) {
    	element.setName(name);
    }
    
    public void setType(
    		org.eclipse.ocl.utilities.TypedElement<Classifier> element,
    		Classifier type) {
    	element.setType(type);
    }
}
