/**
* Copyright (c) 2013-2016 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) {
}
}