private void sortOutlineNodes(TreeMap<Integer, OutlineNode<?>> nodesToProcess, int level) {
    if (nodesToProcess.isEmpty()) {
      return;
    }

    int currentLine = -1;
    for (; ; ) {

      final Map.Entry<Integer, OutlineNode<?>> currentEntry =
          nodesToProcess.higherEntry(currentLine);
      if (currentEntry == null) {
        break;
      }
      final int currentNodeLevel = currentEntry.getValue().getLevel();
      if (currentNodeLevel > level) {
        currentLine = currentEntry.getKey();
      } else if (currentNodeLevel < level) {
        // was already processed; process its children
        sortOutlineNodes(currentEntry.getValue().getContentMap(), level);
        currentLine = currentEntry.getKey();
      } else {
        final OutlineNode<?> currentNode = currentEntry.getValue();
        int continueAfter = currentNode.createContentMap(nodesToProcess);
        nodesToProcess.keySet().removeAll(currentNode.getContentMap().keySet());
        currentLine = continueAfter;
      }
    }
  }
 private void sortOutlineNodes() {
   for (int level = 1; level <= configuration.getNumberOfLevels(); level++) {
     sortOutlineNodes(outlineNodesMap, level);
     //			System.out.println("--- Outline nodes map after sorting at level " + level + " ---");
     //			dumpOutlineNodesMap();
   }
   OutlineNode.createTreePositions(null, outlineNodesMap);
 }
  public TreeNode[] getTreeNodesAsArray() {
    if (outlineNodesMap.isEmpty()) {
      return new TreeNode[0];
    }

    final List<TreeNode> treeNodes = new ArrayList<>();
    for (OutlineNode<? extends OutlineNodeContent> outlineNode : outlineNodesMap.values()) {
      TreeNode tn = outlineNode.createTreeNode(this);
      if (tn != null && !tn.isEmpty()) {
        tn.removeEmptyChildren();
        treeNodes.add(tn);
      }
    }

    TreeNode.removeEmptyRoots(treeNodes, null);

    // System.out.println("Tree nodes:");
    // dumpTreeNodes(treeNodes, 0);

    return treeNodes.toArray(new TreeNode[0]);
  }