Clover Coverage Report
Coverage timestamp: Fri May 24 2013 13:47:27 UTC
../../../../img/srcFileCovDistChart10.png 0% of files have more coverage
55   232   34   3.93
30   109   0.62   14
14     2.43  
1    
 
  Path       Line # 37 55 34 100% 1.0
 
  (51)
 
1    /* This file is part of the project "Hilbert II" - http://www.qedeq.org
2    *
3    * Copyright 2000-2013, Michael Meyling <mime@qedeq.org>.
4    *
5    * "Hilbert II" is free software; you can redistribute
6    * it and/or modify it under the terms of the GNU General Public
7    * License as published by the Free Software Foundation; either
8    * version 2 of the License, or (at your option) any later version.
9    *
10    * This program is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13    * GNU General Public License for more details.
14    */
15   
16    package org.qedeq.base.io;
17   
18    import java.util.ArrayList;
19    import java.util.List;
20   
21    import org.apache.commons.lang.ArrayUtils;
22    import org.qedeq.base.utility.EqualsUtility;
23    import org.qedeq.base.utility.StringUtility;
24   
25   
26    /**
27    * A file path that leads to a directory or file and is absolute or relative.
28    * This abstraction of a file location was done to create relative file paths.
29    * This class makes some assumptions about a file path:
30    * "/" is the directory separator, "/" is also the root directory and ".." specifies
31    * the parent directory. "." is the current directory.
32    * A directory path must end with a "/" if a path ends not with a "/" it will be a file path
33    * (but the empty path "" is a directory).
34    *
35    * @author Michael Meyling
36    */
 
37    public final class Path {
38   
39    /** Directories that build up the path. If this is an absolute path the first
40    * name is empty. */
41    private final String[] path;
42   
43    /** File name. */
44    private final String name;
45   
46    /**
47    * Create file with given path and name.
48    *
49    * @param filePath Path to file with "/" as directory name separator. Relative directories
50    * are removed from the file path if possible. Must not be
51    * <code>null</code>. Might be "" this is called the <em>empty path</em>.
52    */
 
53  1203 toggle public Path(final String filePath) {
54  1203 final String[] p = StringUtility.split(filePath, "/");
55  1202 name = p[p.length - 1];
56  1202 final String[] p2 = new String[p.length - 1];
57  1202 System.arraycopy(p, 0, p2, 0, p2.length);
58  1202 path = removeRelativeDirs(p2);
59    }
60   
61    /**
62    * Create file with given path and name. Relative directories are removed from
63    * the file path if possible.
64    *
65    * @param dirPath Directory path to file with "/" as directory name separator.
66    * This value can end with a "/" but it must not be <code>null</code>.
67    * @param fileName File name. It should not contain "/" but this is not checked.
68    */
 
69  1859 toggle public Path(final String dirPath, final String fileName) {
70  1859 this((dirPath.endsWith("/") ? StringUtility.split(dirPath.substring(0,
71    dirPath.length() - 1), "/") : StringUtility.split(dirPath, "/")), fileName);
72    }
73   
74    /**
75    * Create file with given path and name. Relative directories are removed
76    * from the file path if possible.
77    *
78    * @param dirNames Directory names. If this is an absolute path the first
79    * name is empty. Must not be <code>null</code>.
80    * @param fileName File name. It should not contain "/" but this is not checked.
81    */
 
82  1884 toggle public Path(final String[] dirNames, final String fileName) {
83  1884 path = removeRelativeDirs(dirNames);
84  1883 name = (fileName != null ? fileName : "");
85    }
86   
87    /**
88    * Create new file path relative to given one. If the original path or <code>filePath</code>
89    * is a relative path it will return <code>filePath</code>.
90    *
91    * @param filePath Path to file relative to <code>this</code>.
92    * @return Relative file path (if possible).
93    */
 
94  31 toggle public Path createRelative(final String filePath) {
95  31 final Path to = new Path(filePath);
96  31 if (isRelative()) {
97    // if from is relative, then we don't need to think further
98  9 return to;
99    }
100  22 if (to.isRelative()) {
101  2 return to;
102    }
103    // both are absolute so we try to navigate within the file system
104    // to get a relative path
105  20 int max = 0;
106  155 while (max < path.length && max < to.path.length) {
107  140 if (!"..".equals(path[max]) && EqualsUtility.equals(path[max], to.path[max])) {
108  135 max++;
109    } else {
110  5 break;
111    }
112    }
113  20 final String[] r = new String[path.length - max + to.path.length - max];
114  29 for (int i = max; i < path.length; i++) {
115  9 r[i - max] = "..";
116    }
117  33 for (int i = max; i < to.path.length; i++) {
118  13 r[i - max + path.length - max] = to.path[i];
119    }
120  20 return new Path(r, to.name);
121    }
122   
123    /**
124    * Describes this path a directory?
125    *
126    * @return Is directory?
127    */
 
128  17 toggle public boolean isDirectory() {
129  17 return name.length() == 0;
130    }
131   
132    /**
133    * Describes this path a file (and not a directory)?
134    *
135    * @return Is this a path to a file?
136    */
 
137  2 toggle public boolean isFile() {
138  2 return !isDirectory();
139    }
140   
141    /**
142    * Is this an absolute path? If first path directory name is empty or ends with ":"
143    * (MS windows tribute) this is the case.
144    *
145    * @return Is absolute path?
146    */
 
147  3046 toggle public boolean isAbsolute() {
148  3046 return path.length > 0 && (path[0].length() == 0 || path[0].endsWith(":"));
149    }
150   
151    /**
152    * Is this a relative path?
153    *
154    * @return Is this a relative path?
155    */
 
156  1200 toggle public boolean isRelative() {
157  1200 return !isAbsolute();
158    }
159   
160    /**
161    * Get filename. Is "" if this is a pure directory path.
162    *
163    * @return File name. Might be "" but not <code>null</code>.
164    */
 
165  1147 toggle public String getFileName() {
166  1147 return name;
167    }
168   
169    /**
170    * Get directory of this path. This might be a relative or absolute
171    * path and ends with "/". (Only the empty path "" has no ending "/".)
172    *
173    * @return Directory this path points to. Will end with "/" if this is not
174    * an empty path.
175    */
 
176  1147 toggle public String getDirectory() {
177  1147 StringBuffer result = new StringBuffer(256);
178  13578 for (int i = 0; i < path.length; i++) {
179  12431 result.append(path[i]).append("/");
180    }
181  1147 return result.toString();
182    }
183   
184    /**
185    * Remove ".." and "." directories out of path if possible.
186    *
187    * @param dirNames Directories that build up the path.
188    * @return Directories that build up the same path.
189    */
 
190  3086 toggle private String[] removeRelativeDirs(final String[] dirNames) {
191  3086 List d = new ArrayList();
192  19397 for (int i = 0; i < dirNames.length; i++) {
193  16312 d.add(dirNames[i]);
194    }
195  19397 for (int i = 0; i < d.size(); ) {
196  16312 if (i > 0 && "..".equals(d.get(i)) && !"".equals(d.get(i - 1))
197    && !"..".equals(d.get(i - 1))) {
198  766 d.remove(i - 1);
199  766 d.remove(i - 1);
200  766 i--;
201  15546 } else if (".".equals(d.get(i))) {
202  3 d.remove(i);
203    } else {
204  15543 i++;
205    }
206    }
207  3085 return (String[]) d.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
208    }
209   
 
210  3456 toggle public String toString() {
211  3456 StringBuffer result = new StringBuffer(256);
212  40845 for (int i = 0; i < path.length; i++) {
213  37389 result.append(path[i]).append("/");
214    }
215  3456 result.append(name);
216  3456 return result.toString();
217    }
218   
 
219  12 toggle public boolean equals(final Object obj) {
220  12 if (!(obj instanceof Path)) {
221  3 return false;
222    }
223  9 final Path other = (Path) obj;
224  9 return EqualsUtility.equals(path, other.path) && name.equals(other.name);
225    }
226   
 
227  4 toggle public int hashCode() {
228  4 return toString().hashCode();
229    }
230   
231    }
232