package org.eclipse.uml2.diagram.common.internal.stereo;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
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.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.uml2.diagram.common.stereo.StereotypeListener;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Extension;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.Profile;
import org.eclipse.uml2.uml.UMLPackage;
import org.eclipse.uml2.uml.util.UMLUtil;
public class PackageStereotypeAdapter extends AdapterImpl {
private final StereotypeListener myListener;
public PackageStereotypeAdapter(StereotypeListener listener) {
myListener = listener;
}
@Override
public void setTarget(Notifier newTarget) {
if (newTarget == null) {
for (EObject application : getStereotypeApplications(getTarget())) {
disconnectFromStereotypeApplication(application);
}
}
if (newTarget != null) {
for (EObject application : getStereotypeApplications(newTarget)) {
connectToStereotypeApplication(application);
}
}
super.setTarget(newTarget);
}
private List<EObject> getStereotypeApplications(Object target) {
if (target instanceof Resource) {
Package pakkage = getPackage((Resource) target);
Resource resource = (Resource) target;
List<EObject> result = new LinkedList<EObject>();
for (EObject o : resource.getContents()) {
if (isStereotypeApplication(pakkage, o)) {
result.add(o);
}
}
return result;
}
return Collections.emptyList();
}
public boolean isForListener(StereotypeListener that) {
return myListener == that;
}
@Override
public void notifyChanged(Notification notification) {
if (Notification.ADD == notification.getEventType()) {
Object newValue = notification.getNewValue();
if (newValue != null && newValue instanceof EObject) {
EObject application = (EObject) newValue;
if (isStereotypeApplication(application)) {
connectToStereotypeApplication(application);
}
}
}
if (Notification.REMOVE == notification.getEventType()) {
Object oldValue = notification.getOldValue();
if (oldValue != null && oldValue instanceof EObject) {
EObject application = (EObject) oldValue;
if (isStereotypeApplication(application)) {
disconnectFromStereotypeApplication(application);
}
}
}
}
private boolean isStereotypeApplication(EObject application) {
org.eclipse.uml2.uml.Package pakkage = getPackage((Resource) getTarget());
return isStereotypeApplication(pakkage, application);
}
private Package getPackage(Resource resource) {
return (Package) EcoreUtil.getObjectByType(resource.getContents(), UMLPackage.Literals.PACKAGE);
}
private boolean isStereotypeApplication(Package pakkage, EObject application) {
EList<Profile> profiles = pakkage.getAllAppliedProfiles();
EPackage ePackage = application.eClass().getEPackage();
return profiles.contains(UMLUtil.getProfile(ePackage));
}
private void connectToStereotypeApplication(EObject newEObject) {
newEObject.eAdapters().add(new StereotypeApplicationAdapter(myListener));
}
private void disconnectFromStereotypeApplication(EObject newEObject) {
StereotypeApplicationAdapter forListener = null;
for (Adapter next : newEObject.eAdapters()) {
if (next instanceof StereotypeApplicationAdapter && ((StereotypeApplicationAdapter) next).isForListener(myListener)) {
forListener = (StereotypeApplicationAdapter) next;
break;
}
}
if (forListener != null) {
newEObject.eAdapters().remove(forListener);
}
}
private static class StereotypeApplicationAdapter extends AdapterImpl {
private final StereotypeListener myListener;
public StereotypeApplicationAdapter(StereotypeListener listener) {
myListener = listener;
}
public boolean isForListener(StereotypeListener that) {
return myListener == that;
}
@Override
public void notifyChanged(Notification notification) {
if (Notification.SET == notification.getEventType() && notification.getFeature() instanceof EStructuralFeature) {
EStructuralFeature feature = ((EStructuralFeature) notification.getFeature());
if (feature.getName() != null && feature.getName().startsWith(Extension.METACLASS_ROLE_PREFIX)) {
EObject application = (EObject) getTarget();
Object newValue = notification.getNewValue();
if (newValue != null && newValue instanceof Element) {
myListener.stereotypeApplied((Element) newValue, UMLUtil.getStereotype(application), application);
}
Object oldValue = notification.getOldValue();
if (oldValue != null) {
myListener.stereotypeUnapplied((Element) oldValue, UMLUtil.getStereotype(application));
}
}
}
}
}
}