/**
* Copyright (c) 2006 Borland Software Corporation
*
* 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:
* bblajer - initial API and implementation
*/
package org.eclipse.gmf.runtime.lite.edit.parts.update.canonical;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.gmf.runtime.lite.commands.CreateNotationalElementCommand;
import org.eclipse.gmf.runtime.lite.commands.ReconnectNotationalEdgeSourceCommand;
import org.eclipse.gmf.runtime.lite.commands.ReconnectNotationalEdgeTargetCommand;
import org.eclipse.gmf.runtime.lite.commands.RemoveNotationalEdgeCommand;
import org.eclipse.gmf.runtime.lite.commands.ReplaceNotationalElementCommand;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.gmf.runtime.notation.Edge;
import org.eclipse.gmf.runtime.notation.View;
public abstract class OwnedLinksNotationModelRefresher extends AbstractNotationModelRefresher {
private final IViewService myViewService;
public OwnedLinksNotationModelRefresher(IViewService viewService) {
myViewService = viewService;
}
public Command buildRefreshNotationModelCommand() {
List/*<LinkDescriptor>*/ semanticChildLinks = getSemanticChildLinks();
List/*<Edge>*/ notationalChildLinks = getNotationalChildLinks();
if (semanticChildLinks.isEmpty() && notationalChildLinks.isEmpty()) {
return null;
}
final Map semanticToNotationalTypeBasedLinks = new HashMap();
final Map/*<EObject, List<Edge>>*/ semanticToNotationalFeatureBasedLinks = new HashMap();
for(Iterator it = notationalChildLinks.iterator(); it.hasNext(); ) {
Edge next = (Edge) it.next();
EObject nextSemantic = next.getElement();
if (nextSemantic != null) {
semanticToNotationalTypeBasedLinks.put(nextSemantic, next);
} else {
List featureBasedLinksForSource = (List) semanticToNotationalFeatureBasedLinks.get(next.getSource().getElement());
if (featureBasedLinksForSource == null) {
featureBasedLinksForSource = new LinkedList();
semanticToNotationalFeatureBasedLinks.put(next.getSource().getElement(), featureBasedLinksForSource);
}
featureBasedLinksForSource.add(next);
}
}
Diagram parentView = getHost().getDiagram();
CompoundCommand command = new CompoundCommand();
for(Iterator it = semanticChildLinks.iterator(); it.hasNext(); ) {
LinkDescriptor next = (LinkDescriptor) it.next();
EObject nextLinkElement = next.getElement();
Edge currentEdge;
if (nextLinkElement != null) {
currentEdge = (Edge) semanticToNotationalTypeBasedLinks.remove(nextLinkElement);
} else {
List featureBasedLinksForSource = (List) semanticToNotationalFeatureBasedLinks.get(next.getSource());
if (featureBasedLinksForSource == null || featureBasedLinksForSource.isEmpty()) {
currentEdge = null;
} else {
currentEdge = (Edge) featureBasedLinksForSource.remove(0);
}
}
int linkVisualID = next.getVisualID();
if (currentEdge == null) {
if (nextLinkElement == null || shouldCreateView(next)) {
command.appendIfCanExecute(getCreateNotationalElementCommand(next));
}
} else {
boolean changedSource = currentEdge.getSource().getElement() != next.getSource();
boolean changedTarget = currentEdge.getTarget().getElement() != next.getDestination();
boolean changedVID = linkVisualID != getVisualID(currentEdge);
if (!changedSource && !changedTarget) {
if (changedVID) {
CreateNotationalElementCommand notationalCommand = getCreateNotationalElementCommand(next);
if (notationalCommand != null) {
command.appendIfCanExecute(new ReplaceNotationalElementCommand(parentView, notationalCommand, currentEdge));
} else {
command.appendIfCanExecute(new RemoveNotationalEdgeCommand(parentView, currentEdge));
}
}
} else {
if (changedVID) {
command.appendIfCanExecute(new RemoveNotationalEdgeCommand(parentView, currentEdge));
command.appendIfCanExecute(getCreateNotationalElementCommand(next));
} else {
View newSourceView = myViewService.findView(next.getSource());
if (changedSource) {
if (newSourceView != null && isValidLinkSource(newSourceView, next)) {
command.appendIfCanExecute(new ReconnectNotationalEdgeSourceCommand(currentEdge, newSourceView));
} else {
command.appendIfCanExecute(new RemoveNotationalEdgeCommand(currentEdge.getDiagram(), currentEdge));
}
}
View newTargetView = myViewService.findView(next.getDestination());
if (changedTarget) {
if (newTargetView != null && isValidLinkTarget(newTargetView, next)) {
command.appendIfCanExecute(new ReconnectNotationalEdgeTargetCommand(currentEdge, newTargetView));
} else {
command.appendIfCanExecute(new RemoveNotationalEdgeCommand(currentEdge.getDiagram(), currentEdge));
}
}
}
}
}
}
for(Iterator it = semanticToNotationalTypeBasedLinks.values().iterator(); it.hasNext(); ) {
View obsoleteView = (View) it.next();
command.appendIfCanExecute(new RemoveNotationalEdgeCommand(parentView, obsoleteView));
}
for(Iterator it = semanticToNotationalFeatureBasedLinks.values().iterator(); it.hasNext(); ) {
List obsoleteViews = (List) it.next();
for(Iterator obsoleteViewsIt = obsoleteViews.iterator(); obsoleteViewsIt.hasNext(); ) {
View obsoleteView = (View) obsoleteViewsIt.next();
command.appendIfCanExecute(new RemoveNotationalEdgeCommand(parentView, obsoleteView));
}
}
return command.getCommandList().isEmpty() ? null : command;
}
protected abstract List/*<LinkDescriptor>*/ getSemanticChildLinks();
protected abstract List/*<Edge>*/ getNotationalChildLinks();
/**
* Returns whether the given view can be source of the given link.
*/
protected boolean isValidLinkSource(View sourceCandidate, LinkDescriptor linkDescriptor) {
return true;
}
/**
* Returns whether the given view can be source of the given link.
*/
protected boolean isValidLinkTarget(View targetCandidate, LinkDescriptor linkDescriptor) {
return true;
}
}