package org.argeo.slc.core.structure.tree;
import java.util.List;
import java.util.StringTokenizer;
import java.util.Vector;
import org.argeo.slc.core.SlcException;
import org.argeo.slc.core.structure.StructurePath;
import org.argeo.slc.core.structure.StructureRegistry;
/**
* Path for tree based StructureRegistry
implementations.
*/
public class TreeSPath implements StructurePath, Comparable {
/** Default character to use a separator: /. */
public static Character DEFAULT_SEPARATOR = '/';
private TreeSPath parent;
private String name;
private Character separator = DEFAULT_SEPARATOR;
private String asUniqueString;
/** For ORM */
private Long tid;
public String getAsUniqueString() {
if (asUniqueString == null) {
String parentStr = parent != null ? parent.getAsUniqueString() : "";
asUniqueString = parentStr + separator + name;
}
return asUniqueString;
}
/** Sets all the required data from a string. */
public void setAsUniqueString(String str) {
TreeSPath twin = parseToCreatePath(str, getSeparator());
name = twin.name;
parent = twin.parent;
asUniqueString = getAsUniqueString();
}
/** The separator actually used by this path. */
public Character getSeparator() {
return separator;
}
/** Gets the parent path. */
public TreeSPath getParent() {
return parent;
}
/** Gets the name part of the path. */
public String getName() {
return name;
}
/** Create a path without parent. */
public static TreeSPath createRootPath(String name) {
TreeSPath path = new TreeSPath();
path.parent = null;
path.name = name;
return path;
}
/** Create a child . */
public TreeSPath createChild(String name) {
if (name.indexOf(separator) > -1) {
throw new SlcException("Tree path name '" + name
+ "' contains separator character " + separator);
}
TreeSPath path = new TreeSPath();
path.parent = this;
path.name = name;
return path;
}
/** Parses a string to a path. */
public static TreeSPath parseToCreatePath(String path) {
return parseToCreatePath(path, DEFAULT_SEPARATOR);
}
/** Parses a string to a path. */
public static TreeSPath parseToCreatePath(String path, Character separator) {
StringTokenizer st = new StringTokenizer(path, Character
.toString(separator));
TreeSPath currPath = null;
while (st.hasMoreTokens()) {
if (currPath == null) {// begin
currPath = createRootPath(st.nextToken());
} else {
currPath = currPath.createChild(st.nextToken());
}
}
return currPath;
}
/** Lists the children from a registry. */
public List listChildren(StructureRegistry registry) {
return listChildrenPaths(registry, this);
}
/** Lists the children from a given path from a registry. */
public static List listChildrenPaths(StructureRegistry registry,
TreeSPath path) {
List paths = new Vector();
List allPaths = registry.listPaths();
for (StructurePath sPath : allPaths) {
TreeSPath pathT = (TreeSPath) sPath;
if (pathT.parent != null && pathT.parent.equals(path)) {
paths.add(pathT);
}
}
return paths;
}
/** Gets the root tree path of this path. */
public TreeSPath getRoot() {
TreeSPath root = this;
while (root.getParent() != null) {
root = root.getParent();
}
return root;
}
/** Depth of this path. */
public Integer getDepth() {
return depthImpl(this);
}
protected int depthImpl(TreeSPath path) {
if (path.getParent() == null) {
return 1;
} else {
return depthImpl(path.getParent()) + 1;
}
}
public List getHierarchyAsList() {
List lst = new Vector();
addParentToList(lst, this);
lst.add(this);
return lst;
}
protected void addParentToList(List lst, TreeSPath current) {
TreeSPath parent = current.getParent();
if (parent != null) {
addParentToList(lst, parent);
lst.add(parent);
}
}
@Override
public String toString() {
return getAsUniqueString();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof StructurePath) {
StructurePath path = (StructurePath) obj;
return getAsUniqueString().equals(path.getAsUniqueString());
}
return false;
}
@Override
public int hashCode() {
return getAsUniqueString().hashCode();
}
public int compareTo(StructurePath o) {
return getAsUniqueString().compareTo(o.getAsUniqueString());
}
public Long getTid() {
return tid;
}
void setTid(Long tid) {
this.tid = tid;
}
/**
* Sets the separator character to use.
*
* @deprecated
*/
public void setSeparator(Character separator) {
this.separator = separator;
}
/** Sets the parent (for ORM). */
protected void setParent(TreeSPath parent) {
this.parent = parent;
}
/** Sets the name (for ORM). */
protected void setName(String name) {
this.name = name;
}
}