EMMA Coverage Report (generated Fri Feb 14 08:28:31 UTC 2014)
[all classes][org.qedeq.base.io]

COVERAGE SUMMARY FOR SOURCE FILE [Path.java]

nameclass, %method, %block, %line, %
Path.java100% (1/1)100% (14/14)100% (386/386)100% (59/59)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class Path100% (1/1)100% (14/14)100% (386/386)100% (59/59)
Path (String [], String): void 100% (1/1)100% (15/15)100% (4/4)
Path (String): void 100% (1/1)100% (33/33)100% (7/7)
Path (String, String): void 100% (1/1)100% (21/21)100% (2/2)
createRelative (String): Path 100% (1/1)100% (105/105)100% (15/15)
equals (Object): boolean 100% (1/1)100% (24/24)100% (4/4)
getDirectory (): String 100% (1/1)100% (26/26)100% (4/4)
getFileName (): String 100% (1/1)100% (3/3)100% (1/1)
hashCode (): int 100% (1/1)100% (4/4)100% (1/1)
isAbsolute (): boolean 100% (1/1)100% (21/21)100% (1/1)
isDirectory (): boolean 100% (1/1)100% (8/8)100% (1/1)
isFile (): boolean 100% (1/1)100% (7/7)100% (1/1)
isRelative (): boolean 100% (1/1)100% (7/7)100% (1/1)
removeRelativeDirs (String []): String [] 100% (1/1)100% (81/81)100% (12/12)
toString (): String 100% (1/1)100% (31/31)100% (5/5)

1/* This file is part of the project "Hilbert II" - http://www.qedeq.org
2 *
3 * Copyright 2000-2014,  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 
16package org.qedeq.base.io;
17 
18import java.util.ArrayList;
19import java.util.List;
20 
21import org.apache.commons.lang.ArrayUtils;
22import org.qedeq.base.utility.EqualsUtility;
23import 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 */
37public 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    public Path(final String filePath) {
54        final String[] p = StringUtility.split(filePath, "/");
55        name = p[p.length - 1];
56        final String[] p2 = new String[p.length - 1];
57        System.arraycopy(p, 0, p2, 0, p2.length);
58        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    public Path(final String dirPath, final String fileName) {
70        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    public Path(final String[] dirNames, final String fileName) {
83        path = removeRelativeDirs(dirNames);
84        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    public Path createRelative(final String filePath) {
95        final Path to = new Path(filePath);
96        if (isRelative()) {
97            // if from is relative, then we don't need to think further
98            return to;
99        }
100        if (to.isRelative()) {
101            return to;
102        }
103        // both are absolute so we try to navigate within the file system
104        // to get a relative path
105        int max = 0;
106        while (max < path.length && max < to.path.length) {
107            if (!"..".equals(path[max]) && EqualsUtility.equals(path[max], to.path[max])) {
108                max++;
109            } else {
110                break;
111            }
112        }
113        final String[] r = new String[path.length - max + to.path.length - max];
114        for (int i = max; i < path.length; i++) {
115            r[i - max] = "..";
116        }
117        for (int i = max; i < to.path.length; i++) {
118            r[i - max + path.length - max] = to.path[i];
119        }
120        return new Path(r, to.name);
121    }
122 
123    /**
124     * Describes this path a directory?
125     *
126     * @return  Is directory?
127     */
128    public boolean isDirectory() {
129        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    public boolean isFile() {
138        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    public boolean isAbsolute() {
148        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    public boolean isRelative() {
157        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    public String getFileName() {
166        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    public String getDirectory() {
177        StringBuffer result = new StringBuffer(256);
178        for (int i = 0; i < path.length; i++) {
179            result.append(path[i]).append("/");
180        }
181        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    private String[] removeRelativeDirs(final String[] dirNames) {
191        List d = new ArrayList();
192        for (int i = 0; i < dirNames.length; i++) {
193            d.add(dirNames[i]);
194        }
195        for (int i = 0; i < d.size(); ) {
196            if (i > 0 && "..".equals(d.get(i)) && !"".equals(d.get(i - 1))
197                    && !"..".equals(d.get(i - 1))) {
198                d.remove(i - 1);
199                d.remove(i - 1);
200                i--;
201            } else if (".".equals(d.get(i))) {
202                d.remove(i);
203            } else {
204                i++;
205            }
206        }
207        return (String[]) d.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
208    }
209 
210    public String toString() {
211        StringBuffer result = new StringBuffer(256);
212        for (int i = 0; i < path.length; i++) {
213            result.append(path[i]).append("/");
214        }
215        result.append(name);
216        return result.toString();
217    }
218 
219    public boolean equals(final Object obj) {
220        if (!(obj instanceof Path)) {
221            return false;
222        }
223        final Path other = (Path) obj;
224        return EqualsUtility.equals(path, other.path) && name.equals(other.name);
225    }
226 
227    public int hashCode() {
228        return toString().hashCode();
229    }
230 
231}
232 

[all classes][org.qedeq.base.io]
EMMA 2.1.5320 (stable) (C) Vladimir Roubtsov