/*
 * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.jndi.dns;


import java.util.Hashtable;


/**
 * A NameNode represents a node in the DNS namespace.  Each node
 * has a label, which is its name relative to its parent (so the
 * node at Sun.COM has label "Sun").  Each node has a hashtable of
 * children indexed by their labels converted to lower-case.
 *
 * <p> A node may be addressed from another by giving a DnsName
 * consisting of the sequence of labels from one node to the other.
 *
 * <p> Each node also has an <tt>isZoneCut</tt> flag, used to indicate
 * if the node is a zone cut.  A zone cut is a node with an NS record
 * that is contained in one zone, but that actually belongs to a child zone.
 *
 * <p> All access is unsynchronized.
 *
 * @author Scott Seligman
 */


class NameNode {

    private String label;               // name of this node relative to its
                                        // parent, or null for root of a tree
    private Hashtable<String,NameNode> children = null;  // child nodes
    private boolean isZoneCut = false;  // true if this node is a zone cut
    private int depth = 0;              // depth in tree (0 for root)

    NameNode(String label) {
        this.label = label;
    }

    /*
     * Returns a newly-allocated NameNode.  Used to allocate new nodes
     * in a tree.  Should be overridden in a subclass to return an object
     * of the subclass's type.
     */
    protected NameNode newNameNode(String label) {
        return new NameNode(label);
    }

    /*
     * Returns the name of this node relative to its parent, or null for
     * the root of a tree.
     */
    String getLabel() {
        return label;
    }

    /*
     * Returns the depth of this node in the tree.  The depth of the root
     * is 0.
     */
    int depth() {
        return depth;
    }

    boolean isZoneCut() {
        return isZoneCut;
    }

    void setZoneCut(boolean isZoneCut) {
        this.isZoneCut = isZoneCut;
    }

    /*
     * Returns the children of this node, or null if there are none.
     * The caller must not modify the Hashtable returned.
     */
    Hashtable<String,NameNode> getChildren() {
        return children;
    }

    /*
     * Returns the child node given the hash key (the down-cased label)
     * for its name relative to this node, or null if there is no such
     * child.
     */
    NameNode get(String key) {
        return (children != null)
            ? children.get(key)
            : null;
    }

    /*
     * Returns the node at the end of a path, or null if the
     * node does not exist.
     * The path is specified by the labels of <tt>name</tt>, beginning
     * at index idx.
     */
    NameNode get(DnsName name, int idx) {
        NameNode node = this;
        for (int i = idx; i < name.size() && node != null; i++) {
            node = node.get(name.getKey(i));
        }
        return node;
    }

    /*
     * Returns the node at the end of a path, creating it and any
     * intermediate nodes as needed.
     * The path is specified by the labels of <tt>name</tt>, beginning
     * at index idx.
     */
    NameNode add(DnsName name, int idx) {
        NameNode node = this;
        for (int i = idx; i < name.size(); i++) {
            String label = name.get(i);
            String key = name.getKey(i);

            NameNode child = null;
            if (node.children == null) {
                node.children = new Hashtable<>();
            } else {
                child = node.children.get(key);
            }
            if (child == null) {
                child = newNameNode(label);
                child.depth = node.depth + 1;
                node.children.put(key, child);
            }
            node = child;
        }
        return node;
    }
}
