KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > src > JavaDocMemoryImpl


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.openide.src;
21
22 import java.util.List JavaDoc;
23 import java.util.ArrayList JavaDoc;
24
25 import org.openide.src.SourceException;
26 import org.openide.src.JavaDoc;
27 import org.openide.src.JavaDocTag;
28
29 /** Represents a JavaDoc comment block.
30 *
31 * @author Jaroslav Tulach, Petr Hrebejk, Petr Hamernik
32 */

33 class JavaDocMemoryImpl implements JavaDoc, java.io.Serializable JavaDoc {
34
35     protected String JavaDoc rawText;
36
37     private transient String JavaDoc text;
38
39     // PENDING - clear this
40

41     private static final JavaDocTagMemoryImpl[] EMPTY_ARRAY = new JavaDocTagMemoryImpl[] {};
42
43     /**
44      * Native line separator.
45      */

46     private static final String JavaDoc lineSeparator;
47     
48     /**
49      * length of the native line separator.
50      */

51     private static final int lineSeparatorLength;
52     
53     private static final char LINEFEED = '\n';
54     
55     static {
56         String JavaDoc sep = System.getProperty("line.separator"); // NOI18N
57
if (sep == null ||
58             sep.equals("\n")) { // NOI18N
59
lineSeparator = null;
60             lineSeparatorLength = 0;
61         } else {
62             lineSeparator = sep;
63             lineSeparatorLength = sep.length();
64         }
65     }
66
67
68     /** Constructs the JavaDoc object held in memory. Parses the tags from rawText
69      */

70
71     public JavaDocMemoryImpl( String JavaDoc rawText ) {
72         this.rawText = rawText;
73     }
74
75     /** Get the entire text of the comment.
76     * @return the whole text
77     */

78     public String JavaDoc getRawText () {
79         return rawText;
80     }
81
82     /** Set the raw text of the comment.
83     * @param s the whole text to set
84     * @exception SourceException if the modification cannot be performed
85     */

86     public void setRawText (String JavaDoc s) throws SourceException {
87         rawText = s;
88     }
89
90     /** Get the actual text, cleared of all (non-inline) tags.
91     * @return the plain text
92     */

93     public String JavaDoc getText () {
94         if ( rawText == null )
95             return ""; // NOI18N
96
List JavaDoc tmp = new ArrayList JavaDoc();
97         parseComment( tmp );
98         return text;
99     }
100
101     /** Set the actual text.
102     * @param s the actual text, without any (non-inline) tags
103     * @exception SourceException if the modification cannot be performed
104     */

105     public void setText (String JavaDoc s) throws SourceException {
106         // do a CRLF conversion because different line delimiters would
107
// only obscure the text later.
108
regenerateRawText( convertNewLines(s), getTags(), getSeeTags() );
109     }
110
111     /** Clears the javadoc from the source.
112     */

113     public void clearJavaDoc() throws SourceException {
114         rawText = null;
115     }
116
117     /** Test if this javadoc is empty.
118     * @return true if it is not generated to the source.
119     */

120     public boolean isEmpty() {
121         return rawText == null;
122     }
123
124     /** Gets all tags from comment.
125      */

126     public JavaDocTag[] getTags() {
127         if ( rawText == null )
128             return EMPTY_ARRAY;
129
130         List JavaDoc tagList = new ArrayList JavaDoc();
131
132         parseComment( tagList );
133
134         JavaDocTag[] tagArray = new JavaDocTag[ tagList.size() ];
135         tagList.toArray( tagArray );
136
137         return tagArray;
138     }
139
140     /** Gets all tags of given name
141      */

142     public JavaDocTag[] getTags( String JavaDoc name ) {
143         JavaDocTag[] allTags = getTags();
144         ArrayList JavaDoc resultList = new ArrayList JavaDoc( allTags.length );
145
146         for( int i = 0; i < allTags.length; i++ ) {
147             if ( allTags[i].name().equals( name ) )
148                 resultList.add( allTags[i] );
149         }
150
151         JavaDocTag result[] = new JavaDocTag[ resultList.size() ];
152         resultList.toArray( result );
153         return result;
154     }
155
156     /** Adds removes or sets tags used in this comment
157      * @param elems the new initializers
158      * @param action {@link #ADD}, {@link #REMOVE}, or {@link #SET}
159      * @exception SourceException if impossible
160      */

161     synchronized public void changeTags( JavaDocTag[] tags, int action ) throws SourceException {
162
163         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
164
165         switch ( action ) {
166         case ADD:
167         case SET:
168             sb.append( action == ADD ? getRawText() : getText() );
169             for( int i = 0; i < tags.length; i++ ) {
170                 sb.append( "\n" ).append( tags[i].toString() ); // NOI18N
171
}
172             setRawText( sb.toString() );
173             break;
174
175         case REMOVE:
176             JavaDocTag currTags[] = getTags();
177             sb.append( getText() );
178
179             for( int i = 0; i < currTags.length; i++ ) {
180                 boolean found = false;
181                 String JavaDoc strTag = currTags[i].toString();
182                 for( int j = 0; j < tags.length; j ++ ) {
183                     if ( strTag.equals( tags[j].toString() ) ) {
184                         found = true;
185                         break;
186                     }
187                 }
188                 if ( !found )
189                     sb.append( "\n" ).append( strTag ); // NOI18N
190
}
191             setRawText( sb.toString() );
192             break;
193         }
194     }
195
196     /** Gets all @see tags
197      */

198     public JavaDocTag.See[] getSeeTags() {
199
200         JavaDocTag[] allTags = getTags();
201         ArrayList JavaDoc resultList = new ArrayList JavaDoc( allTags.length );
202
203         for( int i = 0; i < allTags.length; i++ ) {
204             if ( allTags[i] instanceof JavaDocTag.See )
205                 resultList.add( allTags[i] );
206         }
207
208         JavaDocTag.See result[] = new JavaDocTag.See[ resultList.size() ];
209         resultList.toArray( result );
210         return result;
211     }
212
213
214     /** Regenerates the rawText form tags
215      */

216     protected void regenerateRawText( String JavaDoc text, JavaDocTag[] tags, JavaDocTag.See[] seeTags ) {
217         StringBuffer JavaDoc sb = new StringBuffer JavaDoc( text.length() + tags.length * 80 + seeTags.length * 80 );
218
219         sb.append( text );
220
221         for (int i = 0; i < tags.length; i++ ) {
222             sb.append( tags[i].toString() );
223         }
224
225         for (int i = 0; i < seeTags.length; i++ ) {
226             sb.append( seeTags[i].toString() );
227         }
228
229         rawText = sb.toString();
230     }
231
232
233     /** The JavaDoc of a class.
234     * Class javadoc adds no special tags.
235     */

236     static class Class extends JavaDocMemoryImpl implements JavaDoc.Class {
237         static final long serialVersionUID =3206093459760846163L;
238         Class( String JavaDoc rawText ) {
239             super( rawText );
240         }
241     }
242
243     /** The JavaDoc of a field.
244     * <p>Currently adds special @SerialField tag
245     */

246     static class Field extends JavaDocMemoryImpl implements JavaDoc.Field {
247
248         Field ( String JavaDoc rawText ) {
249             super( rawText );
250         }
251
252         /** Gets SerialField tags.
253         */

254         public JavaDocTag.SerialField[] getSerialFieldTags() {
255             JavaDocTag[] allTags = this.getTags();
256             ArrayList JavaDoc resultList = new ArrayList JavaDoc( allTags.length );
257
258             for( int i = 0; i < allTags.length; i++ ) {
259                 if ( allTags[i] instanceof JavaDocTag.SerialField )
260                     resultList.add( allTags[i] );
261             }
262
263             JavaDocTag.SerialField result[] = new JavaDocTag.SerialField[ resultList.size() ];
264             resultList.toArray( result );
265             return result;
266         }
267
268     }
269
270     /** The JavaDoc of a method. Adds two special tags: @para tag and @throws tag.
271     */

272     static class Method extends JavaDocMemoryImpl implements JavaDoc.Method {
273
274         Method ( String JavaDoc rawText ) {
275             super( rawText );
276         }
277
278         /** Gets param tags.
279         */

280         public JavaDocTag.Param[] getParamTags() {
281             JavaDocTag[] allTags = this.getTags();
282             ArrayList JavaDoc resultList = new ArrayList JavaDoc( allTags.length );
283
284             for( int i = 0; i < allTags.length; i++ ) {
285                 if ( allTags[i] instanceof JavaDocTag.Param )
286                     resultList.add( allTags[i] );
287             }
288
289             JavaDocTag.Param result[] = new JavaDocTag.Param[ resultList.size() ];
290             resultList.toArray( result );
291             return result;
292         }
293
294         /** Gets throws tags.
295         */

296         public JavaDocTag.Throws[] getThrowsTags() {
297             JavaDocTag[] allTags = this.getTags();
298             ArrayList JavaDoc resultList = new ArrayList JavaDoc( allTags.length );
299
300             for( int i = 0; i < allTags.length; i++ ) {
301                 if ( allTags[i] instanceof JavaDocTag.Throws )
302                     resultList.add( allTags[i] );
303             }
304
305             JavaDocTag.Throws result[] = new JavaDocTag.Throws[ resultList.size() ];
306             resultList.toArray( result );
307             return result;
308         }
309     }
310
311     // PRIVATE & UTILITY METHODS ----------------------------------------------------------
312

313     /**
314     * Parses the rawText and generates list of tags;
315     */

316
317     private void parseComment( List JavaDoc tagList ) {
318         final int IN_TEXT = 1;
319         final int TAG_GAP = 2;
320         final int TAG_NAME = 3;
321     final int TAG_TEXT = 4;
322
323         int state = IN_TEXT;
324
325     boolean newLine = true;
326     
327         String JavaDoc tagName = null;
328
329         int tagStart = 0;
330         int textStart = 0;
331     int textEnd = 0;
332         int lastNonWhite = -1;
333         int len = rawText.length();
334
335         for (int inx = 0; inx < len; ++inx) {
336
337             char ch = rawText.charAt(inx);
338             boolean isWhite = Character.isWhitespace(ch);
339         
340         switch (state) {
341             case IN_TEXT:
342             if (newLine && ch == '@') {
343             parseCommentComponent(tagList, null, 0, textEnd);
344             tagStart = inx;
345             state = TAG_NAME;
346         }
347         break;
348         case TAG_NAME:
349         if (isWhite) {
350             tagName = rawText.substring(tagStart, inx);
351             state = TAG_GAP;
352         }
353         break;
354         case TAG_GAP:
355         if (isWhite) {
356             break;
357         }
358         textStart = inx;
359         state = TAG_TEXT;
360         // Fall through (in case of @tagname\n@anothertagname)
361
case TAG_TEXT:
362         if (newLine && ch == '@') {
363             parseCommentComponent(tagList, tagName, textStart, lastNonWhite + 1);
364             tagStart = inx;
365             state = TAG_NAME;
366         }
367         break;
368         }
369
370             // more idiot-proof check for newline terminator:
371
if (lineSeparator != null &&
372                 inx + lineSeparatorLength <= len &&
373                 rawText.regionMatches(inx, lineSeparator, 0, lineSeparatorLength)) {
374                 newLine = true;
375         if (state == IN_TEXT) {
376             textEnd = inx;
377         }
378                 // advance the scan pointer after the separator string.
379
inx += lineSeparatorLength - 1;
380             } else if (ch == '\n') {
381                 newLine = true;
382         if (state == IN_TEXT) {
383             textEnd = inx;
384         }
385             } else if (!isWhite) {
386                 lastNonWhite = inx;
387                 newLine = false;
388             }
389         }
390
391         // Finish what's currently being processed
392
switch (state) {
393         case TAG_NAME:
394             tagName = rawText.substring(tagStart, len);
395             /* fall thru */
396         case TAG_GAP:
397             textStart = len;
398             /* fall thru */
399     case TAG_TEXT:
400         case IN_TEXT:
401             parseCommentComponent(tagList, tagName, textStart, lastNonWhite + 1);
402             break;
403         };
404
405     }
406
407     /**
408      * Parses the tag.
409      * Saves away the last parsed item.
410      */

411     private void parseCommentComponent( List JavaDoc tagList, String JavaDoc tagName, int from, int upto) {
412         String JavaDoc tx = upto <= from ? "" : rawText.substring(from, upto); // NOI18N
413
if (tagName == null) {
414             text = tx;
415         }
416         else {
417             JavaDocTagMemoryImpl tag;
418             if (tagName.equals("@exception") || tagName.equals("@throws")) { // NOI18N
419
warnIfEmpty(tagName, tx);
420                 tag = new JavaDocTagMemoryImpl.Throws(tagName, tx);
421             }
422             else if (tagName.equals("@param")) { // NOI18N
423
warnIfEmpty(tagName, tx);
424                 tag = new JavaDocTagMemoryImpl.Param(tagName, tx);
425             }
426             else if (tagName.equals("@see")) { // NOI18N
427
warnIfEmpty( tagName, tx);
428                 tag = new JavaDocTagMemoryImpl.See(tagName, tx);
429             }
430             else if (tagName.equals("@serialField")) { // NOI18N
431
warnIfEmpty( tagName, tx);
432                 tag = new JavaDocTagMemoryImpl.SerialField(tagName, tx);
433             }
434             else if (tagName.equals("@return")) { // NOI18N
435
warnIfEmpty(tagName, tx);
436                 tag = new JavaDocTagMemoryImpl(tagName, tx);
437             }
438             else if (tagName.equals("@author")) { // NOI18N
439
warnIfEmpty(tagName, tx);
440                 tag = new JavaDocTagMemoryImpl(tagName, tx);
441             }
442             else if (tagName.equals("@version")) { // NOI18N
443
warnIfEmpty( tagName, tx);
444                 tag = new JavaDocTagMemoryImpl(tagName, tx);
445             }
446             else {
447                 tag = new JavaDocTagMemoryImpl(tagName, tx);
448             }
449             tagList.add(tag);
450         }
451     }
452
453
454     // PENDING : REMOVE THIS METHOD
455
private void warnIfEmpty( String JavaDoc tagName, String JavaDoc tx) {
456         /*
457         if (tx.length() == 0) {
458           System.out.println("tag.tag_has_no_arguments" + tagName); // NOI18N
459     }
460         */

461     }
462     
463     static String JavaDoc convertNewLines(String JavaDoc input) {
464         if (lineSeparator == null)
465             return input;
466
467         int firstIndex;
468         /*System.err.println("original length = " + input.length()); // NOI18N
469         for (int i = 0; i < input.length(); i++) {
470             System.err.print(((int)input.charAt(i)) + ", ");
471         }
472     */

473         firstIndex = input.indexOf(lineSeparator);
474         if (firstIndex == -1)
475             return input;
476         // replace from the beginning to the firstIndex
477
StringBuffer JavaDoc result = new StringBuffer JavaDoc();
478         char[] contents = input.toCharArray();
479         if (firstIndex > 0)
480             result.append(contents, 0, firstIndex);
481         result.append(LINEFEED);
482
483         firstIndex += lineSeparatorLength;
484         int lastPos = firstIndex;
485         while (firstIndex < contents.length) {
486             firstIndex = input.indexOf(lineSeparator, firstIndex);
487             if (firstIndex == -1) {
488                 // put there the rest of the string.
489
result.append(contents, lastPos, contents.length - lastPos);
490                 return result.toString();
491             }
492             // put the portion not containing the separator.
493
result.append(contents, lastPos, firstIndex - lastPos);
494             result.append(LINEFEED);
495             firstIndex += lineSeparatorLength;
496             lastPos = firstIndex;
497         }
498         // execution comes here only if the line.sep is the last thing
499
// in the string.
500
result.append(contents, lastPos, firstIndex - lastPos);
501         //System.err.println("result length = " + result.length()); // NOI18N
502
return result.toString();
503     }
504
505 }
506
Popular Tags