All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.kuali.common.util.tree.MutableNode Maven / Gradle / Ivy

There is a newer version: 4.4.17
Show newest version
/**
 * Copyright 2010-2014 The Kuali Foundation
 *
 * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php
 *
 * 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 org.kuali.common.util.tree;

import static com.google.common.base.Optional.absent;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.Lists.newArrayList;
import static org.kuali.common.util.base.Precondition.checkNotNull;

import java.util.List;

import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;

public class MutableNode extends AbstractNode {

	protected Optional> mutableParent = absent();
	protected List> mutableChildren = newArrayList();
	protected T element;

	public static  MutableNode of(T element) {
		return new MutableNode(element);
	}

	public static  MutableNode copyOf(Node node) {
		MutableNode mutable = new MutableNode(node.getElement());
		for (Node child : node.getChildren()) {
			mutable.add(copyOf(child));
		}
		return mutable;
	}

	protected MutableNode() {
	}

	public MutableNode(T element) {
		setElement(element);
	}

	public void setElement(T element) {
		checkNotNull(element, "element");
		this.element = element;
	}

	@Override
	public T getElement() {
		return element;
	}

	@Override
	public Optional> getParent() {
		return Optional.> fromNullable(getMutableParent().orNull());
	}

	public Optional> getMutableParent() {
		return mutableParent;
	}

	protected void setMutableParent(Optional> parent) {
		this.mutableParent = parent;
	}

	protected void setParent(MutableNode parent) {
		setMutableParent(Optional.of(checkNotNull(parent, "parent")));
	}

	/**
	 * Returns an immutable list of the nodes current children
	 */
	@Override
	public List> getChildren() {
		List> list = newArrayList();
		for (Node child : mutableChildren) {
			list.add(child);
		}
		return ImmutableList.copyOf(list);
	}

	public void remove(MutableNode child) {
		boolean parent = isParent(checkNotNull(child, "child"));
		checkArgument(parent, "remove can only be invoked with a current child of this node");
		remove(mutableChildren.indexOf(child));
	}

	public void remove(int index) {
		MutableNode child = mutableChildren.get(index);
		mutableChildren.remove(index);
		child.setMutableParent(Optional.> absent());
	}

	public void add(List> children) {
		for (MutableNode child : checkNotNull(children, "children")) {
			add(child);
		}
	}

	public void add(MutableNode child1, MutableNode child2) {
		add(ImmutableList.of(child1, child2));
	}

	public void add(MutableNode child1, MutableNode child2, MutableNode child3) {
		add(ImmutableList.of(child1, child2, child3));
	}

	public void add(MutableNode child1, MutableNode child2, MutableNode child3, MutableNode child4) {
		add(ImmutableList.of(child1, child2, child3, child4));
	}

	public void add(MutableNode child1, MutableNode child2, MutableNode child3, MutableNode child4, MutableNode child5) {
		add(ImmutableList.of(child1, child2, child3, child4, child5));
	}

	public void add(MutableNode child) {
		checkNotNull(child, "child");
		add(mutableChildren.size(), child);
	}

	public void add(int index, MutableNode child) {
		// Can't be null
		checkNotNull(child, "child");

		// If it's already a child, it gets removed from it's current position and then added to the end
		// Thus, index needs to be children.size() - 1 if it's already a child
		int actualIndex = isChild(child) ? mutableChildren.size() - 1 : mutableChildren.size();

		// Child can't be us, our parent, our grandparent, etc
		checkArgument(!isAncestor(child), "cannot be an ancestor of 'child'");

		// Remove this child from it's current parent
		// If the child's parent is us, this decreases our child count by 1 (temporarily)
		if (child.getMutableParent().isPresent()) {
			child.getMutableParent().get().remove(child);
		}

		// Make the child's parent this node
		child.setParent(this);

		// Add the child
		mutableChildren.add(actualIndex, child);
	}

	public void removeAllChildren() {
		for (int i = 0; i < mutableChildren.size(); i++) {
			remove(i);
		}
	}

	/**
	 * Removes the subtree rooted at this node from the tree, giving this node an absent parent. Does nothing if this node is the root of its tree.
	 */
	public void removeFromParent() {
		Optional> parent = getMutableParent();
		if (parent.isPresent()) {
			parent.get().remove(this);
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy