001 /*
002 * Copyright (C) 2010 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 /**
026 * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
027 * @version $Revision$
028 */
029 public final class Path implements Iterable<String> {
030
031 /** . */
032 private final boolean dir;
033
034 /** . */
035 private final String[] names;
036
037 /** . */
038 private String value;
039
040 public static Path get(Path parent, String name, boolean dir) {
041 if (!parent.dir) {
042 throw new IllegalArgumentException("Not a dir");
043 }
044 int length = parent.names.length;
045 String[] names = new String[length + 1];
046 System.arraycopy(parent.names, 0, names, 0, length);
047 names[length] = name;
048 return new Path(dir, names);
049 }
050
051 public static Path get(String s) {
052 if (s.length() == 0) {
053 throw new IllegalArgumentException("No empty path");
054 }
055 if (s.charAt(0) != '/') {
056 throw new IllegalArgumentException("Path must begin with a '/'");
057 }
058
059 // Count
060 int end = s.length();
061
062 //
063 int count = 0;
064 int prev = 1;
065 while (true) {
066 int next = s.indexOf('/', prev);
067 if (next == -1) {
068 if (prev < end) {
069 count++;
070 }
071 break;
072 } else if (next - prev > 0) {
073 count++;
074 }
075 prev = next + 1;
076 }
077
078 //
079 String[] names = new String[count];
080 prev = 1;
081 count = 0;
082 boolean dir;
083 while (true) {
084 int next = s.indexOf('/', prev);
085 if (next == -1) {
086 if (prev < end) {
087 names[count] = s.substring(prev);
088 dir = false;
089 } else {
090 dir = true;
091 }
092 break;
093 } else if (next - prev > 0) {
094 names[count++] = s.substring(prev, next);
095 }
096 prev = next + 1;
097 }
098
099 //
100 return new Path(dir, names);
101 }
102
103 private Path(boolean dir, String[] names) {
104 this.dir = dir;
105 this.names = names;
106 }
107
108 public Iterator<String> iterator() {
109 return new Iterator<String>() {
110 int index = 0;
111 public boolean hasNext() {
112 return index < names.length;
113 }
114 public String next() {
115 if (index < names.length) {
116 return names[index++];
117 } else {
118 throw new NoSuchElementException();
119 }
120 }
121 public void remove() {
122 throw new UnsupportedOperationException();
123 }
124 };
125 }
126
127 public int getSize() {
128 return names.length;
129 }
130
131 public boolean isDir() {
132 return dir;
133 }
134
135 public String getName() {
136 return names.length > 0 ? names[names.length - 1] : "";
137 }
138
139 @Override
140 public boolean equals(Object o) {
141 if (o == this) {
142 return true;
143 }
144 if (o instanceof Path) {
145 Path that = (Path)o;
146 return dir == that.dir && super.equals(that);
147 }
148 return false;
149 }
150
151 public String getValue() {
152 if (value == null) {
153 StringBuilder sb = new StringBuilder(8 * names.length);
154 for (String name : names) {
155 sb.append('/').append(name);
156 }
157 if (dir) {
158 sb.append('/');
159 }
160 value = sb.toString();
161 }
162 return value;
163 }
164
165 @Override
166 public int hashCode() {
167 return super.hashCode() ^ (dir ? 1 : 0);
168 }
169
170 public String toString() {
171 return "Path[value=" + getValue() + "]";
172 }
173 }