001: /*
002: * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.tools.javadoc;
027:
028: import com.sun.javadoc.*;
029:
030: import java.io.InputStream;
031: import java.io.IOException;
032: import java.text.CollationKey;
033: import com.sun.tools.javac.util.Position;
034:
035: /**
036: * abstract base class of all Doc classes. Doc item's are representations
037: * of java language constructs (class, package, method,...) which have
038: * comments and have been processed by this run of javadoc. All Doc items
039: * are unique, that is, they are == comparable.
040: *
041: * @since 1.2
042: * @author Robert Field
043: * @author Atul M Dambalkar
044: * @author Neal Gafter (rewrite)
045: */
046: abstract class DocImpl implements Doc, Comparable<Object> {
047:
048: /**
049: * Doc environment
050: */
051: protected final DocEnv env; //### Rename this everywhere to 'docenv' ?
052:
053: /**
054: * The complex comment object, lazily initialized.
055: */
056: private Comment comment;
057:
058: /**
059: * The cached sort key, to take care of Natural Language Text sorting.
060: */
061: private CollationKey collationkey = null;
062:
063: /**
064: * Raw documentation string.
065: */
066: protected String documentation; // Accessed in PackageDocImpl, RootDocImpl
067:
068: /**
069: * Cached first sentence.
070: */
071: private Tag[] firstSentence;
072:
073: /**
074: * Cached inline tags.
075: */
076: private Tag[] inlineTags;
077:
078: /**
079: * Constructor.
080: */
081: DocImpl(DocEnv env, String documentation) {
082: this .documentation = documentation;
083: this .env = env;
084: }
085:
086: /**
087: * So subclasses have the option to do lazy initialization of
088: * "documentation" string.
089: */
090: String documentation() {
091: if (documentation == null)
092: documentation = "";
093: return documentation;
094: }
095:
096: /**
097: * For lazy initialization of comment.
098: */
099: Comment comment() {
100: if (comment == null) {
101: comment = new Comment(this , documentation());
102: }
103: return comment;
104: }
105:
106: /**
107: * Return the text of the comment for this doc item.
108: * TagImpls have been removed.
109: */
110: public String commentText() {
111: return comment().commentText();
112: }
113:
114: /**
115: * Return all tags in this Doc item.
116: *
117: * @return an array of TagImpl containing all tags on this Doc item.
118: */
119: public Tag[] tags() {
120: return comment().tags();
121: }
122:
123: /**
124: * Return tags of the specified kind in this Doc item.
125: *
126: * @param tagname name of the tag kind to search for.
127: * @return an array of TagImpl containing all tags whose 'kind()'
128: * matches 'tagname'.
129: */
130: public Tag[] tags(String tagname) {
131: return comment().tags(tagname);
132: }
133:
134: /**
135: * Return the see also tags in this Doc item.
136: *
137: * @return an array of SeeTag containing all @see tags.
138: */
139: public SeeTag[] seeTags() {
140: return comment().seeTags();
141: }
142:
143: public Tag[] inlineTags() {
144: if (inlineTags == null) {
145: inlineTags = Comment.getInlineTags(this , commentText());
146: }
147: return inlineTags;
148: }
149:
150: public Tag[] firstSentenceTags() {
151: if (firstSentence == null) {
152: //Parse all sentences first to avoid duplicate warnings.
153: inlineTags();
154: try {
155: env.setSilent(true);
156: firstSentence = Comment.firstSentenceTags(this ,
157: commentText());
158: } finally {
159: env.setSilent(false);
160: }
161: }
162: return firstSentence;
163: }
164:
165: /**
166: * Utility for subclasses which read HTML documentation files.
167: */
168: String readHTMLDocumentation(InputStream input, String filename)
169: throws IOException {
170: int filesize = input.available();
171: byte[] filecontents = new byte[filesize];
172: input.read(filecontents, 0, filesize);
173: input.close();
174: String encoding = env.getEncoding();
175: String rawDoc = (encoding != null) ? new String(filecontents,
176: encoding) : new String(filecontents);
177: String upper = null;
178: int bodyIdx = rawDoc.indexOf("<body");
179: if (bodyIdx == -1) {
180: bodyIdx = rawDoc.indexOf("<BODY");
181: if (bodyIdx == -1) {
182: upper = rawDoc.toUpperCase();
183: bodyIdx = upper.indexOf("<BODY");
184: if (bodyIdx == -1) {
185: env.error(SourcePositionImpl.make(filename,
186: Position.NOPOS, null),
187: "javadoc.Body_missing_from_html_file");
188: return "";
189: }
190: }
191: }
192: bodyIdx = rawDoc.indexOf('>', bodyIdx);
193: if (bodyIdx == -1) {
194: env.error(SourcePositionImpl.make(filename, Position.NOPOS,
195: null), "javadoc.Body_missing_from_html_file");
196: return "";
197: }
198: ++bodyIdx;
199: int endIdx = rawDoc.indexOf("</body", bodyIdx);
200: if (endIdx == -1) {
201: endIdx = rawDoc.indexOf("</BODY", bodyIdx);
202: if (endIdx == -1) {
203: if (upper == null) {
204: upper = rawDoc.toUpperCase();
205: }
206: endIdx = upper.indexOf("</BODY", bodyIdx);
207: if (endIdx == -1) {
208: env.error(SourcePositionImpl.make(filename,
209: Position.NOPOS, null),
210: "javadoc.End_body_missing_from_html_file");
211: return "";
212: }
213: }
214: }
215: return rawDoc.substring(bodyIdx, endIdx);
216: }
217:
218: /**
219: * Return the full unprocessed text of the comment. Tags
220: * are included as text. Used mainly for store and retrieve
221: * operations like internalization.
222: */
223: public String getRawCommentText() {
224: return documentation();
225: }
226:
227: /**
228: * Set the full unprocessed text of the comment. Tags
229: * are included as text. Used mainly for store and retrieve
230: * operations like internalization.
231: */
232: public void setRawCommentText(String rawDocumentation) {
233: documentation = rawDocumentation;
234: comment = null;
235: }
236:
237: /**
238: * return a key for sorting.
239: */
240: CollationKey key() {
241: if (collationkey == null) {
242: collationkey = generateKey();
243: }
244: return collationkey;
245: }
246:
247: /**
248: * Generate a key for sorting.
249: * <p>
250: * Default is name().
251: */
252: CollationKey generateKey() {
253: String k = name();
254: // System.out.println("COLLATION KEY FOR " + this + " is \"" + k + "\"");
255: return env.doclocale.collator.getCollationKey(k);
256: }
257:
258: /**
259: * Returns a string representation of this Doc item.
260: */
261: public String toString() {
262: return qualifiedName();
263: }
264:
265: /**
266: * Returns the name of this Doc item.
267: *
268: * @return the name
269: */
270: public abstract String name();
271:
272: /**
273: * Returns the qualified name of this Doc item.
274: *
275: * @return the name
276: */
277: public abstract String qualifiedName();
278:
279: /**
280: * Compares this Object with the specified Object for order. Returns a
281: * negative integer, zero, or a positive integer as this Object is less
282: * than, equal to, or greater than the given Object.
283: * <p>
284: * Included so that Doc item are java.lang.Comparable.
285: *
286: * @param o the <code>Object</code> to be compared.
287: * @return a negative integer, zero, or a positive integer as this Object
288: * is less than, equal to, or greater than the given Object.
289: * @exception ClassCastException the specified Object's type prevents it
290: * from being compared to this Object.
291: */
292: public int compareTo(Object obj) {
293: // System.out.println("COMPARE \"" + this + "\" to \"" + obj + "\" = " + key().compareTo(((DocImpl)obj).key()));
294: return key().compareTo(((DocImpl) obj).key());
295: }
296:
297: /**
298: * Is this Doc item a field? False until overridden.
299: *
300: * @return true if it represents a field
301: */
302: public boolean isField() {
303: return false;
304: }
305:
306: /**
307: * Is this Doc item an enum constant? False until overridden.
308: *
309: * @return true if it represents an enum constant
310: */
311: public boolean isEnumConstant() {
312: return false;
313: }
314:
315: /**
316: * Is this Doc item a constructor? False until overridden.
317: *
318: * @return true if it represents a constructor
319: */
320: public boolean isConstructor() {
321: return false;
322: }
323:
324: /**
325: * Is this Doc item a method (but not a constructor or annotation
326: * type element)?
327: * False until overridden.
328: *
329: * @return true if it represents a method
330: */
331: public boolean isMethod() {
332: return false;
333: }
334:
335: /**
336: * Is this Doc item an annotation type element?
337: * False until overridden.
338: *
339: * @return true if it represents an annotation type element
340: */
341: public boolean isAnnotationTypeElement() {
342: return false;
343: }
344:
345: /**
346: * Is this Doc item a interface (but not an annotation type)?
347: * False until overridden.
348: *
349: * @return true if it represents a interface
350: */
351: public boolean isInterface() {
352: return false;
353: }
354:
355: /**
356: * Is this Doc item a exception class? False until overridden.
357: *
358: * @return true if it represents a exception
359: */
360: public boolean isException() {
361: return false;
362: }
363:
364: /**
365: * Is this Doc item a error class? False until overridden.
366: *
367: * @return true if it represents a error
368: */
369: public boolean isError() {
370: return false;
371: }
372:
373: /**
374: * Is this Doc item an enum type? False until overridden.
375: *
376: * @return true if it represents an enum type
377: */
378: public boolean isEnum() {
379: return false;
380: }
381:
382: /**
383: * Is this Doc item an annotation type? False until overridden.
384: *
385: * @return true if it represents an annotation type
386: */
387: public boolean isAnnotationType() {
388: return false;
389: }
390:
391: /**
392: * Is this Doc item an ordinary class (i.e. not an interface,
393: * annotation type, enumeration, exception, or error)?
394: * False until overridden.
395: *
396: * @return true if it represents an ordinary class
397: */
398: public boolean isOrdinaryClass() {
399: return false;
400: }
401:
402: /**
403: * Is this Doc item a class
404: * (and not an interface or annotation type)?
405: * This includes ordinary classes, enums, errors and exceptions.
406: * False until overridden.
407: *
408: * @return true if it represents a class
409: */
410: public boolean isClass() {
411: return false;
412: }
413:
414: /**
415: * return true if this Doc is include in the active set.
416: */
417: public abstract boolean isIncluded();
418:
419: /**
420: * Return the source position of the entity, or null if
421: * no position is available.
422: */
423: public SourcePosition position() {
424: return null;
425: }
426: }
|