/** * Copyright (c) 2002-2011 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 * Christian Damus (Zeligsoft) - 255469 */ package org.eclipse.emf.ecore.impl; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.ListIterator; 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.notify.impl.BasicNotifierImpl; import org.eclipse.emf.common.util.AbstractTreeIterator; import org.eclipse.emf.common.util.BasicEList; import org.eclipse.emf.common.util.Callback; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.InvocationTargetException; import org.eclipse.emf.common.util.TreeIterator; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.common.util.WrappedException; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EDataType; import org.eclipse.emf.ecore.EFactory; 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.ETypedElement; import org.eclipse.emf.ecore.EcorePackage; import org.eclipse.emf.ecore.InternalEObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.util.EContentsEList; import org.eclipse.emf.ecore.util.ECrossReferenceEList; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.ecore.util.ExtendedMetaData; import org.eclipse.emf.ecore.util.FeatureMap; import org.eclipse.emf.ecore.util.FeatureMapUtil; import org.eclipse.emf.ecore.util.InternalEList; import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.rpc.IsSerializable; /** * An implementation of the model object '<em><b>EObject</b></em>'. */ public class BasicEObjectImpl extends BasicNotifierImpl implements EObject, InternalEObject, IsSerializable { /** * An internal interface for holding less frequently members variables. */ protected interface EPropertiesHolder extends EStructuralFeature.Internal.DynamicValueHolder { EClass getEClass(); void setEClass(EClass eClass); URI getEProxyURI(); void setEProxyURI(URI eProxyURI); Resource.Internal getEResource(); void setEResource(Resource.Internal eResource); EList<EObject> getEContents(); void setEContents(EList<EObject> eContents); EList<EObject> getECrossReferences(); void setECrossReferences(EList<EObject> eCrossReferences); boolean hasSettings(); void allocateSettings(int dynamicFeatureCount); } /** * An internal class for holding the least frequently members variables. */ protected static class EPropertiesHolderBaseImpl implements EPropertiesHolder { protected EClass eClass; protected Resource.Internal eResource; protected Object [] eSettings; protected static final Object [] NO_SETTINGS = new Object [0]; public EClass getEClass() { return eClass; } public void setEClass(EClass eClass) { this.eClass = eClass; } public URI getEProxyURI() { throw new UnsupportedOperationException(); } public void setEProxyURI(URI eProxyURI) { throw new UnsupportedOperationException(); } public Resource.Internal getEResource() { return eResource; } public void setEResource(Resource.Internal eResource) { this.eResource = eResource; } public EList<EObject> getEContents() { throw new UnsupportedOperationException(); } public void setEContents(EList<EObject> eContents) { throw new UnsupportedOperationException(); } public EList<EObject> getECrossReferences() { throw new UnsupportedOperationException(); } public void setECrossReferences(EList<EObject> eCrossReferences) { throw new UnsupportedOperationException(); } public boolean hasSettings() { return eSettings != null; } public void allocateSettings(int dynamicFeatureCount) { eSettings = dynamicFeatureCount == 0 ? NO_SETTINGS : new Object [dynamicFeatureCount]; } public Object dynamicGet(int dynamicFeatureID) { return eSettings[dynamicFeatureID]; } public void dynamicSet(int dynamicFeatureID, Object value) { eSettings[dynamicFeatureID] = value; } public void dynamicUnset(int dynamicFeatureID) { eSettings[dynamicFeatureID] = null; } } /** * An internal class for holding less frequently members variables. */ protected static class EPropertiesHolderImpl extends EPropertiesHolderBaseImpl { protected URI eProxyURI; protected EList<EObject> eContents; protected EList<EObject> eCrossReferences; @Override public URI getEProxyURI() { return eProxyURI; } @Override public void setEProxyURI(URI eProxyURI) { this.eProxyURI = eProxyURI; } @Override public EList<EObject> getEContents() { return eContents; } @Override public void setEContents(EList<EObject> eContents) { this.eContents = eContents; } @Override public EList<EObject> getECrossReferences() { return eCrossReferences; } @Override public void setECrossReferences(EList<EObject> eCrossReferences) { this.eCrossReferences = eCrossReferences; } } /** * Creates a basic EObject. */ protected BasicEObjectImpl() { super(); } protected int eStaticFeatureCount() { return eStaticClass().getFeatureCount(); } protected int eStaticOperationCount() { return eStaticClass().getOperationCount(); } protected EPropertiesHolder eProperties() { throw new UnsupportedOperationException(); // if (eProperties == null) // { // eProperties = new EPropertiesHolderImpl(); // } // return eProperties; } protected EPropertiesHolder eBasicProperties() { throw new UnsupportedOperationException(); // return eProperties; } protected boolean eHasSettings() { EPropertiesHolder eProperties = eBasicProperties(); return eProperties != null && eProperties.hasSettings(); } protected EStructuralFeature.Internal.DynamicValueHolder eSettings() { if (!eHasSettings()) { int size = eClass().getFeatureCount() - eStaticFeatureCount(); eProperties().allocateSettings(size); } return eBasicProperties(); } protected int eDynamicFeatureID(EStructuralFeature eStructuralFeature) { return eClass().getFeatureID(eStructuralFeature) - eStaticFeatureCount(); } protected EStructuralFeature eDynamicFeature(int dynamicFeatureID) { return eClass().getEStructuralFeature(dynamicFeatureID + eStaticFeatureCount()); } public String eURIFragmentSegment(EStructuralFeature eStructuralFeature, EObject eObject) { if (eStructuralFeature == null) { for (@SuppressWarnings("unchecked") EContentsEList.FeatureIterator<EObject> crossReferences = (EContentsEList.FeatureIterator<EObject>)((InternalEList<?>)eCrossReferences()).basicIterator(); crossReferences.hasNext(); ) { EObject crossReference = crossReferences.next(); if (crossReference == eObject) { eStructuralFeature = crossReferences.feature(); } } } StringBuilder result = new StringBuilder(); result.append('@'); result.append(eStructuralFeature.getName()); if (eStructuralFeature instanceof EAttribute) { FeatureMap featureMap = (FeatureMap)eGet(eStructuralFeature, false); for (int i = 0, size = featureMap.size(); i < size; ++i) { if (featureMap.getValue(i) == eObject) { EStructuralFeature entryFeature = featureMap.getEStructuralFeature(i); if (entryFeature instanceof EReference && ((EReference)entryFeature).isContainment()) { result.append('.'); result.append(i); return result.toString(); } } } result.append(".-1"); } else if (eStructuralFeature.isMany()) { EList<EAttribute> eKeys = ((EReference)eStructuralFeature).getEKeys(); if (eKeys.isEmpty()) { EList<?> eList = (EList<?>)eGet(eStructuralFeature, false); int index = eList.indexOf(eObject); result.append('.'); result.append(index); } else { EAttribute [] eAttributes = (EAttribute[])((BasicEList<?>)eKeys).data(); result.append('['); for (int i = 0, size = eAttributes.length; i < size; ++i) { EAttribute eAttribute = eAttributes[i]; if (eAttribute == null) { break; } else { if (i != 0) { result.append(','); } result.append(eAttribute.getName()); result.append('='); EDataType eDataType = eAttribute.getEAttributeType(); EFactory eFactory = eDataType.getEPackage().getEFactoryInstance(); if (eAttribute.isMany()) { List<?> values = (List<?>)eObject.eGet(eAttribute); result.append('['); if (!values.isEmpty()) { Iterator<?> j = values.iterator(); eEncodeValue(result, eFactory, eDataType, j.next()); while (j.hasNext()) { result.append(','); eEncodeValue(result, eFactory, eDataType, j.next()); } } result.append(']'); } else { eEncodeValue(result, eFactory, eDataType, eObject.eGet(eAttribute)); } } } result.append(']'); } } return result.toString(); } private static final String [] ESCAPE = { "%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07", "%08", "%09", "%0A", "%0B", "%0C", "%0D", "%0E", "%0F", "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17", "%18", "%19", "%1A", "%1B", "%1C", "%1D", "%1E", "%1F", "%20", null, "%22", "%23", null, "%25", "%26", "%27", null, null, null, null, "%2C", null, null, "%2F", null, null, null, null, null, null, null, null, null, null, "%3A", null, "%3C", null, "%3E", null, }; private static void eEncodeValue(StringBuilder result, EFactory eFactory, EDataType eDataType, Object value) { String stringValue = eFactory.convertToString(eDataType, value); if (stringValue == null) { result.append("null"); } else { int length = stringValue.length(); result.ensureCapacity(result.length() + length + 2); result.append('\''); for (int i = 0; i < length; ++i) { char character = stringValue.charAt(i); if (character < ESCAPE.length) { String escape = ESCAPE[character]; if (escape != null) { result.append(escape); continue; } } result.append(character); } result.append('\''); } } /** * Returns the encoded value or the original, if no encoding was needed. * @see EModelElementImpl#eURIFragmentSegment(EStructuralFeature, EObject) * @param value the value to be encoded. * @return the encoded value or the original, if no encoding was needed. */ static String eEncodeValue(String value) { int length = value.length(); StringBuilder result = null; for (int i = 0; i < length; ++i) { char character = value.charAt(i); if (character < ESCAPE.length) { String escape = ESCAPE[character]; if (escape != null) { if (result == null) { result = new StringBuilder(length + 2); result.append(value, 0, i); } result.append(escape); continue; } } if (result != null) { result.append(character); } } return result == null ? value : result.toString(); } public EObject eObjectForURIFragmentSegment(String uriFragmentSegment) { int lastIndex = uriFragmentSegment.length() - 1; char lastChar = uriFragmentSegment.charAt(lastIndex); if (lastChar == ']') { int index = uriFragmentSegment.indexOf('['); if (index >= 0) { EReference eReference = eReference(uriFragmentSegment.substring(1, index)); String predicate = uriFragmentSegment.substring(index + 1, lastIndex); return eObjectForURIFragmentPredicate(predicate, eReference); } } else { int dotIndex = -1; if (Character.isDigit(lastChar)) { dotIndex = uriFragmentSegment.lastIndexOf('.', lastIndex - 1); if (dotIndex >= 0) { EList<?> eList = (EList<?>)eGet(eStructuralFeature(uriFragmentSegment.substring(1, dotIndex)), false); int position = 0; try { position = Integer.parseInt(uriFragmentSegment.substring(dotIndex + 1)); } catch (NumberFormatException exception) { throw new WrappedException(exception); } if (position < eList.size()) { Object result = eList.get(position); if (result instanceof FeatureMap.Entry) { result = ((FeatureMap.Entry)result).getValue(); } return (EObject)result; } } } if (dotIndex < 0) { return (EObject)eGet(eStructuralFeature(uriFragmentSegment.substring(1)), false); } } return null; } private EObject eObjectForURIFragmentPredicate(String predicate, EReference eReference) { ArrayList<FeatureMap.Entry> featureMapEntries = new ArrayList<FeatureMap.Entry>(); int length = predicate.length(); EClass eReferenceType = eReference.getEReferenceType(); for (int i = 0; i < length; ++i) { int index = predicate.indexOf('=', i); EAttribute eAttribute = eAttribute(eReferenceType, predicate.substring(i, index)); EDataType eDataType = eAttribute.getEAttributeType(); EFactory eFactory = eDataType.getEPackage().getEFactoryInstance(); switch (predicate.charAt(++index)) { case '\'': { int end = predicate.indexOf('\'', ++index); addEntry(featureMapEntries, eAttribute, eDecodeValue(predicate.substring(index, end), eFactory, eDataType)); i = end + 1; break; } case '"': { int end = predicate.indexOf('"', ++index); addEntry(featureMapEntries, eAttribute, eDecodeValue(predicate.substring(index, end), eFactory, eDataType)); i = end + 1; break; } case '[': { ArrayList<Object> values = new ArrayList<Object>(); addEntry(featureMapEntries, eAttribute, values); LOOP: for (;;) { switch (predicate.charAt(++index)) { case '\'': { int end = predicate.indexOf('\'', ++index); values.add(eDecodeValue(predicate.substring(index, end), eFactory, eDataType)); index = end + 1; break; } case '"': { int end = predicate.indexOf('"', ++index); values.add(eDecodeValue(predicate.substring(index, end), eFactory, eDataType)); index = end + 1; break; } case 'n': { ++index; if (predicate.indexOf("ull", index) == index) { values.add(null); } else { throw new RuntimeException("Expecting null"); } index += 3; break; } } if (index < length) { switch (predicate.charAt(index)) { case ',': { break; } case ']': { break LOOP; } default: { throw new RuntimeException("Expecting , or ]"); } } } else { break; } } i = index + 1; break; } case 'n': { ++index; if (predicate.indexOf("ull", index) == index) { addEntry(featureMapEntries, eAttribute, null); } else { throw new RuntimeException("Expecting null"); } i = index + 3; break; } } if (i < length) { if (predicate.charAt(i) != ',') { throw new RuntimeException("Expecting ,"); } } else { break; } } return eObjectForURIFragmentPredicate(featureMapEntries, eReference); } private static final void addEntry(List<FeatureMap.Entry> featureMapEntries, final EAttribute eAttribute, final Object value) { featureMapEntries.add (new FeatureMap.Entry() { public EStructuralFeature getEStructuralFeature() { return eAttribute; } public Object getValue() { return value; } }); } private static Object eDecodeValue(String encodedValue, EFactory eFactory, EDataType eDataType) { String literal = URI.decode(encodedValue); Object value = eFactory.createFromString(eDataType, literal); return value; } private EObject eObjectForURIFragmentPredicate(List<FeatureMap.Entry> predicate, EReference eReference) { int size = predicate.size(); @SuppressWarnings("unchecked") EList<EObject> list = ((EList<EObject>)eGet(eReference, false)); LOOP: for (EObject eObject : list) { for (int i = 0; i < size; ++i) { FeatureMap.Entry entry = predicate.get(i); Object entryValue = entry.getValue(); EStructuralFeature entryFeature = entry.getEStructuralFeature(); Object actualValue = eObject.eGet(entryFeature, false); if (entryValue == null ? actualValue != null : !entryValue.equals(actualValue)) { continue LOOP; } } return eObject; } return null; } private EStructuralFeature eStructuralFeature(String name) throws IllegalArgumentException { EStructuralFeature eStructuralFeature = eClass().getEStructuralFeature(name); if (eStructuralFeature == null) { throw new IllegalArgumentException("The feature '" + name + "' is not a valid feature"); } return eStructuralFeature; } private EReference eReference(String name) throws IllegalArgumentException { EStructuralFeature eStructuralFeature = eClass().getEStructuralFeature(name); if (eStructuralFeature instanceof EReference) { return (EReference)eStructuralFeature; } throw new IllegalArgumentException("The feature '" + name + "' is not a valid reference"); } private EAttribute eAttribute(EClass eClass, String name) throws IllegalArgumentException { EStructuralFeature eStructuralFeature = eClass.getEStructuralFeature(name); if (eStructuralFeature instanceof EAttribute) { return (EAttribute)eStructuralFeature; } throw new IllegalArgumentException("The feature '" + name + "' is not a valid attribute"); } public boolean eContains(EObject eObject) { return EcoreUtil.isAncestor(this, eObject); } public EObject eContainer() { InternalEObject result = eInternalContainer(); if (result != null) { int eContainerFeatureID = eContainerFeatureID(); if (result.eIsProxy()) { EObject resolved = eResolveProxy(result); if (resolved != result) { NotificationChain notificationChain = eBasicRemoveFromContainer(null); eBasicSetContainer((InternalEObject)resolved, eContainerFeatureID); if (notificationChain != null) { notificationChain.dispatch(); } if (eNotificationRequired() && eContainerFeatureID > EOPPOSITE_FEATURE_BASE) { eNotify(new ENotificationImpl(this, Notification.RESOLVE, eContainerFeatureID, result, resolved)); } return resolved; } } } return result; } public InternalEObject eInternalContainer() { throw new UnsupportedOperationException(); //return eContainer; } public int eContainerFeatureID() { throw new UnsupportedOperationException(); // return eContainerFeatureID; } protected void eBasicSetContainer(InternalEObject newContainer, int newContainerFeatureID) { throw new UnsupportedOperationException(); // eContainer = newContainer; // eContainerFeatureID = newContainerFeatureID; } public EList<EObject> eContents() { EList<EObject> result = eProperties().getEContents(); if (result == null) { eBasicProperties().setEContents(result = EContentsEList.createEContentsEList(this)); } return result; } public EList<EObject> eCrossReferences() { EList<EObject> result = eProperties().getECrossReferences(); if (result == null) { eBasicProperties().setECrossReferences(result = ECrossReferenceEList.createECrossReferenceEList(this)); } return result; } public TreeIterator<EObject> eAllContents() { return new AbstractTreeIterator<EObject>(this, false) { private static final long serialVersionUID = 1L; @Override public Iterator<EObject> getChildren(Object object) { return ((EObject)object).eContents().iterator(); } }; } public EReference eContainmentFeature() { return eContainmentFeature(this, eInternalContainer(), eContainerFeatureID()); } protected static EReference eContainmentFeature(EObject eObject, EObject eContainer, int eContainerFeatureID) { if (eContainer == null) { return null; } else { if (eContainerFeatureID <= EOPPOSITE_FEATURE_BASE) { EStructuralFeature eFeature = eContainer.eClass().getEStructuralFeature(EOPPOSITE_FEATURE_BASE - eContainerFeatureID); if (eFeature instanceof EReference) { return (EReference)eFeature; } else { FeatureMap featureMap = (FeatureMap)eContainer.eGet(eFeature); for (int i = 0, size = featureMap.size(); i < size; ++i) { if (featureMap.getValue(i) == eObject) { EStructuralFeature entryFeature = featureMap.getEStructuralFeature(i); if (entryFeature instanceof EReference) { EReference entryReference = (EReference)entryFeature; if (entryReference.isContainment()) { return entryReference; } } } } throw new IllegalStateException("The containment feature could not be located"); } } else { return ((EReference)eObject.eClass().getEStructuralFeature(eContainerFeatureID)).getEOpposite(); } } } public EStructuralFeature eContainingFeature() { EObject eContainer = eInternalContainer(); if (eContainer == null) { return null; } else { int eContainerFeatureID = eContainerFeatureID(); return eContainerFeatureID <= EOPPOSITE_FEATURE_BASE ? eContainer.eClass().getEStructuralFeature(EOPPOSITE_FEATURE_BASE - eContainerFeatureID) : ((EReference)eClass().getEStructuralFeature(eContainerFeatureID)).getEOpposite(); } } public Resource.Internal eDirectResource() { EPropertiesHolder eProperties = eBasicProperties(); return eProperties == null ? null : eProperties.getEResource(); } public Resource eResource() { return eInternalResource(); } public Resource.Internal eInternalResource() { Resource.Internal result = eDirectResource(); if (result == null) { int count = 0; for (InternalEObject eContainer = eInternalContainer(); eContainer != null; eContainer = eContainer.eInternalContainer()) { // Since the cycle is detected by checking if we hit "this" again, after many iterations we'll call this method recursively // in case we started with something that wasn't part of a cycle but later traversed up to a cycle. // if (++count > 100000) { return eContainer.eInternalResource(); } result = eContainer.eDirectResource(); if (result != null || eContainer == this) { break; } } } return result; } public NotificationChain eSetResource(Resource.Internal resource, NotificationChain notifications) { Resource.Internal oldResource = eDirectResource(); // When setting the resource to null we assume that detach has already been called in the resource implementation // if (oldResource != null && resource != null) { notifications = ((InternalEList<?>)oldResource.getContents()).basicRemove(this, notifications); oldResource.detached(this); } InternalEObject oldContainer = eInternalContainer(); if (oldContainer != null) { if (eContainmentFeature().isResolveProxies()) { Resource.Internal oldContainerResource = oldContainer.eInternalResource(); if (oldContainerResource != null) { // If we're not setting a new resource, attach it to the old container's resource. if (resource == null) { oldContainerResource.attached(this); } // If we didn't detach it from an old resource already, detach it from the old container's resource. // else if (oldResource == null) { oldContainerResource.detached(this); } } } else { notifications = eBasicRemoveFromContainer(notifications); notifications = eBasicSetContainer(null, -1, notifications); } } eSetDirectResource(resource); return notifications; } protected void eSetDirectResource(Resource.Internal resource) { eProperties().setEResource(resource); } public Object eGet(EStructuralFeature eFeature) { return eGet(eFeature, true); } public Object eGet(EStructuralFeature eFeature, boolean resolve) { return eGet(eFeature, resolve, true); } public Object eGet(EStructuralFeature eFeature, boolean resolve, boolean coreType) { int featureID = eDerivedStructuralFeatureID(eFeature); if (featureID >= 0) { return eGet(featureID, resolve, coreType); } else { return eOpenGet(eFeature, resolve); } } public Object eGet(int featureID, boolean resolve, boolean coreType) { EStructuralFeature eFeature = eClass().getEStructuralFeature(featureID); assert eFeature != null : "Invalid featureID: " + featureID; int dynamicFeatureID = featureID - eStaticFeatureCount(); return dynamicFeatureID < 0 ? eGet(eFeature, resolve) /* backward compatibility with old generated overrides */ : eSettingDelegate(eFeature).dynamicGet(this, eSettings(), dynamicFeatureID, resolve, coreType); } public Object eDynamicGet(EStructuralFeature eFeature, boolean resolve) { return eDynamicGet(eDynamicFeatureID(eFeature), eFeature, resolve, true); } public Object eDynamicGet(int featureID, boolean resolve, boolean coreType) { return eDynamicGet(featureID - eStaticFeatureCount(), eClass().getEStructuralFeature(featureID), resolve, coreType); } protected Object eDynamicGet(int dynamicFeatureID, EStructuralFeature eFeature, boolean resolve, boolean coreType) { return dynamicFeatureID < 0 ? eOpenGet(eFeature, resolve) : eSettingDelegate(eFeature).dynamicGet(this, eSettings(), dynamicFeatureID, resolve, coreType); } public Object eOpenGet(EStructuralFeature eFeature, boolean resolve) { EStructuralFeature openFeature = ExtendedMetaData.INSTANCE.getAffiliation(eClass(), eFeature); if (openFeature != null) { if (!FeatureMapUtil.isFeatureMap(openFeature)) { openFeature = ExtendedMetaData.INSTANCE.getGroup(openFeature); } FeatureMap featureMap = (FeatureMap)eGet(openFeature); return ((FeatureMap.Internal)featureMap).get(eFeature, resolve); } else { throw new IllegalArgumentException("The feature '" + eFeature.getName() + "' is not a valid feature"); } } public void eSet(EStructuralFeature eFeature, Object newValue) { int featureID = eDerivedStructuralFeatureID(eFeature); if (featureID >= 0) { eSet(featureID, newValue); } else { eOpenSet(eFeature, newValue); } } public void eSet(int featureID, Object newValue) { EStructuralFeature eFeature = eClass().getEStructuralFeature(featureID); int dynamicFeatureID = featureID - eStaticFeatureCount(); if (dynamicFeatureID < 0) { if (eFeature == null) { throw new IllegalArgumentException("The feature ID" + featureID + " is not a valid feature ID"); } else if (!eFeature.isChangeable()) { throw new IllegalArgumentException("The feature '" + eFeature.getName() + "' is not a valid changeable feature"); } else { eSet(eFeature, newValue); /* backward compatibility with old generated overrides */ } } else { assert eFeature != null : "Invalid featureID: " + featureID; eDynamicSet(dynamicFeatureID, eFeature, newValue); } } public void eDynamicSet(EStructuralFeature eFeature, Object newValue) { eDynamicSet(eDynamicFeatureID(eFeature), eFeature, newValue); } public void eDynamicSet(int featureID, Object newValue) { eDynamicSet(featureID - eStaticFeatureCount(), eClass().getEStructuralFeature(featureID), newValue); } protected void eDynamicSet(int dynamicFeatureID, EStructuralFeature eFeature, Object newValue) { if (dynamicFeatureID < 0) { eOpenSet(eFeature, newValue); } else { if (!eFeature.isChangeable()) { throw new IllegalArgumentException("The feature '" + eFeature.getName() + "' is not a valid changeable feature"); } eSettingDelegate(eFeature).dynamicSet(this, eSettings(), dynamicFeatureID, newValue); } } public void eOpenSet(EStructuralFeature eFeature, Object newValue) { EStructuralFeature openFeature = ExtendedMetaData.INSTANCE.getAffiliation(eClass(), eFeature); if (openFeature != null) { if (!FeatureMapUtil.isFeatureMap(openFeature)) { openFeature = ExtendedMetaData.INSTANCE.getGroup(openFeature); } FeatureMap featureMap = (FeatureMap)eGet(openFeature); ((FeatureMap.Internal)featureMap).set(eFeature, newValue); } else { throw new IllegalArgumentException("The feature '" + eFeature.getName() + "' is not a valid changeable feature"); } } public void eUnset(EStructuralFeature eFeature) { int featureID = eDerivedStructuralFeatureID(eFeature); if (featureID >= 0) { eUnset(featureID); } else { eOpenUnset(eFeature); } } public void eUnset(int featureID) { EStructuralFeature eFeature = eClass().getEStructuralFeature(featureID); int dynamicFeatureID = featureID - eStaticFeatureCount(); if (dynamicFeatureID < 0) { if (eFeature == null) { throw new IllegalArgumentException("The feature ID" + featureID + " is not a valid feature ID"); } else if (!eFeature.isChangeable()) { throw new IllegalArgumentException("The feature '" + eFeature.getName() + "' is not a valid changeable feature"); } else { eUnset(eFeature); /* backward compatibility with old generated overrides */ } } else { assert eFeature != null : "Invalid featureID: " + featureID; eDynamicUnset(dynamicFeatureID, eFeature); } } public void eDynamicUnset(EStructuralFeature eFeature) { eDynamicUnset(eDynamicFeatureID(eFeature), eFeature); } public void eDynamicUnset(int featureID) { eDynamicUnset(featureID - eStaticFeatureCount(), eClass().getEStructuralFeature(featureID)); } protected void eDynamicUnset(int dynamicFeatureID, EStructuralFeature eFeature) { if (dynamicFeatureID < 0) { eOpenUnset(eFeature); } else { if (!eFeature.isChangeable()) { throw new IllegalArgumentException("The feature '" + eFeature.getName() + "' is not a valid changeable feature"); } eSettingDelegate(eFeature).dynamicUnset(this, eSettings(), dynamicFeatureID); } } public void eOpenUnset(EStructuralFeature eFeature) { EStructuralFeature openFeature = ExtendedMetaData.INSTANCE.getAffiliation(eClass(), eFeature); if (openFeature != null) { if (!FeatureMapUtil.isFeatureMap(openFeature)) { openFeature = ExtendedMetaData.INSTANCE.getGroup(openFeature); } FeatureMap featureMap = (FeatureMap)eGet(openFeature); ((FeatureMap.Internal)featureMap).unset(eFeature); } else { throw new IllegalArgumentException("The feature '" + eFeature.getName() + "' is not a valid changeable feature"); } } public boolean eIsSet(EStructuralFeature eFeature) { int featureID = eDerivedStructuralFeatureID(eFeature); if (featureID >= 0) { return eIsSet(featureID); } else { return eOpenIsSet(eFeature); } } public boolean eIsSet(int featureID) { EStructuralFeature eFeature = eClass().getEStructuralFeature(featureID); assert eFeature != null : "Invalid featureID: " + featureID; int dynamicFeatureID = featureID - eStaticFeatureCount(); return dynamicFeatureID < 0 ? eIsSet(eFeature) /* backward compatibility with old generated overrides */ : eDynamicIsSet(dynamicFeatureID, eFeature); } public boolean eDynamicIsSet(EStructuralFeature eFeature) { return eDynamicIsSet(eDynamicFeatureID(eFeature), eFeature); } public boolean eDynamicIsSet(int featureID) { return eDynamicIsSet(featureID - eStaticFeatureCount(), eClass().getEStructuralFeature(featureID)); } protected boolean eDynamicIsSet(int dynamicFeatureID, EStructuralFeature eFeature) { return dynamicFeatureID < 0 ? eOpenIsSet(eFeature) : eSettingDelegate(eFeature).dynamicIsSet(this, eSettings(), dynamicFeatureID); } public boolean eOpenIsSet(EStructuralFeature eFeature) { EStructuralFeature openFeature = ExtendedMetaData.INSTANCE.getAffiliation(eClass(), eFeature); if (openFeature != null) { if (!FeatureMapUtil.isFeatureMap(openFeature)) { openFeature = ExtendedMetaData.INSTANCE.getGroup(openFeature); } FeatureMap featureMap = (FeatureMap)eGet(openFeature); return ((FeatureMap.Internal)featureMap).isSet(eFeature); } else { throw new IllegalArgumentException("The feature '" + eFeature.getName() + "' is not a valid feature"); } } public NotificationChain eBasicSetContainer(InternalEObject newContainer, int newContainerFeatureID, NotificationChain msgs) { InternalEObject oldContainer = eInternalContainer(); Resource.Internal oldResource = this.eDirectResource(); Resource.Internal newResource = null; if (oldResource != null) { if (newContainer != null && !eContainmentFeature(this, newContainer, newContainerFeatureID).isResolveProxies()) { msgs = ((InternalEList<?>)oldResource.getContents()).basicRemove(this, msgs); eSetDirectResource(null); newResource = newContainer.eInternalResource(); } else { oldResource = null; } } else { if (oldContainer != null) { oldResource = oldContainer.eInternalResource(); } if (newContainer != null) { newResource = newContainer.eInternalResource(); } } if (oldResource != newResource && oldResource != null) { oldResource.detached(this); } int oldContainerFeatureID = eContainerFeatureID(); eBasicSetContainer(newContainer, newContainerFeatureID); if (oldResource != newResource && newResource != null) { newResource.attached(this); } if (eNotificationRequired()) { if (oldContainer != null && oldContainerFeatureID >=0 && oldContainerFeatureID != newContainerFeatureID) { ENotificationImpl notification = new ENotificationImpl (this, Notification.SET, oldContainerFeatureID, oldContainer, null); if (msgs == null) { msgs = notification; } else { msgs.add(notification); } } if (newContainerFeatureID >= 0) { ENotificationImpl notification = new ENotificationImpl (this, Notification.SET, newContainerFeatureID, oldContainerFeatureID == newContainerFeatureID ? oldContainer : null, newContainer); if (msgs == null) { msgs = notification; } else { msgs.add(notification); } } } return msgs; } public NotificationChain eBasicRemoveFromContainer(NotificationChain msgs) { int eContainerFeatureID = eContainerFeatureID(); if (eContainerFeatureID >= 0) { return eBasicRemoveFromContainerFeature(msgs); } else { return eInternalContainer().eInverseRemove(this, EOPPOSITE_FEATURE_BASE - eContainerFeatureID, null, msgs); } } public NotificationChain eBasicRemoveFromContainerFeature(NotificationChain msgs) { return eDynamicBasicRemoveFromContainer(msgs); } public NotificationChain eDynamicBasicRemoveFromContainer(NotificationChain msgs) { EReference inverseFeature = ((EReference)eClass().getEStructuralFeature(eContainerFeatureID())).getEOpposite(); return eInternalContainer().eInverseRemove(this, inverseFeature.getFeatureID(), inverseFeature.getContainerClass(), msgs); } public NotificationChain eInverseAdd(InternalEObject otherEnd, int featureID, Class<?> baseClass, NotificationChain msgs) { if (featureID >= 0) { return eInverseAdd(otherEnd, eDerivedStructuralFeatureID(featureID, baseClass), msgs); } else { if (eInternalContainer() != null) { msgs = eBasicRemoveFromContainer(msgs); } return eBasicSetContainer(otherEnd, featureID, msgs); } } public NotificationChain eInverseAdd(InternalEObject otherEnd, int featureID, NotificationChain msgs) { return eDynamicInverseAdd(otherEnd, featureID, msgs); } public NotificationChain eDynamicInverseAdd(InternalEObject otherEnd, int featureID, Class<?> inverseClass, NotificationChain msgs) { return eDynamicInverseAdd(otherEnd, featureID, msgs); } protected NotificationChain eDynamicInverseAdd(InternalEObject otherEnd, int featureID, NotificationChain msgs) { EStructuralFeature.Internal feature = (EStructuralFeature.Internal)eClass().getEStructuralFeature(featureID); return feature.getSettingDelegate().dynamicInverseAdd(this, eSettings(), featureID - eStaticFeatureCount(), otherEnd, msgs); } public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, Class<?> baseClass, NotificationChain msgs) { if (featureID >= 0) { return eInverseRemove(otherEnd, eDerivedStructuralFeatureID(featureID, baseClass), msgs); } else { return eBasicSetContainer(null, featureID, msgs); } } public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) { return eDynamicInverseRemove(otherEnd, featureID, msgs); } public NotificationChain eDynamicInverseRemove(InternalEObject otherEnd, int featureID, Class<?> inverseClass, NotificationChain msgs) { return eDynamicInverseRemove(otherEnd, featureID, msgs); } protected NotificationChain eDynamicInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) { EStructuralFeature.Internal feature = (EStructuralFeature.Internal)eClass().getEStructuralFeature(featureID); return feature.getSettingDelegate().dynamicInverseRemove(this, eSettings(), featureID - eStaticFeatureCount(), otherEnd, msgs); } public URI eProxyURI() { return eBasicProperties() == null ? null : eBasicProperties().getEProxyURI(); } public void eSetProxyURI(URI uri) { eProperties().setEProxyURI(uri); } public EObject eResolveProxy(InternalEObject proxy) { final EObject result = EcoreUtil.resolve(proxy, this); if (result == proxy && GWT.isClient()) { Resource eResource = eResource(); if (eResource != null) { ResourceSet resourceSet = eResource.getResourceSet(); if (resourceSet != null) { resourceSet.getEObject (proxy.eProxyURI(), new Callback<EObject>() { public void onSuccess(EObject eObject) { // If the proxy successfully resolved... // if (eObject != null) { for (EReference eReference : eClass().getEAllReferences()) { Object value = eGet(eReference, false, true); if (eReference.isMany()) { InternalEList<?> list = (InternalEList<?>)value; for (ListIterator<?> i = list.basicListIterator(); i.hasNext(); ) { if (i.next() == result) { // Force this proxy at this index to be resolved. // list.get(i.previousIndex()); break; } } } else if (value == result) { // Force this proxy to resolve. // eGet(eReference, true, true); } } } } public void onFailure(Throwable caught) { // Ignore failed proxy resolutions. } }); } } } return result; } public boolean eIsProxy() { return eBasicProperties() != null && eBasicProperties().getEProxyURI() != null; } public int eBaseStructuralFeatureID(int derivedFeatureID, Class<?> baseClass) { return derivedFeatureID; } public int eDerivedStructuralFeatureID(int baseFeatureID, Class<?> baseClass) { return baseFeatureID; } public int eDerivedStructuralFeatureID(EStructuralFeature eStructuralFeature) { Class<?> containerClass = eStructuralFeature.getContainerClass(); if (containerClass == null) { return eClass().getFeatureID(eStructuralFeature); } else { assert eClass().getEAllStructuralFeatures().contains(eStructuralFeature) : "The feature '" + eStructuralFeature.getName() + "' is not a valid feature"; return eDerivedStructuralFeatureID(eStructuralFeature.getFeatureID(), containerClass); } } public int eDerivedOperationID(int baseOperationID, Class<?> baseClass) { return baseOperationID; } public int eDerivedOperationID(EOperation eOperation) { Class<?> containerClass = eOperation.getEContainingClass().getInstanceClass(); if (containerClass == null) { EClass eClass = eClass(); EOperation override = eClass.getOverride(eOperation); return eClass.getOperationID(override != null ? override : eOperation); } else { assert eClass().getEAllOperations().contains(eOperation) : "The operation '" + eOperation.getName() + "' is not a valid operation"; return eDerivedOperationID(eOperation.getOperationID(), containerClass); } } public EClass eClass() { if (eBasicProperties() != null) { EClass result = eBasicProperties().getEClass(); if (result != null) { return result; } } return eStaticClass(); } // Subclasses MUST override this function protected EClass eStaticClass() { return EcorePackage.eINSTANCE.getEObject(); } protected EClass eDynamicClass() { return eBasicProperties() == null ? null : eBasicProperties().getEClass(); } public void eSetClass(EClass eClass) { eProperties().setEClass(eClass); } protected EStructuralFeature.Internal.SettingDelegate eSettingDelegate(EStructuralFeature eFeature) { return ((EStructuralFeature.Internal)eFeature).getSettingDelegate(); } public EStructuralFeature.Setting eSetting(final EStructuralFeature eFeature) { EClass eClass = eClass(); int index = eClass.getFeatureID(eFeature); int dynamicIndex = eStaticFeatureCount(); if (index >= dynamicIndex) { return eSettingDelegate(eFeature).dynamicSetting(this, eSettings(), index - dynamicIndex); } else if (index <= -1) { EStructuralFeature openFeature = ExtendedMetaData.INSTANCE.getAffiliation(eClass, eFeature); if (openFeature != null) { if (!FeatureMapUtil.isFeatureMap(openFeature)) { openFeature = ExtendedMetaData.INSTANCE.getGroup(openFeature); } FeatureMap featureMap = (FeatureMap)eGet(openFeature); int upperBound = openFeature.getUpperBound(); if (upperBound > 1 || upperBound == ETypedElement.UNBOUNDED_MULTIPLICITY) { return (EStructuralFeature.Setting)((FeatureMap.Internal)featureMap).get(eFeature, false); } } else { throw new IllegalArgumentException("The feature '" + eFeature.getName() + "' is not a valid feature"); } } else if (eFeature.isMany()) { return (EStructuralFeature.Setting)eGet(eFeature, false); } EStructuralFeature.Setting setting = new EStructuralFeature.Setting() { public EObject getEObject() { return BasicEObjectImpl.this; } public EStructuralFeature getEStructuralFeature() { return eFeature; } public Object get(boolean resolve) { return BasicEObjectImpl.this.eGet(eFeature, resolve); } public void set(Object newValue) { BasicEObjectImpl.this.eSet(eFeature, newValue); } public boolean isSet() { return BasicEObjectImpl.this.eIsSet(eFeature); } public void unset() { BasicEObjectImpl.this.eUnset(eFeature); } }; return setting; } protected EOperation.Internal.InvocationDelegate eInvocationDelegate(EOperation eOperation) { return ((EOperation.Internal)eOperation).getInvocationDelegate(); } public InternalEObject.EStore eStore() { return null; } public void eSetStore(InternalEObject.EStore store) { throw new UnsupportedOperationException(); } /** * Returns the {@link #eBasicAdapterArray() adapter array} of the {@link #eInternalContainer() container}. * @return the adapter array of the container. */ protected Adapter [] eContainerAdapterArray() { InternalEObject eInternalContainer = eInternalContainer(); return eInternalContainer instanceof BasicEObjectImpl ? ((BasicEObjectImpl)eInternalContainer).eBasicAdapterArray() : null; } /** * Returns the number of bits that are on in the two's complement bit pattern. * This is used to maintain the bit set representing which feature IDs * currently have and index allocated in the {@link #eVirtualValues() virtual values}. * @param value a two's complement bit pattern. * @return the number of bits that are on. */ protected static int eVirtualBitCount(int value) { value -= value >>> 1 & 0x55555555; value = (value & 0x33333333) + (value >>> 2 & 0x33333333); value = (value + (value >>> 4)) & 0x0F0F0F0F; value += value >>> 8; value += value >>> 16; return value & 0x3F; } /** * Returns the bit pattern at the given offset within the sequence of bit patterns * representing which features are assigned an index in the {@link #eVirtualValues() virtual values}. * @param offset the offset within the bit sequence of bit patterns. * @return the bit pattern at the offset. */ protected int eVirtualIndexBits(int offset) { // return eVirtualIndexBits[offset]; throw new UnsupportedOperationException(); } /** * Sets the bit pattern at the given offset within the sequence of bit patterns * representing which features are assigned an index in the {@link #eVirtualValues() virtual values}. * @param offset the offset within the bit sequence of bit patterns. * @param newIndexBits the new bit pattern at the offset. */ protected void eSetVirtualIndexBits(int offset, int newIndexBits) { // eVirtualIndexBits[offset] = newIndexBits; throw new UnsupportedOperationException(); } /** * An action code indicating that an {@link #eVirtualIndex(int, int) index} * needs to be computed to perform a {@link #eVirtualSet(int, Object)} set. */ protected static final int EVIRTUAL_SET = 0; /** * An action code indicating that an {@link #eVirtualIndex(int, int)} index * needs to be computed to perform an {@link #eVirtualUnset(int) unset}. */ protected static final int EVIRTUAL_UNSET = 1; /** * An action code indicating that an {@link #eVirtualIndex(int, int) index} * needs to be computed to perform a {@link #eVirtualGet(int) get}. */ protected static final int EVIRTUAL_GET = 2; /** * An action code indicating that an {@link #eVirtualIndex(int, int) index} * needs to be computed to perform an {@link #eVirtualIsSet(int) isSet}. */ protected static final int EVIRTUAL_IS_SET = 3; /** * Returns the index in the {@link #eVirtualValues() virtual values} for the feature ID, * with the side effect of toggling the necessary bits to suit the action code. * A result of less than zero indicates that the feature ID is not assigned an index. * In the case of a set action, when the value was not previously set, * the result will be the complement of the assigned index, * which can be corrected by <code>~index</code>. * @param eDerivedStructuralFeatureID the ID of a feature of the class. * @param action the reason for computing the ID. * @return the virtual index. */ protected int eVirtualIndex(int eDerivedStructuralFeatureID, int action) { // Compute the offset in the sequence of bit patterns for this feature ID // and then get the bit pattern at that index. // int offset = eDerivedStructuralFeatureID >>> 5; int bits = eVirtualIndexBits(offset); // Compute the index within that bit pattern for this feature ID // and fetch that bit at that index. // int bitIndex = eDerivedStructuralFeatureID & 31; int bit = bits >>> bitIndex & 1; switch (action) { case EVIRTUAL_IS_SET: { // For isSet, we only need to check the bit and return -1 when the bit is 0. // return bit - 1; } case EVIRTUAL_GET: case EVIRTUAL_UNSET: { if (bit == 0) { // If the value index set, there's no index to return. // return -1; } // Continue to compute the offset. } case EVIRTUAL_SET: default: { // Depending on the action and the current state, we'll toggle the state. // i.e., for unset, we need to turn it off if it's on, // and for set we need to turn it on if it's off. // if (bit == action) { eSetVirtualIndexBits(offset, bits ^ (1 << bitIndex)); } // Count just the bits up to this one. // Note that shifting 32 bits is a no op. // int result = eVirtualBitCount(bitIndex == 0 ? 0 : bits << 32 - bitIndex); // Count all the bits in the bit patterns up to this one in the sequence of bit patterns. // for (int i = offset; --i >= 0;) { result += eVirtualBitCount(eVirtualIndexBits(i)); } // If the index was previously assigned, return it. // Otherwise, return a negative result that encodes the newly assigned index. // return bit != 0 ? result : ~result; } } } /** * Returns the array of virtual values of the features that are current set. * @return the array of virtual values of the features that are current set. */ protected Object[] eVirtualValues() { // return eVirtualValues; throw new UnsupportedOperationException(); } /** * Sets the array of virtual values of the features that are current set. * @param newValues the new array of virtual values. */ protected void eSetVirtualValues(Object[] newValues) { // eVirtualValues = newValues; throw new UnsupportedOperationException(); } /** * Returns the value at the index. * @param index the {@link #eVirtualIndex(int, int) index} in the {@link #eVirtualValues() virtual values}. * @return the value at the index. */ protected Object eVirtualValue(int index) { return eVirtualValues()[index]; } /** * Sets the value at the index. * @param index the {@link #eVirtualIndex(int, int) index} in the {@link #eVirtualValues() virtual values}. * @return the previous value at the index. */ protected Object eSetVirtualValue(int index, Object value) { Object[] values = eVirtualValues(); Object oldValue = values[index]; values[index] = value; return oldValue; } /** * This method controls the growth of the {@link #eVirtualValues() virtual values} by returning the new capacity * that should be allocated for the given minimum required capacity. Subclasses can override this to be more or * less liberal in growth. * @param minimumCapacity the minimum number of virtual value entries required. * @return the actual number of entries to allocate space for, including a growth factor. */ protected int eComputeVirtualValuesCapacity(int minimumCapacity) { // return minimumCapacity; return minimumCapacity + (minimumCapacity >> 3) + 2; } /** * Adds the value at the index. * @param index the {@link #eVirtualIndex(int, int) index} in the {@link #eVirtualValues() virtual values}. */ protected void eAddVirtualValue(int index, Object value) { Object[] values = eVirtualValues(); if (values == null) { int newLength = eComputeVirtualValuesCapacity(1); values = new Object [newLength]; values[0] = value; for (int i = 1; i < newLength; ++i) { values[i] = EVIRTUAL_NO_VALUE; } eSetVirtualValues(values); } else { int length = values.length; if (values[length - 1] == EVIRTUAL_NO_VALUE) { if (index + 1 < length) { System.arraycopy(values, index, values, index + 1, length - index - 1); } values[index] = value; } else { int newLength = eComputeVirtualValuesCapacity(length + 1); Object[] newValues = new Object [newLength]; for (int i = length; ++i < newLength;) { newValues[i] = EVIRTUAL_NO_VALUE; } if (index > 0) { System.arraycopy(values, 0, newValues, 0, index); } if (index < length) { System.arraycopy(values, index, newValues, index + 1, length - index); } newValues[index] = value; eSetVirtualValues(newValues); } } } /** * Removes the value at the index. * @param index the {@link #eVirtualIndex(int, int) index} in the {@link #eVirtualValues() virtual values}. * @return the value at the index. */ protected Object eRemoveVirtualValue(int index) { Object[] values = eVirtualValues(); Object oldValue = values[index]; int length = values.length - 1; if (index == 0 && (length == 0 || values[1] == EVIRTUAL_NO_VALUE)) { eSetVirtualValues(null); } else { if (index < length) { System.arraycopy(values, index + 1, values, index, length - index); } } return oldValue; } /** * Returns the value for the feature ID, or <code>null</code>, if there isn't one. * @param eDerivedStructuralFeatureID the feature ID to fetch. * @return the value for the feature ID. */ public Object eVirtualGet(int eDerivedStructuralFeatureID) { return eVirtualGet(eDerivedStructuralFeatureID, null); } /** * Returns the value for the feature ID, or the default value, if there isn't one. * @param eDerivedStructuralFeatureID the feature ID to fetch. * @param defaultValue the default value. * @return the value for the feature ID. */ public Object eVirtualGet(int eDerivedStructuralFeatureID, Object defaultValue) { // Determine the index for the feature and return the value at that index, if an index is assigned. // int index = eVirtualIndex(eDerivedStructuralFeatureID, EVIRTUAL_GET); return index < 0 ? defaultValue : eVirtualValue(index); } /** * Returns whether there is a value set for the feature ID. * @param eDerivedStructuralFeatureID the feature ID to test. * @return whether there is a value set for the feature ID. */ public boolean eVirtualIsSet(int eDerivedStructuralFeatureID) { // Determine if an index is assigned. // return eVirtualIndex(eDerivedStructuralFeatureID, EVIRTUAL_IS_SET) >= 0; } protected static final Object EVIRTUAL_NO_VALUE = new Object(); /** * Sets the value for the feature ID. * @param eDerivedStructuralFeatureID the feature ID to set. * @return the previous value for the feature ID or {@link #EVIRTUAL_NO_VALUE}. */ public Object eVirtualSet(int eDerivedStructuralFeatureID, Object value) { // Determine the index. // int index = eVirtualIndex(eDerivedStructuralFeatureID, EVIRTUAL_SET); if (index < 0) { // If it's newly allocated, add a new value, and indicate there was no previous value. // eAddVirtualValue(~index, value); return EVIRTUAL_NO_VALUE; } else { // Set the value at the previously allocated index and return the previous value there. // return eSetVirtualValue(index, value); } } /** * Unsets the value for the feature ID. * @param eDerivedStructuralFeatureID the feature ID to unset. * @return the previous value for the feature ID or {@link #EVIRTUAL_NO_VALUE}. */ public Object eVirtualUnset(int eDerivedStructuralFeatureID) { int index = eVirtualIndex(eDerivedStructuralFeatureID, EVIRTUAL_UNSET); if (index < 0) { return EVIRTUAL_NO_VALUE; } else { return eRemoveVirtualValue(index); } } public Object eInvoke(EOperation eOperation, EList<?> arguments) throws InvocationTargetException { int operationID = eDerivedOperationID(eOperation); if (operationID >= 0) { return eInvoke(operationID, arguments); } else { throw new IllegalArgumentException("The operation '" + eOperation.getName() + "' is not a valid operation"); } } public Object eInvoke(int operationID, EList<?> arguments) throws InvocationTargetException { EOperation eOperation = eClass().getEOperation(operationID); assert eOperation != null : "Invalid operationID: " + operationID; return eInvocationDelegate(eOperation).dynamicInvoke(this, arguments); } public Object eDynamicInvoke(int operationID, EList<?> arguments) throws InvocationTargetException { return eDynamicInvoke(eClass().getEOperation(operationID), arguments); } protected Object eDynamicInvoke(EOperation eOperation, EList<?> arguments) throws InvocationTargetException { return eInvocationDelegate(eOperation).dynamicInvoke(this, arguments); } @Override public String toString() { StringBuilder result = new StringBuilder(getClass().getName()); result.append('@'); result.append(Integer.toHexString(hashCode())); if (eIsProxy()) { result.append(" (eProxyURI: "); result.append(eProxyURI()); if (eDynamicClass() != null) { result.append(" eClass: "); result.append(eDynamicClass()); } result.append(')'); } else if (eDynamicClass() != null) { result.append(" (eClass: "); result.append(eDynamicClass()); result.append(')'); } return result.toString(); } }