Package org.eclipse.emf.ecore.util

Source Code of org.eclipse.emf.ecore.util.DelegatingFeatureMap$FeatureMapEObjectImpl

/**
* <copyright>
*
* Copyright (c) 2003-2009 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
*
* </copyright>
*
* $Id: DelegatingFeatureMap.java,v 1.33 2010/02/09 16:05:38 emerks Exp $
*/
package org.eclipse.emf.ecore.util;


import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.NotificationChain;
import org.eclipse.emf.common.notify.impl.NotificationImpl;
import org.eclipse.emf.common.util.AbstractEList;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
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.ETypedElement;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.ENotificationImpl;


public abstract class DelegatingFeatureMap extends DelegatingEcoreEList<FeatureMap.Entry> implements FeatureMap.Internal, FeatureMap.Internal.Wrapper
{
  private static final long serialVersionUID = 1L;

  protected FeatureMap.Internal.Wrapper wrapper = this;
  protected final FeatureMapUtil.Validator featureMapValidator;
  protected final EStructuralFeature eStructuralFeature;

  public DelegatingFeatureMap(InternalEObject owner, int featureID)
  {
    super(owner);
    this.eStructuralFeature = owner.eClass().getEStructuralFeature(featureID);
    featureMapValidator = FeatureMapUtil.getValidator(owner.eClass(), getEStructuralFeature());
  }

  public DelegatingFeatureMap(InternalEObject owner, EStructuralFeature eStructuralFeature)
  {
    super(owner);
    this.eStructuralFeature = eStructuralFeature;
    featureMapValidator = FeatureMapUtil.getValidator(owner.eClass(), getEStructuralFeature());
  }

/*
  List theList = new java.util.ArrayList();
  protected List delegateList()
  {
    return theList;
  }
*/
 
  public Wrapper getWrapper()
  {
    return wrapper;
  }

  public void setWrapper(Wrapper wrapper)
  {
    this.wrapper = wrapper;
  }

  public FeatureMap featureMap()
  {
    return this;
  }
 
  @Override
  protected Entry validate(int index, Entry object)
  {
    if (modCount == 0) return object;

    Entry result = super.validate(index, object);
    EStructuralFeature eStructuralFeature = object.getEStructuralFeature();
    if (!eStructuralFeature.isChangeable() || !featureMapValidator.isValid(eStructuralFeature))
    {
      throw
        new RuntimeException
          ("Invalid entry feature '" + eStructuralFeature.getEContainingClass().getName() + "." + eStructuralFeature.getName() + "'");
    }
    return result;
  }

  @Override
  protected boolean isEObject()
  {
    return false;
  }

  @Override
  protected boolean isUnique()
  {
    return false;
  }

  @Override
  protected boolean canContainNull()
  {
    return false;
  }

  @Override
  protected EClassifier getFeatureType()
  {
    return org.eclipse.emf.ecore.EcorePackage.Literals.EJAVA_OBJECT;
  }

  @Override
  public EStructuralFeature getEStructuralFeature()
  {
    return eStructuralFeature;
  }

  protected FeatureMap.Entry createEntry(EStructuralFeature eStructuralFeature, Object value)
  {
    return FeatureMapUtil.createEntry(eStructuralFeature, value);
  }

  protected FeatureMap.Entry.Internal createRawEntry(EStructuralFeature eStructuralFeature, Object value)
  {
    return FeatureMapUtil.createRawEntry(eStructuralFeature, value);
  }

  protected NotificationImpl createNotification
    (int eventType, EStructuralFeature feature, Object oldObject, Object newObject, int index, boolean wasSet)
  {
    return new FeatureMapUtil.FeatureENotificationImpl(owner, eventType, feature, oldObject, newObject, index, wasSet);
  }

  protected boolean isMany(EStructuralFeature feature)
  {
    return FeatureMapUtil.isMany(owner, feature);
  }

  @Override
  protected boolean hasInverse()
  {
    return true;
  }

  @Override
  protected boolean hasShadow()
  {
    return true;
  }

  protected int entryIndex(EStructuralFeature feature, int index)
  {
    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
    int count = 0;
    int size = delegateSize();
    int result = size;
    for (int i = 0; i < size; ++i)
    {
      Entry entry = delegateGet(i);
      if (validator.isValid(entry.getEStructuralFeature()))
      {
        if (index == count)
        {
          return i;
        }
        ++count;
        result = i + 1;
      }
    }

    if (index == count)
    {
      return result;
    }
    else
    {
      throw new IndexOutOfBoundsException("index=" + index + ", size=" + count);
    }
  }

  protected boolean isResolveProxies(EStructuralFeature feature)
  {
    return feature instanceof EReference && ((EReference)feature).isResolveProxies();
  }

  public Object resolveProxy(EStructuralFeature feature, int entryIndex, int index, Object object)
  {
    EObject resolved = resolveProxy((EObject)object);
    if (resolved != object)
    {
      Entry oldObject = delegateGet(entryIndex);
      Entry entry = createEntry(feature, resolved);
      delegateSet(entryIndex, validate(entryIndex, entry));
      didSet(entryIndex, entry, oldObject);

      if (isNotificationRequired())
      {
        NotificationImpl notifications =
          createNotification
            (Notification.RESOLVE,
             entry.getEStructuralFeature(),
             object,
             resolved,
             index,
             false);

        notifications.add(createNotification(Notification.RESOLVE, oldObject, entry, index, false));
        notifications.dispatch();
      }

      return resolved;
    }

    return object;
  }

  @Override
  protected EObject resolveProxy(EObject eObject)
  {
    return owner.eResolveProxy((InternalEObject)eObject);
  }

  public int getModCount()
  {
    return modCount;
  }

  public EStructuralFeature getEStructuralFeature(int index)
  {
    return get(index).getEStructuralFeature();
  }

  public Object getValue(int index)
  {
    return get(index).getValue();
  }

  public Object setValue(int index, Object value)
  {
    return set(index, createEntry(getEStructuralFeature(index), value)).getValue();
  }

  @Override
  public NotificationChain shadowAdd(Entry object, NotificationChain notifications)
  {
    if (isNotificationRequired())
    {
      EStructuralFeature feature = object.getEStructuralFeature();
      Object value = object.getValue();
      // EATM must fix isSet bits.
      NotificationImpl notification =
        feature.isMany() ?
          createNotification
            (Notification.ADD,
             feature,
             null,
             value,
             indexOf(feature, value),
             true) :
          createNotification
            (Notification.SET,
             feature,
             feature.getDefaultValue(),
             value,
             Notification.NO_INDEX,
             true);
 
      if (notifications != null)
      {
        notifications.add(notification);
      }
      else
      {
        notifications = notification;
      }
    }
    return notifications;
  }

  @Override
  public NotificationChain inverseAdd(Entry object, NotificationChain notifications)
  {
    FeatureMap.Entry.Internal entry = (FeatureMap.Entry.Internal)object;
    return entry.inverseAdd(owner, getFeatureID(), notifications);
  }

  @Override
  public NotificationChain shadowRemove(Entry object, NotificationChain notifications)
  {
    if (isNotificationRequired())
    {
      EStructuralFeature feature = object.getEStructuralFeature();
      Object value = object.getValue();
      NotificationImpl notification =
        feature.isMany() ?
          createNotification
            (Notification.REMOVE,
             feature,
             value,
             null,
             indexOf(feature, value),
             true) :
          createNotification
            (feature.isUnsettable() ? Notification.UNSET : Notification.SET,
             feature,
             value,
             feature.getDefaultValue(),
             Notification.NO_INDEX,
             true);

      if (notifications != null)
      {
        notifications.add(notification);
      }
      else
      {
        notifications = notification;
      }
    }
    return notifications;
  }

  @Override
  public NotificationChain inverseRemove(Entry object, NotificationChain notifications)
  {
    FeatureMap.Entry.Internal entry = (FeatureMap.Entry.Internal)object;
    return entry.inverseRemove(owner, getFeatureID(), notifications);
  }

  @Override
  public NotificationChain shadowSet(Entry oldObject, Entry newObject, NotificationChain notifications)
  {
    if (isNotificationRequired())
    {
      EStructuralFeature feature = oldObject.getEStructuralFeature();
      Object oldValue = oldObject.getValue();
      Object newValue = newObject.getValue();
      NotificationImpl notification =
        createNotification
          (Notification.SET,
           feature,
           oldValue,
           newValue,
           feature.isMany() ? indexOf(feature, newValue) : Notification.NO_INDEX,
           true);

      if (notifications != null)
      {
        notifications.add(notification);
      }
      else
      {
        notifications = notification;
      }
    }
    return notifications;
  }

  public NotificationChain inverseTouch(Object object, NotificationChain notifications)
  {
    if (isNotificationRequired())
    {
      Entry entry = (Entry)object;
      EStructuralFeature feature = entry.getEStructuralFeature();
      Object value = entry.getValue();
      NotificationImpl notification =
        createNotification
          (Notification.SET,
           feature,
           value,
           value,
           feature.isMany() ? indexOf(feature, value) : Notification.NO_INDEX,
           true);
 
      if (notifications != null)
      {
        notifications.add(notification);
      }
      else
      {
        notifications = notification;
      }
    }

    return notifications;
  }

  @Override
  public Entry move(int targetIndex, int sourceIndex)
  {
    if (!isNotificationRequired())
    {
      return doMove(targetIndex, sourceIndex);
    }
    else if (targetIndex != sourceIndex)
    {
      Entry sourceEntry =  delegateGet(sourceIndex);
      EStructuralFeature feature = sourceEntry.getEStructuralFeature();
      if (isMany(feature))
      {
        FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
        int featureTargetIndex = -1;
        int featureSourceIndex = -1;
        int count = 0;
        for (int i = 0, maxIndex= targetIndex > sourceIndex ? targetIndex : sourceIndex; i <= maxIndex; ++i)
        {
          if (i == sourceIndex)
          {
            featureSourceIndex = count++;
          }
          else
          {
            Entry entry = delegateGet(i);
            boolean isValid = validator.isValid(entry.getEStructuralFeature());
            if (i == targetIndex)
            {
              featureTargetIndex = i == maxIndex && !isValid ? count-1 : count;
            }
           
            if (isValid)
            {
                ++count;
            }
          }
        }

        Entry result = super.move(targetIndex, sourceIndex);
       
        if (featureSourceIndex != featureTargetIndex)
        {
          dispatchNotification
            (new ENotificationImpl
               (owner,
                Notification.MOVE,
                feature,
                featureSourceIndex,
                sourceEntry.getValue(),
                featureTargetIndex));
        }
        return result;
      }
    }
    return super.move(targetIndex, sourceIndex);
  }

  @Override
  public Entry set(int index, Entry object)
  {
    EStructuralFeature entryFeature = object.getEStructuralFeature();
    if (isMany(entryFeature))
    {
      if (entryFeature.isUnique())
      {
        for (int i = 0, size = delegateSize(); i < size; ++i)
        {
          Entry otherEntry = delegateGet(i);
          if (otherEntry.equals(object) && i != index)
          {
            throw new IllegalArgumentException("The 'no duplicates' constraint is violated");
          }
        }
      }
    }
    else
    {
      FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), entryFeature);
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry otherEntry = delegateGet(i);
        if (validator.isValid(otherEntry.getEStructuralFeature()) && i != index)
        {
          throw new IllegalArgumentException("The multiplicity constraint is violated");
        }
      }
    }

    return doSet(index, object);
  }

  public Entry doSet(int index, Entry object)
  {
    return super.set(index, object);
  }

  @Override
  public boolean add(Entry object)
  {
    EStructuralFeature entryFeature = object.getEStructuralFeature();
    if (isMany(entryFeature))
    {
      if (entryFeature.isUnique() && contains(entryFeature, object.getValue()))
      {
        return false;
      }
    }
    else
    {
      FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), entryFeature);
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry otherEntry = delegateGet(i);
        if (validator.isValid(otherEntry.getEStructuralFeature()))
        {
          if (otherEntry.equals(object))
          {
            return false;
          }
          else
          {
            doSet(i, object);
            return true;
          }
        }
      }
    }

    return doAdd(object);
  }

  protected boolean doAdd(Entry object)
  {
    return super.add(object);
  }

  @Override
  public void add(int index, Entry object)
  {
    EStructuralFeature entryFeature = object.getEStructuralFeature();
    if (isMany(entryFeature))
    {
      if (entryFeature.isUnique())
      {
        for (int i = 0, size = delegateSize(); i < size; ++i)
        {
          Entry otherEntry = delegateGet(i);
          if (otherEntry.equals(object) && i != index)
          {
            throw new IllegalArgumentException("The 'no duplicates' constraint is violated");
          }
        }
      }
    }
    else
    {
      FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), entryFeature);
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry otherEntry = delegateGet(i);
        if (validator.isValid(otherEntry.getEStructuralFeature()))
        {
          throw new IllegalArgumentException("The multiplicity constraint is violated");
        }
      }
    }

    doAdd(index, object);
  }

  public void doAdd(int index, Entry object)
  {
    super.add(index, object);
  }

  @Override
  public boolean addAll(Collection<? extends Entry> collection)
  {
    Collection<Entry> uniqueCollection = new BasicEList<Entry>(collection.size());
    for (Entry entry : collection)
    {
      EStructuralFeature entryFeature = entry.getEStructuralFeature();
      if (isMany(entryFeature))
      {
        if (!entryFeature.isUnique() || !contains(entryFeature, entry.getValue()) && !uniqueCollection.contains(entry))
        {
          uniqueCollection.add(entry);
        }
      }
      else
      {
        FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), entryFeature);
        boolean include = true;
        for (int j = 0, size = delegateSize(); j < size; ++j)
        {
          Entry otherEntry = delegateGet(j);
          if (validator.isValid(otherEntry.getEStructuralFeature()))
          {
            doSet(j, entry);
            include = false;
            break;
          }
        }
        if (include)
        {
          uniqueCollection.add(entry);
        }
      }
    }

    return doAddAll(uniqueCollection);
  }

  public boolean doAddAll(Collection<? extends Entry> collection)
  {
    return super.addAll(collection);
  }

  @Override
  public boolean addAll(int index, Collection<? extends Entry> collection)
  {
    Collection<Entry> uniqueCollection = new BasicEList<Entry>(collection.size());
    for (Entry entry : collection)
    {
      EStructuralFeature entryFeature = entry.getEStructuralFeature();
      if (isMany(entryFeature))
      {
        if (!entryFeature.isUnique() || !contains(entryFeature, entry.getValue()) && !uniqueCollection.contains(entry))
        {
          uniqueCollection.add(entry);
        }
      }
      else
      {
        FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), entryFeature);
        boolean include = true;
        for (int j = 0, size = delegateSize(); j < size; ++j)
        {
          Entry otherEntry = delegateGet(j);
          if (validator.isValid(otherEntry.getEStructuralFeature()))
          {
            doSet(j, entry);
            include = false;
            break;
          }
        }
        if (include)
        {
          uniqueCollection.add(entry);
        }
      }
    }

    return doAddAll(index, uniqueCollection);
  }

  public boolean doAddAll(int index, Collection<? extends Entry> collection)
  {
    return super.addAll(index, collection);
  }


  public int size(EStructuralFeature feature)
  {
    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
    int result = 0;
    for (int i = 0, size = delegateSize(); i < size; ++i)
    {
      Entry entry = delegateGet(i);
      if (validator.isValid(entry.getEStructuralFeature()))
      {
        ++result;
      }
    }
    return result;
  }

  public boolean isEmpty(EStructuralFeature feature)
  {
    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
    for (int i = 0, size = delegateSize(); i < size; ++i)
    {
      Entry entry = delegateGet(i);
      if (validator.isValid(entry.getEStructuralFeature()))
      {
        return false;
      }
    }
    return true;
  }

  public boolean contains(EStructuralFeature feature, Object object)
  {
    return contains(feature, object, isResolveProxies(feature));
  }

  public boolean basicContains(EStructuralFeature feature, Object object)
  {
    return contains(feature, object, false);
  }

  protected boolean contains(EStructuralFeature feature, Object object, boolean resolve)
  {
    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
    if (FeatureMapUtil.isFeatureMap(feature))
    {
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()) && entry.equals(object))
        {
          return true;
        }
      }
    }
    else if (object != null)
    {
      int size = delegateSize();
      for (int i = 0; i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()) && object.equals(entry.getValue()))
        {
          return true;
        }
      }
      if (resolve)
      {
        for (int i = 0; i < size; ++i)
        {
          Entry entry = delegateGet(i);
          if (validator.isValid(entry.getEStructuralFeature()) && object == resolveProxy((EObject)entry.getValue()))
          {
            return true;
          }
        }
      }
    }
    else
    {
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()) && entry.getValue() == null)
        {
          return false;
        }
      }
    }

    return false;
  }

  public boolean containsAll(EStructuralFeature feature, Collection<?> collection)
  {
    for (Object object : collection)
    {
      if (!contains(feature, object))
      {
        return false;
      }
    }

    return true;
  }

  public boolean basicContainsAll(EStructuralFeature feature, Collection<?> collection)
  {
    for (Object object : collection)
    {
      if (!basicContains(feature, object))
      {
        return false;
      }
    }

    return true;
  }

  public int indexOf(EStructuralFeature feature, Object object)
  {
    return indexOf(feature, object, isResolveProxies(feature));
  }

  public int basicIndexOf(EStructuralFeature feature, Object object)
  {
    return indexOf(feature, object, false);
  }

  protected int indexOf(EStructuralFeature feature, Object object, boolean resolve)
  {
    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
    int result = 0;
    if (FeatureMapUtil.isFeatureMap(feature))
    {
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          if (entry.equals(object))
          {
            return result;
          }
          ++result;
        }
      }
    }
    else if (object != null)
    {
      int size = delegateSize();
      for (int i = 0; i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          if (object.equals(entry.getValue()))
          {
            return result;
          }
          ++result;
        }
      }
      if (resolve)
      {
        result = 0;
        for (int i = 0; i < size; ++i)
        {
          Entry entry = delegateGet(i);
          if (validator.isValid(entry.getEStructuralFeature()))
          {
            if (object == resolveProxy((EObject)entry.getValue()))
            {
              return result;
            }
            ++result;
          }
        }
      }
    }
    else
    {
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          if (entry.getValue() == null)
          {
            return result;
          }
          ++result;
        }
      }
    }

    return -1;
  }

  public int lastIndexOf(EStructuralFeature feature, Object object)
  {
    return lastIndexOf(feature, object, isResolveProxies(feature));
  }

  public int basicLastIndexOf(EStructuralFeature feature, Object object)
  {
    return lastIndexOf(feature, object, false);
  }

  protected int lastIndexOf(EStructuralFeature feature, Object object, boolean resolve)
  {
    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
    int result = -1;
    int count = 0;
    if (FeatureMapUtil.isFeatureMap(feature))
    {
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          if (entry.equals(object))
          {
            result = count;
          }
          ++count;
        }
      }
    }
    else if (object != null)
    {
      int size = delegateSize();
      for (int i = 0; i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          if (object.equals(entry.getValue()))
          {
            result = count;
          }
          ++count;
        }
      }
      if (resolve)
      {
        result = -1;
        count = 0;
        for (int i = 0; i < size; ++i)
        {
          Entry entry = delegateGet(i);
          if (validator.isValid(entry.getEStructuralFeature()))
          {
            if (object == resolveProxy((EObject)entry.getValue()))
            {
              result = count;
            }
            ++count;
          }
        }
      }
    }
    else
    {
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          if (entry.getValue() == null)
          {
            result = count;
          }
          ++count;
        }
      }
    }

    return result;
  }

  public Iterator<Object> iterator(EStructuralFeature feature)
  {
    return
      feature instanceof EReference && ((EReference)feature).isResolveProxies() ?
        new ResolvingFeatureEIterator<Object>(feature, this) :
        new FeatureEIterator<Object>(feature, this);
  }

  public ListIterator<Object> listIterator(EStructuralFeature feature)
  {
    return
      feature instanceof EReference && ((EReference)feature).isResolveProxies() ?
        new ResolvingFeatureEIterator<Object>(feature, this) :
        new FeatureEIterator<Object>(feature, this);
  }

  public ListIterator<Object> listIterator(EStructuralFeature feature, int index)
  {
    ListIterator<Object> result =
      feature instanceof EReference && ((EReference)feature).isResolveProxies() ?
        new ResolvingFeatureEIterator<Object>(feature, this) :
        new FeatureEIterator<Object>(feature, this);
    for (int i = 0; i < index; ++i)
    {
      result.next();
    }
    return result;
  }

  public ValueListIterator<Object> valueListIterator()
  {
    return new ValueListIteratorImpl<Object>();
  }
 
  public ValueListIterator<Object> valueListIterator(int index)
  {
    return new ValueListIteratorImpl<Object>(index);
  }
 
  protected class ValueListIteratorImpl<E> extends AbstractEList<FeatureMap.Entry>.EListIterator<E> implements ValueListIterator<E>
  {
    public ValueListIteratorImpl()
    {
      super();
    }
   
    public ValueListIteratorImpl(int index)
    {
      super(index);
    }
   
    public EStructuralFeature feature()
    {
      if (lastCursor == -1)
      {
        throw new IllegalStateException();
      }
      return getEStructuralFeature(lastCursor);
    }
   
    @SuppressWarnings("unchecked")
    @Override
    public E next()
    {
      return (E)doNext().getValue();
    }
   
    @SuppressWarnings("unchecked")
    @Override
    public E previous()
    {
      return (E)doPrevious().getValue();
    }

    @Override
    public void add(E value)
    {
      doAdd(FeatureMapUtil.createEntry(feature(), value));
    }
   
    public void add(EStructuralFeature eStructuralFeature, Object value)
    {
      doAdd(FeatureMapUtil.createEntry(eStructuralFeature, value));
    }
  }

/*
  public List subList(EStructuralFeature feature, int from, int to)
  {
    return null;
  }
*/

  @SuppressWarnings("unchecked")
  public <T> EList<T> list(EStructuralFeature feature)
  {
    return
      FeatureMapUtil.isFeatureMap(feature) ?
        (EList<T>)new FeatureMapUtil.FeatureFeatureMap(feature, this) :
        new FeatureMapUtil.FeatureEList<T>(feature, this);
  }

  public EStructuralFeature.Setting setting(EStructuralFeature feature)
  {
    return
      isMany(feature) ?
        (EStructuralFeature.Setting)list(feature) :
        (EStructuralFeature.Setting)new FeatureMapUtil.FeatureValue(feature, this);
  }

  public List<Object> basicList(EStructuralFeature feature)
  {
    return new FeatureMapUtil.FeatureEList.Basic<Object>(feature, this);
  }

  public Iterator<Object> basicIterator(EStructuralFeature feature)
  {
    return new FeatureEIterator<Object>(feature, this);
  }

  public ListIterator<Object> basicListIterator(EStructuralFeature feature)
  {
    return new FeatureEIterator<Object>(feature, this);
  }

  public ListIterator<Object> basicListIterator(EStructuralFeature feature, int index)
  {
    ListIterator<Object> result = new FeatureEIterator<Object>(feature, this);
    for (int i = 0; i < index; ++i)
    {
      result.next();
    }
    return result;
  }

  public Object[] toArray(EStructuralFeature feature)
  {
    return toArray(feature, isResolveProxies(feature));
  }

  public Object[] basicToArray(EStructuralFeature feature)
  {
    return toArray(feature, false);
  }

  protected Object[] toArray(EStructuralFeature feature, boolean resolve)
  {
    List<Object> result = new BasicEList<Object>();
    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
    if (FeatureMapUtil.isFeatureMap(feature))
    {
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          result.add(entry);
        }
      }
    }
    else
    {
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          Object value = entry.getValue();
          result.add(resolve ? resolveProxy(feature, i, result.size(), value) : value);
        }
      }
    }
    return result.toArray();
  }

  public <T> T[] toArray(EStructuralFeature feature, T [] array)
  {
    return toArray(feature, array, isResolveProxies(feature));
  }

  public <T> T[] basicToArray(EStructuralFeature feature, T [] array)
  {
    return toArray(feature, array, false);
  }

  protected <T> T[] toArray(EStructuralFeature feature, T [] array, boolean resolve)
  {
    List<Object> result = new BasicEList<Object>();
    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
    if (FeatureMapUtil.isFeatureMap(feature))
    {
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          result.add(entry);
        }
      }
    }
    else
    {
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          Object value = entry.getValue();
          result.add(resolve ? resolveProxy(feature, i, result.size(), value) : value);
        }
      }
    }
    return result.toArray(array);
  }


  public void set(EStructuralFeature feature, Object object)
  {
    if (isMany(feature))
    {
      List<Object> list = list(feature);
      list.clear();
      list.addAll((Collection<?>)object);
    }
    else
    {
      FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          if (shouldUnset(feature, object))
          {
            remove(i);
          }
          else
          {
            doSet(i, FeatureMapUtil.isFeatureMap(feature) ? (Entry)object : createEntry(feature, object));
          }
          return;
        }
      }
 
      if (!shouldUnset(feature, object))
      {
        doAdd(FeatureMapUtil.isFeatureMap(feature) ? (Entry)object : createEntry(feature, object));
      }
    }
  }

  protected boolean shouldUnset(EStructuralFeature feature, Object value)
  {
    if (feature.getUpperBound() != ETypedElement.UNSPECIFIED_MULTIPLICITY && !feature.isUnsettable())
    {
      Object defaultValue = feature.getDefaultValue();
      return defaultValue == null ? value == null : defaultValue.equals(value);
    }
    else
    {
      return false;
    }
  }

  public void add(int index, EStructuralFeature feature, Object object)
  {
    boolean isFeatureMap = FeatureMapUtil.isFeatureMap(feature);
    if (isMany(feature))
    {
      if (feature.isUnique() && contains(feature, object))
      {
        throw new IllegalArgumentException("The 'no duplicates' constraint is violated");
      }
    }
    else
    {
      FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          if (isFeatureMap ? entry.equals(object) : object == null ? entry.getValue() == null : object.equals(entry.getValue()))
          {
            throw new IllegalArgumentException("The 'no duplicates' constraint is violated");
          }
        }
      }
    }

    doAdd(index, isFeatureMap ? (Entry)object : createEntry(feature, object));
  }

  public boolean add(EStructuralFeature feature, Object object)
  {
    boolean isFeatureMap = FeatureMapUtil.isFeatureMap(feature);
    if (isMany(feature))
    {
      if (feature.isUnique() && contains(feature, object))
      {
        return false;
      }
    }
    else
    {
      FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          if (isFeatureMap ? entry.equals(object) : object == null ? entry.getValue() == null : object.equals(entry.getValue()))
          {
            return false;
          }
          else
          {
            doSet(i, isFeatureMap ? (Entry)object : createEntry(feature, object));
            return true;
          }
        }
      }
    }

    return doAdd(isFeatureMap ? (Entry)object : createEntry(feature, object));
  }

  public void add(EStructuralFeature feature, int index, Object object)
  {
    boolean isFeatureMap = FeatureMapUtil.isFeatureMap(feature);
    if (isMany(feature))
    {
      if (feature.isUnique() && contains(feature, object))
      {
        throw new IllegalArgumentException("The 'no duplicates' constraint is violated");
      }
    }
    else
    {
      FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          throw new IllegalArgumentException("The multiplicity constraint is violated");
        }
      }
    }

    doAdd(entryIndex(feature, index), isFeatureMap ? (Entry)object : createEntry(feature, object));
  }

  public boolean addAll(int index, EStructuralFeature feature, Collection<?> collection)
  {
    if (collection.size() == 0)
    {
      return false;
    }
    boolean isFeatureMap = FeatureMapUtil.isFeatureMap(feature);
    @SuppressWarnings("unchecked") Collection<Entry> entryCollection =
      isFeatureMap ? (Collection<Entry>)collection : new BasicEList<Entry>(collection.size());
    if (isMany(feature))
    {
      if (feature.isUnique())
      {
        for (Object object : collection)
        {
          if (!contains(feature, object))
          {
            Entry entry = createEntry(feature, object);
            if (!entryCollection.contains(entry))
            {
              entryCollection.add(entry);
            }
          }
        }
      }
      else if (!isFeatureMap)
      {
        for (Object object : collection)
        {
          Entry entry = createEntry(feature, object);
          entryCollection.add(entry);
        }
      }
    }
    else
    {
      if (collection.size() > 1)
      {
        throw new IllegalArgumentException("The multiplicity constraint is violated");
      }

      if (isFeatureMap)
      {
        if (contains(feature, collection.iterator().next()))
        {
          return false;
        }
      }
      else
      {
        FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
        for (int i = 0, size = delegateSize(); i < size; ++i)
        {
          Entry entry = delegateGet(i);
          if (validator.isValid(entry.getEStructuralFeature()))
          {
            if (collection.contains(entry.getValue()))
            {
              return false;
            }
            else
            {
              throw new IllegalArgumentException("The multiplicity constraint is violated");
            }
          }
        }
        Entry entry = createEntry(feature, collection.iterator().next());
        entryCollection.add(entry);
      }
    }

    return doAddAll(index, entryCollection);
  }

  public boolean addAll(EStructuralFeature feature, Collection<?> collection)
  {
    if (collection.size() == 0)
    {
      return false;
    }
    boolean isFeatureMap = FeatureMapUtil.isFeatureMap(feature);
    @SuppressWarnings("unchecked") Collection<Entry> entryCollection =
      isFeatureMap ? (Collection<Entry>)collection : new BasicEList<Entry>(collection.size());
    if (isMany(feature))
    {
      if (feature.isUnique())
      {
        for (Object object : collection)
        {
          if (!contains(feature, object))
          {
            Entry entry = createEntry(feature, object);
            if (!entryCollection.contains(entry))
            {
              entryCollection.add(entry);
            }
          }
        }
      }
      else if (!isFeatureMap)
      {
        for (Object object : collection)
        {
          Entry entry = createEntry(feature, object);
          entryCollection.add(entry);
        }
      }
    }
    else
    {
      if (collection.size() > 1)
      {
        throw new IllegalArgumentException("The multiplicity constraint is violated");
      }
      FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          if (collection.contains(isFeatureMap ? entry : entry.getValue()))
          {
            return false;
          }
          else
          {
            for (Object object : collection)
            {
              doSet(i, isFeatureMap ? (Entry)object : createEntry(feature, object));
            }
            return true;
          }
        }
      }
      if (!isFeatureMap)
      {
        Entry entry = createEntry(feature, collection.iterator().next());
        entryCollection.add(entry);
      }
    }

    return doAddAll(entryCollection);
  }

  public boolean addAll(EStructuralFeature feature, int index, Collection<?> collection)
  {
    if (collection.size() == 0)
    {
      return false;
    }
    boolean isFeatureMap = FeatureMapUtil.isFeatureMap(feature);
    @SuppressWarnings("unchecked") Collection<Entry> entryCollection =
      isFeatureMap ? (Collection<Entry>)collection : new BasicEList<Entry>(collection.size());
    if (isMany(feature))
    {
      if (feature.isUnique())
      {
        for (Object object : collection)
        {
          if (!contains(feature, object))
          {
            Entry entry = createEntry(feature, object);
            entryCollection.add(entry);
          }
        }
      }
      else if (!isFeatureMap)
      {
        for (Object object : collection)
        {
          Entry entry = createEntry(feature, object);
          entryCollection.add(entry);
        }
      }
    }
    else
    {
      FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          throw new IllegalArgumentException("The multiplicity constraint is violated");
        }
      }

      if (collection.size() > 1)
      {
        throw new IllegalArgumentException("The multiplicity constraint is violated");
      }

      if (!isFeatureMap)
      {
        Entry entry = createEntry(feature, collection.iterator().next());
        entryCollection.add(entry);
      }
    }

    return doAddAll(entryIndex(feature, index), entryCollection);
  }

  public void addUnique(EStructuralFeature feature, Object object)
  {
    modCount = -1;
    addUnique(createRawEntry(feature, object));
  }

  public void addUnique(EStructuralFeature feature, int index, Object object)
  {
    modCount = -1;
    addUnique(entryIndex(feature, index), createRawEntry(feature, object));
  }

  @Override
  public void addUnique(Entry object)
  {
    // Validate now since the call we make after will skip validating.
    ++modCount;
    validate(delegateSize(), object);

    super.addUnique(object);
  }

  public void addUnique(Entry.Internal entry)
  {
    modCount = -1;
    super.addUnique(entry);
  }

  @Override
  public boolean addAllUnique(Collection<? extends Entry> collection)
  {
    modCount = -1;
    return super.addAllUnique(collection);
  }

  public boolean addAllUnique(Entry.Internal [] entries, int start, int end)
  {
    modCount = -1;
    return super.addAllUnique(size(), entries, start, end);
  }

  public boolean addAllUnique(int index, Entry.Internal [] entries, int start, int end)
  {
    modCount = -1;
    return super.addAllUnique(index, entries, start, end);
  }

  public NotificationChain basicAdd(EStructuralFeature feature, Object object, NotificationChain notifications)
  {
    if (object == null)
    {
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (entry.getEStructuralFeature() == feature)
        {
          return super.basicRemove(entry, notifications);
        }
      }
    }

    Entry entry = FeatureMapUtil.isFeatureMap(feature) ? (Entry)object : createEntry(feature, object);

    notifications = basicAdd(entry, notifications);
    if (isNotificationRequired())
    {
      boolean oldIsSet = !isEmpty(feature);
      NotificationImpl notification =
        feature.isMany() ?
          createNotification
            (Notification.ADD,
             feature,
             null,
             object,
             indexOf(feature, object),
             oldIsSet) :
          createNotification
            (Notification.SET,
             feature,
             feature.getDefaultValue(),
             object,
             Notification.NO_INDEX,
             oldIsSet);

      if (notifications != null)
      {
        notifications.add(notification);
      }
      else
      {
        notifications = notification;
      }
    }
    return notifications;
  }

  public boolean remove(EStructuralFeature feature, Object object)
  {
    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
    if (FeatureMapUtil.isFeatureMap(feature))
    {
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          if (entry.equals(object))
          {
            remove(i);
            return true;
          }
        }
      }
    }
    else if (object != null)
    {
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          if (object.equals(entry.getValue()))
          {
            remove(i);
            return true;
          }
        }
      }
    }
    else
    {
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          if (entry.getValue() == null)
          {
            remove(i);
            return true;
          }
        }
      }
    }

    return false;
  }

  public Object remove(EStructuralFeature feature, int index)
  {
    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
    int count = 0;
    for (int i = 0, size = delegateSize(); i < size; ++i)
    {
      Entry entry = delegateGet(i);
      if (validator.isValid(entry.getEStructuralFeature()))
      {
        if (count == index)
        {
          remove(i);
          return FeatureMapUtil.isFeatureMap(feature) ? entry : entry.getValue();
        }
        ++count;
      }
    }

    throw new IndexOutOfBoundsException("index=" + index + ", size=" + count);
  }

  public boolean removeAll(EStructuralFeature feature, Collection<?> collection)
  {
    if (FeatureMapUtil.isFeatureMap(feature))
    {
      return removeAll(collection);
    }
    else
    {
      FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
      List<Entry> entryCollection = new BasicEList<Entry>(collection.size());
      for (int i = delegateSize(); --i >= 0; )
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          if (collection.contains(entry.getValue()))
          {
            entryCollection.add(entry);
          }
        }
      }

      return removeAll(entryCollection);
    }
  }

  public NotificationChain basicRemove(EStructuralFeature feature, Object object, NotificationChain notifications)
  {
    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
    int count = 0;
    Entry match = null;
    if (FeatureMapUtil.isFeatureMap(feature))
    {
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          if (entry.equals(object))
          {
            match = entry;
            break;
          }
          ++count;
        }
      }
    }
    if (object != null)
    {
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          if (object.equals(entry.getValue()))
          {
            match = entry;
            break;
          }
          ++count;
        }
      }
    }
    else
    {
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          if (entry.getValue() == null)
          {
            match = entry;
            break;
          }
          ++count;
        }
      }
    }

    if (match != null)
    {
      if (isNotificationRequired())
      {
        NotificationImpl notification =
          feature.isMany() ?
            createNotification
              (Notification.REMOVE,
               feature,
               object,
               null,
               count,
               true) :
            createNotification
              (feature.isUnsettable() ? Notification.UNSET : Notification.SET,
               feature,
               object,
               feature.getDefaultValue(),
               Notification.NO_INDEX,
               true);
 
        if (notifications != null)
        {
          notifications.add(notification);
        }
        else
        {
          notifications = notification;
        }
      }
      notifications = basicRemove(match, notifications);
    }

    return notifications;
  }

  public boolean retainAll(EStructuralFeature feature, Collection<?> collection)
  {
    boolean isFeatureMap = FeatureMapUtil.isFeatureMap(feature);
    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
    List<Entry> entryCollection = new BasicEList<Entry>(collection.size());
    for (int i = delegateSize(); --i >= 0; )
    {
      Entry entry = delegateGet(i);
      if (validator.isValid(entry.getEStructuralFeature()))
      {
        if (!collection.contains(isFeatureMap ? entry : entry.getValue()))
        {
          entryCollection.add(entry);
        }
      }
    }

    return removeAll(entryCollection);
  }

  public void clear(EStructuralFeature feature)
  {
    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
    List<Entry> entryCollection = new BasicEList<Entry>();
    for (int i = delegateSize(); --i >= 0; )
    {
      Entry entry = delegateGet(i);
      if (validator.isValid(entry.getEStructuralFeature()))
      {
        entryCollection.add(entry);
      }
    }

    if (!removeAll(entryCollection))
    {
      dispatchNotification
        (feature.isMany() ?
           createNotification
             (Notification.REMOVE_MANY,
              feature,
              Collections.EMPTY_LIST,
              null,
              Notification.NO_INDEX,
              false) :
           createNotification
             (feature.isUnsettable() ? Notification.UNSET : Notification.SET,
              feature,
              null,
              null,
              Notification.NO_INDEX,
              false));
    }
  }

  public void move(EStructuralFeature feature, int index, Object object)
  {
    move(feature, index, indexOf(feature, object));
  }

  public Object move(EStructuralFeature feature, int targetIndex, int sourceIndex)
  {
    if (isMany(feature))
    {
      FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
      Object result = null;
      int entryTargetIndex = -1;
      int entrySourceIndex = -1;
      int count = 0;
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          if (count == targetIndex)
          {
            entryTargetIndex = i;
          }
          if (count == sourceIndex)
          {
            entrySourceIndex = i;
            result = entry.getValue();
          }
          ++count;
        }
      }
      if (entryTargetIndex == -1)
      {
        throw new IndexOutOfBoundsException("targetIndex=" + targetIndex + ", size=" + count);
      }
      if (entrySourceIndex == -1)
      {
        throw new IndexOutOfBoundsException("sourceIndex=" + sourceIndex + ", size=" + count);
      }

      super.move(entryTargetIndex, entrySourceIndex);

      if (isNotificationRequired())
      {
        dispatchNotification
          (createNotification
             (Notification.MOVE,
              feature,
              sourceIndex,
              result,
              targetIndex,
              true));
      }

      return result;
    }
    else
    {
      throw new IllegalArgumentException("The feature must be many-valued to support move");
    }
  }

  public Object get(EStructuralFeature feature, boolean resolve)
  {
    if (isMany(feature))
    {
      return list(feature);
    }
    else
    {
      FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
      int count = 0;
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          if (FeatureMapUtil.isFeatureMap(feature))
          {
            return entry;
          }
          else
          {
            Object value = entry.getValue();
            if (value != null && resolve && isResolveProxies(feature))
            {
              value = resolveProxy(feature, i, count, value);
            }
            return value;
          }
        }
        ++count;
      }

      return feature.getDefaultValue();
    }
  }

  public Object get(EStructuralFeature feature, int index, boolean resolve)
  {
    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
    if (isMany(feature))
    {
      int count = 0;
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          if (count == index)
          {
            if (FeatureMapUtil.isFeatureMap(feature))
            {
              return entry;
            }
            else
            {
              Object value = entry.getValue();
              if (value != null && resolve && isResolveProxies(feature))
              {
                value = resolveProxy(feature, i, count, entry.getValue());
              }
              return value;
            }
          }
          ++count;
        }
      }
      throw new IndexOutOfBoundsException("index=" + index + ", size=" + count);
    }
    else
    {
      int count = 0;
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          if (FeatureMapUtil.isFeatureMap(feature))
          {
            return entry;
          }
          else
          {
            Object value = entry.getValue();
            if (value != null && resolve && isResolveProxies(feature))
            {
              value = resolveProxy(feature, i, count, value);
            }
            return value;
          }
        }
        ++count;
      }

      return feature.getDefaultValue();
    }
  }

  public Object set(EStructuralFeature feature, int index, Object object)
  {
    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
    if (isMany(feature))
    {
      if (feature.isUnique())
      {
        int currentIndex = indexOf(feature, object);
        if (currentIndex >=0 && currentIndex != index)
        {
          throw new IllegalArgumentException("The 'no duplicates' constraint is violated");
        }
      }

      int count = 0;
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          if (count == index)
          {
            return doSet(i, FeatureMapUtil.isFeatureMap(feature) ? (Entry)object : createEntry(feature, object));
          }
          ++count;
        }
      }
      throw new IndexOutOfBoundsException("index=" + index + ", size=" + count);
    }
    else
    {
      // Index should be -1.

      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          return FeatureMapUtil.isFeatureMap(feature) ? entry : entry.getValue();
        }
      }

      return null;
    }
  }

  public Object setUnique(EStructuralFeature feature, int index, Object object)
  {
    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
    if (isMany(feature))
    {
      int count = 0;
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          if (count == index)
          {
            return setUnique(i, FeatureMapUtil.isFeatureMap(feature) ? (Entry)object : createEntry(feature, object));
          }
          ++count;
        }
      }
      throw new IndexOutOfBoundsException("index=" + index + ", size=" + count);
    }
    else
    {
      // Index should be -1.

      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          return setUnique(i, FeatureMapUtil.isFeatureMap(feature) ? (Entry)object : createEntry(feature, object));
        }
      }

      return feature.getDefaultValue();
    }
  }

  public boolean isSet(EStructuralFeature feature)
  {
    return !isEmpty(feature);
  }

  public void unset(EStructuralFeature feature)
  {
    FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
    List<Entry> removals = null;
    for (int i = 0, size = delegateSize(); i < size; ++i)
    {
      Entry entry = delegateGet(i);
      if (validator.isValid(entry.getEStructuralFeature()))
      {
        if (removals == null)
        {
          removals = new BasicEList<Entry>();
        }
        removals.add(entry);
      }
    }

    if (removals != null)
    {
      removeAll(removals);
    }
  }

  @Override
  public NotificationChain basicRemove(Object object, NotificationChain notifications)
  {
    // This may be called directly on an EObject for the case of a containment.
    //
    if (object instanceof FeatureMap.Entry)
    {
      return super.basicRemove(object, notifications);
    }
    else
    {
      Entry match = null;
      EStructuralFeature feature = null;
      for (int i = 0, size = delegateSize(); i < size; ++i)
      {
        Entry entry = delegateGet(i);
        if (object.equals(entry.getValue()))
        {
          feature = entry.getEStructuralFeature();
          if (feature instanceof EReference && ((EReference)feature).isContainment())
          {
            match = entry;
            break;
          }
        }
      }

      if (match != null)
      {
        if (isNotificationRequired())
        {
          @SuppressWarnings("null")
          NotificationImpl notification =
            feature.isMany() ?
              createNotification
                (Notification.REMOVE,
                 feature,
                 object,
                 null,
                 indexOf(feature, object),
                 true) :
              createNotification
                (feature.isUnsettable() ? Notification.UNSET : Notification.SET,
                 feature,
                 object,
                 feature.getDefaultValue(),
                 Notification.NO_INDEX,
                 true);

          if (notifications != null)
          {
            notifications.add(notification);
          }
          else
          {
            notifications = notification;
          }
        }
        notifications = basicRemove(match, notifications);
      }

      return notifications;
    }
  }

  /**
   * -------------------------------------------
   */
  public static class FeatureEIterator<E> extends FeatureMapUtil.BasicFeatureEIterator<E>
  {
    public FeatureEIterator(EStructuralFeature eStructuralFeature, FeatureMap.Internal featureMap)
    {
      super(eStructuralFeature, featureMap);
    }

    @Override
    protected boolean scanNext()
    {
      int size = featureMap.size();
      while (entryCursor < size)
      {
        Entry entry = featureMap.get(entryCursor);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          preparedResult = extractValue(entry);
          prepared = 2;
          return true;
        }
        ++entryCursor;
      }

      prepared = 1;
      lastCursor = -1;
      return false;
    }

    @Override
    protected boolean scanPrevious()
    {
      while (--entryCursor >= 0)
      {
        Entry entry = featureMap.get(entryCursor);
        if (validator.isValid(entry.getEStructuralFeature()))
        {
          preparedResult = extractValue(entry);
          prepared = -2;
          return true;
        }
      }

      prepared = -1;
      lastCursor = -1;
      return false;
    }
  }

  /**
   * -------------------------------------------
   */
  public static class ResolvingFeatureEIterator<E> extends FeatureEIterator<E>
  {
    public ResolvingFeatureEIterator(EStructuralFeature eStructuralFeature, FeatureMap.Internal featureMap)
    {
      super(eStructuralFeature, featureMap);
    }

    @Override
    protected boolean resolve()
    {
      return true;
    }
  }

  /**
   * Temporary for testing purposes only.
   */
  public static class FeatureMapEObjectImpl extends org.eclipse.emf.ecore.impl.EObjectImpl
  {
    protected DelegatingFeatureMap featureMap =
      new DelegatingFeatureMap(this, -1)
      {
        private static final long serialVersionUID = 1L;

        protected List<Entry> theList = new java.util.ArrayList<Entry>();
        @Override
        protected List<Entry> delegateList()
        {
          return theList;
        }
      };


    public FeatureMapEObjectImpl()
    {
      super();
    }

    @Override
    public Object eDynamicGet(EStructuralFeature eFeature, boolean resolve)
    {
      if (eFeature instanceof EReference && ((EReference)eFeature).isContainer())
      {
        return eSettingDelegate(eFeature).dynamicGet(this, null, -1, true, true);
      }
      else
      {
        return featureMap.setting(eFeature).get(resolve);
      }
    }

    @Override
    public void eDynamicSet(EStructuralFeature eFeature, Object newValue)
    {
      if (eFeature instanceof EReference && ((EReference)eFeature).isContainer())
      {
        eSettingDelegate(eFeature).dynamicSet(this, null, -1, newValue);
      }
      else
      {
        if (!eFeature.isUnsettable())
        {
          Object defaultValue = eFeature.getDefaultValue();
          if (defaultValue == null ? newValue == null : defaultValue.equals(newValue))
          {
            featureMap.setting(eFeature).unset();
            return;
          }
        }
        featureMap.setting(eFeature).set(newValue);
      }
    }

    @Override
    public void eDynamicUnset(EStructuralFeature eFeature)
    {
      if (eFeature instanceof EReference && ((EReference)eFeature).isContainer())
      {
        eSettingDelegate(eFeature).dynamicUnset(this, null, -1);
      }
      else
      {
        featureMap.setting(eFeature).unset();
      }
    }

    @Override
    public boolean eDynamicIsSet(EStructuralFeature eFeature)
    {
      if (eFeature instanceof EReference && ((EReference)eFeature).isContainer())
      {
        return eSettingDelegate(eFeature).dynamicIsSet(this, null, -1);
      }
      else
      {
        return featureMap.setting(eFeature).isSet();
      }
    }

    @Override
    public NotificationChain eDynamicInverseAdd(InternalEObject otherEnd, int featureID, Class<?> inverseClass, NotificationChain notifications)
    {
      EStructuralFeature.Internal feature = (EStructuralFeature.Internal)eClass().getEStructuralFeature(featureID);
      if (feature.isMany())
      {
        return featureMap.basicAdd(feature, otherEnd, notifications);
      }
      else if (feature instanceof EReference && ((EReference)feature).isContainer())
      {
        return eSettingDelegate(feature).dynamicInverseAdd(this, null, -1, otherEnd, notifications);
      }
      else
      {
        InternalEObject oldValue = (InternalEObject)eDynamicGet(feature, false);
        if (oldValue != null)
        {
          notifications = oldValue.eInverseRemove
            (this, oldValue.eClass().getFeatureID(((EReference)feature).getEOpposite()), null, notifications);
          notifications = featureMap.basicRemove(feature, oldValue, notifications);
        }

        return featureMap.basicAdd(feature, otherEnd, notifications);
      }
    }

    @Override
    public NotificationChain eDynamicInverseRemove(InternalEObject otherEnd, int featureID, Class<?> inverseClass, NotificationChain notifications)
    {
      EStructuralFeature.Internal feature = (EStructuralFeature.Internal)eClass().getEStructuralFeature(featureID);
      if (feature instanceof EReference && ((EReference)feature).isContainer())
      {
        return eSettingDelegate(feature).dynamicInverseRemove(this, null, -1, otherEnd, notifications);
      }
      else
      {
        return featureMap.basicRemove(feature, otherEnd, notifications);
      }
    }

    public FeatureMap featureMap()
    {
      return featureMap;
    }

    @Override
    public void eNotify(Notification notification)
    {
      if (notification.getFeatureID(null) != -1)
      {
        super.eNotify(notification);
      }
    }

    @Override
    public String toString()
    {
      String result = super.toString();
      result = "org.eclipse.emf.ecore.impl.EObjectImpl" + result.substring(result.indexOf("@"));
      return result;
    }
  }

    @Override
   public void set(Object newValue)
   {
     super.set(newValue instanceof FeatureMap ? newValue : ((FeatureMap.Internal.Wrapper)newValue).featureMap());
   }

  @Override
  protected Entry resolve(int index, Entry entry)
  {
    EStructuralFeature feature = entry.getEStructuralFeature();
    if (isResolveProxies(feature))
   {
     InternalEObject object = (InternalEObject)entry.getValue();
     EObject resolved = resolveProxy(object);
     if (resolved != object)
     {
       Entry newEntry = createEntry(feature, resolved);
       delegateSet(index, validate(index, newEntry));
       didSet(index, newEntry, entry);

       NotificationChain notifications = null;

       // Produce a proxy resolve notification for the reference feature of the owner, if there is one.
       //
       if (isNotificationRequired())
       {
         EStructuralFeature affiliatedFeature = ExtendedMetaData.INSTANCE.getAffiliation(owner.eClass(), feature);
         if (affiliatedFeature != getEStructuralFeature())
         {
           FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
           int featureIndex = 0;
           for (int i = 0; i < index; ++i)
           {
             Entry affliatedEntry = delegateGet(i);
             if (validator.isValid(affliatedEntry.getEStructuralFeature()))
             {
               ++featureIndex;
             }
           }

           notifications =
             createNotification
               (Notification.RESOLVE,
                affiliatedFeature,
                object,
                resolved,
                featureIndex,
                false);
       
           notifications.add(createNotification(Notification.RESOLVE, entry, newEntry, index, false));
         }
       }

       EReference reference = (EReference)feature;
       EReference opposite = reference.getEOpposite();
       if (opposite != null)
       {
         notifications = object.eInverseRemove(owner, object.eClass().getFeatureID(opposite), null, notifications);
         notifications = ((InternalEObject)resolved).eInverseAdd(owner, resolved.eClass().getFeatureID(opposite), null, notifications);
       }
       else if (reference.isContainment())
       {
         int inverseFeatureID = InternalEObject.EOPPOSITE_FEATURE_BASE - owner.eClass().getFeatureID(reference);
         notifications = object.eInverseRemove(owner, inverseFeatureID, null, null);
         if (((InternalEObject)resolved).eInternalContainer() == null)
         {
           notifications = ((InternalEObject)resolved).eInverseAdd(owner, inverseFeatureID, null, notifications);
         }
       }
       if (notifications != null)
       {
         notifications.dispatch();
       }

       return newEntry;
     }
    }
    return entry;
  }
}
TOP

Related Classes of org.eclipse.emf.ecore.util.DelegatingFeatureMap$FeatureMapEObjectImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.