1 19 20 package org.netbeans.modules.javacore.parser; 21 22 import java.util.Arrays ; 23 import java.util.HashMap ; 24 import java.util.List ; 25 import java.util.ArrayList ; 26 27 28 32 public class JavaDocParser { 33 34 private static final String TEXT_TAG_NAME = "@@@@@"; 36 protected String rawText; 37 protected JavaDocTag[] tags; 38 39 42 private static final String lineSeparator; 43 private static final int lineSeparatorLength; 44 45 static { 46 String sep = System.getProperty("line.separator"); if (sep == null || sep.equals("\n")) { lineSeparator = null; 49 lineSeparatorLength = 0; 50 } else { 51 lineSeparator = sep; 52 lineSeparatorLength = sep.length(); 53 } 54 } 55 56 57 59 60 public JavaDocParser(String rawText) { 61 this.rawText = rawText; 62 this.tags = null; 63 } 64 65 67 68 public JavaDocParser(JavaDocTag[] tags) { 69 this.rawText = null; 70 this.tags = tags; 71 } 72 73 public JavaDocParser(String text, JavaDocTag[] tags) { 74 this.rawText = null; 75 if (text == null) { 76 this.tags = tags; 77 } 78 else { 79 int newSize = (tags != null) ? tags.length+1 : 1; 80 JavaDocTag[] newTags = new JavaDocTag[newSize]; 81 newTags[0] = new JavaDocTag(TEXT_TAG_NAME, text); 82 if (tags != null) 83 System.arraycopy(tags, 0, newTags, 1, tags.length); 84 this.tags = newTags; 85 } 86 } 87 88 91 public String getRawText() { 92 return getRawText(false); 93 } 94 public String getRawText(boolean reorder) { 95 if (rawText != null && !reorder) 96 return rawText; 97 if (rawText != null) 98 tags = getTags(); 99 if (reorder) 100 Arrays.sort(tags); 101 String javadocContent = buildComment(tags); 102 return javadocContent; 104 } 105 106 108 public void clearJavaDoc() { 109 rawText = null; 110 } 111 112 115 public boolean isEmpty() { 116 return rawText == null; 117 } 118 119 121 public JavaDocTag[] getTags() { 122 if (tags != null) 123 return tags; 124 125 if ( rawText == null ) 126 return null; 127 128 List tagList = new ArrayList (); 129 int[] textIndexes = removeJavaDocStars(getRawText()); 130 parseComment(tagList, getRawText(), textIndexes); 131 132 JavaDocTag[] tagArray = new JavaDocTag[tagList.size()]; 133 tagList.toArray(tagArray); 134 return tagArray; 135 } 136 137 139 public JavaDocTag[] getTags(String name) { 140 JavaDocTag[] allTags = getTags(); 141 ArrayList resultList = new ArrayList ( allTags.length ); 142 143 for( int i = 0; i < allTags.length; i++ ) { 144 if (allTags[i].getName().equals(name)) 145 resultList.add(allTags[i]); 146 } 147 148 JavaDocTag result[] = new JavaDocTag[resultList.size()]; 149 resultList.toArray(result); 150 return result; 151 } 152 153 155 158 159 private void parseComment(List tagList, String textWithStars, int[] textIndexes) { 160 final int IN_TEXT = 1; 161 final int TAG_GAP = 2; 162 final int TAG_NAME = 3; 163 final int TAG_TEXT = 4; 164 165 int state = IN_TEXT; 166 167 boolean newLine = true; 168 169 int tagStart = 0; 170 int tagEnd = 0; 171 int textStart = 0; 172 int textEnd = 0; 173 int lastNonWhite = -1; 174 String rawText = rebuildText(textWithStars, textIndexes); 175 int len = rawText.length(); 178 179 for (int i = 0; i < len; ++i) { 180 181 char ch = rawText.charAt(i); 182 boolean isWhite = Character.isWhitespace(ch); 183 184 switch (state) { 185 case IN_TEXT: 186 if (newLine && ch == '@') { 187 parseCommentComponent(tagList, rawText, textIndexes, -1, -1, 0, textEnd); 188 tagStart = i; 189 state = TAG_NAME; 190 } 191 break; 192 case TAG_NAME: 193 if (isWhite) { 194 tagEnd = i; 195 state = TAG_GAP; 196 } 197 break; 198 case TAG_GAP: 199 if (isWhite) { 200 break; 201 } 202 textStart = i; 203 state = TAG_TEXT; 204 case TAG_TEXT: 206 if (newLine && ch == '@') { 207 parseCommentComponent(tagList, rawText, textIndexes, tagStart, tagEnd, textStart, lastNonWhite + 1); 208 tagStart = i; 209 state = TAG_NAME; 210 } 211 break; 212 } 213 214 if (lineSeparator != null && i + lineSeparatorLength <= len && rawText.regionMatches(i, lineSeparator, 0, lineSeparatorLength)) { 216 newLine = true; 217 if (state == IN_TEXT) { 218 textEnd = i; 219 } 220 i += lineSeparatorLength - 1; 222 } else if (ch == '\n') { 223 newLine = true; 224 if (state == IN_TEXT) { 225 textEnd = i; 226 } 227 } else if (!isWhite) { 228 lastNonWhite = i; 229 newLine = false; 230 } 231 } 232 233 switch (state) { 235 case TAG_NAME: 236 tagEnd = len; 237 238 case TAG_GAP: 239 textStart = len; 240 241 case TAG_TEXT: 242 case IN_TEXT: 243 parseCommentComponent(tagList, rawText, textIndexes, tagStart, tagEnd, textStart, lastNonWhite + 1); 244 break; 245 }; 246 247 } 248 249 253 private void parseCommentComponent(List tagList, String text, int[] textIndexes, int tagStart, int tagEnd, int textStart, int textEnd) { 254 String tagName = (tagStart < 0 || tagEnd < 0 || tagStart > tagEnd || (tagStart == 0 && tagEnd == 0)) ? TEXT_TAG_NAME : text.substring(tagStart, tagEnd); 257 String tx = (textStart < 0 || textEnd < 0 || textStart > textEnd) ? "" : text.substring(textStart, textEnd); 258 259 if (TEXT_TAG_NAME.equals(tagName)) { 260 JavaDocTag tag = new JavaDocTag(TEXT_TAG_NAME, tx, -1, -1, (textIndexes!=null)?textIndexes[textStart]:textStart, (textIndexes!=null)?textIndexes[textEnd]:textEnd); 261 tagList.add(tag); 262 } 263 else { 264 JavaDocTag tag = new JavaDocTag(tagName, tx, (textIndexes!=null)?textIndexes[tagStart]:tagStart, (textIndexes!=null)?textIndexes[tagEnd]:tagEnd, 265 (textIndexes!=null)?textIndexes[textStart]:textStart, (textIndexes!=null)?textIndexes[textEnd]:textEnd); 266 tagList.add(tag); 267 } 268 } 269 270 public int[] removeJavaDocStars(String rawText) { 271 final int SPACE_BEFORE=1; 272 final int ASTERIX=2; 273 final int SPACE_AFTER=3; 274 final int TEXT=4; 275 final int LINE_BREAK=5; 276 277 if (rawText == null || rawText.length() < 4) 278 return null; 279 280 int len = rawText.length(); 281 int text[] = new int[len]; 282 int i, j = 0; 283 int state = ASTERIX; 284 285 int start = rawText.indexOf("/*"); 286 int end = rawText.lastIndexOf("*/"); if (start == -1 || end == -1 || (start+2) > end) 288 return null; 289 int linebreak = -1; 290 291 for (i=start+2; i<end; i++) { 292 char ch = rawText.charAt(i); 293 if (ch=='\n' || ch=='\r') 294 linebreak = i; 295 else if (ch=='*' && linebreak >= 0) 296 linebreak = -1; 297 298 switch (state) { 299 case SPACE_BEFORE: 300 if (ch=='*') 301 state = ASTERIX; 302 else if (ch=='\n' || ch=='\r') 303 state = LINE_BREAK; 304 else if (ch!=' ' && ch!='\t') 305 state = TEXT; 306 break; 307 case SPACE_AFTER: 308 if (ch=='\n' || ch=='\r') 309 state = LINE_BREAK; 310 else if (ch!=' ' && ch!='\t') 311 state = TEXT; 312 break; 313 case ASTERIX: 314 if (ch=='\n' || ch=='\r') 315 state = LINE_BREAK; 316 else if (ch==' ' || ch=='\t') 317 state = SPACE_AFTER; 318 else if (ch != '*') 319 state = TEXT; 320 break; 321 case TEXT: 322 if (ch=='\n' || ch=='\r') 323 state = LINE_BREAK; 324 break; 325 case LINE_BREAK: 326 if (ch=='*') 327 state = ASTERIX; 328 else if (ch==' ' || ch=='\t') 329 state = SPACE_BEFORE; 330 else if (ch!='\n' && ch!='\r') 331 state = TEXT; 332 break; 333 } 334 335 if (state==LINE_BREAK || state==SPACE_AFTER) { 336 text[j++]=i; 337 } 338 else if (state==TEXT) { 339 if (linebreak != -1) { 340 for (int k = linebreak+1; k <= i; k++) { 341 text[j++]=k; 342 } 343 linebreak = -1; 344 } 345 else { 346 text[j++]=i; 347 } 348 } 349 } 350 351 int result[]; 352 if (j < len) { 353 result = new int[j]; 354 System.arraycopy(text, 0, result, 0, j); 355 } 356 else 357 result = text; 358 return result; 359 } 360 361 private String rebuildText(String text, int[] textIndexes) { 362 String rawText = text; 363 if (textIndexes != null) { 364 char[] rawTextChars = new char[textIndexes.length]; 365 for (int i = 0; i < textIndexes.length; i++) 366 rawTextChars[i] = text.charAt(textIndexes[i]); 367 rawText = new String (rawTextChars, 0, rawTextChars.length); 368 } 369 return rawText; 370 } 371 372 private String buildComment(JavaDocTag[] tags) { 373 if (tags == null) 374 return null; 375 if (tags.length == 0) 376 return ""; 377 378 String separator = (lineSeparator != null) ? lineSeparator : "\n"; String separator2 = separator+separator; 380 381 StringBuffer sb = new StringBuffer (); 382 for (int i = 0; i < tags.length; i++) { 383 if (TEXT_TAG_NAME.equals(tags[i].getName())) { 384 String value = tags[i].getValue(); 385 sb.append(value); 386 387 if (!value.endsWith(separator2)) { 388 if (!value.endsWith(separator)) { 389 sb.append('\n'); 390 } 391 sb.append('\n'); 392 } 393 } 394 else { 395 String value = tags[i].getValue(); 396 sb.append(tags[i].getName()).append(" ").append(value); if (!value.endsWith(separator)) { 398 sb.append(separator); 399 } 400 } 401 } 402 return sb.toString(); 403 } 404 405 411 public static String surroundWithJavaDocStars(String javadocContent) { 412 if (javadocContent == null) 413 return null; 414 415 String separator = "\n"; 417 StringBuffer sb = new StringBuffer ("/**\n *"); String [] tokens = javadocContent.split(separator); 419 for (int i = 0; i < tokens.length; i++) { 420 if (!tokens[i].startsWith(" ")) { 421 sb.append(' '); 422 } 423 sb.append(tokens[i]); 424 sb.append(separator).append(" *"); } 426 sb.append('/'); return sb.toString(); 428 } 429 430 431 public static class JavaDocTag implements Comparable { 432 public static final HashMap nameValues = new HashMap (); 433 static { 434 nameValues.put(TEXT_TAG_NAME, new Integer (1)); 435 nameValues.put("@author", new Integer (2)); nameValues.put("@version", new Integer (3)); nameValues.put("@param", new Integer (4)); nameValues.put("@return", new Integer (5)); nameValues.put("@exception", new Integer (6)); nameValues.put("@see", new Integer (7)); nameValues.put("@since", new Integer (8)); nameValues.put("@serial", new Integer (9)); nameValues.put("@deprecated", new Integer (10)); } 445 446 String name; 447 String text; 448 449 450 private int startName; 451 452 453 private int endName; 454 455 456 private int startText; 457 458 459 private int endText; 460 461 462 public JavaDocTag(String name, String text) { 463 this.name = name; 464 this.text = text; 465 startName = endName = startText = endText = -1; 466 } 467 468 JavaDocTag(String name, String text, int startName, int endName, int startText, int endText) { 469 this.name = name; 470 this.text = text; 471 this.startName = startName; 472 this.endName = endName; 473 this.startText = startText; 474 this.endText = endText; 475 } 476 477 public String toString() { 478 return name+" "+text; } 480 481 public String toInfo() { 482 return startName+","+endName+"{"+name+"} "+startText+","+endText+"{"+text+"}"; } 484 485 488 public String getName() { 489 return name; 490 } 491 492 495 public String getKind() { 496 return name; 497 } 498 499 public boolean isText() { 500 return TEXT_TAG_NAME.equals(getName()); 501 } 502 503 506 public String getValue() { 507 return text; 508 } 509 510 514 public int getStartName() { 515 return startName; 516 } 517 518 522 public int getEndName() { 523 return endName; 524 } 525 526 530 public int getStartText() { 531 return startText; 532 } 533 534 538 public int getEndText() { 539 return endText; 540 } 541 542 private int getNameValue(String name) { 543 Integer value = (Integer ) nameValues.get(name); 544 if (value != null) 545 return value.intValue(); 546 return 0; 547 } 548 549 public int compareTo(Object o) { 550 if (o == null || !(o instanceof JavaDocTag)) 551 return -1; 552 String name1 = getName(); 553 String name2 = ((JavaDocTag)o).getName(); 554 int value1 = getNameValue(name1); 555 int value2 = getNameValue(name2); 556 557 if (value1 > 0 && value2 > 0) { 558 return value1-value2; 559 } 560 else if (value1 >0) { 561 return -100; 562 } 563 else if (value2 >0) { 564 return 100; 565 } 566 return name1.compareTo(name2); 567 } 568 } 569 570 } 571 | Popular Tags |