package org.freeplane.core.ui.ribbon;
import java.util.Enumeration;
public class StructureTree {
private final WeightedMutableTreeNode<StructureTreeHull> root = new WeightedMutableTreeNode<StructureTree.StructureTreeHull>();
public static final StructurePath ROOT_PATH = new RootStructurePath();
public static final int FIRST = WeightedMutableTreeNode.FIRST;
public static final int PREPEND = WeightedMutableTreeNode.PREPEND;
public static final int APPEND = WeightedMutableTreeNode.APPEND;
public static final int LAST = WeightedMutableTreeNode.LAST;
/***********************************************************************************
* CONSTRUCTORS
**********************************************************************************/
public StructureTree() {
root.setUserObject(new StructureTreeHull(null, ROOT_PATH));
}
/***********************************************************************************
* METHODS
**********************************************************************************/
public boolean insert(StructurePath path, Object obj, int position) {
if(path == null || obj == null) {
return false;
}
StructureTreeHull hull = new StructureTreeHull(obj, path);
WeightedMutableTreeNode<StructureTreeHull> newChild = new WeightedMutableTreeNode<StructureTree.StructureTreeHull>(hull, position);
WeightedMutableTreeNode<StructureTreeHull> child = get(path.getParent());
if(child != null) {
child.addChild(newChild);
return true;
}
return false;
}
public Object getObject(StructurePath path) {
return get(root, path).getUserObject().getObject();
}
public WeightedMutableTreeNode<StructureTreeHull> get(StructurePath path) {
return get(root, path);
}
public boolean contains(StructurePath path) {
return get(root, path) != null;
}
public StructurePath getRootPath() {
return ROOT_PATH;
}
public StructurePath getPathByUserObject(Object userObject) {
return findRecursive(root, userObject);
}
private StructurePath findRecursive(WeightedMutableTreeNode<StructureTreeHull> parent, Object userObject) {
Enumeration<WeightedMutableTreeNode<StructureTreeHull>> children = parent.children();
StructurePath path = null;
while (path == null && children.hasMoreElements()) {
WeightedMutableTreeNode<StructureTreeHull> child = children.nextElement();
if (userObject == child.getUserObject().getObject()) {
return child.getUserObject().getPath();
}
else {
path = findRecursive(child, userObject);
}
}
return path;
}
private WeightedMutableTreeNode<StructureTreeHull> get(WeightedMutableTreeNode<StructureTreeHull> parent, StructurePath path) {
if(path != null) {
if(getRootPath().equals(path)) {
return root;
}
Enumeration<WeightedMutableTreeNode<StructureTreeHull>> children = parent.children();
while (children.hasMoreElements()) {
WeightedMutableTreeNode<StructureTreeHull> child = children.nextElement();
if(path.equals(child.getUserObject().getPath())) {
return child;
}
else if (path.isAncestor(child.getUserObject().getPath())) {
return get(child, path);
}
}
}
return null;
}
/***********************************************************************************
* NESTED TYPE DECLARATION
**********************************************************************************/
public static class StructurePath {
private final StructurePath parentPath;
private final String id;
public StructurePath(StructurePath parent, String id) {
if (id == null || id.trim().isEmpty()) {
throw new IllegalArgumentException("id cannot be NULL or EMPTY");
}
this.id = id;
this.parentPath = parent;
}
public String getId() {
return this.id;
}
public StructurePath getParent() {
return parentPath;
}
public StructurePath clone() {
try {
return (StructurePath) super.clone();
} catch (CloneNotSupportedException e) {
}
return null;
}
public boolean equals(Object o) {
if (o instanceof StructurePath) {
return toString().equals(o.toString());
}
return false;
}
public boolean isAncestor(StructurePath ancestor) {
if (ancestor != null) {
if (this.equals(ancestor)) {
return true;
}
else if(getParent() != null){
return getParent().isAncestor(ancestor);
}
}
return false;
}
public String toString() {
return (parentPath != null ? parentPath.toString() : "") + "/" + getId();
}
}
private static class RootStructurePath extends StructurePath {
public RootStructurePath() {
super(null, "root");
}
public String getId() {
return "";
}
public boolean equals(Object o) {
if (o instanceof StructurePath) {
StructurePath other = (StructurePath) o;
return other.getParent() == null && other.getId().isEmpty();
}
return false;
}
public boolean isAncestor(StructurePath ancestor) {
return false;
}
public String toString() {
return "";
}
}
public static class StructureTreeHull {
private Object object;
private final StructurePath path;
/***********************************************************************************
* CONSTRUCTORS
**********************************************************************************/
public StructureTreeHull(Object obj, StructurePath path) {
this.path = path;
setObject(obj);
}
/***********************************************************************************
* METHODS
**********************************************************************************/
public StructurePath getPath() {
return path;
}
public void setObject(Object obj) {
this.object = obj;
}
public Object getObject() {
return object;
}
public String toString() {
return "StructureTreeNodeHull[path=" + getPath() + ";object=" + getObject() + "]";
}
/***********************************************************************************
* REQUIRED METHODS FOR INTERFACES
**********************************************************************************/
}
}