/*
 * Copyright 2014 JimVoris.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.qumasoft.server.directorytree;

import com.qumasoft.qvcslib.QVCSRuntimeException;
import java.util.Map;
import java.util.TreeMap;

/**
 * Composite pattern representation of a directory node.
 * @author Jim Voris
 */
class DirectoryNode implements Node {

    private final Integer nodeId;
    private final Integer parentId;
    private final String nodeName;
    Map<Integer, Node> idMap;
    Map<String, Node> nameMap;

    DirectoryNode(Integer id, DirectoryNode parent, String name) {
        this.nodeId = id;
        if (parent != null) {
            this.parentId = parent.getId();
        } else {
            this.parentId = null;
        }
        this.nodeName = name;
        idMap = new TreeMap<>();
        nameMap = new TreeMap<>();
    }

    @Override
    public Integer getId() {
        return this.nodeId;
    }

    @Override
    public Integer getParentId() {
        return this.parentId;
    }

    @Override
    public String getName() {
        return this.nodeName;
    }


    @Override
    public NodeType getNodeType() {
        return NodeType.DIRECTORY;
    }

    public synchronized void addNode(Node node) {
        if (idMap.containsKey(node.getId())) {
            throw new QVCSRuntimeException("Directory [" + getName() + "] already contains [" + node.getName() + "]");
        }
        if (nameMap.containsKey(node.getName())) {
            throw new QVCSRuntimeException("Directory [" + getName() + "] already contains [" + node.getName() + "]");
        }
        idMap.put(node.getId(), node);
        nameMap.put(node.getName(), node);
    }

    @Override
    public synchronized String asString() {
        String o = "<D id=:" + this.getId() + ": parentId=:" + this.getParentId() + ": name=:" + this.getName() + ":/>\n";
        return o;
    }

    public synchronized String asTree(int depth) {
        StringBuilder o = new StringBuilder();
        StringBuilder indent = new StringBuilder();
        for (int i = 0; i < depth; i++) {
            indent.append("  ");
        }
        o.append(indent.toString());
        o.append(asString());
        for (Node node : idMap.values()) {
            if (node instanceof FileNode) {
                o.append(indent.toString()).append(node.asString());
            } else if (node instanceof DirectoryNode) {
                DirectoryNode childDirectoryNode = (DirectoryNode) node;
                o.append(childDirectoryNode.asTree(depth++));
            }
        }
        return o.toString();
    }
}

@@ -2386,32 +2386,346 @@
 eturn o;%0A    %7D%0A%0A
+    /**%0A     * Show this directory in a kind of tree presentation. This method is only for test/debugging purposes.%0A     * @param depth how deep are we in the directory tree. 0 is for the root of the tree, 1 is for 1 deeper than the root, etc.%0A     * @return a String representation of the directory tree.%0A     */%0A
     public synch
@@ -2992,29 +2992,115 @@
     
-o.append(asString());
+String childIndent = indent.toString() + %22  %22;%0A        o.append(asString());%0A        // Show files first...
 %0A   
@@ -3208,33 +3208,27 @@
 .append(
-indent.toString()
+childIndent
 ).append
@@ -3259,21 +3259,117 @@
        %7D
- else
+%0A        %7D%0A        // Then show directories...%0A        for (Node node : idMap.values()) %7B%0A           
  if (nod
@@ -3527,18 +3527,20 @@
 ee(depth
-++
+ + 1
 ));%0A    

Add to asTree method to make output more useful.