001 /*
002 * Copyright (C) 2012 eXo Platform SAS.
003 *
004 * This is free software; you can redistribute it and/or modify it
005 * under the terms of the GNU Lesser General Public License as
006 * published by the Free Software Foundation; either version 2.1 of
007 * the License, or (at your option) any later version.
008 *
009 * This software is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * You should have received a copy of the GNU Lesser General Public
015 * License along with this software; if not, write to the Free
016 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018 */
019
020 package org.crsh.vfs;
021
022 import java.util.Iterator;
023 import java.util.NoSuchElementException;
024
025 public final class Path implements Iterable<String> {
026
027 /** . */
028 private final boolean dir;
029
030 /** . */
031 private final String[] names;
032
033 /** . */
034 private String value;
035
036 public static Path get(Path parent, String name, boolean dir) {
037 if (!parent.dir) {
038 throw new IllegalArgumentException("Not a dir");
039 }
040 int length = parent.names.length;
041 String[] names = new String[length + 1];
042 System.arraycopy(parent.names, 0, names, 0, length);
043 names[length] = name;
044 return new Path(dir, names);
045 }
046
047 public static Path get(String s) {
048 if (s.length() == 0) {
049 throw new IllegalArgumentException("No empty path");
050 }
051 if (s.charAt(0) != '/') {
052 throw new IllegalArgumentException("Path must begin with a '/'");
053 }
054
055 // Count
056 int end = s.length();
057
058 //
059 int count = 0;
060 int prev = 1;
061 while (true) {
062 int next = s.indexOf('/', prev);
063 if (next == -1) {
064 if (prev < end) {
065 count++;
066 }
067 break;
068 } else if (next - prev > 0) {
069 count++;
070 }
071 prev = next + 1;
072 }
073
074 //
075 String[] names = new String[count];
076 prev = 1;
077 count = 0;
078 boolean dir;
079 while (true) {
080 int next = s.indexOf('/', prev);
081 if (next == -1) {
082 if (prev < end) {
083 names[count] = s.substring(prev);
084 dir = false;
085 } else {
086 dir = true;
087 }
088 break;
089 } else if (next - prev > 0) {
090 names[count++] = s.substring(prev, next);
091 }
092 prev = next + 1;
093 }
094
095 //
096 return new Path(dir, names);
097 }
098
099 private Path(boolean dir, String[] names) {
100 this.dir = dir;
101 this.names = names;
102 }
103
104 public Iterator<String> iterator() {
105 return new Iterator<String>() {
106 int index = 0;
107 public boolean hasNext() {
108 return index < names.length;
109 }
110 public String next() {
111 if (index < names.length) {
112 return names[index++];
113 } else {
114 throw new NoSuchElementException();
115 }
116 }
117 public void remove() {
118 throw new UnsupportedOperationException();
119 }
120 };
121 }
122
123 public int getSize() {
124 return names.length;
125 }
126
127 public boolean isDir() {
128 return dir;
129 }
130
131 public String getName() {
132 return names.length > 0 ? names[names.length - 1] : "";
133 }
134
135 public boolean isChildOf(Path parent) {
136 if (parent.dir) {
137 int length = parent.names.length;
138 if (names.length == length + 1) {
139 for (int i = 0;i < length;i++) {
140 if (names[i].equals(parent.names[i])) {
141 return false;
142 }
143 }
144 return true;
145 }
146 }
147 return false;
148 }
149
150 @Override
151 public boolean equals(Object o) {
152 if (o == this) {
153 return true;
154 }
155 if (o instanceof Path) {
156 Path that = (Path)o;
157 int length = that.names.length;
158 if (names.length == length) {
159 for (int i = 0;i < length;i++) {
160 if (!names[i].equals(that.names[i])) {
161 return false;
162 }
163 }
164 return true;
165 }
166 }
167 return false;
168 }
169
170 @Override
171 public int hashCode() {
172 int hashCode = dir ? 1 : 0;
173 for (int i = names.length - 1;i >= 0;i--) {
174 hashCode = hashCode * 41 + names[i].hashCode();
175 }
176 return hashCode;
177 }
178
179 public String getValue() {
180 if (value == null) {
181 StringBuilder sb = new StringBuilder(8 * names.length);
182 for (String name : names) {
183 sb.append('/').append(name);
184 }
185 if (dir) {
186 sb.append('/');
187 }
188 value = sb.toString();
189 }
190 return value;
191 }
192
193 public String toString() {
194 return "Path[value=" + getValue() + "]";
195 }
196 }