blob: 9844cfa5ba5bfa75e431f72665a31be24d819eb5 [file] [log] [blame]
/**
* 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 v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* IBM - Initial API and implementation
*/
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.EDataType;
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 class BasicFeatureMap
extends EDataTypeEList<FeatureMap.Entry>
implements FeatureMap.Internal, FeatureMap.Internal.Wrapper
{
private static final long serialVersionUID = 1L;
protected Wrapper wrapper = this;
protected final FeatureMapUtil.Validator featureMapValidator;
public BasicFeatureMap(InternalEObject owner, int featureID)
{
super(Entry.Internal.class, owner, featureID);
featureMapValidator = FeatureMapUtil.getValidator(owner.eClass(), getEStructuralFeature());
}
public BasicFeatureMap(InternalEObject owner, int featureID, EStructuralFeature eStructuralFeature)
{
super(Entry.Internal.class, owner, featureID);
featureMapValidator = FeatureMapUtil.getValidator(owner.eClass(), eStructuralFeature);
}
public Wrapper getWrapper()
{
return wrapper;
}
public void setWrapper(Wrapper wrapper)
{
this.wrapper = wrapper;
}
public FeatureMap featureMap()
{
return this;
}
@Override
protected Object [] newData(int capacity)
{
return new FeatureMap.Entry.Internal [capacity];
}
@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;
}
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 result = size;
Entry [] entries = (Entry[])data;
for (int i = 0; i < size; ++i)
{
Entry entry = entries[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 = (Entry)data[entryIndex];
Entry entry = createEntry(feature, resolved);
assign(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)
{
return shadowAdd((FeatureMap.Entry.Internal)object, notifications);
}
public NotificationChain shadowAdd(FeatureMap.Entry.Internal entry, NotificationChain notifications)
{
EStructuralFeature feature = entry.getEStructuralFeature();
Object value = entry.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)
{
return inverseAdd((FeatureMap.Entry.Internal)object, notifications);
}
public NotificationChain inverseAdd(FeatureMap.Entry.Internal entry, NotificationChain notifications)
{
return entry.inverseAdd(owner, featureID, notifications);
}
@Override
public NotificationChain shadowRemove(Entry object, NotificationChain notifications)
{
return shadowRemove((FeatureMap.Entry.Internal)object, notifications);
}
public NotificationChain shadowRemove(FeatureMap.Entry.Internal entry, NotificationChain notifications)
{
EStructuralFeature feature = entry.getEStructuralFeature();
Object value = entry.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)
{
return inverseRemove((FeatureMap.Entry.Internal)object, notifications);
}
public NotificationChain inverseRemove(FeatureMap.Entry.Internal entry, NotificationChain notifications)
{
return entry.inverseRemove(owner, featureID, 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 [] entries = (Entry[])data;
Entry sourceEntry = entries[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 = entries[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)
{
Entry entry = object;
EStructuralFeature entryFeature = entry.getEStructuralFeature();
if (isMany(entryFeature))
{
if (entryFeature.isUnique())
{
Entry [] entries = (Entry[])data;
for (int i = 0; i < size; ++i)
{
Entry otherEntry = entries[i];
if (otherEntry.equals(entry) && i != index)
{
throw new IllegalArgumentException("The 'no duplicates' constraint is violated");
}
}
}
}
else
{
FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), entryFeature);
Entry [] entries = (Entry[])data;
for (int i = 0; i < size; ++i)
{
Entry otherEntry = entries[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)
{
Entry entry = object;
EStructuralFeature entryFeature = entry.getEStructuralFeature();
if (isMany(entryFeature))
{
if (entryFeature.isUnique() && contains(entryFeature, entry.getValue()))
{
return false;
}
}
else
{
FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), entryFeature);
Entry [] entries = (Entry[])data;
for (int i = 0; i < size; ++i)
{
Entry otherEntry = entries[i];
if (validator.isValid(otherEntry.getEStructuralFeature()))
{
if (otherEntry.equals(entry))
{
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)
{
Entry entry = object;
EStructuralFeature entryFeature = entry.getEStructuralFeature();
if (isMany(entryFeature))
{
if (entryFeature.isUnique())
{
Entry [] entries = (Entry[])data;
for (int i = 0; i < size; ++i)
{
Entry otherEntry = entries[i];
if (otherEntry.equals(entry) && i != index)
{
throw new IllegalArgumentException("The 'no duplicates' constraint is violated");
}
}
}
}
else
{
FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), entryFeature);
Entry [] entries = (Entry[])data;
for (int i = 0; i < size; ++i)
{
Entry otherEntry = entries[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);
Entry [] entries = (Entry[])data;
boolean include = true;
for (int j = 0; j < size; ++j)
{
Entry otherEntry = entries[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);
Entry [] entries = (Entry[])data;
boolean include = true;
for (int j = 0; j < size; ++j)
{
Entry otherEntry = entries[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;
Entry [] entries = (Entry[])data;
for (int i = 0; i < size; ++i)
{
Entry entry = entries[i];
if (validator.isValid(entry.getEStructuralFeature()))
{
++result;
}
}
return result;
}
public boolean isEmpty(EStructuralFeature feature)
{
FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
Entry [] entries = (Entry[])data;
for (int i = 0; i < size; ++i)
{
Entry entry = entries[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);
Entry [] entries = (Entry[])data;
if (FeatureMapUtil.isFeatureMap(feature))
{
for (int i = 0; i < size; ++i)
{
Entry entry = entries[i];
if (validator.isValid(entry.getEStructuralFeature()) && entry.equals(object))
{
return true;
}
}
}
else if (object != null)
{
for (int i = 0; i < size; ++i)
{
Entry entry = entries[i];
if (validator.isValid(entry.getEStructuralFeature()) && object.equals(entry.getValue()))
{
return true;
}
}
if (resolve)
{
for (int i = 0; i < size; ++i)
{
Entry entry = entries[i];
if (validator.isValid(entry.getEStructuralFeature()) && object == resolveProxy((EObject)entry.getValue()))
{
return true;
}
}
}
}
else
{
for (int i = 0; i < size; ++i)
{
Entry entry = entries[i];
if (validator.isValid(entry.getEStructuralFeature()) && entry.getValue() == null)
{
return false;
}
}
}
return false;
}
public boolean containsAll(EStructuralFeature feature, Collection<?> collection)
{
for (Iterator<?> i = collection.iterator(); i.hasNext(); )
{
if (!contains(feature, i.next()))
{
return false;
}
}
return true;
}
public boolean basicContainsAll(EStructuralFeature feature, Collection<?> collection)
{
for (Iterator<?> i = collection.iterator(); i.hasNext(); )
{
if (!basicContains(feature, i.next()))
{
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;
Entry [] entries = (Entry[])data;
if (FeatureMapUtil.isFeatureMap(feature))
{
for (int i = 0; i < size; ++i)
{
Entry entry = entries[i];
if (validator.isValid(entry.getEStructuralFeature()))
{
if (entry.equals(object))
{
return result;
}
++result;
}
}
}
else if (object != null)
{
for (int i = 0; i < size; ++i)
{
Entry entry = entries[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 = entries[i];
if (validator.isValid(entry.getEStructuralFeature()))
{
if (object == resolveProxy((EObject)entry.getValue()))
{
return result;
}
++result;
}
}
}
}
else
{
for (int i = 0; i < size; ++i)
{
Entry entry = entries[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;
Entry [] entries = (Entry[])data;
if (FeatureMapUtil.isFeatureMap(feature))
{
for (int i = 0; i < size; ++i)
{
Entry entry = entries[i];
if (validator.isValid(entry.getEStructuralFeature()))
{
if (entry.equals(object))
{
result = count;
}
++count;
}
}
}
else if (object != null)
{
for (int i = 0; i < size; ++i)
{
Entry entry = entries[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 = entries[i];
if (validator.isValid(entry.getEStructuralFeature()))
{
if (object == resolveProxy((EObject)entry.getValue()))
{
result = count;
}
++count;
}
}
}
}
else
{
for (int i = 0; i < size; ++i)
{
Entry entry = entries[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<E1> extends AbstractEList<FeatureMap.Entry>.EListIterator<E1> implements ValueListIterator<E1>
{
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 E1 next()
{
return (E1)doNext().getValue();
}
@SuppressWarnings("unchecked")
@Override
public E1 previous()
{
return (E1)doPrevious().getValue();
}
@Override
public void add(E1 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(final 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);
Entry [] entries = (Entry[])data;
if (FeatureMapUtil.isFeatureMap(feature))
{
for (int i = 0; i < size; ++i)
{
Entry entry = entries[i];
if (validator.isValid(entry.getEStructuralFeature()))
{
result.add(entry);
}
}
}
else
{
for (int i = 0; i < size; ++i)
{
Entry entry = entries[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);
Entry [] entries = (Entry[])data;
if (FeatureMapUtil.isFeatureMap(feature))
{
for (int i = 0; i < size; ++i)
{
Entry entry = entries[i];
if (validator.isValid(entry.getEStructuralFeature()))
{
result.add(entry);
}
}
}
else
{
for (int i = 0; i < size; ++i)
{
Entry entry = entries[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);
Entry [] entries = (Entry[])data;
for (int i = 0; i < size; ++i)
{
Entry entry = entries[i];
EStructuralFeature entryFeature = entry.getEStructuralFeature();
if (validator.isValid(entryFeature))
{
if (entryFeature == XMLTypeFeatures.TEXT || entryFeature == XMLTypeFeatures.CDATA)
{
boolean shouldUnset = shouldUnset(feature, object);
int index = i;
if (shouldUnset)
{
remove(i);
}
else
{
++i;
}
while (i < size)
{
entry = entries[i];
entryFeature = entry.getEStructuralFeature();
if (entryFeature == XMLTypeFeatures.TEXT || entryFeature == XMLTypeFeatures.CDATA)
{
remove(i);
}
else
{
++i;
}
}
if (!shouldUnset)
{
doSet(index, createEntry(feature, object));
}
}
else if (shouldUnset(feature, object))
{
remove(i);
}
else
{
doSet(i, FeatureMapUtil.isFeatureMap(feature) ? (Entry)object : (Entry)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 the feature is unsettable, then regardless of the value, we should not be unsetting the feature.
//
if (feature.isUnsettable())
{
return false;
}
// If it's not an open content element, unset the feature if the value is the same as the default value.
//
else if (feature.getUpperBound() != ETypedElement.UNSPECIFIED_MULTIPLICITY)
{
Object defaultValue = feature.getDefaultValue();
return defaultValue == null ? value == null : defaultValue.equals(value);
}
// If this is a feature of the document root itself, unset if the value is null.
// If it was a nillable element, it would have been unsettable.
//
else if (feature.getEContainingClass() == owner.eClass())
{
return value == null;
}
// Otherwise, return false.
//
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);
Entry [] entries = (Entry[])data;
for (int i = 0; i < size; ++i)
{
Entry entry = entries[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);
Entry [] entries = (Entry[])data;
for (int i = 0; i < size; ++i)
{
Entry entry = entries[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);
Entry [] entries = (Entry[])data;
for (int i = 0; i < size; ++i)
{
Entry entry = entries[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.isEmpty())
{
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);
Entry [] entries = (Entry[])data;
for (int i = 0; i < size; ++i)
{
Entry entry = entries[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.isEmpty())
{
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);
Entry [] entries = (Entry[])data;
for (int i = 0; i < size; ++i)
{
Entry entry = entries[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.isEmpty())
{
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);
Entry [] entries = (Entry[])data;
for (int i = 0; i < size; ++i)
{
Entry entry = entries[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(size, object);
addUnique((FeatureMap.Entry.Internal)object);
}
public void addUnique(Entry.Internal entry)
{
modCount = -1;
if (isNotificationRequired())
{
int index = size;
boolean oldIsSet = isSet();
doAddUnique(entry);
NotificationImpl notification = createNotification(Notification.ADD, null, entry, index, oldIsSet);
if (hasInverse())
{
NotificationChain notifications = inverseAdd(entry, null);
notifications = shadowAdd(entry, notifications);
if (notifications == null)
{
dispatchNotification(notification);
}
else
{
notifications.add(notification);
notifications.dispatch();
}
}
else
{
dispatchNotification(notification);
}
}
else
{
doAddUnique(entry);
NotificationChain notifications = inverseAdd(entry, null);
if (notifications != null) notifications.dispatch();
}
}
@Override
public boolean addAllUnique(Collection<? extends Entry> collection)
{
modCount = -1;
return super.addAllUnique(collection);
}
public boolean addAllUnique(FeatureMap.Entry.Internal [] entries, int start, int end)
{
return addAllUnique(size, entries, start, end);
}
public boolean addAllUnique(int index, FeatureMap.Entry.Internal [] entries, int start, int end)
{
modCount = -1;
int collectionSize = end - start;
if (collectionSize == 0)
{
return false;
}
else
{
if (isNotificationRequired())
{
boolean oldIsSet = isSet();
doAddAllUnique(index, entries, start, end);
NotificationImpl notification;
if (collectionSize == 0)
{
notification = createNotification(Notification.ADD, null, entries[0], index, oldIsSet);
}
else
{
if (start != 0 || end != entries.length)
{
Object [] actualObjects = new Object [collectionSize];
for (int i = 0, j = start; j < end; ++i, ++j)
{
actualObjects[i] = entries[j];
}
notification = createNotification(Notification.ADD_MANY, null, actualObjects, index, oldIsSet);
}
else
{
notification = createNotification(Notification.ADD_MANY, null, entries, index, oldIsSet);
}
}
NotificationChain notifications = null;
for (int i = start; i < end; ++i)
{
FeatureMap.Entry.Internal value = entries[i];
notifications = inverseAdd(value, notifications);
notifications = shadowAdd(value, notifications);
}
if (notifications == null)
{
dispatchNotification(notification);
}
else
{
notifications.add(notification);
notifications.dispatch();
}
}
else
{
doAddAllUnique(index, entries, start, end);
NotificationChain notifications = null;
for (int i = start; i < end; ++i)
{
notifications = inverseAdd(entries[i], notifications);
}
if (notifications != null) notifications.dispatch();
}
return true;
}
}
public NotificationChain basicAdd(EStructuralFeature feature, Object object, NotificationChain notifications)
{
if (object == null)
{
Entry [] entries = (Entry[])data;
for (int i = 0; i < size; ++i)
{
Entry entry = entries[i];
if (entry.getEStructuralFeature() == feature)
{
return super.basicRemove(entry, notifications);
}
}
}
Entry entry = FeatureMapUtil.isFeatureMap(feature) ? (Entry)object : createEntry(feature, object);
if (isNotificationRequired())
{
boolean oldIsSet = !isEmpty(feature);
notifications = basicAdd(entry, notifications);
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;
}
}
else
{
notifications = basicAdd(entry, notifications);
}
return notifications;
}
public boolean remove(EStructuralFeature feature, Object object)
{
FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
Entry [] entries = (Entry[])data;
if (FeatureMapUtil.isFeatureMap(feature))
{
for (int i = 0; i < size; ++i)
{
Entry entry = entries[i];
if (validator.isValid(entry.getEStructuralFeature()))
{
if (entry.equals(object))
{
remove(i);
return true;
}
}
}
}
else if (object != null)
{
for (int i = 0; i < size; ++i)
{
Entry entry = entries[i];
if (validator.isValid(entry.getEStructuralFeature()))
{
if (object.equals(entry.getValue()))
{
remove(i);
return true;
}
}
}
}
else
{
for (int i = 0; i < size; ++i)
{
Entry entry = entries[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);
Entry [] entries = (Entry[])data;
int count = 0;
for (int i = 0; i < size; ++i)
{
Entry entry = entries[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());
Entry [] entries = (Entry[])data;
for (int i = size; --i >= 0; )
{
Entry entry = entries[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 [] entries = (Entry[])data;
Entry match = null;
if (FeatureMapUtil.isFeatureMap(feature))
{
for (int i = 0; i < size; ++i)
{
Entry entry = entries[i];
if (validator.isValid(entry.getEStructuralFeature()))
{
if (entry.equals(object))
{
match = entry;
break;
}
++count;
}
}
}
else if (object != null)
{
for (int i = 0; i < size; ++i)
{
Entry entry = entries[i];
if (validator.isValid(entry.getEStructuralFeature()))
{
if (object.equals(entry.getValue()))
{
match = entry;
break;
}
++count;
}
}
}
else
{
for (int i = 0; i < size; ++i)
{
Entry entry = entries[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());
Entry [] entries = (Entry[])data;
for (int i = size; --i >= 0; )
{
Entry entry = entries[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>();
Entry [] entries = (Entry[])data;
for (int i = size; --i >= 0; )
{
Entry entry = entries[i];
if (validator.isValid(entry.getEStructuralFeature()))
{
entryCollection.add(entry);
}
}
if (!removeAll(entryCollection) && owner.eNotificationRequired())
{
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);
Entry [] entries = (Entry[])data;
Object result = null;
int entryTargetIndex = -1;
int entrySourceIndex = -1;
int count = 0;
for (int i = 0; i < size; ++i)
{
Entry entry = entries[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)
{
Entry [] entries = (Entry[])data;
if (isMany(feature))
{
return list(feature);
}
else
{
FeatureMapUtil.Validator validator = FeatureMapUtil.getValidator(owner.eClass(), feature);
int count = 0;
for (int i = 0; i < size; ++i)
{
Entry entry = entries[i];
EStructuralFeature entryFeature = entry.getEStructuralFeature();
if (validator.isValid(entryFeature))
{
if (FeatureMapUtil.isFeatureMap(feature))
{
return entry;
}
else if (entryFeature == XMLTypeFeatures.TEXT || entryFeature == XMLTypeFeatures.CDATA)
{
StringBuilder result = new StringBuilder(entry.getValue().toString());
while (++i < size)
{
entry = entries[i];
entryFeature = entry.getEStructuralFeature();
if (entryFeature == XMLTypeFeatures.TEXT || entryFeature == XMLTypeFeatures.CDATA)
{
result.append(entry.getValue().toString());
}
}
return EcoreUtil.createFromString((EDataType)feature.getEType(), result.toString());
}
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);
Entry [] entries = (Entry[])data;
if (isMany(feature))
{
int count = 0;
for (int i = 0; i < size; ++i)
{
Entry entry = entries[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, value);
}
return value;
}
}
++count;
}
}
throw new IndexOutOfBoundsException("index=" + index + ", size=" + count);
}
else
{
int count = 0;
for (int i = 0; i < size; ++i)
{
Entry entry = entries[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);
Entry [] entries = (Entry[])data;
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; i < size; ++i)
{
Entry entry = entries[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; i < size; ++i)
{
Entry entry = entries[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);
Entry [] entries = (Entry[])data;
if (isMany(feature))
{
int count = 0;
for (int i = 0; i < size; ++i)
{
Entry entry = entries[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; i < size; ++i)
{
Entry entry = entries[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;
Entry [] entries = (Entry[])data;
for (int i = 0; i < size; ++i)
{
Entry entry = entries[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;
Entry [] entries = (Entry[])data;
for (int i = 0; i < size; ++i)
{
Entry entry = entries[i];
if (object.equals(entry.getValue()))
{
feature = entry.getEStructuralFeature();
if (feature instanceof EReference && ((EReference)feature).isContainment())
{
match = entry;
break;
}
}
}
if (match != null)
{
if (isNotificationRequired())
{
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();
Entry [] entries = (Entry [])((BasicEList<?>)featureMap).data();
while (entryCursor < size)
{
Entry entry = entries[entryCursor];
if (validator.isValid(entry.getEStructuralFeature()))
{
preparedResult = extractValue(entry);
prepared = 2;
return true;
}
++entryCursor;
}
prepared = 1;
lastCursor = -1;
return false;
}
@Override
protected boolean scanPrevious()
{
Entry [] entries = (Entry [])((BasicEList<?>)featureMap).data();
while (--entryCursor >= 0)
{
Entry entry = entries[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 BasicFeatureMap featureMap = new BasicFeatureMap(this, -1);
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);
assign(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;
Entry [] entries = (Entry[])data;
for (int i = 0; i < index; ++i)
{
Entry affliatedEntry = entries[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;
}
}