public Node node(String path, Integer changesetNumber, String changesetIdentifier) {
   Map<String, String> rawContent = contentCache.readFor(changesetNumber);
   if (!path.equals("") && rawContent.containsKey(path)) {
     return new FileNode(this, path, changesetNumber, changesetIdentifier, rawContent.get(path));
   } else {
     DirNode dirNode =
         new DirNode(this, path, changesetNumber, changesetIdentifier, rawContent.get(path) + "/");
     dirNode.setChildren(childNodesFor(dirNode, rawContent));
     return dirNode;
   }
 }
  public Node[] childNodesFor(DirNode dirNode, Map<String, String> rawChangesetContent) {
    if (rawChangesetContent == null) {
      rawChangesetContent = contentCache.readFor(dirNode.changesetNumber());
    }

    List<Node> children = new ArrayList<Node>();

    String dirPath = dirNode.isRootNode() ? "" : dirNode.path() + "/";

    List<String> paths = new ArrayList<String>(rawChangesetContent.keySet());
    Collections.sort(paths);

    String lastAddedChildPath = "";
    for (String path : paths) {
      if (path.indexOf(lastAddedChildPath + "/") != 0) {

        if (path.indexOf(dirPath) == 0 && path.length() > dirPath.length() && !path.equals("/")) {
          if (path.endsWith("/")) {
            lastAddedChildPath = path.substring(0, path.length() - 1);
            children.add(
                new DirNode(
                    this,
                    path.substring(0, path.length() - 1),
                    dirNode.changesetNumber(),
                    dirNode.changesetIdentifier(),
                    rawChangesetContent.get(path)));
          } else {
            lastAddedChildPath = path;
            children.add(
                new FileNode(
                    this,
                    path,
                    dirNode.changesetNumber(),
                    dirNode.changesetIdentifier(),
                    rawChangesetContent.get(path)));
          }
        }
      }
    }

    return children.toArray(new Node[0]);
  }