/**
* Copyright (c) 2002-2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
*/
package org.eclipse.emf.common.notify.impl;
import java.util.Collection;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.ECollections;
import org.eclipse.emf.common.util.EList;
/**
* An extensible notifier implementation.
*/
public class BasicNotifierImpl implements Notifier
{
/**
* Creates a blank new instance.
*/
public BasicNotifierImpl()
{
super();
}
public static class EAdapterList<E extends Object & Adapter> extends BasicEList<E>
{
private static final long serialVersionUID = 1L;
protected Notifier notifier;
public EAdapterList(Notifier notifier)
{
this.notifier = notifier;
}
protected boolean safe;
@Override
protected boolean canContainNull()
{
return false;
}
@Override
protected boolean useEquals()
{
return false;
}
@Override
protected Object [] newData(int capacity)
{
return new Adapter [capacity];
}
@Override
protected void didAdd(int index, E newObject)
{
newObject.setTarget(notifier);
}
@Override
protected void didRemove(int index, E oldObject)
{
E adapter = oldObject;
if (notifier.eDeliver())
{
Notification notification =
new NotificationImpl(Notification.REMOVING_ADAPTER, oldObject, null, index)
{
@Override
public Object getNotifier()
{
return notifier;
}
};
adapter.notifyChanged(notification);
}
if (adapter instanceof Adapter.Internal)
{
((Adapter.Internal)adapter).unsetTarget(notifier);
}
else if (adapter.getTarget() == notifier)
{
adapter.setTarget(null);
}
}
@Override
public Object [] data()
{
safe = true;
if (data != null && data.length != size)
{
if (size == 0)
{
data = null;
}
else
{
Object [] oldData = data;
data = newData(size);
System.arraycopy(oldData, 0, data, 0, size);
}
}
return data;
}
protected void ensureSafety()
{
if (safe && data != null)
{
Object [] oldData = data;
data = newData(data.length);
System.arraycopy(oldData, 0, data, 0, size);
safe = false;
}
}
@Override
public boolean add(E object)
{
ensureSafety();
return super.add(object);
}
@Override
public void add(int index, E object)
{
ensureSafety();
super.add(index, object);
}
@Override
public boolean addAll(Collection<? extends E> collection)
{
ensureSafety();
return super.addAll(collection);
}
@Override
public boolean remove(Object object)
{
ensureSafety();
return super.remove(object);
}
@Override
public E remove(int index)
{
ensureSafety();
return super.remove(index);
}
@Override
public boolean removeAll(Collection<?> collection)
{
ensureSafety();
return super.removeAll(collection);
}
@Override
public void clear()
{
ensureSafety();
super.clear();
}
@Override
public boolean retainAll(Collection<?> collection)
{
ensureSafety();
return super.retainAll(collection);
}
@Override
public E set(int index, E object)
{
ensureSafety();
return super.set(index, object);
}
@Override
public void move(int newPosition, E object)
{
ensureSafety();
super.move(newPosition, object);
}
@Override
public E move(int newPosition, int oldPosition)
{
ensureSafety();
return super.move(newPosition, oldPosition);
}
}
public EList<Adapter> eAdapters()
{
return ECollections.emptyEList();
}
/**
* Returns the adapter list, even if it is <code>null</code>.
* @return the adapter list, even if it is <code>null</code>.
*/
protected BasicEList<Adapter> eBasicAdapters()
{
return null;
}
/**
* Returns the underlying array of adapters.
* The length of this array reflects exactly the number of adapters
* where <code>null</code> represents the lack of any adapters.
* This array may not be modified by the caller
* and must be guaranteed not to be modified even if the {@link #eAdapters() list of adapters} is modified.
* @return the underlying array of adapters.
*/
protected Adapter[] eBasicAdapterArray()
{
BasicEList<Adapter> eBasicAdapters = eBasicAdapters();
return eBasicAdapters == null ? null : (Adapter[])eBasicAdapters.data();
}
/**
* Returns whether there are any adapters.
* @return whether there are any adapters.
*/
protected boolean eBasicHasAdapters()
{
BasicEList<Adapter> eBasicAdapters = eBasicAdapters();
return eBasicAdapters != null && eBasicAdapters.size() != 0;
}
/*
* Javadoc copied from interface.
*/
public boolean eDeliver()
{
return false;
}
/*
* Javadoc copied from interface.
*/
public void eSetDeliver(boolean deliver)
{
throw new UnsupportedOperationException();
}
/*
* Javadoc copied from interface.
*/
public void eNotify(Notification notification)
{
Adapter[] eAdapters = eBasicAdapterArray();
if (eAdapters != null && eDeliver())
{
for (int i = 0, size = eAdapters.length; i < size; ++i)
{
eAdapters[i].notifyChanged(notification);
}
}
}
/**
* Returns whether {@link #eNotify eNotify} needs to be called.
* This may return <code>true</code> even when {@link #eDeliver eDeliver} is <code>false</code>
* or when {@link #eAdapters eAdapters} is empty.
* @return whether {@link #eNotify eNotify} needs to be called.
*/
public boolean eNotificationRequired()
{
return eBasicHasAdapters() && eDeliver();
}
}