/* * Copyright (c) 2012, 2013, 2015, 2016 Eike Stepper (Berlin, Germany) 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: * Eike Stepper - initial API and implementation * Christian W. Damus - Fix failure to attach CDOLegacyAdapter to EGenericTypes (bug 403681) */ package org.eclipse.emf.internal.cdo.object; import org.eclipse.emf.cdo.CDOObject; import org.eclipse.emf.cdo.common.model.EMFUtil; import org.eclipse.emf.cdo.eresource.impl.CDOResourceImpl; import org.eclipse.emf.cdo.view.CDOView; import org.eclipse.emf.internal.cdo.bundle.OM; import org.eclipse.emf.common.notify.Adapter; 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.common.util.TreeIterator; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EOperation; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.EStructuralFeature.Setting; import org.eclipse.emf.ecore.EcorePackage; import org.eclipse.emf.ecore.InternalEObject; import org.eclipse.emf.ecore.impl.BasicEObjectImpl; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.spi.cdo.FSMUtil; import org.eclipse.emf.spi.cdo.InternalCDOView; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.List; /** * @author Eike Stepper * @since 2.0 */ public abstract class CDOObjectWrapperBase implements CDOObject, InternalEObject { private static final Method E_SET_DIRECT_RESOURCE = getMethod("eSetDirectResource", Resource.Internal.class); private static final Method E_BASIC_SET_CONTAINER = getMethod("eBasicSetContainer", InternalEObject.class, int.class); protected InternalEObject instance; public CDOObjectWrapperBase() { } public CDOResourceImpl cdoResource() { Resource resource = eResource(); if (resource instanceof CDOResourceImpl) { return (CDOResourceImpl)resource; } return null; } /** * @since 2.0 */ public CDOResourceImpl cdoDirectResource() { Resource.Internal resource = eDirectResource(); if (resource instanceof CDOResourceImpl) { return (CDOResourceImpl)resource; } return null; } public InternalEObject cdoInternalInstance() { return instance; } /** * @since 2.0 */ public boolean cdoConflict() { return FSMUtil.isConflict(this); } /** * @since 2.0 */ public boolean cdoInvalid() { return FSMUtil.isInvalid(this); } /** * @since 3.0 */ public void cdoPrefetch(int depth) { InternalCDOView view = (InternalCDOView)cdoView(); view.prefetchRevisions(cdoID(), depth); } public EStructuralFeature cdoInternalDynamicFeature(int dynamicFeatureID) { return eDynamicFeature(dynamicFeatureID); } /** * @since 3.0 */ protected EStructuralFeature eDynamicFeature(int dynamicFeatureID) { EClass eClass = eClass(); return eClass.getEStructuralFeature(dynamicFeatureID + eStaticFeatureCount()); } /** * @since 3.0 */ protected int eStaticFeatureCount() { return eStaticClass().getFeatureCount(); } /** * @since 3.0 */ protected final EClass eStaticClass() { return EcorePackage.eINSTANCE.getEObject(); } public Resource.Internal getInstanceResource(InternalEObject instance) { return instance.eDirectResource(); } public InternalEObject getInstanceContainer(InternalEObject instance) { return instance.eInternalContainer(); } public int getInstanceContainerFeatureID(InternalEObject instance) { return instance.eContainerFeatureID(); } public Object getInstanceValue(InternalEObject instance, EStructuralFeature feature) { return instance.eGet(feature); } public boolean isSetInstanceValue(InternalEObject instance, EStructuralFeature feature) { // Single-valued features that need special handling if (feature == EMFUtil.ETYPED_ELEMENT_EGENERIC_TYPE || feature == EMFUtil.ECLASSIFIER_INSTANCE_TYPE_NAME) { return getInstanceValue(instance, feature) != null; } // Many-valued features that need special handling if (feature == EMFUtil.ECLASS_EGENERIC_SUPER_TYPES || feature == EMFUtil.EOPERATION_EGENERIC_EXCEPTIONS) { return !((List<?>)getInstanceValue(instance, feature)).isEmpty(); } return instance.eIsSet(feature); } public void setInstanceResource(Resource.Internal resource) { try { E_SET_DIRECT_RESOURCE.invoke(instance, resource); } catch (Exception ex) { OM.LOG.error(ex); } } public void setInstanceContainer(InternalEObject container, int containerFeatureID) { try { E_BASIC_SET_CONTAINER.invoke(instance, container, containerFeatureID); } catch (Exception ex) { OM.LOG.error(ex); } } public void setInstanceValue(InternalEObject instance, EStructuralFeature feature, Object value) { instance.eSet(feature, value); } public EList<Adapter> eAdapters() { return instance.eAdapters(); } public TreeIterator<EObject> eAllContents() { return instance.eAllContents(); } public int eBaseStructuralFeatureID(int derivedFeatureID, Class<?> baseClass) { return instance.eBaseStructuralFeatureID(derivedFeatureID, baseClass); } public NotificationChain eBasicRemoveFromContainer(NotificationChain notifications) { return instance.eBasicRemoveFromContainer(notifications); } public NotificationChain eBasicSetContainer(InternalEObject newContainer, int newContainerFeatureID, NotificationChain notifications) { return instance.eBasicSetContainer(newContainer, newContainerFeatureID, notifications); } public EClass eClass() { return instance.eClass(); } public EObject eContainer() { return instance.eContainer(); } public int eContainerFeatureID() { return instance.eContainerFeatureID(); } public EStructuralFeature eContainingFeature() { return instance.eContainingFeature(); } public EReference eContainmentFeature() { return instance.eContainmentFeature(); } public EList<EObject> eContents() { return instance.eContents(); } public EList<EObject> eCrossReferences() { return instance.eCrossReferences(); } public boolean eDeliver() { return instance.eDeliver(); } public int eDerivedStructuralFeatureID(int baseFeatureID, Class<?> baseClass) { return instance.eDerivedStructuralFeatureID(baseFeatureID, baseClass); } public Resource.Internal eDirectResource() { return instance.eDirectResource(); } public Object eGet(EStructuralFeature feature, boolean resolve, boolean coreType) { return instance.eGet(feature, resolve, coreType); } public Object eGet(EStructuralFeature feature, boolean resolve) { return instance.eGet(feature, resolve); } public Object eGet(EStructuralFeature feature) { return instance.eGet(feature); } public Object eGet(int featureID, boolean resolve, boolean coreType) { return instance.eGet(featureID, resolve, coreType); } /** * @since 3.0 */ public int eDerivedOperationID(int baseOperationID, Class<?> baseClass) { // Note: This causes a compiler error with EMF < 2.6M4!!! Ignore it or update your target platform. return instance.eDerivedOperationID(baseOperationID, baseClass); } /** * @since 3.0 */ public Object eInvoke(EOperation operation, EList<?> arguments) throws InvocationTargetException { // Note: This causes a compiler error with EMF < 2.6M4!!! Ignore it or update your target platform. return instance.eInvoke(operation, arguments); } /** * @since 3.0 */ public Object eInvoke(int operationID, EList<?> arguments) throws InvocationTargetException { // Note: This causes a compiler error with EMF < 2.6M4!!! Ignore it or update your target platform. return instance.eInvoke(operationID, arguments); } public InternalEObject eInternalContainer() { return instance.eInternalContainer(); } public Resource.Internal eInternalResource() { CDOView view = cdoView(); if (view != null && view.isClosed()) { return null; } return instance.eInternalResource(); } public NotificationChain eInverseAdd(InternalEObject otherEnd, int featureID, Class<?> baseClass, NotificationChain notifications) { return instance.eInverseAdd(otherEnd, featureID, baseClass, notifications); } public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, Class<?> baseClass, NotificationChain notifications) { return instance.eInverseRemove(otherEnd, featureID, baseClass, notifications); } public boolean eIsProxy() { return instance.eIsProxy(); } public boolean eIsSet(EStructuralFeature feature) { return isSetInstanceValue(instance, feature); } public boolean eIsSet(int featureID) { // Features that need special handling if (featureID == EcorePackage.ETYPED_ELEMENT__EGENERIC_TYPE || featureID == EcorePackage.ECLASSIFIER__INSTANCE_TYPE_NAME || featureID == EcorePackage.ECLASS__EGENERIC_SUPER_TYPES || featureID == EcorePackage.EOPERATION__EGENERIC_EXCEPTIONS) { return isSetInstanceValue(instance, instance.eClass().getEStructuralFeature(featureID)); } return instance.eIsSet(featureID); } public boolean eNotificationRequired() { return instance.eNotificationRequired(); } public void eNotify(Notification notification) { instance.eNotify(notification); } public EObject eObjectForURIFragmentSegment(String uriFragmentSegment) { return instance.eObjectForURIFragmentSegment(uriFragmentSegment); } public URI eProxyURI() { return instance.eProxyURI(); } public EObject eResolveProxy(InternalEObject proxy) { return instance.eResolveProxy(proxy); } public Resource eResource() { return instance.eResource(); } public void eSet(EStructuralFeature feature, Object newValue) { instance.eSet(feature, newValue); } public void eSet(int featureID, Object newValue) { instance.eSet(featureID, newValue); } public void eSetClass(EClass class1) { instance.eSetClass(class1); } public void eSetDeliver(boolean deliver) { instance.eSetDeliver(deliver); } public void eSetProxyURI(URI uri) { instance.eSetProxyURI(uri); } public NotificationChain eSetResource(Resource.Internal resource, NotificationChain notifications) { return instance.eSetResource(resource, notifications); } public void eSetStore(EStore store) { instance.eSetStore(store); } public Setting eSetting(EStructuralFeature feature) { return instance.eSetting(feature); } public EStore eStore() { return instance.eStore(); } public void eUnset(EStructuralFeature feature) { instance.eUnset(feature); } public void eUnset(int featureID) { instance.eUnset(featureID); } public String eURIFragmentSegment(EStructuralFeature feature, EObject object) { return instance.eURIFragmentSegment(feature, object); } @Override public boolean equals(Object obj) { return obj == this || obj == instance || // obj instanceof CDOObjectWrapperBase && ((CDOObjectWrapperBase)obj).instance == instance; } @Override public int hashCode() { if (instance != null) { return instance.hashCode(); } return super.hashCode(); } @Override public String toString() { return getClass().getSimpleName() + "[" + instance.getClass().getSimpleName() + "@" + cdoID() + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } private static Method getMethod(String methodName, Class<?>... parameterTypes) { Method method = null; try { method = BasicEObjectImpl.class.getDeclaredMethod(methodName, parameterTypes); method.setAccessible(true); } catch (Throwable ex) { method = null; } return method; } }