com.synflow.models.node.Node.java Source code

Java tutorial

Introduction

Here is the source code for com.synflow.models.node.Node.java

Source

/*******************************************************************************
 * Copyright (c) 2013-2014 Synflow SAS.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Matthieu Wipliez - initial API and implementation and/or initial documentation
 *******************************************************************************/
package com.synflow.models.node;

import java.util.Iterator;

import com.google.common.base.Strings;

/**
 * This class defines a Node to create tree models. A Node has links to its parent, previous and
 * next siblings, and first and last child. All fields are updated automatically when a new Node is
 * created with an existing parent node. To get an iterable over a node's children, call the
 * {@link #getChildren()} method.
 * 
 * @author Matthieu Wipliez
 */
public class Node {

    private Object content;

    private Node firstChild;

    private Node lastChild;

    private Node next;

    private Node parent;

    private Node previous;

    /**
     * Creates a root empty node, i.e. with no parent and no content.
     */
    public Node() {
        this(null, null);
    }

    /**
     * Creates an empty node, i.e. with no content, and the given parent.
     * 
     * @param parent
     *            a parent node (may be <code>null</code>)
     */
    public Node(Node parent) {
        this(parent, null);
    }

    /**
     * Creates a node with the given parent and content. If <code>parent != null</code>, this node
     * is added as a child of <code>parent</code>.
     * 
     * @param parent
     *            a parent node (may be <code>null</code>)
     * @param content
     *            an object to use as this node's content (may be <code>null</code>)
     */
    public Node(Node parent, Object content) {
        if (parent != null) {
            parent.add(this);
        }

        this.content = content;
        this.parent = parent;
    }

    /**
     * Creates a root node, i.e. with no parent and the given content.
     * 
     * @param content
     *            an object to use as this node's content
     */
    public Node(Object content) {
        this(null, content);
    }

    /**
     * Adds a child node to this node.
     * 
     * @param node
     *            a node
     */
    private void add(Node node) {
        if (!hasChildren()) {
            lastChild = firstChild = node;
        } else {
            lastChild.addSibling(node);
            lastChild = node;
        }
    }

    /**
     * Adds the given node as a sibling of this node.
     * 
     * @param node
     *            a node
     */
    private void addSibling(Node node) {
        next = node;
        node.previous = this;
    }

    /**
     * Removes children of this node. This method just removes links to the first and last child of
     * this node.
     */
    public void clearChildren() {
        firstChild = lastChild = null;
    }

    /**
     * Deletes this node and all its descendants (children, grand-children, etc).
     */
    public void delete() {
        if (hasChildren()) {
            removeChildren();
        }
        remove();
    }

    /**
     * Returns an iterable over this node's children.
     * 
     * @return an {@link Iterable}&lt;{@link Node}&gt;
     */
    public Iterable<Node> getChildren() {
        return new NodeIterable(this);
    }

    /**
     * Returns this node's content
     * 
     * @return an object
     */
    public Object getContent() {
        return content;
    }

    /**
     * Returns this node's first child.
     * 
     * @return a node, or <code>null</code> if this node has no children
     */
    public Node getFirstChild() {
        return firstChild;
    }

    /**
     * Returns this node's last child.
     * 
     * @return a node, or <code>null</code> if this node has no children
     */
    public Node getLastChild() {
        return lastChild;
    }

    /**
     * Returns this node's next sibling.
     * 
     * @return a node, or <code>null</code> if this node has no next sibling
     */
    public Node getNextSibling() {
        return next;
    }

    /**
     * Returns this node's parent.
     * 
     * @return a node, or <code>null</code> if this node has no parent
     */
    public Node getParent() {
        return parent;
    }

    /**
     * Returns this node's previous sibling.
     * 
     * @return a node, or <code>null</code> if this node has no previous sibling
     */
    public Node getPreviousSibling() {
        return previous;
    }

    /**
     * Returns a boolean indicating if this node has children.
     * 
     * @return a boolean
     */
    public boolean hasChildren() {
        return firstChild != null;
    }

    /**
     * Removes this node.
     */
    public void remove() {
        // remove incoming link from previous
        if (previous != null) {
            previous.next = next;
        }

        // remove incoming link from next
        if (next != null) {
            next.previous = previous;
        }

        // remove incoming links from parent
        if (parent != null) {
            if (parent.firstChild == this) {
                parent.firstChild = next;
            }

            if (parent.lastChild == this) {
                parent.lastChild = previous;
            }
        }

        // remove outgoing links
        parent = previous = next = null;
    }

    /**
     * Removes children recursively.
     */
    void removeChildren() {
        Iterator<Node> it = getChildren().iterator();
        while (it.hasNext()) {
            it.next().removeChildren();
            it.remove();
        }
    }

    /**
     * Sets the content of this node to the given object.
     * 
     * @param content
     *            an object
     */
    public void setContent(Object content) {
        this.content = content;
    }

    @Override
    public String toString() {
        return toString(0);
    }

    private String toString(int indent) {
        StringBuilder builder = new StringBuilder(Strings.repeat("|  ", indent));
        builder.append(content);
        builder.append('\n');
        for (Node child : getChildren()) {
            builder.append(child.toString(indent + 1));
        }
        return builder.toString();
    }

}