View Javadoc

1   /*
2    * $Id: Path.java,v 1.2 2007/11/06 09:14:27 oeuillot Exp $
3    */
4   package org.rcfaces.core.internal.util;
5   
6   import java.util.ArrayList;
7   import java.util.Arrays;
8   import java.util.Collections;
9   import java.util.Iterator;
10  import java.util.List;
11  import java.util.StringTokenizer;
12  
13  import org.apache.commons.logging.Log;
14  import org.apache.commons.logging.LogFactory;
15  import org.rcfaces.core.internal.lang.StringAppender;
16  
17  /**
18   * 
19   * @author Olivier Oeuillot (latest modification by $Author: oeuillot $)
20   * @version $Revision: 1.2 $ $Date: 2007/11/06 09:14:27 $
21   */
22  public class Path implements IPath {
23      private static final String REVISION = "$Revision: 1.2 $";
24  
25      private static final Log LOG = LogFactory.getLog(Path.class);
26  
27      private List segments;
28  
29      private boolean absolute;
30  
31      private Path(List segments, boolean absolute) {
32          this.segments = new ArrayList(segments);
33          this.absolute = absolute;
34      }
35  
36      public Path(String path) {
37          StringTokenizer st = new StringTokenizer(path, "/", true);
38  
39          segments = new ArrayList(st.countTokens() / 2 + 2);
40  
41          for (; st.hasMoreTokens();) {
42              String token = st.nextToken();
43  
44              if (token.equals("/")) {
45                  if (segments.isEmpty()) {
46                      absolute = true;
47                  }
48  
49                  continue;
50              }
51  
52              segments.add(token);
53          }
54  
55          normalizePath(segments, absolute);
56      }
57  
58      public boolean isAbsolute() {
59          return absolute;
60      }
61  
62      public IPath makeAbsolute() {
63          if (absolute) {
64              return this;
65          }
66          return new Path(segments, true);
67      }
68  
69      public IPath makeRelative() {
70          if (absolute == false) {
71              return this;
72          }
73          return new Path(segments, false);
74      }
75  
76      public String segment(int index) {
77          if (index < 0 || index >= segments.size()) {
78              throw new IndexOutOfBoundsException();
79          }
80  
81          return (String) segments.get(index);
82      }
83  
84      public int segmentCount() {
85          return segments.size();
86      }
87  
88      public String[] segments() {
89          return (String[]) segments.toArray(new String[segments.size()]);
90      }
91  
92      public String lastSegment() {
93          return segment(segments.size() - 1);
94      }
95  
96      public IPath uptoSegment(int count) {
97          if (count < 1) {
98              return new Path(Collections.EMPTY_LIST, absolute);
99          }
100 
101         if (count >= segments.size()) {
102             return new Path(segments, absolute);
103         }
104 
105         return new Path(segments.subList(0, count), absolute);
106     }
107 
108     public IPath append(IPath path) {
109         if (path.isAbsolute()) {
110             return path;
111         }
112 
113         List l = new ArrayList(segments);
114 
115         l.addAll(Arrays.asList(path.segments()));
116 
117         normalizePath(l, absolute);
118 
119         return new Path(l, absolute);
120     }
121 
122     public IPath removeFirstSegments(int count) {
123         if (count < 0 || count >= segments.size()) {
124             return new Path(Collections.EMPTY_LIST, absolute);
125         }
126 
127         return new Path(segments.subList(count, segments.size()), absolute);
128     }
129 
130     public IPath removeLastSegments(int count) {
131         return uptoSegment(segments.size() - count);
132     }
133 
134     public int hashCode() {
135         final int prime = 31;
136         int result = 1;
137         result = prime * result + (absolute ? 1231 : 1237);
138         result = prime * result
139                 + ((segments == null) ? 0 : segments.hashCode());
140         return result;
141     }
142 
143     public boolean equals(Object obj) {
144         if (this == obj)
145             return true;
146         if (obj == null)
147             return false;
148         if (getClass() != obj.getClass())
149             return false;
150         final Path other = (Path) obj;
151         if (absolute != other.absolute)
152             return false;
153         if (segments == null) {
154             if (other.segments != null)
155                 return false;
156         } else if (!segments.equals(other.segments))
157             return false;
158         return true;
159     }
160 
161     public String toString() {
162         StringAppender sa = new StringAppender(segments.size() * 16);
163 
164         boolean first = true;
165         for (Iterator it = segments.iterator(); it.hasNext();) {
166             if (first) {
167                 first = false;
168                 if (absolute) {
169                     sa.append('/');
170                 }
171             } else {
172                 sa.append('/');
173             }
174 
175             sa.append((String) it.next());
176         }
177 
178         return sa.toString();
179     }
180 
181     private static void normalizePath(List segments, boolean absolute) {
182         for (int i = 0; i < segments.size();) {
183             String segment = (String) segments.get(i);
184 
185             if (segment.length() == 0 || segment.equals(".")) {
186                 segments.remove(i);
187                 continue;
188             }
189 
190             if (segment.equals("..")) {
191                 if (i == 0) {
192                     if (absolute == false) {
193                         i++;
194                         continue;
195                     }
196                     segments.remove(i);
197                     continue;
198                 }
199 
200                 if (segments.get(i - 1).equals("..")) {
201                     i++;
202                     continue;
203                 }
204 
205                 segments.remove(i--);
206                 segments.remove(i);
207                 continue;
208             }
209 
210             i++;
211         }
212     }
213 }