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 public boolean isChildOf(Path parent) { 140 if (parent.dir) { 141 int length = parent.names.length; 142 if (names.length == length + 1) { 143 for (int i = 0;i < length;i++) { 144 if (names[i].equals(parent.names[i])) { 145 return false; 146 } 147 } 148 return true; 149 } 150 } 151 return false; 152 } 153 154 @Override 155 public boolean equals(Object o) { 156 if (o == this) { 157 return true; 158 } 159 if (o instanceof Path) { 160 Path that = (Path)o; 161 int length = that.names.length; 162 if (names.length == length) { 163 for (int i = 0;i < length;i++) { 164 if (!names[i].equals(that.names[i])) { 165 return false; 166 } 167 } 168 return true; 169 } 170 } 171 return false; 172 } 173 174 @Override 175 public int hashCode() { 176 int hashCode = dir ? 1 : 0; 177 for (int i = names.length - 1;i >= 0;i--) { 178 hashCode = hashCode * 41 + names[i].hashCode(); 179 } 180 return hashCode; 181 } 182 183 public String getValue() { 184 if (value == null) { 185 StringBuilder sb = new StringBuilder(8 * names.length); 186 for (String name : names) { 187 sb.append('/').append(name); 188 } 189 if (dir) { 190 sb.append('/'); 191 } 192 value = sb.toString(); 193 } 194 return value; 195 } 196 197 public String toString() { 198 return "Path[value=" + getValue() + "]"; 199 } 200 }