001/**
002 * Copyright 2010-2014 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.common.util.tree;
017
018import static com.google.common.collect.Lists.newArrayList;
019import static com.google.common.collect.Lists.reverse;
020import static com.google.common.collect.Lists.transform;
021import static org.kuali.common.util.base.Precondition.checkNotNull;
022
023import java.util.List;
024
025public abstract class AbstractNode<T> implements Node<T> {
026
027        /**
028         * Return true if this is the root node (ie it has no parent)
029         */
030        @Override
031        public boolean isRoot() {
032                return !getParent().isPresent();
033        }
034
035        /**
036         * Return true if this is a leaf node (ie it has no children)
037         */
038        @Override
039        public boolean isLeaf() {
040                return getChildren().isEmpty();
041        }
042
043        /**
044         * Returns the number of levels above this node. The distance from the root to this node. If this node is the root, returns 0.
045         */
046        @Override
047        public int getLevel() {
048                int level = 0;
049                Node<T> ancestor = this;
050                while (ancestor.getParent().isPresent()) {
051                        ancestor = ancestor.getParent().get();
052                        level++;
053                }
054                return level;
055        }
056
057        /**
058         * Returns the path from the root, to get to this node. The last element in the path is this node.
059         */
060        @Override
061        public List<Node<T>> getPath() {
062                Node<T> ancestor = this;
063                List<Node<T>> list = newArrayList();
064                list.add(ancestor);
065                while (ancestor.getParent().isPresent()) {
066                        ancestor = ancestor.getParent().get();
067                        list.add(ancestor);
068                }
069                return reverse(list);
070        }
071
072        /**
073         * Returns the node elements in the path from the root, to get to this node. The last entry is the element from this node
074         */
075        @Override
076        public List<T> getElementPath() {
077                return transform(getPath(), new NodeElementFunction<T>());
078        }
079
080        /**
081         * Return true if this node is a child of parent
082         */
083        @Override
084        public boolean isChild(Node<T> parent) {
085                checkNotNull(parent, "parent");
086                return parent.getChildren().contains(this);
087        }
088
089        /**
090         * Return true if this node is a parent of child
091         */
092        @Override
093        public boolean isParent(Node<T> child) {
094                checkNotNull(child, "child");
095                return getChildren().contains(child);
096        }
097
098        /**
099         * Return true if this node descends from parent OR is parent
100         */
101        @Override
102        public boolean isAncestor(Node<T> parent) {
103                checkNotNull(parent, "parent");
104                return getPath().contains(parent);
105        }
106
107}