1 19 20 package org.netbeans.api.lexer; 21 22 import java.lang.ref.Reference ; 23 import java.lang.ref.SoftReference ; 24 import java.util.Map ; 25 import java.util.WeakHashMap ; 26 27 62 public final class LanguagePath { 63 64 67 private static final LanguagePath EMPTY = new LanguagePath(); 68 69 75 public static LanguagePath get(Language<? extends TokenId> language) { 76 return get(null, language); 77 } 78 79 93 public static LanguagePath get(LanguagePath prefix, Language<? extends TokenId> language) { 94 if (prefix == null) 95 prefix = EMPTY; 96 return prefix.createEmbedded(language); 97 } 98 99 104 private final Language<? extends TokenId>[] languages; 105 106 109 private Map <Language<? extends TokenId>, Reference <LanguagePath>> language2path; 110 111 114 private String mimePath; 115 116 117 private LanguagePath(LanguagePath prefix, Language<? extends TokenId> language) { 118 int prefixSize = prefix.size(); 119 this.languages = allocateLanguageArray(prefixSize + 1); 120 System.arraycopy(prefix.languages, 0, this.languages, 0, prefixSize); 121 this.languages[prefixSize] = language; 122 } 123 124 125 private LanguagePath() { 126 this.languages = allocateLanguageArray(0); 127 } 128 129 134 public int size() { 135 return languages.length; 136 } 137 138 148 public Language<? extends TokenId> language(int index) { 149 return languages[index]; 150 } 151 152 163 public boolean isLanguage(int index, Language<? extends TokenId> language) { 164 return (language(index) == language); 165 } 166 167 174 public Language<? extends TokenId> topLanguage() { 175 return language(0); 176 } 177 178 184 public boolean isTopLanguage(Language<? extends TokenId> language) { 185 return (topLanguage() == language); 186 } 187 188 195 public Language<? extends TokenId> innerLanguage() { 196 return language(size() - 1); 197 } 198 199 205 public boolean isInnerLanguage(Language<? extends TokenId> language) { 206 return (innerLanguage() == language); 207 } 208 209 219 public boolean endsWith(LanguagePath languagePath) { 220 if (languagePath == this || languagePath == EMPTY) 221 return true; 222 int lpSize = languagePath.size(); 223 if (lpSize <= size()) { 224 for (int i = 1; i <= lpSize; i++) { 225 if (language(size() - i) != languagePath.language(lpSize - i)) 226 return false; 227 } 228 return true; 229 } 230 return false; 231 } 232 233 239 public LanguagePath subPath(int startIndex) { 240 return subPath(startIndex, size()); 241 } 242 243 252 public LanguagePath subPath(int startIndex, int endIndex) { 253 if (startIndex < 0) { 254 throw new IndexOutOfBoundsException ("startIndex=" + startIndex + " < 0"); } 256 if (endIndex > size()) { 257 throw new IndexOutOfBoundsException ("endIndex=" + endIndex + " > size()=" + size()); 258 } 259 if (startIndex >= endIndex) { 260 throw new IndexOutOfBoundsException ("startIndex=" + startIndex + " >= endIndex=" + endIndex); 261 } 262 if (startIndex == 0 && endIndex == size()) { 263 return this; 264 } 265 LanguagePath lp = LanguagePath.get(language(startIndex++)); 266 while (startIndex < endIndex) { 267 lp = LanguagePath.get(lp, language(startIndex++)); 268 } 269 return lp; 270 } 271 272 291 public String mimePath() { 292 synchronized (languages) { 293 if (mimePath == null) { 294 StringBuilder sb = new StringBuilder (15 * languages.length); 295 for (Language<? extends TokenId> language : languages) { 296 if (sb.length() > 0) { 297 sb.append('/'); 298 } 299 sb.append(language.mimeType()); 300 } 301 mimePath = sb.toString().intern(); 303 } 304 return mimePath; 305 } 306 } 307 308 private LanguagePath createEmbedded(Language<? extends TokenId> language) { 309 if (language == null) { 310 throw new IllegalArgumentException ("language cannot be null"); 311 } 312 synchronized (languages) { 314 if (language2path == null) { 315 language2path = new WeakHashMap <Language<? extends TokenId>,Reference <LanguagePath>>(); 316 } 317 Reference <LanguagePath> lpRef = language2path.get(language); 318 LanguagePath lp; 319 if (lpRef == null || (lp = (LanguagePath)lpRef.get()) == null) { 320 lp = new LanguagePath(this, language); 322 language2path.put(language, new SoftReference <LanguagePath>(lp)); 323 } 324 325 return lp; 326 } 327 } 328 329 private Language<? extends TokenId>[] allocateLanguageArray(int length) { 330 return (Language<? extends TokenId>[])(new Language[length]); 331 } 332 333 public String toString() { 334 StringBuilder sb = new StringBuilder (); 335 sb.append("LanguagePath: size="); 336 sb.append(size()); 337 sb.append('\n'); 338 for (int i = 0; i < size(); i++) { 339 sb.append('[').append(i).append("]: "); sb.append(language(i)).append('\n'); 341 } 342 return sb.toString(); 343 } 344 345 } | Popular Tags |