/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.diagram.ui.custom;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EObject;
import org.teiid.designer.core.notification.util.NotificationUtilities;
import org.teiid.designer.core.transaction.SourcedNotification;
import org.teiid.designer.metamodels.diagram.Diagram;
import org.teiid.designer.metamodels.diagram.DiagramEntity;
import org.teiid.designer.ui.viewsupport.ModelObjectUtilities;
/**
* @since 8.0
*/
public class CustomDiagramNotificationHelper {
private static final int IGNORE = 0;
private static final int ADDED = 1;
private static final int REMOVED = 2;
private static final int CHANGED = 3;
private Notification rootNotification;
private Diagram customDiagram;
// private Object helperSource;
Collection addNotifications;
Collection removeNotifications;
Collection changedNotifications;
Collection movedEObjects;
HashMap undoAddedObjects;
/**
*
* @since 4.2
*/
public CustomDiagramNotificationHelper(Notification notification, Diagram customDiagram, Object source ) {
super();
this.rootNotification = notification;
this.customDiagram = customDiagram;
// helperSource = source;
init();
processNotifications();
}
private void init() {
addNotifications = new ArrayList();
removeNotifications = new ArrayList();
changedNotifications = new ArrayList();
undoAddedObjects = new HashMap();
}
private void processNotifications() {
// Let's check if the notification is sourced or not
if (rootNotification instanceof SourcedNotification) {
Collection notifications = ((SourcedNotification)rootNotification).getNotifications();
Iterator iter = notifications.iterator();
while (iter.hasNext()) {
// Process notification so it get's in a list or ignored.
processNotification((Notification)iter.next());
}
} else {
// Process notification so it get's in a list or ignored.
processNotification(rootNotification);
}
processForMoves();
}
private void processNotification(Notification notification) {
switch( getNotificationType(notification) ) {
case ADDED: {
if(!preProcessAddNofication(notification))
addNotifications.add(notification);
} break;
case REMOVED: {
if( !preProcessRemoveNofication(notification))
removeNotifications.add(notification);
} break;
case CHANGED: {
changedNotifications.add(notification);
} break;
case IGNORE:
default: {
}
}
}
private int getNotificationType(Notification notification) {
if (NotificationUtilities.isAdded(notification)) {
return ADDED;
} else if (NotificationUtilities.isRemoved(notification)) {
return REMOVED;
} else if (NotificationUtilities.isChanged(notification)) {
return CHANGED;
}
return IGNORE;
}
/*
* This method looks at add and remove lists, and when there is a match, we assume that the object has been moved and not
* added or deleted. In this case we remove the notifications from add and remove lists, then add the eObject to the move list.
*/
private void processForMoves() {
if( !addNotifications.isEmpty() && !removeNotifications.isEmpty() ) {
Collection tempAdds = new ArrayList(addNotifications);
Collection tempRemoves = new ArrayList(removeNotifications);
movedEObjects = new ArrayList();
Notification removeNotification = null;
Iterator iter = tempRemoves.iterator();
// Now look at each notification, and see if there is a corresponding "Added" eObject;
while( iter.hasNext() ) {
removeNotification = (Notification)iter.next();
Notification addedNotification = null;
// If so, then let's treat this as a move.
EObject[] oldChildren = NotificationUtilities.getRemovedChildren(removeNotification);
for(int i=0; i<oldChildren.length; i++ ) {
addedNotification = getAddedNotification(oldChildren[i], tempAdds);
if( addedNotification != null )
break;
}
if( addedNotification != null ) {
removeNotifications.remove(removeNotification);
addNotifications.remove(addedNotification);
for(int i=0; i<oldChildren.length; i++ )
movedEObjects.add(oldChildren[i]);
}
}
}
}
private Notification getAddedNotification(EObject eObj, Collection addList) {
String targetID = ModelObjectUtilities.getUuid(eObj);
Iterator iter = addList.iterator();
Notification nextNotification = null;
String newChildID = null;
while( iter.hasNext() ) {
nextNotification = (Notification)iter.next();
EObject[] newChildren = NotificationUtilities.getAddedChildren(nextNotification);
for(int i=0; i<newChildren.length; i++ ) {
newChildID = ModelObjectUtilities.getUuid(newChildren[i]);
if( targetID != null && targetID.equals(newChildID)) {
return nextNotification;
}
}
}
return null;
}
/**
* This method looks at an add notification, checks to see if any of the added children also have
* an accompanying diagram entity added that's diagram is this custom diagram. If so, we add these children to the undoAddNotifications list
* so the are processed diffently.
* @param notification
* @return true if added children are also in
* @since 4.2
*/
private boolean preProcessAddNofication(Notification notification) {
// Get the added children
EObject[] newChildren = NotificationUtilities.getAddedChildren(notification);
// See if any of them have a associationed "added Diagram Entity"
for(int i=0; i<newChildren.length; i++ ) {
if( newChildren[i] instanceof DiagramEntity)
return true;
else if( wasDiagramEntityAdded(newChildren[i])) {
if( undoAddedObjects.get(newChildren[i]) == null )
undoAddedObjects.put(newChildren[i], "x"); //$NON-NLS-1$$
return true;
}
}
return false;
}
/**
* This method looks at an add notification, checks to see if any of the added children also have
* an accompanying diagram entity added that's diagram is this custom diagram. If so, we add these children to the undoAddNotifications list
* so the are processed diffently.
* @param notification
* @return true if added children are also in
* @since 4.2
*/
private boolean preProcessRemoveNofication(Notification notification) {
// Get the added children
EObject[] oldChildren = NotificationUtilities.getRemovedChildren(notification);
// See if any of them have a associationed "added Diagram Entity"
for(int i=0; i<oldChildren.length; i++ ) {
if( oldChildren[i] instanceof DiagramEntity)
return true;
}
return false;
}
private boolean wasDiagramEntityAdded(EObject eObj) {
String targetID = ModelObjectUtilities.getUuid(eObj);
// Need to walk through the whole notification list
if (rootNotification instanceof SourcedNotification) {
Notification nextNotification = null;
Collection notifications = ((SourcedNotification)rootNotification).getNotifications();
Iterator iter = notifications.iterator();
while (iter.hasNext()) {
nextNotification = (Notification)iter.next();
// Process notification so it get's in a list or ignored.
if( getNotificationType(nextNotification) == ADDED ) {
EObject[] newChildren = NotificationUtilities.getAddedChildren(nextNotification);
for(int i=0; i<newChildren.length; i++ ) {
if( newChildren[i] instanceof DiagramEntity ){
Diagram deDiagram = ((DiagramEntity)newChildren[i]).getDiagram();
if( deDiagram != null && deDiagram == customDiagram ) {
EObject modelObject = ((DiagramEntity)newChildren[i]).getModelObject();
if( modelObject != null && modelObject == eObj)
return true;
}
}
}
}
}
} else {
// Process notification so it get's in a list or ignored.
if( getNotificationType(rootNotification) == ADDED ) {
EObject[] newChildren = NotificationUtilities.getAddedChildren(rootNotification);
String newChildID = null;
for(int i=0; i<newChildren.length; i++ ) {
if( newChildren[i] instanceof DiagramEntity ) {
EObject modelObject = ((DiagramEntity)newChildren[i]).getModelObject();
if( modelObject != null )
newChildID = ModelObjectUtilities.getUuid(newChildren[i]);
}
if( newChildID != null && targetID != null && targetID.equals(newChildID)) {
return true;
}
}
}
}
return false;
}
public Collection getAddNotifications() {
if( addNotifications == null || addNotifications.isEmpty() )
return Collections.EMPTY_LIST;
return this.addNotifications;
}
public Collection getChangedNotifications() {
if( changedNotifications == null || changedNotifications.isEmpty() )
return Collections.EMPTY_LIST;
return this.changedNotifications;
}
public Collection getMovedEObjects() {
if( movedEObjects == null || movedEObjects.isEmpty() )
return Collections.EMPTY_LIST;
return this.movedEObjects;
}
public Collection getRemoveNotifications() {
if( removeNotifications == null || removeNotifications.isEmpty() )
return Collections.EMPTY_LIST;
return this.removeNotifications;
}
public Collection getUndoAddedEObjects() {
if( undoAddedObjects == null || undoAddedObjects.isEmpty() )
return Collections.EMPTY_LIST;
return new ArrayList(this.undoAddedObjects.keySet());
}
}