/**
*
*/
package org.feature.multi.perspective.model.editor.editors;
import java.util.HashSet;
import java.util.Set;
import org.apache.log4j.Logger;
import org.eclipse.core.runtime.Assert;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;
import org.feature.multi.perspective.model.viewmodel.AbstractGroup;
import org.feature.multi.perspective.model.viewmodel.ViewmodelPackage;
import org.feature.multi.perspective.model.viewmodel.CoreGroup;
import org.feature.multi.perspective.model.viewmodel.Group;
import org.feature.multi.perspective.model.viewmodel.ViewPoint;
import org.feature.multi.perspective.model.viewmodel.impl.GroupImpl;
/**
* @author Tim Winkelmann
*
*/
public class ViewPointContentProvider implements ITreeContentProvider {
private static Logger log = Logger.getLogger(ViewPointContentProvider.class);
private Viewer viewer = null;
/** used to display the ViewPoint as root element. */
private ViewPoint rootViewPoint = null;
private Adapter viewPointObserver = new AdapterImpl() {
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.common.notify.impl.AdapterImpl#notifyChanged(org.eclipse.emf.common.notify.Notification)
*/
@Override
public void notifyChanged(Notification msg) {
viewPointChanged(msg);
}
};
private Set<EObject> observedViewPoints = new HashSet<EObject>();
protected void viewPointChanged(Notification msg) {
if (ViewmodelPackage.Literals.VIEW_POINT__CONTAINED_IN_GROUP.equals(msg.getFeature())) {
if (Notification.ADD == msg.getEventType()) {
log.debug("ViewPoint changed.");
addToViewer(msg.getNotifier(), msg.getNewValue());
}
if (Notification.REMOVE == msg.getEventType()) {
removeFromViewer(msg.getNotifier(), msg.getOldValue());
}
}
}
private void addToViewer(final Object parent, final Object newValue) {
Assert.isTrue(viewer instanceof AbstractTreeViewer);
final AbstractTreeViewer atv = (AbstractTreeViewer) viewer;
if (!atv.getControl().isDisposed()) {
atv.getControl().getDisplay().syncExec(new Runnable() {
@Override
public void run() {
if (!atv.getControl().isDisposed()) {
atv.add(parent, newValue);
}
}
});
}
}
private void removeFromViewer(final Object parent, final Object oldValue) {
Assert.isTrue(viewer instanceof AbstractTreeViewer);
final AbstractTreeViewer atv = (AbstractTreeViewer) viewer;
if (!atv.getControl().isDisposed()) {
atv.getControl().getDisplay().syncExec(new Runnable() {
@Override
public void run() {
if (!atv.getControl().isDisposed()) {
atv.remove(parent, new Object[] { oldValue });
}
}
});
}
}
/**
*
*/
private void clearObserver() {
for (EObject group : observedViewPoints) {
group.eAdapters().remove(viewPointObserver);
}
observedViewPoints.clear();
}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
// clear Observer
clearObserver();
this.viewer = viewer;
if (newInput instanceof EObject) {
EObject ebj = (EObject) newInput;
TreeIterator<EObject> eAllContents = ebj.eAllContents();
while (eAllContents.hasNext()) {
EObject eObject = (EObject) eAllContents.next();
observeViewPoint(eObject);
}
}
}
@Override
public Object[] getElements(Object inputElement) {
return getChildren(inputElement);
}
@Override
public Object[] getChildren(Object parentElement) {
if (parentElement instanceof ViewPoint) {
final ViewPoint viewPoint = (ViewPoint) parentElement;
if (rootViewPoint == null || !rootViewPoint.equals(viewPoint)) {
observeViewPoint(viewPoint);
rootViewPoint = viewPoint;
ViewPoint[] viewPoints = new ViewPoint[1];
viewPoints[0] = viewPoint;
return viewPoints;
} else if (viewPoint.getContainedInGroup().isEmpty() && viewPoint.eContainer() instanceof CoreGroup) {
CoreGroup defaultGroupImpl = (CoreGroup) viewPoint.eContainer();
CoreGroup[] coreGroups = new CoreGroup[1];
coreGroups[0] = defaultGroupImpl;
return coreGroups;
} else {
EList<AbstractGroup> groups = viewPoint.getContainedInGroup();
AbstractGroup[] noRedundantGroups = catchSubGroup(groups);
return noRedundantGroups;
}
} else if (parentElement instanceof GroupImpl) {
GroupImpl groupImpl = (GroupImpl) parentElement;
EObject eContainer = groupImpl.eContainer();
EObject[] groups = new EObject[1];
groups[0] = eContainer;
return groups;
} else {
return new Object[0];
}
}
/**
*
* @param eObject
*/
public void observeViewPoint(EObject eObject) {
if (eObject instanceof ViewPoint) {
ViewPoint viewPoint = (ViewPoint) eObject;
if (!observedViewPoints.contains(viewPoint)) {
viewPoint.eAdapters().add(viewPointObserver);
observedViewPoints.add(viewPoint);
}
}
}
/**
* catches unnecessary subgroups and removes them from the array.
*
* @param groups groups to be checked
* @return subset of groups
*/
private AbstractGroup[] catchSubGroup(EList<AbstractGroup> groups) {
Set<AbstractGroup> listOfGroupsToRemove = new HashSet<AbstractGroup>();
for (AbstractGroup group : groups) {
EObject eContainer = group.eContainer();
while (eContainer instanceof AbstractGroup) {
AbstractGroup subGroup = (AbstractGroup) eContainer;
for (AbstractGroup group2 : groups) {
if (group2.getName().equals(subGroup.getName())) {
listOfGroupsToRemove.add(subGroup);
}
}
eContainer = subGroup.eContainer();
}
}
AbstractGroup[] newGroups = new AbstractGroup[groups.size() - listOfGroupsToRemove.size()];
int j = 0;
for (AbstractGroup group : groups) {
if (!listOfGroupsToRemove.contains(group)) {
newGroups[j] = group;
j++;
}
}
return newGroups;
}
@Override
public Object getParent(Object element) {
return null;
}
@Override
public boolean hasChildren(Object element) {
return getChildren(element).length > 0;
}
@Override
public void dispose() {
clearObserver();
}
}