/**
* <copyright>
*
* Copyright (c) 2002-2006 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: EContentAdapter.java,v 1.9 2007/06/14 18:32:46 emerks Exp $
*/
package org.eclipse.emf.ecore.util;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
/**
* An adapter that maintains itself as an adapter for all contained objects
* as they come and go.
* It can be installed for an {@link EObject}, a {@link Resource}, or a {@link ResourceSet}.
*/
public class EContentAdapter extends AdapterImpl
{
/**
* Handles a notification by calling {@link #selfAdapt selfAdapter}.
*/
@Override
public void notifyChanged(Notification notification)
{
selfAdapt(notification);
super.notifyChanged(notification);
}
/**
* Handles a notification by calling {@link #handleContainment handleContainment}
* for any containment-based notification.
*/
protected void selfAdapt(Notification notification)
{
Object notifier = notification.getNotifier();
if (notifier instanceof ResourceSet)
{
if (notification.getFeatureID(ResourceSet.class) == ResourceSet.RESOURCE_SET__RESOURCES)
{
handleContainment(notification);
}
}
else if (notifier instanceof Resource)
{
if (notification.getFeatureID(Resource.class) == Resource.RESOURCE__CONTENTS)
{
handleContainment(notification);
}
}
else if (notifier instanceof EObject)
{
Object feature = notification.getFeature();
if (feature instanceof EReference)
{
EReference eReference = (EReference)feature;
if (eReference.isContainment())
{
handleContainment(notification);
}
}
}
}
/**
* Handles a containment change by adding and removing the adapter as appropriate.
*/
protected void handleContainment(Notification notification)
{
switch (notification.getEventType())
{
case Notification.RESOLVE:
{
// We need to be careful that the proxy may be resolved while we are attaching this adapter.
// We need to avoid attaching the adapter during the resolve
// and also attaching it again as we walk the eContents() later.
// Checking here avoids having to check during addAdapter.
//
Notifier oldValue = (Notifier)notification.getOldValue();
if (oldValue.eAdapters().contains(this))
{
removeAdapter(oldValue);
Notifier newValue = (Notifier)notification.getNewValue();
addAdapter(newValue);
}
break;
}
case Notification.UNSET:
{
Object oldValue = notification.getOldValue();
if (oldValue != Boolean.TRUE && oldValue != Boolean.FALSE)
{
if (oldValue != null)
{
removeAdapter((Notifier)oldValue);
}
Notifier newValue = (Notifier)notification.getNewValue();
if (newValue != null)
{
addAdapter(newValue);
}
}
break;
}
case Notification.SET:
{
Notifier oldValue = (Notifier)notification.getOldValue();
if (oldValue != null)
{
removeAdapter(oldValue);
}
Notifier newValue = (Notifier)notification.getNewValue();
if (newValue != null)
{
addAdapter(newValue);
}
break;
}
case Notification.ADD:
{
Notifier newValue = (Notifier)notification.getNewValue();
if (newValue != null)
{
addAdapter(newValue);
}
break;
}
case Notification.ADD_MANY:
{
@SuppressWarnings("unchecked") Collection<Notifier> newValues = (Collection<Notifier>)notification.getNewValue();
for (Notifier newValue : newValues)
{
addAdapter(newValue);
}
break;
}
case Notification.REMOVE:
{
Notifier oldValue = (Notifier)notification.getOldValue();
if (oldValue != null)
{
removeAdapter(oldValue);
}
break;
}
case Notification.REMOVE_MANY:
{
@SuppressWarnings("unchecked") Collection<Notifier> oldValues = (Collection<Notifier>)notification.getOldValue();
for ( Notifier oldContentValue : oldValues)
{
removeAdapter(oldContentValue);
}
break;
}
}
}
/**
* Handles installation of the adapter
* by adding the adapter to each of the directly contained objects.
*/
@Override
public void setTarget(Notifier target)
{
if (target instanceof EObject)
{
setTarget((EObject)target);
}
else if (target instanceof Resource)
{
setTarget((Resource)target);
}
else if (target instanceof ResourceSet)
{
setTarget((ResourceSet)target);
}
else
{
basicSetTarget(target);
}
}
/**
* Actually sets the target by calling super.
*/
protected void basicSetTarget(Notifier target)
{
super.setTarget(target);
}
/**
* Handles installation of the adapter on an EObject
* by adding the adapter to each of the directly contained objects.
*/
protected void setTarget(EObject target)
{
basicSetTarget(target);
for (Iterator<? extends Notifier> i = resolve() ?
target.eContents().iterator() :
((InternalEList<? extends Notifier>)target.eContents()).basicIterator();
i.hasNext(); )
{
Notifier notifier = i.next();
addAdapter(notifier);
}
}
/**
* Handles installation of the adapter on a Resource
* by adding the adapter to each of the directly contained objects.
*/
protected void setTarget(Resource target)
{
basicSetTarget(target);
List<EObject> contents = target.getContents();
for (int i = 0, size = contents.size(); i < size; ++i)
{
Notifier notifier = contents.get(i);
addAdapter(notifier);
}
}
/**
* Handles installation of the adapter on a ResourceSet
* by adding the adapter to each of the directly contained objects.
*/
protected void setTarget(ResourceSet target)
{
basicSetTarget(target);
List<Resource> resources = target.getResources();
for (int i = 0; i < resources.size(); ++i)
{
Notifier notifier = resources.get(i);
addAdapter(notifier);
}
}
/**
* Handles undoing the installation of the adapter
* by removing the adapter from each of the directly contained objects.
*/
@Override
public void unsetTarget(Notifier target)
{
unsetTarget((Object)target);
}
/**
* Actually unsets the target by calling super.
*/
protected void basicUnsetTarget(Notifier target)
{
super.unsetTarget(target);
}
/**
* Handles undoing the installation of the adapter
* by removing the adapter from each of the directly contained objects.
* @deprecated Use or override {@link #unsetTarget(Notifier)} instead.
*/
@Deprecated
protected void unsetTarget(Object target)
{
if (target instanceof EObject)
{
unsetTarget((EObject)target);
}
else if (target instanceof Resource)
{
unsetTarget((Resource)target);
}
else if (target instanceof ResourceSet)
{
unsetTarget((ResourceSet)target);
}
else
{
basicUnsetTarget((Notifier)target);
}
}
/**
* Handles undoing the installation of the adapter from an EObject
* by removing the adapter from each of the directly contained objects.
*/
protected void unsetTarget(EObject target)
{
basicUnsetTarget(target);
for (Iterator<? extends Notifier> i = resolve() ?
target.eContents().iterator() :
((InternalEList<EObject>)target.eContents()).basicIterator();
i.hasNext(); )
{
Notifier notifier = i.next();
removeAdapter(notifier);
}
}
/**
* Handles undoing the installation of the adapter from a Resource
* by removing the adapter from each of the directly contained objects.
*/
protected void unsetTarget(Resource target)
{
basicUnsetTarget(target);
List<EObject> contents = target.getContents();
for (int i = 0, size = contents.size(); i < size; ++i)
{
Notifier notifier = contents.get(i);
removeAdapter(notifier);
}
}
/**
* Handles undoing the installation of the adapter from a ResourceSet
* by removing the adapter from each of the directly contained objects.
*/
protected void unsetTarget(ResourceSet target)
{
basicUnsetTarget(target);
List<Resource> resources = target.getResources();
for (int i = 0; i < resources.size(); ++i)
{
Notifier notifier = resources.get(i);
removeAdapter(notifier);
}
}
protected void addAdapter(Notifier notifier)
{
notifier.eAdapters().add(this);
}
protected void removeAdapter(Notifier notifier)
{
notifier.eAdapters().remove(this);
}
protected boolean resolve()
{
return true;
}
}