Package org.eclipse.emf.ecore.impl

Source Code of org.eclipse.emf.ecore.impl.ArrayDelegatingAdapterList

/**
* <copyright>
*
* Copyright (c) 2009 Ed Merks 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:
*   Ed Merks - Initial API and implementation
*
* </copyright>
*
* $Id: MinimalEObjectImpl.java,v 1.3 2010/03/05 15:50:32 emerks Exp $
*/
package org.eclipse.emf.ecore.impl;


import java.util.Arrays;

import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.BasicNotifierImpl;
import org.eclipse.emf.common.notify.impl.NotificationImpl;
import org.eclipse.emf.common.util.ArrayDelegatingEList;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.BasicEMap;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EContentsEList;
import org.eclipse.emf.ecore.util.ECrossReferenceEList;


/**
* A space compact implementation of the model object '<em><b>EObject</b></em>'.
*/
public class MinimalEObjectImpl extends BasicEObjectImpl implements EObject, EStructuralFeature.Internal.DynamicValueHolder
{
  public static class Container extends MinimalEObjectImpl
  {
    public static class Dynamic extends Container
    {
      public static final class BasicEMapEntry<K, V> extends Dynamic implements BasicEMap.Entry<K, V>
      {
        protected int hash = -1;
        protected EStructuralFeature keyFeature;
        protected EStructuralFeature valueFeature;
 
        /**
         * Creates a dynamic EObject.
         */
        public BasicEMapEntry()
        {
          super();
        }
 
        /**
         * Creates a dynamic EObject.
         */
        public BasicEMapEntry(EClass eClass)
        {
          super(eClass);
        }
 
        @SuppressWarnings("unchecked")
        public K getKey()
        {
          return (K)eGet(keyFeature);
        }
 
        public void setKey(Object key)
        {
          eSet(keyFeature, key);
        }
 
        public int getHash()
        {
          if (hash == -1)
          {
            Object theKey = getKey();
            hash = (theKey == null ? 0 : theKey.hashCode());
          }
          return hash;
        }
 
        public void setHash(int hash)
        {
          this.hash = hash;
        }
 
        @SuppressWarnings("unchecked")
        public V getValue()
        {
          return (V)eGet(valueFeature);
        }
 
        public V setValue(V value)
        {
          @SuppressWarnings("unchecked") V result = (V)eGet(valueFeature);
          eSet(valueFeature, value);
          return result;
        }
 
        @Override
        public void eSetClass(EClass eClass)
        {
          super.eSetClass(eClass);
          keyFeature = eClass.getEStructuralFeature("key");
          valueFeature = eClass.getEStructuralFeature("value");
        }
      }
 
      protected EClass eClass;
      protected Object[] eSettings;
 
      public Dynamic()
      {
        super();
      }
 
      public Dynamic(EClass eClass)
      {
        super();
        eSetClass(eClass);
      }
     
      @Override
      public EClass eClass()
      {
        return eClass;
      }
     
      @Override
      protected EClass eDynamicClass()
      {
        return eClass();
      }
     
      @Override
      public void eSetClass(EClass eClass)
      {
        this.eClass = eClass;
      }
     
      @Override
      protected boolean eHasSettings()
      {
        return eSettings != null;
      }
     
      @Override
      protected Object[] eBasicSettings()
      {
        return eSettings;
      }
     
      @Override
      protected void eBasicSetSettings(Object[] settings)
      {
        this.eSettings = settings;
      }
    }
   
    protected InternalEObject eContainer;

    public Container()
    {
      super();
    }
   
    @Override
    public InternalEObject eInternalContainer()
    {
      return eContainer;
    }
   
    @Override
    protected void eBasicSetContainer(InternalEObject newContainer)
    {
      eContainer = newContainer;
    }
  }

  /**
   * The {@link #eFlags bit flag} for {@link #eDeliver()}.
   */
  private static final int NO_DELIVER = 1 << 0;

  /**
   * The {@link #eFlags bit flag} for indicating that a dynamic {@link #eContainer() container} field is allocated.
   * A derived implementation wishing to allocate a static container field
   * should override {@link #eInternalContainer()} and {@link #eBasicSetContainer(InternalEObject)}.
   */
  private static final int CONTAINER = 1 << 1;

  /**
   * The {@link #eFlags bit flag} for indicating that a dynamic {@link #eAdapters() adapters} field is allocated.
   * A derived implementation wishing to allocate a static adapter field
   * should override {@link #eBasicHasAdapters()}, {@link #eBasicAdapterArray()}, and {@link #eBasicSetAdapterArray(Adapter[])}.
   */
  private static final int ADAPTER = 1 << 2;

  /**
   * The {@link #eFlags bit flag} for indicating that a dynamic {@link BasicNotifierImpl.EObservableAdapterList.Listener adapter list listener} field is allocated.
   */
  private static final int ADAPTER_LISTENER = 1 << 3;

  /**
   * The {@link #eFlags bit flag} for indicating that a dynamic {@link #eClass() class} field is allocated.
   * A derived implementation wishing to allocate a static class field
   * should override {@link #eDynamicClass()} and {@link #eSetClass(EClass)}.
   */
  private static final int CLASS = 1 << 4;

  /**
   * The {@link #eFlags bit flag} for indicating that a dynamic {@link #eSettings() settings} field is allocated.
   * A derived implementation wishing to allocate a static settings field
   * should override {@link #eHasSettings()}, {@link #eBasicSettings()}, and {@link #eBasicSetSettings(Object[])}.
   */
  private static final int SETTING = 1 << 5;

  /**
   * The {@link #eFlags bit flag} for indicating that a dynamic {@link #eProxyURI() proxy URI} field is allocated.
   * A derived implementation wishing to allocate a static proxy URI field
   * should override {@link #eIsProxy()}, {@link #eProxyURI()}, and {@link #eSetProxyURI(URI)}.
   */
  private static final int PROXY = 1 << 6;

  /**
   * The {@link #eFlags bit flag} for indicating that a dynamic {@link #eResource() resource} field is allocated.
   * A derived implementation wishing to allocate a static resource field
   * should override {@link #eDirectResource()} and {@link #eSetDirectResource(Resource.Internal)}.
   */
  private static final int RESOURCE = 1 << 7;

  /**
   * A bit mask for all the bit flags representing fields.
   */
  private static final int FIELD_MASK = CONTAINER | ADAPTER | ADAPTER_LISTENER | CLASS | SETTING | PROXY | RESOURCE;

  /**
   * A bit flag field with bits for
   * {@link #NO_DELIVER},
   * {@link #CONTAINER},
   * {@link #ADAPTER},
   * {@link #ADAPTER_LISTENER},
   * {@link #CLASS},
   * {@link #SETTING},
   * {@link #PROXY},
   * and
   * {@link #RESOURCE}.
   * The high order 16 bits are used to represent the {@link #eContainerFeatureID() container feature ID},
   * a derived implementation wishing to allocate a static container feature ID field
   * should override {@link #eContainerFeatureID()} and {@link #eBasicSetContainerFeatureID(int)}.
   * @see #NO_DELIVER
   * @see #CONTAINER
   * @see #ADAPTER
   * @see #ADAPTER_LISTENER
   * @see #CLASS
   * @see #SETTING
   * @see #PROXY
   * @see #RESOURCE
   */
  private int eFlags;

  /**
   * The storage location for dynamic fields.
   */
  private Object eStorage;

  /**
   * Creates a minimal EObject.
   */
  protected MinimalEObjectImpl()
  {
    super();
  }

  @Override
  protected EPropertiesHolder eProperties()
  {
    throw new UnsupportedOperationException();
  }

  @Override
  protected EPropertiesHolder eBasicProperties()
  {
    throw new UnsupportedOperationException();
  }

  @Override
  protected BasicEList<Adapter> eBasicAdapters()
  {
    throw new UnsupportedOperationException();
  }

  private final boolean hasField(int field)
  {
    return (eFlags & field) != 0;
  }

  private final Object getField(int field)
  {
    if (hasField(field))
    {
      int fieldIndex = fieldIndex(field);
      return fieldIndex == -1 ? eStorage : ((Object[])eStorage)[fieldIndex];
    }
    else
    {
      return null;
    }
  }

  private final void setField(int field, Object value)
  {
    if (hasField(field))
    {
      if (value == null)
      {
        removeField(field);
      }
      else
      {
        int fieldIndex = fieldIndex(field);
        if (fieldIndex == -1)
        {
          eStorage = value;
        }
        else
        {
          ((Object[])eStorage)[fieldIndex] = value;
        }
      }
    }
    else if (value != null)
    {
      addField(field, value);
    }
  }

  private final int fieldIndex(int field)
  {
    int result = 0;
    for (int bit = CONTAINER; bit < field; bit <<= 1)
    {
      if ((eFlags & bit) != 0)
      {
        ++result;
      }
    }
    if (result == 0)
    {
      for (int bit = field <<= 1; bit <= RESOURCE; bit <<= 1)
      {
        if ((eFlags & bit) != 0)
        {
          return 0;
        }
      }
      return -1;
    }
    else
    {
      return result;
    }
  }

  private final void addField(int field, Object value)
  {
    int fieldCount = Integer.bitCount(eFlags & FIELD_MASK);
    if (fieldCount == 0)
    {
      eStorage = value;
    }
    else
    {
      Object[] result;
      if (fieldCount == 1)
      {
        result = new Object[2];
        int fieldIndex = fieldIndex(field);
        if (fieldIndex == 0)
        {
          result[0] = value;
          result[1] = eStorage;
        }
        else
        {
          result[0] = eStorage;
          result[1] = value;
        }
      }
      else
      {
        result = new Object[fieldCount + 1];
        Object[] oldStorage = (Object[])eStorage;
        for (int bit = CONTAINER, sourceIndex = 0, targetIndex = 0; bit <= RESOURCE; bit <<= 1)
        {
          if (bit == field)
          {
            result[targetIndex++] = value;
          }
          else if ((eFlags & bit) != 0)
          {
            result[targetIndex++] = oldStorage[sourceIndex++];
          }
        }
      }
      eStorage = result;
    }
    eFlags |= field;
  }

  private final void removeField(int field)
  {
    int fieldCount = Integer.bitCount(eFlags & FIELD_MASK);
    if (fieldCount == 1)
    {
      eStorage = null;
    }
    else
    {
      Object[] oldStorage = (Object[])eStorage;
      if (fieldCount == 2)
      {
        int fieldIndex = fieldIndex(field);
        eStorage = oldStorage[fieldIndex == 0 ? 1 : 0];
      }
      else
      {
        Object[] result = new Object[fieldCount - 1];
        for (int bit = CONTAINER, sourceIndex = 0, targetIndex = 0; bit <= RESOURCE; bit <<= 1)
        {
          if (bit == field)
          {
            sourceIndex++;
          }
          else if ((eFlags & bit) != 0)
          {
            result[targetIndex++] = oldStorage[sourceIndex++];
          }
        }
        eStorage = result;
      }
    }
    eFlags &= ~field;
  }

  @Override
  public EList<Adapter> eAdapters()
  {
    class ArrayDelegatingAdapterList extends ArrayDelegatingEList<Adapter> implements BasicNotifierImpl.EObservableAdapterList
    {
      private static final long serialVersionUID = 1L;

      @Override
      protected Object[] newData(int capacity)
      {
        return new Adapter[capacity];
      }

      @Override
      public Object[] data()
      {
        return eBasicAdapterArray();
      }

      @Override
      public void setData(Object[] data)
      {
        ++modCount;
        InternalEObject eContainer = eInternalContainer();
        if (eContainer instanceof BasicEObjectImpl)
        {
          Adapter[] eContainerAdapterArray = eContainerAdapterArray();
          if (Arrays.equals(data, eContainerAdapterArray))
          {
            eBasicSetAdapterArray(eContainerAdapterArray);
            return;
          }
        }
        eBasicSetAdapterArray((Adapter[])data);
      }

      @Override
      protected void didAdd(int index, Adapter newObject)
      {
        Listener[] listeners = (Listener[])getField(ADAPTER_LISTENER);
        if (listeners != null)
        {
          for (Listener listener : listeners)
          {
            listener.added(MinimalEObjectImpl.this, newObject);
          }
        }
        newObject.setTarget(MinimalEObjectImpl.this);
      }

      @Override
      protected void didRemove(int index, Adapter oldObject)
      {
        Listener[] listeners = (Listener[])getField(ADAPTER_LISTENER);
        if (listeners != null)
        {
          for (Listener listener : listeners)
          {
            listener.removed(MinimalEObjectImpl.this, oldObject);
          }
        }
        Adapter adapter = oldObject;
        if (eDeliver())
        {
          Notification notification =
            new NotificationImpl(Notification.REMOVING_ADAPTER, oldObject, null, index)
            {
              @Override
              public Object getNotifier()
              {
                return MinimalEObjectImpl.this;
              }
            };
          adapter.notifyChanged(notification);
        }
        if (adapter instanceof Adapter.Internal)
        {
          ((Adapter.Internal)adapter).unsetTarget(MinimalEObjectImpl.this);
        }
        else if (adapter.getTarget() == MinimalEObjectImpl.this)
        {
          adapter.setTarget(null);
        }
      }

      public void addListener(Listener listener)
      {
        Listener[] listeners = (Listener[])getField(ADAPTER_LISTENER);
        if (listeners == null)
        {
          listeners = new Listener [] { listener };
        }
        else
        {
          Listener[] newListeners = new Listener[listeners.length + 1];
          System.arraycopy(listeners, 0, newListeners, 0, listeners.length);
          newListeners[listeners.length] = listener;
          listeners = newListeners;
        }
        setField(ADAPTER_LISTENER, listeners);
      }

      public void removeListener(Listener listener)
      {
        Listener[] listeners = (Listener[])getField(ADAPTER_LISTENER);
        if (listeners != null)
        {
          for (int i = 0; i < listeners.length; ++i)
          {
            if (listeners[i] == listener)
            {
              if (listeners.length == 1)
              {
                listeners = null;
              }
              else
              {
                Listener[] newListeners = new Listener[listeners.length - 1];
                System.arraycopy(listeners, 0, newListeners, 0, i);
                if (i != newListeners.length)
                {
                  System.arraycopy(listeners, i + 1, newListeners, i, newListeners.length - i);
                }
                listeners = newListeners;
              }
              setField(ADAPTER_LISTENER, listeners);
              break;
            }
          }
        }
      }
    }
    return new ArrayDelegatingAdapterList();
  }

  @Override
  protected Adapter[] eBasicAdapterArray()
  {
    return (Adapter[])getField(ADAPTER);
  }

  protected void eBasicSetAdapterArray(Adapter[] eAdapters)
  {
    setField(ADAPTER, eAdapters);
  }

  @Override
  protected boolean eBasicHasAdapters()
  {
    return hasField(ADAPTER);
  }

  @Override
  public boolean eDeliver()
  {
    return (eFlags & NO_DELIVER) == 0;
  }

  @Override
  public void eSetDeliver(boolean deliver)
  {
    if (deliver)
    {
      eFlags &= ~NO_DELIVER;
    }
    else
    {
      eFlags |= NO_DELIVER;
    }
  }

  @Override
  public boolean eIsProxy()
  {
    return hasField(PROXY);
  }

  @Override
  public URI eProxyURI()
  {
    return (URI)getField(PROXY);
  }

  @Override
  public void eSetProxyURI(URI uri)
  {
    setField(PROXY, uri);
  }

  @Override
  public InternalEObject eInternalContainer()
  {
    return (InternalEObject)getField(CONTAINER);
  }

  protected void eBasicSetContainer(InternalEObject newContainer)
  {
    setField(CONTAINER, newContainer);
  }

  @Override
  public int eContainerFeatureID()
  {
    return eFlags >> 16;
  }

  protected void eBasicSetContainerFeatureID(int newContainerFeatureID)
  {
    eFlags = newContainerFeatureID << 16  | (eFlags & 0x00FF);
  }

  @Override
  protected void eBasicSetContainer(InternalEObject newContainer, int newContainerFeatureID)
  {
    eBasicSetContainerFeatureID(newContainerFeatureID);
    eBasicSetContainer(newContainer);
  }

  @Override
  protected EClass eDynamicClass()
  {
     return (EClass)getField(CLASS);
  }

  @Override
  public EClass eClass()
  {
    EClass eClass = eDynamicClass();
    return eClass == null ? eStaticClass() : eClass;
  }

  @Override
  public void eSetClass(EClass eClass)
  {
    setField(CLASS, eClass);
  }

  @Override
  protected boolean eHasSettings()
  {
    return hasField(SETTING);
  }

  protected Object[] eBasicSettings()
  {
    return (Object[])getField(SETTING);
  }

  protected void eBasicSetSettings(Object[] settings)
  {
    setField(SETTING, settings);
  }

  @Override
  protected EStructuralFeature.Internal.DynamicValueHolder eSettings()
  {
    if (!eHasSettings())
    {
      int size =  eClass().getFeatureCount() - eStaticFeatureCount();
      if (size != 0)
      {
        eBasicSetSettings(size == 0 ? EPropertiesHolderBaseImpl.NO_SETTINGS : new Object [size]);
      }
    }

    return this;
  }

  @Override
  public Resource.Internal eDirectResource()
  {
    return (Resource.Internal)getField(RESOURCE);
  }

  @Override
  protected void eSetDirectResource(Resource.Internal resource)
  {
    setField(RESOURCE, resource);
  }

  @Override
  public EList<EObject> eContents()
  {
    return EContentsEList.createEContentsEList(this);
  }

  @Override
  public EList<EObject> eCrossReferences()
  {
    return ECrossReferenceEList.createECrossReferenceEList(this);
  }

  private Object[] eDynamicSettings()
  {
    Object[] settings = eBasicSettings();
    if (settings == null)
    {
      eSettings();
      settings = eBasicSettings();
    }
    return settings;
  }

  public Object dynamicGet(int dynamicFeatureID)
  {
    Object[] settings = eDynamicSettings();
    return settings[dynamicFeatureID];
  }

  public void dynamicSet(int dynamicFeatureID, Object newValue)
  {
    Object[] settings = eDynamicSettings();
    settings[dynamicFeatureID] = newValue;
  }

  public void dynamicUnset(int dynamicFeatureID)
  {
    Object[] settings = eDynamicSettings();
    settings[dynamicFeatureID] = null;
  }
}
TOP

Related Classes of org.eclipse.emf.ecore.impl.ArrayDelegatingAdapterList

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.