| /** |
| * Copyright (c) 2006-2013 IBM Corporation 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: |
| * IBM - Initial API and implementation |
| */ |
| package org.eclipse.emf.ecore.impl; |
| |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.Collection; |
| import java.util.Set; |
| |
| import org.eclipse.emf.common.notify.Notification; |
| import org.eclipse.emf.common.notify.NotificationChain; |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.emf.ecore.EAttribute; |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.emf.ecore.EClassifier; |
| import org.eclipse.emf.ecore.EDataType; |
| import org.eclipse.emf.ecore.EGenericType; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EOperation; |
| import org.eclipse.emf.ecore.EReference; |
| import org.eclipse.emf.ecore.EStructuralFeature; |
| import org.eclipse.emf.ecore.ETypeParameter; |
| import org.eclipse.emf.ecore.EcorePackage; |
| import org.eclipse.emf.ecore.InternalEObject; |
| import org.eclipse.emf.ecore.util.EObjectContainmentEList; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| import org.eclipse.emf.ecore.util.InternalEList; |
| |
| |
| /** |
| * <!-- begin-user-doc --> |
| * An implementation of the model object '<em><b>EGeneric Type</b></em>'. |
| * <!-- end-user-doc --> |
| * <p> |
| * The following features are implemented: |
| * <ul> |
| * <li>{@link org.eclipse.emf.ecore.impl.EGenericTypeImpl#getEUpperBound <em>EUpper Bound</em>}</li> |
| * <li>{@link org.eclipse.emf.ecore.impl.EGenericTypeImpl#getETypeArguments <em>EType Arguments</em>}</li> |
| * <li>{@link org.eclipse.emf.ecore.impl.EGenericTypeImpl#getERawType <em>ERaw Type</em>}</li> |
| * <li>{@link org.eclipse.emf.ecore.impl.EGenericTypeImpl#getELowerBound <em>ELower Bound</em>}</li> |
| * <li>{@link org.eclipse.emf.ecore.impl.EGenericTypeImpl#getETypeParameter <em>EType Parameter</em>}</li> |
| * <li>{@link org.eclipse.emf.ecore.impl.EGenericTypeImpl#getEClassifier <em>EClassifier</em>}</li> |
| * </ul> |
| * </p> |
| * |
| * @generated not |
| */ |
| public class EGenericTypeImpl extends MinimalEObjectImpl.Container implements EGenericType |
| { |
| /** |
| * The cached value of the '{@link #getEUpperBound() <em>EUpper Bound</em>}' containment reference. |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @see #getEUpperBound() |
| * @generated |
| * @ordered |
| */ |
| protected EGenericType eUpperBound; |
| |
| /** |
| * The cached value of the '{@link #getETypeArguments() <em>EType Arguments</em>}' containment reference list. |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @see #getETypeArguments() |
| * @generated |
| * @ordered |
| */ |
| protected EList<EGenericType> eTypeArguments; |
| |
| /** |
| * The cached default value for the {@link #eRawType eRawType} field. |
| * It needs to be set to {@link org.eclipse.emf.ecore.EcorePackage.Literals#EJAVA_OBJECT} |
| * but due to bootstrap delays initializing that field, |
| * it needs to be set after the Ecore package has been initialized. |
| * @see org.eclipse.emf.ecore.impl.EcorePackageImpl#internalBootstrap() |
| * @see #eRawType |
| */ |
| static EDataType eJavaObject; |
| |
| /** |
| * The cached value of the '{@link #getERawType() <em>ERaw Type</em>}' reference. |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @see #getERawType() |
| * @generated NOT |
| * @ordered |
| */ |
| protected EClassifier eRawType = eJavaObject; |
| |
| /** |
| * The cached value of the '{@link #getELowerBound() <em>ELower Bound</em>}' containment reference. |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @see #getELowerBound() |
| * @generated |
| * @ordered |
| */ |
| protected EGenericType eLowerBound; |
| |
| /** |
| * The cached value of the '{@link #getETypeParameter() <em>EType Parameter</em>}' reference. |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @see #getETypeParameter() |
| * @generated |
| * @ordered |
| */ |
| protected ETypeParameter eTypeParameter; |
| |
| /** |
| * The cached value of the '{@link #getEClassifier() <em>EClassifier</em>}' reference. |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @see #getEClassifier() |
| * @generated |
| * @ordered |
| */ |
| protected EClassifier eClassifier; |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| protected EGenericTypeImpl() |
| { |
| super(); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| protected EClass eStaticClass() |
| { |
| return EcorePackage.Literals.EGENERIC_TYPE; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public EGenericType getEUpperBound() |
| { |
| return eUpperBound; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public NotificationChain basicSetEUpperBound(EGenericType newEUpperBound, NotificationChain msgs) |
| { |
| EGenericType oldEUpperBound = eUpperBound; |
| eUpperBound = newEUpperBound; |
| if (eNotificationRequired()) |
| { |
| ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, EcorePackage.EGENERIC_TYPE__EUPPER_BOUND, oldEUpperBound, newEUpperBound); |
| if (msgs == null) msgs = notification; else msgs.add(notification); |
| } |
| return msgs; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public void setEUpperBound(EGenericType newEUpperBound) |
| { |
| if (newEUpperBound != eUpperBound) |
| { |
| NotificationChain msgs = null; |
| if (eUpperBound != null) |
| msgs = ((InternalEObject)eUpperBound).eInverseRemove(this, EOPPOSITE_FEATURE_BASE - EcorePackage.EGENERIC_TYPE__EUPPER_BOUND, null, msgs); |
| if (newEUpperBound != null) |
| msgs = ((InternalEObject)newEUpperBound).eInverseAdd(this, EOPPOSITE_FEATURE_BASE - EcorePackage.EGENERIC_TYPE__EUPPER_BOUND, null, msgs); |
| msgs = basicSetEUpperBound(newEUpperBound, msgs); |
| if (msgs != null) msgs.dispatch(); |
| } |
| else if (eNotificationRequired()) |
| eNotify(new ENotificationImpl(this, Notification.SET, EcorePackage.EGENERIC_TYPE__EUPPER_BOUND, newEUpperBound, newEUpperBound)); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public EList<EGenericType> getETypeArguments() |
| { |
| if (eTypeArguments == null) |
| { |
| eTypeArguments = new EObjectContainmentEList<EGenericType>(EGenericType.class, this, EcorePackage.EGENERIC_TYPE__ETYPE_ARGUMENTS); |
| } |
| return eTypeArguments; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public EClassifier getERawType() |
| { |
| if (eRawType != null && eRawType.eIsProxy()) |
| { |
| InternalEObject oldERawType = (InternalEObject)eRawType; |
| eRawType = (EClassifier)eResolveProxy(oldERawType); |
| if (eRawType != oldERawType) |
| { |
| if (eNotificationRequired()) |
| eNotify(new ENotificationImpl(this, Notification.RESOLVE, EcorePackage.EGENERIC_TYPE__ERAW_TYPE, oldERawType, eRawType)); |
| |
| if (eContainer instanceof EOperation) |
| { |
| if (eContainerFeatureID() == (EOPPOSITE_FEATURE_BASE - EcorePackage.EOPERATION__EGENERIC_EXCEPTIONS) && eContainer.eNotificationRequired()) |
| { |
| new ENotificationImpl |
| (eContainer, |
| Notification.RESOLVE, |
| EcorePackage.EOPERATION__EEXCEPTIONS, |
| oldERawType, |
| eRawType, |
| ((EOperation)eContainer).getEGenericExceptions().indexOf(this)).dispatch(); |
| } |
| } |
| else if (eContainer instanceof EClass) |
| { |
| if (eContainerFeatureID() == (EOPPOSITE_FEATURE_BASE - EcorePackage.ECLASS__EGENERIC_SUPER_TYPES) && eContainer.eNotificationRequired()) |
| { |
| EClassifier newERawType = eRawType; |
| if (!(newERawType instanceof EClass)) |
| { |
| newERawType = EcorePackage.Literals.EOBJECT; |
| } |
| if (!(oldERawType instanceof EClass)) |
| { |
| oldERawType = (InternalEObject)EcorePackage.Literals.EOBJECT; |
| } |
| |
| new ENotificationImpl |
| (eContainer, |
| Notification.RESOLVE, |
| EcorePackage.ECLASS__ESUPER_TYPES, |
| oldERawType, |
| newERawType, |
| ((EClass)eContainer).getEGenericSuperTypes().indexOf(this)).dispatch(); |
| } |
| } |
| } |
| } |
| return eRawType; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public EClassifier basicGetERawType() |
| { |
| return eRawType; |
| } |
| |
| public NotificationChain setERawType(EClassifier newERawType, NotificationChain msgs) |
| { |
| EClassifier oldERawType = eRawType; |
| if (newERawType == null) |
| { |
| newERawType = eJavaObject; |
| } |
| eRawType = newERawType; |
| if (eNotificationRequired()) |
| { |
| ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, EcorePackage.EGENERIC_TYPE__ERAW_TYPE, oldERawType, eRawType); |
| if (msgs == null) |
| { |
| msgs = notification; |
| } |
| else |
| { |
| msgs.add(notification); |
| } |
| } |
| |
| if (oldERawType != newERawType) |
| { |
| if (eContainer instanceof ETypedElementImpl) |
| { |
| if (eContainerFeatureID() == (EOPPOSITE_FEATURE_BASE - EcorePackage.ETYPED_ELEMENT__EGENERIC_TYPE)) |
| { |
| msgs = ((ETypedElementImpl)eContainer).setEType(newERawType, msgs); |
| } |
| else if (eContainerFeatureID() == (EOPPOSITE_FEATURE_BASE - EcorePackage.EOPERATION__EGENERIC_EXCEPTIONS)) |
| { |
| if (newERawType == null) |
| { |
| newERawType = EcorePackage.Literals.EJAVA_OBJECT; |
| } |
| if (oldERawType == null) |
| { |
| oldERawType = EcorePackage.Literals.EJAVA_OBJECT; |
| } |
| |
| if (eContainer.eNotificationRequired()) |
| { |
| ENotificationImpl notification = |
| new ENotificationImpl |
| (eContainer, |
| Notification.SET, |
| EcorePackage.EOPERATION__EEXCEPTIONS, |
| oldERawType, |
| newERawType, |
| ((EOperation)eContainer).getEGenericExceptions().indexOf(this), |
| false); |
| |
| if (msgs == null) |
| { |
| msgs = notification; |
| } |
| else |
| { |
| msgs.add(notification); |
| } |
| } |
| } |
| } |
| else if (eContainer instanceof EClass) |
| { |
| if (eContainerFeatureID() == (EOPPOSITE_FEATURE_BASE - EcorePackage.ECLASS__EGENERIC_SUPER_TYPES)) |
| { |
| if (!(newERawType instanceof EClass)) |
| { |
| newERawType = EcorePackage.Literals.EOBJECT; |
| } |
| if (!(oldERawType instanceof EClass)) |
| { |
| oldERawType = EcorePackage.Literals.EOBJECT; |
| } |
| |
| if (eContainer.eNotificationRequired()) |
| { |
| ENotificationImpl notification = |
| new ENotificationImpl |
| (eContainer, |
| Notification.SET, |
| EcorePackage.ECLASS__ESUPER_TYPES, |
| oldERawType, |
| newERawType, |
| ((EClass)eContainer).getEGenericSuperTypes().indexOf(this), |
| false); |
| |
| if (msgs == null) |
| { |
| msgs = notification; |
| } |
| else |
| { |
| msgs.add(notification); |
| } |
| } |
| } |
| } |
| else if (eContainer instanceof ETypeParameter) |
| { |
| ETypeParameter eTypeParameter = (ETypeParameter)eContainer; |
| synchronized (eTypeParameter) |
| { |
| @SuppressWarnings("unchecked") |
| Set<EGenericTypeImpl> eGenericTypes = (Set<EGenericTypeImpl>)(Set<?>)((ETypeParameterImpl)eTypeParameter).getEGenericTypes(); |
| for (EGenericTypeImpl eGenericType : eGenericTypes) |
| { |
| msgs = eGenericType.setERawType(eGenericType.getErasure(eTypeParameter), msgs); |
| } |
| } |
| } |
| } |
| return msgs; |
| } |
| |
| |
| @Override |
| public NotificationChain eBasicSetContainer(InternalEObject newContainer, int newContainerFeatureID, NotificationChain msgs) |
| { |
| msgs = super.eBasicSetContainer(newContainer, newContainerFeatureID, msgs); |
| if (eTypeParameter != null && newContainer instanceof EStructuralFeature) |
| { |
| // When we attached we have to recompute the erasure of the type parameter. |
| // |
| EClassifier newERawType = getErasure(eTypeParameter); |
| if (newERawType != eRawType) |
| { |
| msgs = setERawType(newERawType, msgs); |
| } |
| } |
| return msgs; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public EGenericType getELowerBound() |
| { |
| return eLowerBound; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public NotificationChain basicSetELowerBound(EGenericType newELowerBound, NotificationChain msgs) |
| { |
| EGenericType oldELowerBound = eLowerBound; |
| eLowerBound = newELowerBound; |
| if (eNotificationRequired()) |
| { |
| ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, EcorePackage.EGENERIC_TYPE__ELOWER_BOUND, oldELowerBound, newELowerBound); |
| if (msgs == null) msgs = notification; else msgs.add(notification); |
| } |
| return msgs; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public void setELowerBound(EGenericType newELowerBound) |
| { |
| if (newELowerBound != eLowerBound) |
| { |
| NotificationChain msgs = null; |
| if (eLowerBound != null) |
| msgs = ((InternalEObject)eLowerBound).eInverseRemove(this, EOPPOSITE_FEATURE_BASE - EcorePackage.EGENERIC_TYPE__ELOWER_BOUND, null, msgs); |
| if (newELowerBound != null) |
| msgs = ((InternalEObject)newELowerBound).eInverseAdd(this, EOPPOSITE_FEATURE_BASE - EcorePackage.EGENERIC_TYPE__ELOWER_BOUND, null, msgs); |
| msgs = basicSetELowerBound(newELowerBound, msgs); |
| if (msgs != null) msgs.dispatch(); |
| } |
| else if (eNotificationRequired()) |
| eNotify(new ENotificationImpl(this, Notification.SET, EcorePackage.EGENERIC_TYPE__ELOWER_BOUND, newELowerBound, newELowerBound)); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public ETypeParameter getETypeParameter() |
| { |
| return eTypeParameter; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public NotificationChain basicSetETypeParameter(ETypeParameter newETypeParameter, NotificationChain msgs) |
| { |
| ETypeParameter oldETypeParameter = eTypeParameter; |
| eTypeParameter = newETypeParameter; |
| if (eNotificationRequired()) |
| { |
| ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, EcorePackage.EGENERIC_TYPE__ETYPE_PARAMETER, oldETypeParameter, newETypeParameter); |
| if (msgs == null) msgs = notification; else msgs.add(notification); |
| } |
| if (oldETypeParameter != newETypeParameter) |
| { |
| if (newETypeParameter != null) |
| { |
| msgs = setERawType(getErasure(newETypeParameter), msgs); |
| } |
| else |
| { |
| msgs = setERawType(eClassifier, msgs); |
| } |
| } |
| return msgs; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public void setETypeParameter(ETypeParameter newETypeParameter) |
| { |
| if (newETypeParameter != eTypeParameter) |
| { |
| // Maintain a (weak hash) set on the type parameter of all referencing generic types. |
| // |
| if (eTypeParameter != null) |
| { |
| synchronized (eTypeParameter) |
| { |
| ((ETypeParameterImpl)eTypeParameter).getEGenericTypes().remove(this); |
| } |
| } |
| if (newETypeParameter != null) |
| { |
| synchronized (newETypeParameter) |
| { |
| ((ETypeParameterImpl)newETypeParameter).getEGenericTypes().add(this); |
| } |
| } |
| NotificationChain msgs = basicSetETypeParameter(newETypeParameter, null); |
| if (msgs != null) |
| { |
| msgs.dispatch(); |
| } |
| } |
| else if (eNotificationRequired()) |
| { |
| eNotify(new ENotificationImpl(this, Notification.SET, EcorePackage.EGENERIC_TYPE__ETYPE_PARAMETER, newETypeParameter, newETypeParameter)); |
| } |
| } |
| |
| protected EClassifier getErasure(ETypeParameter eTypeParameter) |
| { |
| if (eTypeParameter == null) |
| { |
| return null; |
| } |
| else |
| { |
| boolean needEClass = eContainer instanceof EClass || eContainer instanceof EReference; |
| boolean needEDataType = !needEClass && eContainer instanceof EAttribute; |
| for (EGenericType eBound : eTypeParameter.getEBounds()) |
| { |
| EClassifier eRawType = eBound.getERawType(); |
| if (needEClass ? eRawType instanceof EClass : needEDataType ? eRawType instanceof EDataType : eRawType!= null) |
| { |
| return eRawType; |
| } |
| } |
| return needEClass ? EcorePackage.Literals.EOBJECT : EcorePackage.Literals.EJAVA_OBJECT; |
| } |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public EClassifier getEClassifier() |
| { |
| if (eClassifier != null && eClassifier.eIsProxy()) |
| { |
| InternalEObject oldEClassifier = (InternalEObject)eClassifier; |
| eClassifier = (EClassifier)eResolveProxy(oldEClassifier); |
| if (eClassifier != oldEClassifier) |
| { |
| if (eNotificationRequired()) |
| eNotify(new ENotificationImpl(this, Notification.RESOLVE, EcorePackage.EGENERIC_TYPE__ECLASSIFIER, oldEClassifier, eClassifier)); |
| } |
| } |
| return eClassifier; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public EClassifier basicGetEClassifier() |
| { |
| return eClassifier; |
| } |
| |
| public NotificationChain setEClassifier(EClassifier newEClassifier, NotificationChain msgs) |
| { |
| EClassifier oldEClassifier = eClassifier; |
| eClassifier = newEClassifier; |
| if (eNotificationRequired()) |
| { |
| ENotificationImpl notification = |
| new ENotificationImpl(this, Notification.SET, EcorePackage.EGENERIC_TYPE__ECLASSIFIER, oldEClassifier, eClassifier); |
| if (msgs == null) |
| { |
| msgs = notification; |
| } |
| else |
| { |
| msgs.add(notification); |
| } |
| } |
| return msgs; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public void setEClassifier(EClassifier newEClassifier) |
| { |
| EClassifier oldEClassifier = eClassifier; |
| NotificationChain msgs = setEClassifier(newEClassifier, null); |
| if (oldEClassifier != newEClassifier && eTypeParameter == null) |
| { |
| msgs = setERawType(newEClassifier, msgs); |
| } |
| if (msgs != null) |
| { |
| msgs.dispatch(); |
| } |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public boolean isInstance(Object object) |
| { |
| // If there is type parameter... |
| // |
| ETypeParameter eTypeParameter = getETypeParameter(); |
| if (eTypeParameter != null) |
| { |
| // If the object isn't an instance of all of the bounds, then it's not an instance of this generic type. |
| // |
| EList<EGenericType> eBounds = eTypeParameter.getEBounds(); |
| for (EGenericType eBound : eBounds) |
| { |
| if (!eBound.isInstance(object)) |
| { |
| return false; |
| } |
| } |
| |
| // No contradiction is found, so it must be an instance. |
| // |
| return true; |
| } |
| else |
| { |
| // If there is no classifier, or the object isn't an instance of that classifier, then it's not an instance of this generic type. |
| // |
| EClassifier eClassifier = getEClassifier(); |
| if (eClassifier == null || !eClassifier.isInstance(object)) |
| { |
| return false; |
| } |
| else if (eClassifier instanceof EDataType) |
| { |
| // If we're dealing with a data type instance, we don't have more Ecore information about the instance so we must assume it's a proper instance. |
| // We could consider using reified Java reflection for further checking. |
| // |
| return true; |
| } |
| else |
| { |
| // Otherwise we're dealing with an instance of an EClass. |
| // |
| EClass eClass = (EClass)eClassifier; |
| |
| // If the class has no type parameters, we're done. |
| // |
| EList<ETypeParameter> eTypeParameters = eClass.getETypeParameters(); |
| if (eTypeParameters.isEmpty()) |
| { |
| return true; |
| } |
| else |
| { |
| // If the generic type has no corresponding arguments, we're done. |
| // |
| EList<EGenericType> eTypeArguments = getETypeArguments(); |
| int size = eTypeArguments.size(); |
| if (size == 0) |
| { |
| return true; |
| } |
| else |
| { |
| // The object is an instance of the eClass, so it must be an EObject. |
| // |
| EObject eObject = (EObject)object; |
| EClass instanceEClass = eObject.eClass(); |
| |
| // If the classes are the same, we're done. |
| // |
| if (eClass == instanceEClass) |
| { |
| return true; |
| } |
| else |
| { |
| // We must necessarily find the class among all the generic super types. |
| // |
| for (EGenericType eGenericSuperType : instanceEClass.getEAllGenericSuperTypes()) |
| { |
| if (eGenericSuperType.getEClassifier() == eClass) |
| { |
| // If it's specified as a raw type, we're done. |
| // |
| EList<EGenericType> instanceETypeArguments = eGenericSuperType.getETypeArguments(); |
| if (instanceETypeArguments.isEmpty()) |
| { |
| return true; |
| } |
| else |
| { |
| // Look for a contradiction between the type arguments of this generic type and the type arguments specified for the instance. |
| // |
| for (int i = 0; i < size; ++i) |
| { |
| EGenericType instanceETypeArgument = instanceETypeArguments.get(i); |
| EGenericType eTypeArgument = eTypeArguments.get(i); |
| EGenericType reifiedType = EcoreUtil.getReifiedType(instanceEClass, instanceETypeArgument); |
| if (eTypeArgument.getETypeParameter() == null ? !isCompatibleArgument(reifiedType, eTypeArgument) : !isSuperType(reifiedType, eTypeArgument)) |
| { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| } |
| } |
| |
| // We should not get here. |
| // |
| return false; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| private static boolean isSuperType(EGenericType eGenericType, EGenericType superEGenericType) |
| { |
| // If there is type parameter... |
| // |
| ETypeParameter eTypeParameter = superEGenericType.getETypeParameter(); |
| if (eTypeParameter != null) |
| { |
| // If the type is not a subtype of of all of the bounds, then it's not an subtype. |
| // |
| EList<EGenericType> eBounds = eTypeParameter.getEBounds(); |
| for (EGenericType eBound : eBounds) |
| { |
| if (!isSuperType(eGenericType, eBound)) |
| { |
| return false; |
| } |
| } |
| |
| // No contradiction is found, so it subtype. |
| // |
| return true; |
| } |
| else |
| { |
| // If there is no classifier, we treat it as a type argument and check for compatibility. |
| // |
| EClassifier eClassifier = superEGenericType.getEClassifier(); |
| if (eClassifier == null) |
| { |
| return isCompatibleArgument(eGenericType, superEGenericType); |
| } |
| else |
| { |
| // If the type doesn't have a classifier, then it's not a subtype. |
| // |
| EClassifier eGenericTypeEClassifier = eGenericType.getEClassifier(); |
| if (eGenericTypeEClassifier == null) |
| { |
| return false; |
| } |
| else |
| { |
| // If both the instance classes are non-null, check Java assignability for them. |
| // |
| Class<?> instanceClass = eClassifier.getInstanceClass(); |
| Class<?> instanceTypeArgumentInstanceClass = eGenericTypeEClassifier.getInstanceClass(); |
| if (instanceClass != null && instanceTypeArgumentInstanceClass != null) |
| { |
| if (!instanceClass.isAssignableFrom(instanceTypeArgumentInstanceClass)) |
| { |
| return false; |
| } |
| } |
| // If their both EClasses, check Ecore super types. |
| // |
| else if (eClassifier instanceof EClass && eGenericTypeEClassifier instanceof EClass) |
| { |
| if (!((EClass)eClassifier).isSuperTypeOf((EClass)eGenericTypeEClassifier)) |
| { |
| return false; |
| } |
| } |
| else if (eClassifier != eGenericTypeEClassifier) |
| { |
| // Otherwise they're not compatible. |
| // |
| return false; |
| } |
| |
| // If the class has no type parameters, we're done. |
| // |
| EList<ETypeParameter> eTypeParameters = eClassifier.getETypeParameters(); |
| if (eTypeParameters.isEmpty()) |
| { |
| return true; |
| } |
| else |
| { |
| // If the generic type has no corresponding arguments, we're done. |
| // |
| EList<EGenericType> eTypeArguments = superEGenericType.getETypeArguments(); |
| int size = eTypeArguments.size(); |
| if (size == 0) |
| { |
| return true; |
| } |
| else if (eClassifier instanceof EDataType) |
| { |
| // If it's an EDataType, check that the arguments, if any, are compatible. |
| // |
| return isCompatibleArguments(eGenericType.getETypeArguments(), eTypeArguments); |
| } |
| else |
| { |
| // They are both EClasses... |
| // |
| EClass eClass = (EClass)eClassifier; |
| EClass eGenericTypeEClass = (EClass)eGenericTypeEClassifier; |
| |
| // If the classes are the same, check that the type arguments, if any, are compatible. |
| // |
| if (eClass == eGenericTypeEClass) |
| { |
| return isCompatibleArguments(eGenericType.getETypeArguments(), eTypeArguments); |
| } |
| else |
| { |
| // We generally expect to find the class among all the generic super types. |
| // |
| for (EGenericType eGenericSuperType : eGenericTypeEClass.getEAllGenericSuperTypes()) |
| { |
| if (eGenericSuperType.getEClassifier() == eClass) |
| { |
| // If it's specified as a raw type, we're done. |
| // |
| EList<EGenericType> instanceETypeArguments = eGenericSuperType.getETypeArguments(); |
| if (instanceETypeArguments.isEmpty()) |
| { |
| return true; |
| } |
| else |
| { |
| // Look for a contradiction between the type arguments of this generic type and the type arguments specified for the instance. |
| // |
| for (int i = 0; i < size; ++i) |
| { |
| EGenericType instanceETypeArgument = instanceETypeArguments.get(i); |
| EGenericType eTypeArgument = eTypeArguments.get(i); |
| EGenericType reifiedType = EcoreUtil.getReifiedType(eGenericTypeEClass, instanceETypeArgument); |
| if (!isCompatibleArgument(reifiedType, eTypeArgument)) |
| { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| } |
| } |
| |
| // We should not get here. |
| // |
| return true; |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| private static boolean isCompatibleArguments(EList<EGenericType> instanceETypeArguments, EList<EGenericType> eTypeArguments) |
| { |
| // Check any argument, if present, for compatibility. |
| // |
| int size = Math.min(instanceETypeArguments.size(), eTypeArguments.size()); |
| if (size > 0) |
| { |
| for (int i = 0; i < size; ++i) |
| { |
| if (!isCompatibleArgument(instanceETypeArguments.get(i), eTypeArguments.get(i))) |
| { |
| return false; |
| } |
| } |
| } |
| return true; |
| } |
| |
| protected static boolean isCompatibleArgument(EGenericType instanceETypeArgument, EGenericType eTypeArgument) |
| { |
| // If the type argument specifies a type parameter... |
| // |
| ETypeParameter eTypeParameter = eTypeArgument.getETypeParameter(); |
| if (eTypeParameter != null) |
| { |
| // The instance type argument must not be incompatible with any of the type argument's bounds. |
| // |
| for (EGenericType eBound : eTypeParameter.getEBounds()) |
| { |
| if (!isCompatibleArgument(instanceETypeArgument, eBound)) |
| { |
| return false; |
| } |
| } |
| return true; |
| } |
| else |
| { |
| // If the type argument specifies a classifier... |
| // |
| EClassifier eClassifier = eTypeArgument.getEClassifier(); |
| if (eClassifier != null) |
| { |
| // If the instance type argument specifies a classifier... |
| // |
| EClassifier instanceTypeArgumentEClassifier = instanceETypeArgument.getEClassifier(); |
| if (instanceTypeArgumentEClassifier != null) |
| { |
| // If they're the same classifier they're compatible... |
| // |
| if (eClassifier == instanceTypeArgumentEClassifier) |
| { |
| return isEqualArguments(instanceETypeArgument.getETypeArguments(), eTypeArgument.getETypeArguments()); |
| } |
| else |
| { |
| // If both the instance classes are non-null, check Java assignability for them. |
| // |
| Class<?> instanceClass = eClassifier.getInstanceClass(); |
| Class<?> instanceTypeArgumentInstanceClass = instanceTypeArgumentEClassifier.getInstanceClass(); |
| if (instanceClass != null && instanceTypeArgumentInstanceClass != null) |
| { |
| // The arguments must be equal. |
| // |
| return instanceClass.isAssignableFrom(instanceTypeArgumentInstanceClass) && isEqualArguments(instanceETypeArgument.getETypeArguments(), eTypeArgument.getETypeArguments()); |
| } |
| // If their both EClasses, check Ecore super types. |
| // |
| else if (eClassifier instanceof EClass && instanceTypeArgumentEClassifier instanceof EClass) |
| { |
| // The arguments must be equal. |
| // |
| return ((EClass)eClassifier).isSuperTypeOf((EClass)instanceTypeArgumentEClassifier) && isEqualArguments(instanceETypeArgument.getETypeArguments(), eTypeArgument.getETypeArguments()); |
| } |
| else |
| { |
| // Otherwise they're not compatible. |
| // |
| return false; |
| } |
| } |
| } |
| else |
| { |
| // If the type argument specifies a type parameter... |
| // |
| ETypeParameter instanceTypeArgumentETypeParameter = instanceETypeArgument.getETypeParameter(); |
| if (instanceTypeArgumentETypeParameter != null) |
| { |
| // One of the bounds must be compatible... |
| // |
| for (EGenericType eBound : instanceTypeArgumentETypeParameter.getEBounds()) |
| { |
| if (isCompatibleArgument(eBound, eTypeArgument)) |
| { |
| return true; |
| } |
| } |
| return false; |
| } |
| else |
| { |
| // It must be wildcard of some sort, but that's not valid. |
| // |
| return false; |
| } |
| } |
| } |
| else |
| { |
| EGenericType eLowerBound = eTypeArgument.getELowerBound(); |
| if (eLowerBound != null) |
| { |
| return isCompatibleArgument(eLowerBound, instanceETypeArgument); |
| } |
| else |
| { |
| EGenericType eUpperBound = eTypeArgument.getEUpperBound(); |
| if (eUpperBound != null) |
| { |
| return isCompatibleArgument(instanceETypeArgument, eUpperBound); |
| } |
| else |
| { |
| // An unbounded wildcard is compatible with anything. |
| // |
| return true; |
| } |
| } |
| } |
| } |
| } |
| |
| protected static boolean isEqualArguments(EList<EGenericType> instanceETypeArguments, EList<EGenericType> eTypeArguments) |
| { |
| // Check all the arguments, if any, for equality. |
| // |
| int size = Math.min(instanceETypeArguments.size(), eTypeArguments.size()); |
| if (size != 0) |
| { |
| for (int i = 0; i < size; ++i) |
| { |
| if (!isEqualArgument(instanceETypeArguments.get(i), eTypeArguments.get(i))) |
| { |
| return false; |
| } |
| } |
| } |
| return true; |
| } |
| |
| protected static boolean isEqualArgument(EGenericType eGenericType1, EGenericType eGenericType2) |
| { |
| // If they are the same instance they are equal. |
| // |
| if (eGenericType1 == eGenericType2) |
| { |
| return true; |
| } |
| // If one is null (but the other is not) then they are not equal. |
| // |
| else if (eGenericType1 == null || eGenericType2 == null) |
| { |
| return false; |
| } |
| else |
| { |
| // Consider the classifiers in a special way |
| // to take into account the fact they they often acts as wrappers for instance type names |
| // and that two classifiers that wrap the same instance type name should be considered equal. |
| // |
| EClassifier eClassifier1 = eGenericType1.getEClassifier(); |
| EClassifier eClassifier2 = eGenericType2.getEClassifier(); |
| |
| // If they are the same classifier, they are of course equal. |
| // |
| if (eClassifier1 != eClassifier2) |
| { |
| // If they both aren't null... |
| // |
| if (eClassifier1 != null && eClassifier2 != null) |
| { |
| // Consider the instance type names they wrap |
| // to see if they are non-null and equal. |
| // |
| String instanceTypeName1 = eClassifier1.getInstanceTypeName(); |
| String instanceTypeName2 = eClassifier2.getInstanceTypeName(); |
| |
| // I.e., the classifiers are considered equal if they wrap the same non-null type. |
| // |
| if (instanceTypeName1 == null || !instanceTypeName1.equals(instanceTypeName2)) |
| { |
| return false; |
| } |
| } |
| // If one is null (but the other is not) then they can't be equal. |
| // |
| else if (eClassifier1 != null || eClassifier2 != null) |
| { |
| return false; |
| } |
| } |
| |
| // Type parameters are assumed to be equal. |
| // |
| ETypeParameter eTypeParameter1 = eGenericType1.getETypeParameter(); |
| ETypeParameter eTypeParameter2 = eGenericType2.getETypeParameter(); |
| if (eTypeParameter1 != null && eTypeParameter2 != null) |
| { |
| return true; |
| } |
| |
| // The arguments, type parameters, lower bounds and upper bounds must be equal type arguments. |
| // |
| return |
| isEqualArguments(eGenericType1.getETypeArguments(), eGenericType2.getETypeArguments()) && |
| isEqualArgument(eGenericType1.getELowerBound(), eGenericType2.getELowerBound()) && |
| isEqualArgument(eGenericType1.getEUpperBound(), eGenericType2.getEUpperBound()); |
| } |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) |
| { |
| switch (featureID) |
| { |
| case EcorePackage.EGENERIC_TYPE__EUPPER_BOUND: |
| return basicSetEUpperBound(null, msgs); |
| case EcorePackage.EGENERIC_TYPE__ETYPE_ARGUMENTS: |
| return ((InternalEList<?>)getETypeArguments()).basicRemove(otherEnd, msgs); |
| case EcorePackage.EGENERIC_TYPE__ELOWER_BOUND: |
| return basicSetELowerBound(null, msgs); |
| } |
| return eDynamicInverseRemove(otherEnd, featureID, msgs); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| public Object eGet(int featureID, boolean resolve, boolean coreType) |
| { |
| switch (featureID) |
| { |
| case EcorePackage.EGENERIC_TYPE__EUPPER_BOUND: |
| return getEUpperBound(); |
| case EcorePackage.EGENERIC_TYPE__ETYPE_ARGUMENTS: |
| return getETypeArguments(); |
| case EcorePackage.EGENERIC_TYPE__ERAW_TYPE: |
| if (resolve) return getERawType(); |
| return basicGetERawType(); |
| case EcorePackage.EGENERIC_TYPE__ELOWER_BOUND: |
| return getELowerBound(); |
| case EcorePackage.EGENERIC_TYPE__ETYPE_PARAMETER: |
| return getETypeParameter(); |
| case EcorePackage.EGENERIC_TYPE__ECLASSIFIER: |
| if (resolve) return getEClassifier(); |
| return basicGetEClassifier(); |
| } |
| return eDynamicGet(featureID, resolve, coreType); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @SuppressWarnings("unchecked") |
| @Override |
| public void eSet(int featureID, Object newValue) |
| { |
| switch (featureID) |
| { |
| case EcorePackage.EGENERIC_TYPE__EUPPER_BOUND: |
| setEUpperBound((EGenericType)newValue); |
| return; |
| case EcorePackage.EGENERIC_TYPE__ETYPE_ARGUMENTS: |
| getETypeArguments().clear(); |
| getETypeArguments().addAll((Collection<? extends EGenericType>)newValue); |
| return; |
| case EcorePackage.EGENERIC_TYPE__ELOWER_BOUND: |
| setELowerBound((EGenericType)newValue); |
| return; |
| case EcorePackage.EGENERIC_TYPE__ETYPE_PARAMETER: |
| setETypeParameter((ETypeParameter)newValue); |
| return; |
| case EcorePackage.EGENERIC_TYPE__ECLASSIFIER: |
| setEClassifier((EClassifier)newValue); |
| return; |
| } |
| eDynamicSet(featureID, newValue); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| public void eUnset(int featureID) |
| { |
| switch (featureID) |
| { |
| case EcorePackage.EGENERIC_TYPE__EUPPER_BOUND: |
| setEUpperBound((EGenericType)null); |
| return; |
| case EcorePackage.EGENERIC_TYPE__ETYPE_ARGUMENTS: |
| getETypeArguments().clear(); |
| return; |
| case EcorePackage.EGENERIC_TYPE__ELOWER_BOUND: |
| setELowerBound((EGenericType)null); |
| return; |
| case EcorePackage.EGENERIC_TYPE__ETYPE_PARAMETER: |
| setETypeParameter((ETypeParameter)null); |
| return; |
| case EcorePackage.EGENERIC_TYPE__ECLASSIFIER: |
| setEClassifier((EClassifier)null); |
| return; |
| } |
| eDynamicUnset(featureID); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| public boolean eIsSet(int featureID) |
| { |
| switch (featureID) |
| { |
| case EcorePackage.EGENERIC_TYPE__EUPPER_BOUND: |
| return eUpperBound != null; |
| case EcorePackage.EGENERIC_TYPE__ETYPE_ARGUMENTS: |
| return eTypeArguments != null && !eTypeArguments.isEmpty(); |
| case EcorePackage.EGENERIC_TYPE__ERAW_TYPE: |
| return eRawType != null; |
| case EcorePackage.EGENERIC_TYPE__ELOWER_BOUND: |
| return eLowerBound != null; |
| case EcorePackage.EGENERIC_TYPE__ETYPE_PARAMETER: |
| return eTypeParameter != null; |
| case EcorePackage.EGENERIC_TYPE__ECLASSIFIER: |
| return eClassifier != null; |
| } |
| return eDynamicIsSet(featureID); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| public Object eInvoke(int operationID, EList<?> arguments) throws InvocationTargetException |
| { |
| switch (operationID) |
| { |
| case EcorePackage.EGENERIC_TYPE___IS_INSTANCE__OBJECT: |
| return isInstance(arguments.get(0)); |
| } |
| return eDynamicInvoke(operationID, arguments); |
| } |
| |
| @Override |
| public String toString() |
| { |
| StringBuilder result = new StringBuilder(super.toString()); |
| result.append(" (expression: "); |
| toString(result); |
| result.append(')'); |
| return result.toString(); |
| } |
| |
| protected void toString(StringBuilder result) |
| { |
| if (eClassifier != null) |
| { |
| String label = eClassifier.getName(); |
| String tail = null; |
| if (label != null) |
| { |
| result.append(label); |
| } |
| else |
| { |
| String instanceTypeName = eClassifier.getInstanceTypeName(); |
| if (instanceTypeName != null) |
| { |
| int index = instanceTypeName.indexOf('['); |
| if (index != -1) |
| { |
| tail = instanceTypeName.substring(index); |
| result.append(instanceTypeName, 0, index); |
| } |
| else |
| { |
| result.append(instanceTypeName); |
| } |
| } |
| } |
| |
| if (eTypeArguments != null && !eTypeArguments.isEmpty()) |
| { |
| boolean first = true; |
| result.append('<'); |
| for (EGenericType eTypeArgument : eTypeArguments) |
| { |
| if (first) |
| { |
| first = false; |
| } |
| else |
| { |
| result.append(", "); |
| } |
| ((EGenericTypeImpl)eTypeArgument).toString(result); |
| } |
| result.append('>'); |
| } |
| |
| if (tail != null) |
| { |
| result.append(tail); |
| } |
| } |
| else if (eTypeParameter != null) |
| { |
| String label = eTypeParameter.getName(); |
| if (label != null) |
| { |
| result.append(label); |
| } |
| } |
| else |
| { |
| result.append('?'); |
| if (eLowerBound != null) |
| { |
| result.append(" super "); |
| ((EGenericTypeImpl)eLowerBound).toString(result); |
| } |
| else |
| { |
| if (eUpperBound != null) |
| { |
| result.append(" extends "); |
| ((EGenericTypeImpl)eUpperBound).toString(result); |
| } |
| } |
| } |
| } |
| |
| } //EGenericTypeImpl |