/*
* Copyright (c) 2006, 2009 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:
* Artem Tikhomirov (Borland) - initial API and implementation
*/
package org.eclipse.gmf.internal.bridge.wizards.pages;
import java.util.LinkedList;
import org.eclipse.gmf.gmfgraph.Canvas;
import org.eclipse.gmf.gmfgraph.Connection;
import org.eclipse.gmf.gmfgraph.DiagramLabel;
import org.eclipse.gmf.gmfgraph.Node;
import org.eclipse.gmf.mappings.LinkMapping;
import org.eclipse.gmf.mappings.NodeMapping;
/**
* FIXME lookup idea doesn't seem to apply well to obtain canvas elements for a mapping element, e.g. when we need to pick a Node
* for a NodeMapping with few LabelMappings
* @author artem
*/
public class GraphDefLookup {
private final Canvas myCanvas;
public GraphDefLookup(Canvas canvas) {
myCanvas = canvas;
}
public Node findSuitableNode(NodeMapping nm) {
if (myCanvas.getNodes().isEmpty()) {
return null;
}
LinkedList<Node> candidateNodes = new LinkedList<Node>();
if (nm.getDomainMetaElement() != null) {
String name = nm.getDomainMetaElement().getName();
for (Node n : myCanvas.getNodes()) {
if (n.getName() != null && n.getName().indexOf(name) >= 0) {
candidateNodes.add(n);
}
}
}
if (candidateNodes.isEmpty()) {
candidateNodes.addAll(myCanvas.getNodes());
}
if (candidateNodes.size() == 1) {
return candidateNodes.getFirst();
}
if (nm.getLabelMappings().isEmpty()) {
L1: for (Node n : candidateNodes) {
for (DiagramLabel dl : myCanvas.getLabels()) {
if (n.getFigure().getAccessors().contains(dl.getAccessor())) {
// one of node's accessors is referenced for a label, however,
// mapping being processed doesn't need any, hence go to next node
continue L1;
}
}
return n;
}
} else {
Node candidateWithLessLabels= null, candidateWithMoreLabels = null;
for (Node n : candidateNodes) {
if (n.getFigure().getAccessors().size() >= nm.getLabelMappings().size()) {
LinkedList<DiagramLabel> labels = collectAccessingLabels(n);
if (labels.isEmpty()) {
continue;
}
// perfect match, same number of labels as labelMappings
if (labels.size() == nm.getLabelMappings().size()) {
return n;
}
if (labels.size() > nm.getLabelMappings().size() && candidateWithMoreLabels == null) {
candidateWithMoreLabels = n;
}
if (labels.size() < nm.getLabelMappings().size() && candidateWithLessLabels == null) {
candidateWithLessLabels = n;
}
}
}
if (candidateWithMoreLabels != null) {
return candidateWithMoreLabels;
}
if (candidateWithLessLabels != null && findFloatingLabel() != null) {
// take the one with less labels *only* if there's spare descriptor for a floating label
return candidateWithLessLabels;
}
// else - fall through, to get any
}
return candidateNodes.get(0); // take any
}
// canvas.labels->select(l | n.figure.accessors.contains(l))
private LinkedList<DiagramLabel> collectAccessingLabels(Node n) {
LinkedList<DiagramLabel> labels = new LinkedList<DiagramLabel>();
for (DiagramLabel l : myCanvas.getLabels()) {
if (l.getFigure() == n.getFigure() && n.getFigure().getAccessors().contains(l.getAccessor())) {
labels.add(l);
}
}
return labels;
}
private DiagramLabel findFloatingLabel() {
for (DiagramLabel dl : myCanvas.getLabels()) {
if (dl.getAccessor() != null) {
continue; // XXX actually, not sure if a label can't use accessor, even if standalone
}
// XXX again, not sure if next check is reasonable, idea is to avoid labels that share a figure with some node
for (Node n : myCanvas.getNodes()) {
if (n.getFigure() == dl.getFigure()) {
continue;
}
}
return dl;
}
return null;
}
public void assignLabels(NodeMapping nm, Node n) {
if (n == null || n.getFigure().getAccessors().isEmpty() || nm.getLabelMappings().isEmpty()) {
return;
}
LinkedList<DiagramLabel> labels = collectAccessingLabels(n);
for(int i = 0; i < nm.getLabelMappings().size(); i++) {
DiagramLabel l = !labels.isEmpty() ? labels.removeFirst() : findFloatingLabel();
nm.getLabelMappings().get(i++).setDiagramLabel(l);
}
}
public Connection findSuitableLink(LinkMapping lm) {
if (myCanvas.getConnections().isEmpty()) {
return null;
}
String name = null;
if (lm.getDomainMetaElement() != null) {
name = lm.getDomainMetaElement().getName();
} else if (lm.getLinkMetaFeature() != null) {
name = lm.getLinkMetaFeature().getEContainingClass().getName();
}
for (Connection c : myCanvas.getConnections()) {
if (c.getName() != null && c.getName().indexOf(name) >= 0) {
return c;
}
}
return myCanvas.getConnections().get(0);
}
public void assignLabels(LinkMapping lm, Connection c) {
if (c == null || lm.getLabelMappings().isEmpty()) {
return;
}
DiagramLabel floating = findFloatingLabel();
for (int i = 0; i < lm.getLabelMappings().size(); i++) {
lm.getLabelMappings().get(i).setDiagramLabel(floating);
}
}
}