1 package ch
.cyberduck
.core
;
4 * Copyright (c) 2005 David Kocher. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * Bug fixes, suggestions and comments should be sent to:
18 * dkocher@cyberduck.ch
21 import ch
.cyberduck
.core
.serializer
.Serializer
;
23 import java
.util
.EnumSet
;
24 import java
.util
.Objects
;
29 public class Path
extends AbstractPath
implements Referenceable
, Serializable
{
32 * The path delimiter for remote paths
34 public static final char DELIMITER
= '/';
36 * Reference to the parent
38 protected Path parent
;
40 * The absolute remote path
44 * An absolute reference here the symbolic link is pointing to
50 private EnumSet
<Type
> type
51 = EnumSet
.noneOf(Type
.class);
54 * Attributes denoting this path
56 private PathAttributes attributes
;
59 * @param parent the absolute directory
60 * @param name the file relative to param path
61 * @param type File type
63 public Path(final Path parent
, final String name
, final EnumSet
<Type
> type
) {
65 this.attributes
= new PathAttributes();
66 this.attributes
.setRegion(parent
.attributes
.getRegion());
67 this._setPath(parent
, name
);
71 * @param absolute The absolute path of the remote file
72 * @param type File type
74 public Path(final String absolute
, final EnumSet
<Type
> type
) {
76 this.attributes
= new PathAttributes();
77 this.setPath(absolute
);
81 * @param absolute The absolute path of the remote file
82 * @param attributes File type
84 public Path(final String absolute
, final EnumSet
<Type
> type
, final PathAttributes attributes
) {
86 this.attributes
= attributes
;
87 this.setPath(absolute
);
91 * @param parent Parent path reference
92 * @param name Filename
93 * @param attributes Attributes
95 public Path(final Path parent
, final String name
, final EnumSet
<Type
> type
, final PathAttributes attributes
) {
97 this.attributes
= attributes
;
98 this._setPath(parent
, name
);
102 public <T
> T
serialize(final Serializer dict
) {
103 dict
.setStringForKey(String
.valueOf(type
), "Type");
104 dict
.setStringForKey(this.getAbsolute(), "Remote");
105 if(symlink
!= null) {
106 dict
.setObjectForKey(symlink
, "Symbolic Link");
108 dict
.setObjectForKey(attributes
, "Attributes");
109 return dict
.getSerialized();
112 private void setPath(final String absolute
) {
113 if(absolute
.equals(String
.valueOf(Path
.DELIMITER
))) {
114 this._setPath(null, PathNormalizer
.name(absolute
));
117 final Path parent
= new Path(PathNormalizer
.parent(PathNormalizer
.normalize(absolute
, true), Path
.DELIMITER
),
118 EnumSet
.of(Type
.directory
));
119 parent
.attributes().setRegion(attributes
.getRegion());
120 if(parent
.isRoot()) {
121 parent
.setType(EnumSet
.of(Type
.volume
, Type
.directory
));
123 this._setPath(parent
, PathNormalizer
.name(absolute
));
127 private void _setPath(final Path parent
, final String name
) {
128 this.parent
= parent
;
133 if(parent
.isRoot()) {
134 this.path
= parent
.getAbsolute() + name
;
137 if(name
.startsWith(String
.valueOf(DELIMITER
))) {
138 this.path
= parent
.getAbsolute() + name
;
141 this.path
= parent
.getAbsolute() + Path
.DELIMITER
+ name
;
148 public EnumSet
<Type
> getType() {
152 public void setType(final EnumSet
<Type
> type
) {
156 public boolean isVolume() {
157 return type
.contains(Type
.volume
);
160 public boolean isDirectory() {
161 return type
.contains(Type
.directory
);
164 public boolean isPlaceholder() {
165 return type
.contains(Type
.placeholder
);
168 public boolean isFile() {
169 return type
.contains(Type
.file
);
172 public boolean isSymbolicLink() {
173 return type
.contains(Type
.symboliclink
);
177 public char getDelimiter() {
178 return String
.valueOf(DELIMITER
).charAt(0);
181 public Path
getParent() {
188 public PathAttributes
attributes() {
193 * @return the path relative to its parent directory
196 public String
getName() {
198 return String
.valueOf(DELIMITER
);
200 final String abs
= this.getAbsolute();
201 int index
= abs
.lastIndexOf(DELIMITER
);
202 return abs
.substring(index
+ 1);
206 * @return the absolute path name, e.g. /home/user/filename
209 public String
getAbsolute() {
214 * @return The target of the symbolic link if this path denotes a symbolic link
215 * @see #isSymbolicLink
217 public Path
getSymlinkTarget() {
221 public void setSymlinkTarget(final Path target
) {
222 this.symlink
= target
;
226 * @return The hashcode of #getAbsolute()
227 * @see #getAbsolute()
230 public int hashCode() {
231 return new DefaultPathReference(this).hashCode();
235 * @param other Path to compare with
236 * @return true if the other path has the same absolute path name
239 public boolean equals(Object other
) {
243 if(other
instanceof Path
) {
244 return new DefaultPathReference(this).equals(new DefaultPathReference((Path
) other
));
250 * @return The absolute path name
253 public String
toString() {
254 final StringBuilder sb
= new StringBuilder("Path{");
255 sb
.append("path='").append(path
).append('\'');
256 sb
.append(", type=").append(type
);
258 return sb
.toString();
262 * @param directory Parent directory
263 * @return True if this is a child in the path hierarchy of the argument passed
265 public boolean isChild(final Path directory
) {
266 if(directory
.isFile()) {
267 // If a file we don't have any children at all
271 // Root cannot be a child of any other path
274 if(directory
.isRoot()) {
275 // Any other path is a child
278 if(Objects
.equals(this.getParent(), directory
.getParent())) {
279 // Cannot be a child if the same parent
282 for(Path parent
= this.getParent(); !parent
.isRoot(); parent
= parent
.getParent()) {
283 if(parent
.equals(directory
)) {