]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.jcr/src/org/argeo/jcr/fs/JcrPath.java
Remove node data model, home areas based on workspaces instead.
[lgpl/argeo-commons.git] / org.argeo.jcr / src / org / argeo / jcr / fs / JcrPath.java
1 package org.argeo.jcr.fs;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.net.URI;
6 import java.net.URISyntaxException;
7 import java.nio.file.FileSystem;
8 import java.nio.file.LinkOption;
9 import java.nio.file.Path;
10 import java.nio.file.WatchEvent.Kind;
11 import java.nio.file.WatchEvent.Modifier;
12 import java.nio.file.WatchKey;
13 import java.nio.file.WatchService;
14 import java.util.Arrays;
15 import java.util.Iterator;
16 import java.util.NoSuchElementException;
17
18 import javax.jcr.Node;
19 import javax.jcr.RepositoryException;
20 import javax.jcr.Session;
21
22 /** A {@link Path} which contains a reference to a JCR {@link Node}. */
23 public class JcrPath implements Path {
24 private final static String delimStr = "/";
25 private final static char delimChar = '/';
26
27 private final JcrFileSystem fs;
28 private final String[] path;// null means root
29 private final boolean absolute;
30
31 // optim
32 private final int hashCode;
33
34 public JcrPath(JcrFileSystem filesSystem, String path) {
35 this.fs = filesSystem;
36 if (path == null)
37 throw new JcrFsException("Path cannot be null");
38 if (path.equals(delimStr)) {// root
39 this.path = null;
40 this.absolute = true;
41 this.hashCode = 0;
42 return;
43 } else if (path.equals("")) {// empty path
44 this.path = new String[] { "" };
45 this.absolute = false;
46 this.hashCode = "".hashCode();
47 return;
48 }
49
50 if (path.equals("~")) {// home
51 path = filesSystem.getUserHomePath();
52 if (path == null)
53 throw new JcrFsException("No home directory available");
54 }
55
56 this.absolute = path.charAt(0) == delimChar ? true : false;
57 String trimmedPath = path.substring(absolute ? 1 : 0,
58 path.charAt(path.length() - 1) == delimChar ? path.length() - 1 : path.length());
59 this.path = trimmedPath.split(delimStr);
60 for (int i = 0; i < this.path.length; i++) {
61 this.path[i] = Text.unescapeIllegalJcrChars(this.path[i]);
62 }
63 this.hashCode = this.path[this.path.length - 1].hashCode();
64 }
65
66 public JcrPath(JcrFileSystem filesSystem, Node node) throws RepositoryException {
67 this(filesSystem, node.getPath());
68 }
69
70 /** Internal optimisation */
71 private JcrPath(JcrFileSystem filesSystem, String[] path, boolean absolute) {
72 this.fs = filesSystem;
73 this.path = path;
74 this.absolute = path == null ? true : absolute;
75 this.hashCode = path == null ? 0 : path[path.length - 1].hashCode();
76 }
77
78 @Override
79 public FileSystem getFileSystem() {
80 return fs;
81 }
82
83 @Override
84 public boolean isAbsolute() {
85 return absolute;
86 }
87
88 @Override
89 public Path getRoot() {
90 try {
91 if (path == null)
92 return this;
93 return new JcrPath(fs, fs.getSession().getRootNode());
94 } catch (RepositoryException e) {
95 throw new JcrFsException("Cannot get root", e);
96 }
97 }
98
99 @Override
100 public String toString() {
101 if (path == null)
102 return "/";
103 StringBuilder sb = new StringBuilder();
104 if (isAbsolute())
105 sb.append('/');
106 for (int i = 0; i < path.length; i++) {
107 if (i != 0)
108 sb.append('/');
109 sb.append(path[i]);
110 }
111 return sb.toString();
112 }
113
114 public String toJcrPath() {
115 if (path == null)
116 return "/";
117 StringBuilder sb = new StringBuilder();
118 if (isAbsolute())
119 sb.append('/');
120 for (int i = 0; i < path.length; i++) {
121 if (i != 0)
122 sb.append('/');
123 sb.append(Text.escapeIllegalJcrChars(path[i]));
124 }
125 return sb.toString();
126 }
127
128 @Override
129 public Path getFileName() {
130 if (path == null)
131 return null;
132 return new JcrPath(fs, path[path.length - 1]);
133 }
134
135 @Override
136 public Path getParent() {
137 if (path == null)
138 return null;
139 if (path.length == 1)// root
140 return new JcrPath(fs, delimStr);
141 String[] parentPath = Arrays.copyOfRange(path, 0, path.length - 1);
142 return new JcrPath(fs, parentPath, absolute);
143 }
144
145 @Override
146 public int getNameCount() {
147 if (path == null)
148 return 0;
149 return path.length;
150 }
151
152 @Override
153 public Path getName(int index) {
154 if (path == null)
155 return null;
156 return new JcrPath(fs, path[index]);
157 }
158
159 @Override
160 public Path subpath(int beginIndex, int endIndex) {
161 if (path == null)
162 return null;
163 String[] parentPath = Arrays.copyOfRange(path, beginIndex, endIndex);
164 return new JcrPath(fs, parentPath, false);
165 }
166
167 @Override
168 public boolean startsWith(Path other) {
169 return toString().startsWith(other.toString());
170 }
171
172 @Override
173 public boolean startsWith(String other) {
174 return toString().startsWith(other);
175 }
176
177 @Override
178 public boolean endsWith(Path other) {
179 return toString().endsWith(other.toString());
180 }
181
182 @Override
183 public boolean endsWith(String other) {
184 return toString().endsWith(other);
185 }
186
187 @Override
188 public Path normalize() {
189 // always normalized
190 return this;
191 }
192
193 @Override
194 public Path resolve(Path other) {
195 JcrPath otherPath = (JcrPath) other;
196 if (otherPath.isAbsolute())
197 return other;
198 String[] newPath;
199 if (path == null) {
200 newPath = new String[otherPath.path.length];
201 System.arraycopy(otherPath.path, 0, newPath, 0, otherPath.path.length);
202 } else {
203 newPath = new String[path.length + otherPath.path.length];
204 System.arraycopy(path, 0, newPath, 0, path.length);
205 System.arraycopy(otherPath.path, 0, newPath, path.length, otherPath.path.length);
206 }
207 return new JcrPath(fs, newPath, absolute);
208 }
209
210 @Override
211 public final Path resolve(String other) {
212 return resolve(getFileSystem().getPath(other));
213 }
214
215 @Override
216 public final Path resolveSibling(Path other) {
217 if (other == null)
218 throw new NullPointerException();
219 Path parent = getParent();
220 return (parent == null) ? other : parent.resolve(other);
221 }
222
223 @Override
224 public final Path resolveSibling(String other) {
225 return resolveSibling(getFileSystem().getPath(other));
226 }
227
228 @Override
229 public final Iterator<Path> iterator() {
230 return new Iterator<Path>() {
231 private int i = 0;
232
233 @Override
234 public boolean hasNext() {
235 return (i < getNameCount());
236 }
237
238 @Override
239 public Path next() {
240 if (i < getNameCount()) {
241 Path result = getName(i);
242 i++;
243 return result;
244 } else {
245 throw new NoSuchElementException();
246 }
247 }
248
249 @Override
250 public void remove() {
251 throw new UnsupportedOperationException();
252 }
253 };
254 }
255
256 @Override
257 public Path relativize(Path other) {
258 if (equals(other))
259 return new JcrPath(fs, "");
260 if (other.startsWith(this)) {
261 String p1 = toString();
262 String p2 = other.toString();
263 String relative = p2.substring(p1.length(), p2.length());
264 if (relative.charAt(0) == '/')
265 relative = relative.substring(1);
266 return new JcrPath(fs, relative);
267 }
268 throw new IllegalArgumentException(other + " cannot be relativized against " + this);
269 }
270
271 @Override
272 public URI toUri() {
273 try {
274 return new URI(fs.provider().getScheme(), toString(), null);
275 } catch (URISyntaxException e) {
276 throw new JcrFsException("Cannot create URI for " + toString(), e);
277 }
278 }
279
280 @Override
281 public Path toAbsolutePath() {
282 if (isAbsolute())
283 return this;
284 return new JcrPath(fs, path, true);
285 }
286
287 @Override
288 public Path toRealPath(LinkOption... options) throws IOException {
289 return this;
290 }
291
292 @Override
293 public File toFile() {
294 throw new UnsupportedOperationException();
295 }
296
297 @Override
298 public WatchKey register(WatchService watcher, Kind<?>[] events, Modifier... modifiers) throws IOException {
299 // TODO Auto-generated method stub
300 return null;
301 }
302
303 @Override
304 public WatchKey register(WatchService watcher, Kind<?>... events) throws IOException {
305 // TODO Auto-generated method stub
306 return null;
307 }
308
309 @Override
310 public int compareTo(Path other) {
311 return toString().compareTo(other.toString());
312 }
313
314 public Node getNode() throws RepositoryException {
315 if (!isAbsolute())// TODO default dir
316 throw new JcrFsException("Cannot get node from relative path");
317 String pathStr = toJcrPath();
318 Session session = fs.getSession();
319 // TODO synchronize on the session ?
320 if (!session.itemExists(pathStr))
321 return null;
322 return session.getNode(pathStr);
323 }
324
325 @Override
326 public boolean equals(Object obj) {
327 if (!(obj instanceof JcrPath))
328 return false;
329 JcrPath other = (JcrPath) obj;
330
331 if (path == null) {// root
332 if (other.path == null)// root
333 return true;
334 else
335 return false;
336 } else {
337 if (other.path == null)// root
338 return false;
339 }
340 // non root
341 if (path.length != other.path.length)
342 return false;
343 for (int i = 0; i < path.length; i++) {
344 if (!path[i].equals(other.path[i]))
345 return false;
346 }
347 return true;
348 }
349
350 @Override
351 public int hashCode() {
352 return hashCode;
353 }
354
355 @Override
356 protected Object clone() throws CloneNotSupportedException {
357 return new JcrPath(fs, toString());
358 }
359
360 @Override
361 protected void finalize() throws Throwable {
362 Arrays.fill(path, null);
363 }
364
365 }