KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > thoughtworks > xstream > io > path > Path


1 package com.thoughtworks.xstream.io.path;
2
3 import com.thoughtworks.xstream.core.util.FastStack;
4
5 import java.util.List JavaDoc;
6 import java.util.ArrayList JavaDoc;
7
8 /**
9  * Represents a path (subset of XPath) to a single node in the tree.
10  *
11  * <p>Two absolute paths can also be compared to calculate the relative path between them.
12  * A relative path can be applied to an absolute path to calculate another absolute path.</p>
13  *
14  * <p>Note that the paths produced are XPath compliant, so can be read by other XPath engines.
15  * The following are examples of path expressions that the Path object supports:</p>
16  * <ul>
17  * <li>/</li>
18  * <li>/some/node</li>
19  * <li>/a/b/c/b/a</li>
20  * <li>/some[3]/node[2]/a</li>
21  * <li>../../../another[3]/node</li>
22  * </ul>
23  *
24  * <h3>Example<h3>
25  *
26  * <pre>
27  * Path a = new Path("/html/body/div/table[2]/tr[3]/td/div");
28  * Path b = new Path("/html/body/div/table[2]/tr[6]/td/form");
29  *
30  * Path relativePath = a.relativeTo(b); // produces: "../../../tr[6]/td/form"
31  * Path c = a.apply(relativePath); // same as Path b.
32  * </pre>
33  *
34  * @see PathTracker
35  *
36  * @author Joe Walnes
37  */

38 public class Path {
39
40     private final String JavaDoc[] chunks;
41     private transient String JavaDoc pathAsString;
42     private static final Path DOT = new Path(new String JavaDoc[] {"."});
43
44     public Path(String JavaDoc pathAsString) {
45         // String.split() too slow. StringTokenizer too crappy.
46
List JavaDoc result = new ArrayList JavaDoc();
47         int currentIndex = 0;
48         int nextSeperator;
49         while ((nextSeperator = pathAsString.indexOf('/', currentIndex)) != -1) {
50             result.add(pathAsString.substring(currentIndex, nextSeperator));
51             currentIndex = nextSeperator + 1;
52         }
53         result.add(pathAsString.substring(currentIndex));
54         String JavaDoc[] arr = new String JavaDoc[result.size()];
55         result.toArray(arr);
56         chunks = arr;
57         this.pathAsString = pathAsString;
58     }
59
60     public Path(String JavaDoc[] chunks) {
61         this.chunks = chunks;
62     }
63
64     public String JavaDoc toString() {
65         if (pathAsString == null) {
66             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
67             for (int i = 0; i < chunks.length; i++) {
68                 if (i > 0) buffer.append('/');
69                 buffer.append(chunks[i]);
70             }
71             pathAsString = buffer.toString();
72         }
73         return pathAsString.toString();
74     }
75
76     public boolean equals(Object JavaDoc o) {
77         if (this == o) return true;
78         if (!(o instanceof Path)) return false;
79
80         final Path other = (Path) o;
81         if (chunks.length != other.chunks.length) return false;
82         for (int i = 0; i < chunks.length; i++) {
83             if (!chunks[i].equals(other.chunks[i])) return false;
84         }
85
86         return true;
87     }
88
89     public int hashCode() {
90         int result = 543645643;
91         for (int i = 0; i < chunks.length; i++) {
92             result = 29 * result + chunks[i].hashCode();
93         }
94         return result;
95     }
96
97     public Path relativeTo(Path that) {
98         int depthOfPathDivergence = depthOfPathDivergence(chunks, that.chunks);
99         String JavaDoc[] result = new String JavaDoc[chunks.length + that.chunks.length - 2 * depthOfPathDivergence];
100         int count = 0;
101
102         for (int i = depthOfPathDivergence; i < chunks.length; i++) {
103             result[count++] = "..";
104         }
105         for (int j = depthOfPathDivergence; j < that.chunks.length; j++) {
106             result[count++] = that.chunks[j];
107         }
108
109         if (count == 0) {
110             return DOT;
111         } else {
112             return new Path(result);
113         }
114     }
115
116     private int depthOfPathDivergence(String JavaDoc[] path1, String JavaDoc[] path2) {
117         int minLength = Math.min(path1.length, path2.length);
118         for (int i = 0; i < minLength; i++) {
119             if (!path1[i].equals(path2[i])) {
120                 return i;
121             }
122         }
123         return minLength;
124     }
125
126     public Path apply(Path relativePath) {
127         FastStack absoluteStack = new FastStack(16);
128
129         for (int i = 0; i < chunks.length; i++) {
130             absoluteStack.push(chunks[i]);
131         }
132
133         for (int i = 0; i < relativePath.chunks.length; i++) {
134             String JavaDoc relativeChunk = relativePath.chunks[i];
135             if (relativeChunk.equals("..")) {
136                 absoluteStack.pop();
137             } else if (!relativeChunk.equals(".")) {
138                 absoluteStack.push(relativeChunk);
139             }
140         }
141
142         String JavaDoc[] result = new String JavaDoc[absoluteStack.size()];
143         for (int i = 0; i < result.length; i++) {
144             result[i] = (String JavaDoc) absoluteStack.get(i);
145         }
146
147         return new Path(result);
148     }
149 }
150
Popular Tags