/*
* 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.mapping.ui.connection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.emf.ecore.EObject;
import org.teiid.designer.diagram.ui.connection.AnchorManager;
import org.teiid.designer.diagram.ui.connection.NodeConnectionAnchor;
import org.teiid.designer.diagram.ui.connection.NodeConnectionEditPart;
import org.teiid.designer.diagram.ui.model.DiagramModelNode;
import org.teiid.designer.diagram.ui.notation.uml.model.UmlClassifierNode;
import org.teiid.designer.diagram.ui.part.DiagramEditPart;
import org.teiid.designer.mapping.ui.model.MappingExtentNode;
import org.teiid.designer.mapping.ui.part.MappingDiagramEditPart;
import org.teiid.designer.mapping.ui.part.MappingExtentEditPart;
import org.teiid.designer.transformation.util.TransformationHelper;
/**
* AnchorManager
*
* @since 8.0
*/
public class MappingClassAnchorManager implements AnchorManager {
private List eastAnchors;
private List westAnchors;
private List southAnchors;
private DiagramEditPart diagramEditPart;
/**
* Construct an instance of AnchorManager.
*/
public MappingClassAnchorManager( DiagramEditPart diagramEditPart ) {
this.diagramEditPart = diagramEditPart;
init();
}
private void init() {
}
private boolean isCoarse() {
MappingDiagramEditPart diagramEP = (MappingDiagramEditPart)diagramEditPart.getParent();
return diagramEP.isCoarseMapping();
}
private boolean isPrimary() {
MappingDiagramEditPart diagramEP = (MappingDiagramEditPart)diagramEditPart.getParent();
return diagramEP.isPrimary(diagramEditPart);
}
private boolean isInputSet() {
if (!isCoarse()) {
EObject eObj = diagramEditPart.getModelObject();
if (TransformationHelper.isSqlInputSet(eObj)) {
return true;
}
}
return false;
}
/**
* @return
*/
private List getEastAnchors() {
return eastAnchors;
}
/**
* @return
*/
private List getWestAnchors() {
return westAnchors;
}
/**
* @return
*/
private List getSouthAnchors() {
return southAnchors;
}
/**
* @param newAnchor
*/
private boolean addEastAnchor( NodeConnectionAnchor newAnchor ) {
if (eastAnchors == null) eastAnchors = new ArrayList(1);
if (!containsEquivalentAnchor(eastAnchors, newAnchor)) {
eastAnchors.add(newAnchor);
return true;
}
return false;
}
/**
* @param newAnchor
*/
private boolean addWestAnchor( NodeConnectionAnchor newAnchor ) {
if (westAnchors == null) westAnchors = new ArrayList(1);
if (!containsEquivalentAnchor(westAnchors, newAnchor)) {
westAnchors.add(newAnchor);
return true;
}
return false;
}
/**
* @param newAnchor
*/
private boolean addSouthAnchor( NodeConnectionAnchor newAnchor ) {
if (southAnchors == null) southAnchors = new ArrayList(1);
if (!containsEquivalentAnchor(southAnchors, newAnchor)) {
southAnchors.add(newAnchor);
return true;
}
return false;
}
private boolean containsEquivalentAnchor( List list,
NodeConnectionAnchor newAnchor ) {
if (eastAnchors == null) eastAnchors = new ArrayList(1);
Iterator it = list.iterator();
while (it.hasNext()) {
NodeConnectionAnchor ncaTemp = (NodeConnectionAnchor)it.next();
if (ncaTemp.equals(newAnchor)) {
return true;
}
}
return false;
}
@Override
public boolean add( NodeConnectionAnchor targetAnchor ) {
boolean added = false;
if (targetAnchor.getDirection() == EAST) {
added = addEastAnchor(targetAnchor);
} else if (targetAnchor.getDirection() == WEST) {
added = addWestAnchor(targetAnchor);
} else if (targetAnchor.getDirection() == SOUTH) {
added = addSouthAnchor(targetAnchor);
}
return added;
}
@Override
public boolean move( NodeConnectionAnchor targetAnchor ) {
// Need to move the target anchor from one anchor list to another.
// remove from any list.
boolean removed = remove(targetAnchor);
// Now add to direction's list
boolean added = add(targetAnchor);
if (removed && added) return true;
return false;
}
@Override
public boolean remove( NodeConnectionAnchor targetAnchor ) {
boolean removed = false;
if (targetAnchor.getDirection() != EAST && getEastAnchors() != null && getEastAnchors().contains(targetAnchor)) {
getEastAnchors().remove(targetAnchor);
removed = true;
}
if (targetAnchor.getDirection() != WEST && getWestAnchors() != null && getWestAnchors().contains(targetAnchor)) {
getWestAnchors().remove(targetAnchor);
removed = true;
}
if (targetAnchor.getDirection() != SOUTH && getSouthAnchors() != null && getSouthAnchors().contains(targetAnchor)) {
getSouthAnchors().remove(targetAnchor);
removed = true;
}
return removed;
}
@Override
public void resetSourceAnchors( boolean updateTargetEnd ) {
cleanUpAnchors();
List sConnections = getSourceConnections();
if (sConnections.isEmpty()) {
return;
}
NodeConnectionEditPart nextConnection = null;
Iterator iter = sConnections.iterator();
DiagramEditPart targetEditPart = null;
NodeConnectionAnchor sourceAnchor = null;
while (iter.hasNext()) {
nextConnection = (NodeConnectionEditPart)iter.next();
sourceAnchor = (NodeConnectionAnchor)nextConnection.getSourceAnchor();
targetEditPart = (DiagramEditPart)nextConnection.getTarget();
if (targetEditPart != null) {
setSourceAnchorPosition(sourceAnchor, targetEditPart);
nextConnection.refresh();
// Update Target side anchors
if (updateTargetEnd) targetEditPart.createOrUpdateAnchorsLocations(false);
}
}
}
@Override
public void resetTargetAnchors( boolean updateSourceEnd ) {
cleanUpAnchors();
List tConnections = getTargetConnections();
if (tConnections.isEmpty()) return;
NodeConnectionEditPart nextConnection = null;
Iterator iter = tConnections.iterator();
DiagramEditPart sourceEditPart = null;
NodeConnectionAnchor targetAnchor = null;
while (iter.hasNext()) {
nextConnection = (NodeConnectionEditPart)iter.next();
targetAnchor = (NodeConnectionAnchor)nextConnection.getTargetAnchor();
sourceEditPart = (DiagramEditPart)nextConnection.getSource();
if (sourceEditPart != null) {
setAnchorPosition(targetAnchor, EAST);
nextConnection.refresh();
// Update Source side anchors
if (updateSourceEnd) sourceEditPart.createOrUpdateAnchorsLocations(false);
}
}
}
/**
* @return
*/
@Override
public List getSourceConnections() {
return diagramEditPart.getSourceConnections();
}
/**
* @return
*/
@Override
public List getTargetConnections() {
return diagramEditPart.getTargetConnections();
}
/**
* @return
*/
@Override
public ConnectionAnchor getSourceAnchor( NodeConnectionEditPart connection ) {
// This anchor manager belongs to the edit part.
// This edit part knows about all it's target connections
// An anchor is either target or source
//
if (connection.getSourceAnchor() == null) {
// Create a anchor for it.
NodeConnectionAnchor newAnchor = createSourceAnchor();
connection.setSourceAnchor(newAnchor);
return newAnchor;
}
return connection.getSourceAnchor();
}
/**
* @return
*/
@Override
public ConnectionAnchor getTargetAnchor( NodeConnectionEditPart connection ) {
// This anchor manager belongs to the edit part.
// This edit part knows about all it's target connections
// An anchor is either target or source
//
if (connection.getTargetAnchor() == null) {
// Create a anchor for it.
NodeConnectionAnchor newAnchor = createTargetAnchor();
connection.setTargetAnchor(newAnchor);
return newAnchor;
}
return connection.getTargetAnchor();
}
private NodeConnectionAnchor createTargetAnchor() {
NodeConnectionAnchor newAnchor = new NodeConnectionAnchor(diagramEditPart.getFigure(), NodeConnectionAnchor.IS_TARGET);
// Set some default direction
newAnchor.setDirection(EAST);
add(newAnchor);
return newAnchor;
}
private NodeConnectionAnchor createSourceAnchor() {
NodeConnectionAnchor newAnchor = new NodeConnectionAnchor(diagramEditPart.getFigure(), NodeConnectionAnchor.IS_SOURCE);
// Set some default direction
newAnchor.setDirection(WEST);
add(newAnchor);
return newAnchor;
}
@Override
public boolean hasSourceAnchors() {
NodeConnectionAnchor nextAnchor = null;
Iterator iter = null;
if (eastAnchors != null && !eastAnchors.isEmpty()) {
iter = eastAnchors.iterator();
while (iter.hasNext()) {
nextAnchor = (NodeConnectionAnchor)iter.next();
if (nextAnchor != null && nextAnchor.isSource()) return true;
}
}
if (westAnchors != null && !westAnchors.isEmpty()) {
iter = westAnchors.iterator();
while (iter.hasNext()) {
nextAnchor = (NodeConnectionAnchor)iter.next();
if (nextAnchor != null && nextAnchor.isSource()) return true;
}
}
if (southAnchors != null && !southAnchors.isEmpty()) {
iter = southAnchors.iterator();
while (iter.hasNext()) {
nextAnchor = (NodeConnectionAnchor)iter.next();
if (nextAnchor != null && nextAnchor.isSource()) return true;
}
}
return false;
}
@Override
public boolean hasTargetAnchors() {
NodeConnectionAnchor nextAnchor = null;
Iterator iter = null;
if (eastAnchors != null && !eastAnchors.isEmpty()) {
iter = eastAnchors.iterator();
while (iter.hasNext()) {
nextAnchor = (NodeConnectionAnchor)iter.next();
if (nextAnchor != null && !nextAnchor.isSource()) return true;
}
}
if (westAnchors != null && !westAnchors.isEmpty()) {
iter = westAnchors.iterator();
while (iter.hasNext()) {
nextAnchor = (NodeConnectionAnchor)iter.next();
if (nextAnchor != null && !nextAnchor.isSource()) return true;
}
}
if (southAnchors != null && !southAnchors.isEmpty()) {
iter = southAnchors.iterator();
while (iter.hasNext()) {
nextAnchor = (NodeConnectionAnchor)iter.next();
if (nextAnchor != null && !nextAnchor.isSource()) return true;
}
}
return false;
}
private int getAnchorListId( List anchors,
NodeConnectionAnchor anchor ) {
int id = 0;
Iterator iter = anchors.iterator();
while (iter.hasNext()) {
if (anchor.equals(iter.next())) {
break;
}
id++;
}
return id;
}
private int getAttributeYMidpoint( int id ) {
int yPosition = 0;
UmlClassifierNode classifierNode = (UmlClassifierNode)diagramEditPart.getModel();
if (classifierNode != null && classifierNode.getAttributesContainer() != null) {
int containerY = classifierNode.getAttributesContainer().getY();
// We need to get the Children of this edit part, and get the Container??
List attributes = classifierNode.getAttributes();
if (id < attributes.size()) {
yPosition = ((DiagramModelNode)attributes.get(id)).getCenterY() + containerY;
}
}
return yPosition;
}
private int getAttributeYMidpoint( EObject attributeEObject ) {
int yPosition = 0;
UmlClassifierNode classifierNode = (UmlClassifierNode)diagramEditPart.getModel();
if (classifierNode != null && classifierNode.getAttributesContainer() != null) {
int containerY = classifierNode.getAttributesContainer().getY();
DiagramModelNode attributeNode = getAttributeNode(attributeEObject);
if (attributeNode != null) {
yPosition = attributeNode.getCenterY() + containerY;
}
}
return yPosition;
}
private DiagramModelNode getAttributeNode( EObject attributeEObject ) {
UmlClassifierNode classifierNode = (UmlClassifierNode)diagramEditPart.getModel();
if (classifierNode != null && classifierNode.getAttributesContainer() != null) {
Iterator iter = classifierNode.getAttributes().iterator();
DiagramModelNode nextNode = null;
while (iter.hasNext()) {
nextNode = (DiagramModelNode)iter.next();
if (nextNode.getModelObject() != null && nextNode.getModelObject() == attributeEObject) // nextNode.getModelObject().equals(attributeEObject))
return nextNode;
}
}
return null;
}
@Override
public void setAnchorPosition( NodeConnectionAnchor theAnchor,
int direction ) {
if (diagramEditPart.getModel() != null) {
Dimension partSize = ((DiagramModelNode)diagramEditPart.getModel()).getSize();
int oldDirection = theAnchor.getDirection();
theAnchor.setDirection(direction);
boolean moved = move(theAnchor);
if (moved) {
setAnchorPositions(oldDirection, direction);
} else if (direction == WEST) {
if (isCoarse()) {
} else {
if (isPrimary()) {
// This is where we make sure that the "WEST" anchor y locations, are matched up with the
// corresponding attribute locations
// there should be one anchor for each attribute.
// Walk through the anchors
int anchorId = getAnchorListId(getWestAnchors(), theAnchor) + 1;
int vOffset = getAttributeYMidpoint(anchorId - 1); // partSize.height/(nAnchors+1);
theAnchor.setOffsetV(vOffset);
theAnchor.setOffsetH(0);
} else {
theAnchor.setOffsetH(0);
theAnchor.setOffsetV(partSize.height / 2);
}
}
} else {
theAnchor.setOffsetH(partSize.width);
theAnchor.setOffsetV(partSize.height / 2);
}
}
}
public void setSourceAnchorPosition( NodeConnectionAnchor theAnchor,
DiagramEditPart targetEditPart ) {
if (diagramEditPart.getModel() != null) {
Dimension partSize = ((DiagramModelNode)diagramEditPart.getModel()).getSize();
theAnchor.setDirection(WEST);
if (isCoarse()) {
} else {
if (isPrimary() && targetEditPart instanceof MappingExtentEditPart) {
EObject targetEObject = ((MappingExtentNode)targetEditPart.getModel()).getExtent().getMappingReference();
// This is where we make sure that the "WEST" anchor y locations, are matched up with the
// corresponding attribute locations
// there should be one anchor for each attribute.
// Walk through the anchors
int vOffset = getAttributeYMidpoint(targetEObject); // partSize.height/(nAnchors+1);
theAnchor.setOffsetV(vOffset);
theAnchor.setOffsetH(0);
} else if (isInputSet()) {
theAnchor.setDirection(SOUTH);
theAnchor.setOffsetH(partSize.width / 2);
theAnchor.setOffsetV(partSize.height);
} else {
theAnchor.setOffsetH(0);
theAnchor.setOffsetV(partSize.height / 2);
}
}
}
}
/**
* This method for setting anchor positions assumes that we want to walk through all anchor positions to insure proper
* spacing..... should be called whenever an anchor is "moved" and there are more than to or from.
*
* @param theAnchor
* @param direction
*/
private void setAnchorPositions( int oldDirection,
int newDirection ) {
setAnchorPositions(oldDirection);
setAnchorPositions(newDirection);
}
private void setAnchorPositions( int direction ) {
if (diagramEditPart.getModel() != null) {
Dimension partSize = ((DiagramModelNode)diagramEditPart.getModel()).getSize();
Iterator iter = null;
if (direction == WEST && getWestAnchors() != null && !getWestAnchors().isEmpty()) {
// Walk through the anchors
iter = getWestAnchors().iterator();
NodeConnectionAnchor theAnchor = null;
while (iter.hasNext()) {
theAnchor = (NodeConnectionAnchor)iter.next();
theAnchor.setOffsetH(0);
theAnchor.setOffsetV(0);
}
} else if (getEastAnchors() != null && !getEastAnchors().isEmpty()) {
// Walk through the anchors
iter = getEastAnchors().iterator();
NodeConnectionAnchor theAnchor = null;
while (iter.hasNext()) {
theAnchor = (NodeConnectionAnchor)iter.next();
theAnchor.setOffsetH(partSize.width);
theAnchor.setOffsetV(partSize.height / 2);
}
} else if (getSouthAnchors() != null && !getSouthAnchors().isEmpty()) {
// Walk through the anchors
iter = getSouthAnchors().iterator();
NodeConnectionAnchor theAnchor = null;
while (iter.hasNext()) {
theAnchor = (NodeConnectionAnchor)iter.next();
theAnchor.setOffsetH(partSize.width / 2);
theAnchor.setOffsetV(partSize.height);
}
}
}
}
private void cleanUpAnchors() {
// Get list of all connections and their anchors to this edit part.
List sConnections = getSourceConnections();
List tConnections = getTargetConnections();
List connectionAnchors = new ArrayList(sConnections.size() + tConnections.size());
if (sConnections.isEmpty()) {
// Let's clear out the WEST anchors here.
if (westAnchors != null) westAnchors.clear();
if (southAnchors != null) southAnchors.clear();
} else {
NodeConnectionEditPart nextConnection = null;
Iterator sIter = sConnections.iterator();
while (sIter.hasNext()) {
nextConnection = (NodeConnectionEditPart)sIter.next();
if (nextConnection.getSourceAnchor() != null) connectionAnchors.add(nextConnection.getSourceAnchor());
}
}
if (tConnections.isEmpty()) {
// Let's clear out the WEST anchors here.
if (eastAnchors != null) eastAnchors.clear();
} else {
NodeConnectionEditPart nextConnection = null;
Iterator tIter = tConnections.iterator();
while (tIter.hasNext()) {
nextConnection = (NodeConnectionEditPart)tIter.next();
if (nextConnection.getTargetAnchor() != null) connectionAnchors.add(nextConnection.getTargetAnchor());
}
}
if (!connectionAnchors.isEmpty()) {
List staleAnchors = new ArrayList();
// Walk through each list and gather up list of any anchors not in connections list
Iterator iter = null;
NodeConnectionAnchor nextAnchor = null;
if (westAnchors != null) {
iter = westAnchors.iterator();
while (iter.hasNext()) {
nextAnchor = (NodeConnectionAnchor)iter.next();
if (connectionAnchors.contains(nextAnchor)) {
// Do nothing
} else {
staleAnchors.add(nextAnchor);
}
}
}
if (eastAnchors != null) {
iter = eastAnchors.iterator();
while (iter.hasNext()) {
nextAnchor = (NodeConnectionAnchor)iter.next();
if (connectionAnchors.contains(nextAnchor)) {
// Do nothing
} else {
staleAnchors.add(nextAnchor);
}
}
}
if (southAnchors != null) {
iter = southAnchors.iterator();
while (iter.hasNext()) {
nextAnchor = (NodeConnectionAnchor)iter.next();
if (connectionAnchors.contains(nextAnchor)) {
// Do nothing
} else {
staleAnchors.add(nextAnchor);
}
}
}
// Remove all extra from their lists.
if (!staleAnchors.isEmpty()) {
iter = staleAnchors.iterator();
while (iter.hasNext()) {
nextAnchor = (NodeConnectionAnchor)iter.next();
if (westAnchors != null) westAnchors.remove(nextAnchor);
if (eastAnchors != null) eastAnchors.remove(nextAnchor);
if (southAnchors != null) southAnchors.remove(nextAnchor);
}
}
}
}
/**
* @see org.teiid.designer.diagram.ui.connection.AnchorManager#reorderAllAnchors()
* @since 4.2
*/
@Override
public void reorderAllAnchors( boolean updateBothEnds ) {
resetSourceAnchors(updateBothEnds);
resetTargetAnchors(updateBothEnds);
}
}