]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/core/structure/tree/TreeSPath.java
Introduce org.argeo.slc.specs
[gpl/argeo-slc.git] / runtime / org.argeo.slc.specs / src / main / java / org / argeo / slc / core / structure / tree / TreeSPath.java
1 package org.argeo.slc.core.structure.tree;
2
3 import java.util.List;
4 import java.util.StringTokenizer;
5 import java.util.Vector;
6
7 import org.argeo.slc.core.SlcException;
8 import org.argeo.slc.core.structure.StructurePath;
9 import org.argeo.slc.core.structure.StructureRegistry;
10
11 /**
12 * Path for tree based <code>StructureRegistry</code> implementations.
13 */
14 public class TreeSPath implements StructurePath, Comparable<StructurePath> {
15 /** Default character to use a separator: /. */
16 private static Character DEFAULT_SEPARATOR = '/';
17
18 private Character separator = DEFAULT_SEPARATOR;
19
20 private String asUniqueString;
21
22 /** For ORM */
23 private Long tid;
24
25 public TreeSPath() {
26
27 }
28
29 public TreeSPath(String asUniqueString) {
30 this.asUniqueString = checkAndFormatPath(asUniqueString);
31 }
32
33 public String getAsUniqueString() {
34 return asUniqueString;
35 }
36
37 /**
38 * Sets all the required data from a string. <b>ATTENTION</b>: the path is
39 * not checked for performance reason. This method should be used only by
40 * ORM/OXM frameworks. Use constructor to create immutable tree structure
41 * paths.
42 */
43 public void setAsUniqueString(String str) {
44 this.asUniqueString = str;
45 }
46
47 /** The separator actually used by this path. */
48 public Character getSeparator() {
49 return separator;
50 }
51
52 /** Gets the parent path. */
53 public TreeSPath getParent() {
54 int lastSep = getAsUniqueString().lastIndexOf(separator);
55 if (lastSep < 1) {
56 return null;
57 }
58 String parentUniqueString = getAsUniqueString().substring(0, lastSep);
59 return new TreeSPath(parentUniqueString);
60 }
61
62 /** Gets the name part of the path. */
63 public String getName() {
64 int lastSep = getAsUniqueString().lastIndexOf(separator);
65 return getAsUniqueString().substring(lastSep + 1);
66 }
67
68 /** Create a path without parent. */
69 public static TreeSPath createRootPath(String name) {
70 if (name.indexOf(DEFAULT_SEPARATOR) >= 0) {
71 throw new SlcException("Name cannot contain " + DEFAULT_SEPARATOR);
72 }
73 return new TreeSPath('/' + name);
74 }
75
76 /** Create a child . */
77 public TreeSPath createChild(String name) {
78 if (name.indexOf(separator) > -1) {
79 throw new SlcException("Tree path name '" + name
80 + "' contains separator character " + separator);
81 }
82 return new TreeSPath(getAsUniqueString() + '/' + name);
83 }
84
85 /**
86 * Parses a string to a path.
87 *
88 * @deprecated use constructor instead
89 */
90 public static TreeSPath parseToCreatePath(String path) {
91 return parseToCreatePath(path, DEFAULT_SEPARATOR);
92 }
93
94 protected String checkAndFormatPath(String str) {
95 if (str.length() < 2) {
96 throw new SlcException("Path " + str + " is not short");
97 }
98 if (str.charAt(0) != separator) {
99 throw new SlcException("Path " + str + " have to start with "
100 + separator);
101 }
102
103 StringBuffer buf = new StringBuffer(str.length() + 5);
104 StringTokenizer st = new StringTokenizer(str, separator.toString());
105 while (st.hasMoreTokens()) {
106 buf.append(separator).append(st.nextToken());
107 }
108 return buf.toString();
109 }
110
111 /**
112 * Parses a string to a path.
113 *
114 * @deprecated use constructor instead
115 */
116 public static TreeSPath parseToCreatePath(String path, Character separator) {
117 return new TreeSPath(path);
118 }
119
120 /** Lists the children from a registry. */
121 public List<TreeSPath> listChildren(StructureRegistry<TreeSPath> registry) {
122 return listChildrenPaths(registry, this);
123 }
124
125 /** Lists the children from a given path from a registry. */
126 public static List<TreeSPath> listChildrenPaths(
127 StructureRegistry<TreeSPath> registry, TreeSPath path) {
128 List<TreeSPath> paths = new Vector<TreeSPath>();
129 List<TreeSPath> allPaths = registry.listPaths();
130 for (TreeSPath pathT : allPaths) {
131 if (pathT.getParent() != null && pathT.getParent().equals(path)) {
132 paths.add(pathT);
133 }
134 }
135 return paths;
136 }
137
138 /** Gets the root tree path of this path. */
139 public TreeSPath getRoot() {
140 TreeSPath root = this;
141 while (root.getParent() != null) {
142 root = root.getParent();
143 }
144 return root;
145 }
146
147 /** Depth of this path. */
148 public Integer getDepth() {
149 return depthImpl(this);
150 }
151
152 protected int depthImpl(TreeSPath path) {
153 if (path.getParent() == null) {
154 return 1;
155 } else {
156 return depthImpl(path.getParent()) + 1;
157 }
158 }
159
160 public List<TreeSPath> getHierarchyAsList() {
161 List<TreeSPath> lst = new Vector<TreeSPath>();
162 addParentToList(lst, this);
163 lst.add(this);
164 return lst;
165 }
166
167 protected void addParentToList(List<TreeSPath> lst, TreeSPath current) {
168 TreeSPath parent = current.getParent();
169 if (parent != null) {
170 addParentToList(lst, parent);
171 lst.add(parent);
172 }
173 }
174
175 @Override
176 public String toString() {
177 return getAsUniqueString();
178 }
179
180 @Override
181 public boolean equals(Object obj) {
182 if (obj instanceof StructurePath) {
183 StructurePath path = (StructurePath) obj;
184 return getAsUniqueString().equals(path.getAsUniqueString());
185 }
186 return false;
187 }
188
189 @Override
190 public int hashCode() {
191 return getAsUniqueString().hashCode();
192 }
193
194 public int compareTo(StructurePath o) {
195 return getAsUniqueString().compareTo(o.getAsUniqueString());
196 }
197
198 public Long getTid() {
199 return tid;
200 }
201
202 void setTid(Long tid) {
203 this.tid = tid;
204 }
205 }