blob: 1de7bfd566a6350b4cd673fcafbcdf4f6ac2c1e5 [file] [log] [blame]
/**
* Copyright (c) 2013-2015 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 org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.util.BasicEMap;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.util.EcoreEMap;
import org.eclipse.emf.ecore.util.FeatureMap;
import org.eclipse.emf.ecore.util.FeatureMapUtil;
/**
* A minimal abstract implementation of '<em><b>EObject</b></em>' that delegates to a {@link org.eclipse.emf.ecore.InternalEObject.EStore store}.
* It's extends {@link MinimalEObjectImpl} and does <b>not</b> introduce any additional fields.
* Clients extending this class must specialize {@link #eStore()}.
* @since 2.9
*/
@SuppressWarnings("javadoc")
public abstract class MinimalEStoreEObjectImpl extends MinimalEObjectImpl
{
private static final EObservableAdapterList.Listener ADAPTERS_LISTENER = new EObservableAdapterList.Listener()
{
public void added(Notifier notifier, Adapter adapter)
{
MinimalEStoreEObjectImpl object = (MinimalEStoreEObjectImpl) notifier;
object.eAdapterAdded(adapter);
}
public void removed(Notifier notifier, Adapter adapter)
{
MinimalEStoreEObjectImpl object = (MinimalEStoreEObjectImpl) notifier;
object.eAdapterRemoved(adapter);
}
};
/**
* Creates a store-based EObject.
*/
public MinimalEStoreEObjectImpl()
{
super();
}
/**
* Creates a store-based EObject.
*/
public MinimalEStoreEObjectImpl(EClass eClass)
{
super();
eSetClass(eClass);
}
@Override
public abstract InternalEObject.EStore eStore();
protected boolean eIsCaching()
{
return true;
}
@Override
Object[] eDynamicSettings()
{
Object[] settings = eBasicSettings();
if (settings == null)
{
eSettings();
settings = eBasicSettings();
}
return settings;
}
@Override
public Object dynamicGet(int dynamicFeatureID)
{
Object[] eSettings = eDynamicSettings();
Object result = eSettings[dynamicFeatureID];
if (result == null)
{
EStructuralFeature eStructuralFeature = eDynamicFeature(dynamicFeatureID);
if (!eStructuralFeature.isTransient())
{
if (FeatureMapUtil.isFeatureMap(eStructuralFeature))
{
eSettings[dynamicFeatureID] = result = createFeatureMap(eStructuralFeature);
}
else if (eStructuralFeature.isMany())
{
eSettings[dynamicFeatureID] = result = createList(eStructuralFeature);
}
else
{
result = eStore().get(this, eStructuralFeature, InternalEObject.EStore.NO_INDEX);
if (eIsCaching())
{
eSettings[dynamicFeatureID] = result;
}
}
}
}
return result;
}
@Override
public void dynamicSet(int dynamicFeatureID, Object value)
{
Object[] eSettings = eDynamicSettings();
EStructuralFeature eStructuralFeature = eDynamicFeature(dynamicFeatureID);
if (eStructuralFeature.isTransient())
{
eSettings[dynamicFeatureID] = value;
}
else
{
eStore().set(this, eStructuralFeature, InternalEObject.EStore.NO_INDEX, value);
if (eIsCaching())
{
eSettings[dynamicFeatureID] = value;
}
}
}
@Override
public void dynamicUnset(int dynamicFeatureID)
{
Object[] eSettings = eDynamicSettings();
EStructuralFeature eStructuralFeature = eDynamicFeature(dynamicFeatureID);
if (eStructuralFeature.isTransient())
{
eSettings[dynamicFeatureID] = null;
}
else
{
eStore().unset(this, eStructuralFeature);
eSettings[dynamicFeatureID] = null;
}
}
@Override
protected boolean eDynamicIsSet(int dynamicFeatureID, EStructuralFeature eFeature)
{
return dynamicFeatureID < 0 ? eOpenIsSet(eFeature) : eFeature.isTransient() ? eSettingDelegate(eFeature).dynamicIsSet(this, eSettings(), dynamicFeatureID)
: eStore().isSet(this, eFeature);
}
@SuppressWarnings("nls")
protected EList<?> createList(final EStructuralFeature eStructuralFeature)
{
final EClassifier eType = eStructuralFeature.getEType();
if (eType.getInstanceClassName() == "java.util.Map$Entry")
{
class EStoreEcoreEMap extends EcoreEMap<Object, Object>
{
private static final long serialVersionUID = 1L;
public EStoreEcoreEMap()
{
super((EClass) eType, BasicEMap.Entry.class, null);
delegateEList = new EStoreEObjectImpl.BasicEStoreEList<BasicEMap.Entry<Object, Object>>(MinimalEStoreEObjectImpl.this, eStructuralFeature)
{
private static final long serialVersionUID = 1L;
@Override
protected void didAdd(int index, BasicEMap.Entry<Object, Object> newObject)
{
EStoreEcoreEMap.this.doPut(newObject);
}
@Override
protected void didSet(int index, BasicEMap.Entry<Object, Object> newObject, BasicEMap.Entry<Object, Object> oldObject)
{
didRemove(index, oldObject);
didAdd(index, newObject);
}
@Override
protected void didRemove(int index, BasicEMap.Entry<Object, Object> oldObject)
{
EStoreEcoreEMap.this.doRemove(oldObject);
}
@Override
protected void didClear(int size, Object[] oldObjects)
{
EStoreEcoreEMap.this.doClear();
}
@Override
protected void didMove(int index, BasicEMap.Entry<Object, Object> movedObject, int oldIndex)
{
EStoreEcoreEMap.this.doMove(movedObject);
}
};
size = delegateEList.size();
}
}
return new EStoreEcoreEMap();
}
return new EStoreEObjectImpl.BasicEStoreEList<Object>(this, eStructuralFeature);
}
protected FeatureMap createFeatureMap(EStructuralFeature eStructuralFeature)
{
return new EStoreEObjectImpl.EStoreFeatureMap(this, eStructuralFeature, eStore());
}
/**
* Returns the container as cached by {@link MinimalEObjectImpl#eInternalContainer()}.
*/
protected InternalEObject eBasicInternalContainer()
{
return super.eInternalContainer();
}
/**
* Returns the container as {@link InternalEObject.EStore#getContainer(InternalEObject) provided} by the store.
*/
@Override
public InternalEObject eInternalContainer()
{
return eStore().getContainer(this);
}
/**
* Returns the container feature ID as cached by {@link MinimalEObjectImpl#eContainerFeatureID()}.
*/
protected int eBasicContainerFeatureID()
{
return super.eContainerFeatureID();
}
/**
* Returns the container feature ID as computed from the container feature {@link InternalEObject.EStore#getContainingFeature(InternalEObject) provided} by the store.
*/
@Override
public int eContainerFeatureID()
{
EObject eContainer = eInternalContainer();
if (eContainer != null)
{
EStructuralFeature eContainingFeature = eStore().getContainingFeature(this);
if (eContainingFeature instanceof EReference)
{
EReference eContainingReference = (EReference) eContainingFeature;
EReference eOpposite = eContainingReference.getEOpposite();
if (eOpposite != null)
{
return eClass().getFeatureID(eOpposite);
}
}
return EOPPOSITE_FEATURE_BASE - eContainer.eClass().getFeatureID(eContainingFeature);
}
return 0;
}
@Override
protected int eStaticFeatureCount()
{
return 0;
}
@Override
public int eDerivedStructuralFeatureID(EStructuralFeature eStructuralFeature)
{
return eClass().getFeatureID(eStructuralFeature);
}
@Override
protected void eBasicSetAdapterArray(Adapter[] adapters)
{
Adapter[] oldAdapters = eBasicAdapterArray();
if (adapters == null || adapters.length == 0)
{
adapters = null;// Optimize possibly empty array
if (oldAdapters != null) // Can't be empty array because of the optimization above
{
((EObservableAdapterList) eAdapters()).removeListener(ADAPTERS_LISTENER);
}
}
else
{
if (oldAdapters == null) // Can't be empty array because of the optimization above
{
((EObservableAdapterList) eAdapters()).addListener(ADAPTERS_LISTENER);
}
}
super.eBasicSetAdapterArray(adapters);
}
@Override
protected EObservableAdapterList.Listener[] eBasicAdapterListeners()
{
throw new UnsupportedOperationException();
}
@Override
protected void eBasicSetAdapterListeners(EObservableAdapterList.Listener[] eAdapterListeners)
{
throw new UnsupportedOperationException();
}
protected void eAdapterAdded(Adapter adapter)
{
}
protected void eAdapterRemoved(Adapter adapter)
{
}
}