/**
   * Updates all coordinates
   *
   * @todo Optimise. Some info can be cached
   * @todo Handle m:n (leftY/rightY etc)
   */
  public void update() {
    /*
     *  int leftY = _leftTable.getY() + _leftTable.getColumnY(_leftRole.getColumnMap().getPrimaryKey());
     *  int rightY;
     *  if (!_leftRole.getRelation().isMany2Many()) {
     *  rightY = _rightTable.getY() + _rightTable.getColumnY(_leftRole.getColumnMap().getForeignKey());
     *  }
     *  else {
     *  rightY = _rightTable.getY() + _rightTable.getColumnY(_rightRole.getColumnMap().getPrimaryKey());
     *  }
     */
    int leftY = _leftTable.getY() + _leftColumnY;
    int rightY = _rightTable.getY() + _rightColumnY;

    // find out which table is farthest west (and east)
    JTablePanel westTable;
    JTablePanel eastTable;
    int westY;
    int eastY;
    Line2D.Float[] westLines;
    Line2D.Float[] eastLines;
    int[] westEdgeY;
    int[] eastEdgeY;

    _leftIsWest = _leftTable.getX() < _rightTable.getX();

    if (_leftIsWest) {
      westTable = _leftTable;
      eastTable = _rightTable;
      westY = leftY;
      eastY = rightY;
      westLines = _leftLines;
      eastLines = _rightLines;
      westEdgeY = _leftEdgeY;
      eastEdgeY = _rightEdgeY;
    } else {
      westTable = _rightTable;
      eastTable = _leftTable;
      westY = rightY;
      eastY = leftY;
      westLines = _rightLines;
      eastLines = _leftLines;
      westEdgeY = _rightEdgeY;
      eastEdgeY = _leftEdgeY;
    }

    // find out whether the tables are more or less vertically aligned
    boolean aligned = (eastTable.getX() - westTable.getX()) < eastTable.getWidth() / 2;
    // TODO: handle different widths

    int westX;
    if (aligned) {
      westX = westTable.getX() - 10;
      for (int i = 0; i < westEdgeY.length; i++) {
        westLines[i].setLine(westX, westY, westTable.getX(), westEdgeY[i] + westTable.getY());
      }
    } else {
      westX = westTable.getX() + westTable.getWidth() + 10;
      for (int i = 0; i < westEdgeY.length; i++) {
        westLines[i].setLine(
            westX, westY, westTable.getX() + westTable.getWidth(), westEdgeY[i] + westTable.getY());
      }
    }
    int eastX = eastTable.getX() - 10;

    for (int i = 0; i < eastEdgeY.length; i++) {
      eastLines[i].setLine(eastX, eastY, eastTable.getX(), eastEdgeY[i] + eastTable.getY());
    }

    _mainLine.setLine(westX, westY, eastX, eastY);

    setCardinalityPoints();
  }
  /**
   * Creates new RelationLine
   *
   * @todo-javadoc Write javadocs for method parameter
   * @todo-javadoc Write javadocs for method parameter
   * @todo-javadoc Write javadocs for method parameter
   * @todo-javadoc Write javadocs for method parameter
   * @todo-javadoc Write javadocs for method parameter
   * @param leftRole Describe what the parameter does
   * @param rightRole Describe what the parameter does
   * @param leftTable Describe what the parameter does
   * @param rightTable Describe what the parameter does
   */
  public RelationLine(
      RelationshipRole leftRole,
      RelationshipRole rightRole,
      JTablePanel leftTable,
      JTablePanel rightTable) {
    _log.debug(
        "new RelationLine for "
            + leftTable.getTable().getSqlName()
            + "-"
            + rightTable.getTable().getSqlName());
    _leftRole = leftRole;
    _rightRole = rightRole;
    _leftTable = leftTable;
    _rightTable = rightTable;

    // left table points
    _log.debug("A:" + _leftRole.getColumnMaps().length);
    _leftEdgeY = new int[_leftRole.getColumnMaps().length];
    for (int i = 0; i < _leftEdgeY.length; i++) {
      _leftEdgeY[i] = _leftTable.getColumnY(_leftRole.getColumnMaps()[i].getPrimaryKey());
      _leftColumnY += _leftEdgeY[i];
    }
    _leftColumnY = _leftColumnY / _leftEdgeY.length;

    // right table points
    if (!_leftRole.getRelation().isMany2Many()) {
      _log.debug("M:" + _leftRole.getColumnMaps().length);
      _rightEdgeY = new int[_leftRole.getColumnMaps().length];
      for (int i = 0; i < _rightEdgeY.length; i++) {
        _rightEdgeY[i] = _rightTable.getColumnY(_leftRole.getColumnMaps()[i].getForeignKey());
        _rightColumnY += _rightEdgeY[i];
      }
      _rightColumnY = _rightColumnY / _rightEdgeY.length;
    } else {
      _log.debug("B:" + _rightRole.getColumnMaps().length);
      _rightEdgeY = new int[_rightRole.getColumnMaps().length];
      for (int i = 0; i < _rightEdgeY.length; i++) {
        _rightEdgeY[i] = _rightTable.getColumnY(_rightRole.getColumnMaps()[i].getPrimaryKey());
        _rightColumnY += _rightEdgeY[i];
      }
      _rightColumnY = _rightColumnY / _rightRole.getColumnMaps().length;
    }

    _leftLines = createLines(_leftEdgeY.length);
    _rightLines = createLines(_rightEdgeY.length);

    _mainLine = new Line2D.Float();

    _leftCardinalityPoint = new Point2D.Float();
    _rightCardinalityPoint = new Point2D.Float();

    _leftFkPoint = new Point2D.Float();
    _rightFkPoint = new Point2D.Float();

    _leftArrowPoint = new Point2D.Float();
    _rightArrowPoint = new Point2D.Float();

    _leftArrowLine1 = new Line2D.Float();
    _leftArrowLine2 = new Line2D.Float();
    _rightArrowLine1 = new Line2D.Float();
    _rightArrowLine2 = new Line2D.Float();
    _leftArrowPoint1 = new Point2D.Float();
    _leftArrowPoint2 = new Point2D.Float();
    _rightArrowPoint1 = new Point2D.Float();
    _rightArrowPoint2 = new Point2D.Float();
    _temp = new Point2D.Float();
    _arrowTransform = new AffineTransform();
  }