/*
* chombo: Hadoop Map Reduce utility
* Author: Pranab Ghosh
*
* 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 org.chombo.util;
import java.util.HashMap;
import java.util.Map;
/**
* Generic tree
* @author pranab
*
* @param <T>
*/
public class NamedObjectTree<T extends NamedObject> {
protected T current;
protected Map<String, NamedObjectTree<T>> children = new HashMap<String, NamedObjectTree<T>>();
/**
* @param current
*/
public NamedObjectTree(T current) {
super();
this.current = current;
}
/**
* Adds child node
* @param child
*/
public void addChild(T child) {
NamedObjectTree<T> childNode = new NamedObjectTree<T>(child);
children.put(child.getName(), childNode);
}
/**
* Adds child node
* @param child
*/
private void addChild(NamedObjectTree<T> childNode) {
children.put(childNode.current.getName(), childNode);
}
/**
* @param path between current node and parent of node to be added
* @param child
*/
public void addChild(String[] path, T child) {
NamedObjectTree<T> thisNode = this;
for (String childName : path) {
thisNode = thisNode.children.get(childName);
if (null == thisNode) {
throw new IllegalArgumentException("invalid parent path");
}
}
thisNode.addChild(child);
}
/**
* Gets immediate child
* @param childName
* @return
*/
public T getChild(String childName) {
return children.get(childName).current;
}
/**
* Gets a node at the end of the path. Created node along the way if needed
* @param path between current node and node desired
* @return
*/
public T getDescendent(String[] path) {
return getDescendent(path,false);
}
/**
* Gets a node at the end of the path. Created node along the way if needed
* @param path between current node and node desired
* @return
*/
public T getOrAddDescendent(String[] path) {
return getDescendent(path,true);
}
/**
* Gets a node at the end of the path. Created node along the way if needed
* @param path between current node and node desired
* @return
*/
public T getDescendent(String[] path, boolean create) {
NamedObjectTree<T> childNode = this;
NamedObjectTree<T> nextChildNode = null;
for (String childName : path) {
nextChildNode = childNode.children.get(childName);
if (null == nextChildNode) {
if (create) {
//alowed to create
T child = createChild(childName);
if (null == child) {
throw new IllegalStateException("createChild method must be overridden");
}
nextChildNode = new NamedObjectTree<T>(child);
childNode.addChild(nextChildNode);
} else {
//supposed to exist
throw new IllegalArgumentException("failed to find node along path");
}
}
childNode = nextChildNode;
}
return childNode.current;
}
protected T createChild(String childName) {
return null;
}
/**
* @return
*/
public T getCurrent() {
return current;
}
/**
* @param current
*/
public void setCurrent(T current) {
this.current = current;
}
/**
* @return
*/
public Map<String, NamedObjectTree<T>> getChildren() {
return children;
}
public void setChildren(Map<String, NamedObjectTree<T>> children) {
this.children = children;
}
}