private void prepareLanes(BPMNElement lane, int level) {
   maxLaneDepth = Math.max(maxLaneDepth, level);
   List<BPMNElement> childs = new ArrayList<BPMNElement>();
   BPMNElement aChild = null;
   for (LayoutingElement c : diagram.getChildElementsOf(lane)) {
     BPMNElement child = (BPMNElement) c;
     if (BPMNType.isASwimlane(child.getType())) {
       prepareLanes(child, level + 1);
       childs.add(child);
     }
     aChild = child;
   }
   // Create Grid for lane (=
   // aChild.getParent())
   if (aChild != null) {
     getContextByElement(aChild);
   } else {
     // create empty grid for empty lanes
     // to prevent nullpointer-exception
     GridContext result = new GridContext();
     result.grid = new Grid<BPMNElement>();
     result.startCell = result.grid.getFirstRow().getFirstCell();
     superGrid.add(result.grid);
     parent2Context.put(lane, result);
   }
   lane2LaneChilds.put(lane, childs);
 }
 private GridContext getContextByElement(BPMNElement el) {
   BPMNElement elParent = null;
   if (el != null) {
     elParent = (BPMNElement) el.getParent();
   }
   GridContext result = parent2Context.get(elParent);
   if (result == null) {
     result = new GridContext();
     result.grid = new Grid<BPMNElement>();
     result.startCell = result.grid.getFirstRow().getFirstCell();
     superGrid.add(result.grid);
     parent2Context.put(elParent, result);
   }
   return result;
 }
  /**
   * @param currentElement
   * @param precedingElements
   * @param context
   * @return cellOfElement
   */
  private Cell<BPMNElement> placeElement(
      BPMNElement currentElement, List<LayoutingElement> precedingElements, GridContext context) {
    Cell<BPMNElement> newCell;
    if (precedingElements.isEmpty()) {
      // StartEvents
      context.startCell.setValue(currentElement);
      newCell = context.startCell;
      context.startCell = context.startCell.beneath();
    } else {
      Cell<BPMNElement> leftCell;
      newCell = context.grid.getCellOfItem(currentElement); // not
      // null
      // if
      // join
      if (currentElement.isJoin()) {

        Point tmp;
        boolean splitFound = false;
        BPMNElement split = (BPMNElement) currentElement.prevSplit();
        if (split != null) {
          // get all close splits
          Queue<BPMNElement> splits =
              new PriorityQueue<BPMNElement>(
                  precedingElements.size() / 2, // should be a
                  // good rule of
                  // thumb
                  new BackwardDistanceComperator(currentElement));
          splits.add(split);
          for (LayoutingElement elem : precedingElements) {
            split = (BPMNElement) elem.prevSplit();
            if (split != null && !splits.contains(split)) {
              splits.add(split);
            }
          }
          split = null;
          // get split with most connections
          int maxCon = 0;
          for (BPMNElement target : splits) {
            if (target == currentElement) {
              // beeing my own splits only makes trouble
              continue;
            } else if (target.getParent() != currentElement.getParent()) {

              continue;
            }
            int curCon = 0;
            for (LayoutingElement elem : precedingElements) {
              if (elem.backwardDistanceTo(target) < Integer.MAX_VALUE) {
                curCon++;
              }
            }
            if (curCon > maxCon) {
              maxCon = curCon;
              split = target;
            }
          }
          splitFound = split != null;
        }

        int x = 0;
        int yAcc = 0;
        int yCnt = 0;
        for (LayoutingElement el : precedingElements) {
          BPMNElement elem = (BPMNElement) el;
          tmp = context.grid.find(context.grid.getCellOfItem(elem));
          if (tmp == null) {
            Grid<BPMNElement> preGrid = getContextByElement(elem).grid;
            tmp = preGrid.find(preGrid.getCellOfItem(elem));
            if (tmp == null) {
              tmp = new Point(0, 0);
            }
          } else {
            yAcc += tmp.y;
            yCnt++;
          }
          x = Math.max(x, tmp.x);
        }
        if (splitFound) {

          leftCell = context.grid.getCellOfItem(split).getParent().get(x);
          // set path to split unpackable
          for (Cell<BPMNElement> cCell = leftCell;
              cCell.getValue() != split;
              cCell = cCell.getPrevCell()) {
            cCell.setPackable(false);
          }

        } else {
          if (yCnt == 0) {
            leftCell = context.grid.getFirstRow().above().get(x);
          } else {
            leftCell = context.grid.get(yAcc / yCnt).get(x);
          }
        }
        if (newCell != null && newCell.getValue() == currentElement) {
          newCell.setValue(null);
        }
        newCell = leftCell.after();

        // set all incoming pathes unpackable
        for (LayoutingElement e : precedingElements) {
          BPMNElement el = (BPMNElement) e;
          Cell<BPMNElement> target = context.grid.getCellOfItem(el);
          if (target == null) {
            // don't set unpackable in other grids (other edge
            // layout)
            continue;
          }
          Cell<BPMNElement> start = target.getParent().get(x + 1);
          for (Cell<BPMNElement> cCell = start; cCell != target; cCell = cCell.getPrevCell()) {
            cCell.setPackable(false);
          }
        }

        // if not prelayouted
      } else if (newCell == null) {
        BPMNElement preElem = (BPMNElement) precedingElements.get(0);
        leftCell = context.grid.getCellOfItem(preElem);
        if (leftCell == null) {
          Grid<BPMNElement> preGrid = getContextByElement(preElem).grid;
          Cell<BPMNElement> preCell = preGrid.getCellOfItem(preElem);
          if (preCell == null) {
            System.err.println("Cannot find Cell for " + preElem);
          }

          List<Grid<BPMNElement>> grids = superGrid.getGrids();
          Row<BPMNElement> newRow = null;
          if (grids.indexOf(preGrid) < grids.indexOf(context.grid)) {
            newRow = context.grid.addFirstRow();
          } else {
            newRow = context.grid.addLastRow();
          }
          leftCell = newRow.get(Math.max(0, preCell.getParent().find(preCell)));
        }
        newCell = leftCell.after();
      }
      if (newCell.isFilled() && !newCell.getValue().equals(currentElement)) {
        newCell.getParent().insertRowBeneath();
        newCell = newCell.beneath();
      }
      newCell.setValue(currentElement);
    }
    return newCell;
  }