diff options
Diffstat (limited to 'plugins/core/org.eclipse.xtext.gmf.glue/src/org/eclipse/xtext/gmf/glue/editingdomain/ChangeAggregatorAdapter.java')
-rw-r--r-- | plugins/core/org.eclipse.xtext.gmf.glue/src/org/eclipse/xtext/gmf/glue/editingdomain/ChangeAggregatorAdapter.java | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/plugins/core/org.eclipse.xtext.gmf.glue/src/org/eclipse/xtext/gmf/glue/editingdomain/ChangeAggregatorAdapter.java b/plugins/core/org.eclipse.xtext.gmf.glue/src/org/eclipse/xtext/gmf/glue/editingdomain/ChangeAggregatorAdapter.java new file mode 100644 index 00000000000..c6279d42563 --- /dev/null +++ b/plugins/core/org.eclipse.xtext.gmf.glue/src/org/eclipse/xtext/gmf/glue/editingdomain/ChangeAggregatorAdapter.java @@ -0,0 +1,163 @@ +/******************************************************************************* + * Copyright (c) 2009 itemis AG (http://www.itemis.eu) 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 + *******************************************************************************/ +package org.eclipse.xtext.gmf.glue.editingdomain; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.eclipse.emf.common.notify.Notification; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.util.EContentAdapter; +import org.eclipse.xtext.resource.XtextResource; + +import com.google.common.collect.Lists; + +/** + * @author Knut Wannheden - Initial contribution and API + * @author Jan Koehnlein + */ +public class ChangeAggregatorAdapter extends EContentAdapter { + + private Collection<EObject> modifiedObjects = new LinkedHashSet<EObject>(); + + private boolean isRecording = false; + + private boolean isSuspended = false; + + @Override + public void notifyChanged(Notification notification) { + super.notifyChanged(notification); + + if (!doRecord(notification)) + return; + + if (notification.getNotifier() instanceof EObject) { + recordObjectModification((EObject) notification.getNotifier()); + } + } + + protected void recordObjectModification(EObject obj) { + if (obj.eResource() == null || false == obj.eResource() instanceof XtextResource) + modifiedObjects.remove(obj); + else + modifiedObjects.add(obj); + } + + protected boolean doRecord(Notification notification) { + if (!isRecording || isSuspended || notification.isTouch()) + return false; + + switch (notification.getEventType()) { + case Notification.ADD: + case Notification.ADD_MANY: + case Notification.MOVE: + case Notification.REMOVE: + case Notification.REMOVE_MANY: + case Notification.SET: + case Notification.UNSET: + return true; + default: + return false; + } + } + + private void reset() { + modifiedObjects.clear(); + } + + /** + * This element comes from the XText/GMF integration example, and was not originally documented. + */ + public void beginRecording() { + reset(); + isRecording = true; + } + + /** + * This element comes from the XText/GMF integration example, and was not originally documented. + */ + public void endRecording() { + isRecording = false; + } + + /** + * This element comes from the XText/GMF integration example, and was not originally documented. + * @param isSuspended + */ + public void setSuspended(boolean isSuspended) { + this.isSuspended = isSuspended; + } + + /** + * This element comes from the XText/GMF integration example, and was not originally documented. + * @return List<EOject> + */ + public List<EObject> getModificationRoots() { + Map<Resource, List<EObject>> resource2ChangePathMap = new HashMap<Resource, List<EObject>>(); + for (EObject eObject : modifiedObjects) { + if (!eObject.eIsProxy()) { + Resource resource = eObject.eResource(); + List<EObject> resourceChangePath = resource2ChangePathMap.get(resource); + if (resourceChangePath == null) { + resourceChangePath = allContainers(eObject); + resource2ChangePathMap.put(resource, resourceChangePath); + } else { + resourceChangePath.retainAll(allContainers(eObject)); + } + } + } + List<EObject> modificationRoots = new ArrayList<EObject>(resource2ChangePathMap.size()); + for (List<EObject> changePath : resource2ChangePathMap.values()) { + if (!changePath.isEmpty()) { + modificationRoots.add(changePath.get(changePath.size() - 1)); + } + } + return modificationRoots; + } + + private LinkedList<EObject> allContainers(EObject eObject) { + final LinkedList<EObject> allContainers = Lists.newLinkedList(); + allContainers.add(eObject); + EObject currentContainer = eObject.eContainer(); + final Resource resource = eObject.eResource(); + while (currentContainer != null && resource == currentContainer.eResource()) { + allContainers.addFirst(currentContainer); + currentContainer = currentContainer.eContainer(); + } + return allContainers; + } + + /** + * Only attach to XtextResources + */ + @Override + protected void setTarget(Resource target) { + if (target instanceof XtextResource) { + super.setTarget(target); + } + } + + @Override + protected void setTarget(EObject target) { + if (target.eResource() instanceof XtextResource) { + super.setTarget(target); + } + } + + @Override + public boolean isAdapterForType(Object type) { + return type == ChangeAggregatorAdapter.class; + } + +}
\ No newline at end of file |