/* Copyright 2010 Visin Suresh Paliath Distributed under the BSD license */ package com.laytonsmith.core; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; public class GenericTreeNode<T> implements Cloneable{ public T data; public List<GenericTreeNode<T>> children; public boolean optimized = false; @Override public GenericTreeNode<T> clone() throws CloneNotSupportedException{ GenericTreeNode<T> clone = (GenericTreeNode<T>) super.clone(); Class c = data.getClass(); if(Arrays.asList(c.getInterfaces()).contains(Cloneable.class)){ try{ Method m = c.getMethod("clone", new Class[]{}); Object obj = m.invoke(data, new Object[]{}); clone.data = (T) obj; clone.children = new ArrayList<GenericTreeNode<T>>(children); clone.optimized = optimized; } catch (IllegalAccessException ex) { throw new CloneNotSupportedException(); } catch (IllegalArgumentException ex) { throw new CloneNotSupportedException(); } catch (InvocationTargetException ex) { throw new CloneNotSupportedException(); } catch(NoSuchMethodException e){ throw new CloneNotSupportedException(); } } return clone; } public GenericTreeNode() { super(); children = new ArrayList<GenericTreeNode<T>>(); } public GenericTreeNode(T data) { this(); setData(data); } public synchronized List<GenericTreeNode<T>> getChildren() { return this.children; } public int getNumberOfChildren() { return getChildren().size(); } public boolean hasChildren() { return (getNumberOfChildren() > 0); } public void setChildren(List<GenericTreeNode<T>> children) { this.children = children; } public void addChild(GenericTreeNode<T> child) { children.add(child); } public void addChildAt(int index, GenericTreeNode<T> child) throws IndexOutOfBoundsException { children.add(index, child); } public void removeChildren() { this.children = new ArrayList<GenericTreeNode<T>>(); } public void removeChildAt(int index) throws IndexOutOfBoundsException { children.remove(index); } public GenericTreeNode<T> getChildAt(int index) throws IndexOutOfBoundsException { return children.get(index); } public T getData() { return this.data; } public void setData(T data) { this.data = data; } @Override public String toString() { return getData().toString(); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } GenericTreeNode<?> other = (GenericTreeNode<?>) obj; if (data == null) { if (other.data != null) { return false; } } else if (!data.equals(other.data)) { return false; } return true; } /* (non-Javadoc) * @see java.lang.Object#hashCode() */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((data == null) ? 0 : data.hashCode()); return result; } public String toStringVerbose() { String stringRepresentation = getData().toString() + ":["; for (GenericTreeNode<T> node : getChildren()) { stringRepresentation += node.getData().toString() + ", "; } //Pattern.DOTALL causes ^ and $ to match. Otherwise it won't. It's retarded. Pattern pattern = Pattern.compile(", $", Pattern.DOTALL); Matcher matcher = pattern.matcher(stringRepresentation); stringRepresentation = matcher.replaceFirst(""); stringRepresentation += "]"; return stringRepresentation; } }