Tue, 11 Dec 2012 15:05:55 -0800
8004828: refactor init of *DocImpl classes
Reviewed-by: darcy
1 /*
2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.tools.javadoc;
28 import java.io.DataInputStream;
29 import java.io.IOException;
30 import java.io.InputStream;
31 import java.text.CollationKey;
32 import java.util.regex.Matcher;
33 import java.util.regex.Pattern;
35 import javax.tools.FileObject;
37 import com.sun.javadoc.*;
38 import com.sun.source.util.TreePath;
39 import com.sun.tools.javac.tree.JCTree;
40 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
41 import com.sun.tools.javac.util.Position;
43 /**
44 * abstract base class of all Doc classes. Doc item's are representations
45 * of java language constructs (class, package, method,...) which have
46 * comments and have been processed by this run of javadoc. All Doc items
47 * are unique, that is, they are == comparable.
48 *
49 * <p><b>This is NOT part of any supported API.
50 * If you write code that depends on this, you do so at your own risk.
51 * This code and its internal interfaces are subject to change or
52 * deletion without notice.</b>
53 *
54 * @since 1.2
55 * @author Robert Field
56 * @author Atul M Dambalkar
57 * @author Neal Gafter (rewrite)
58 */
59 public abstract class DocImpl implements Doc, Comparable<Object> {
61 /**
62 * Doc environment
63 */
64 protected final DocEnv env; //### Rename this everywhere to 'docenv' ?
66 /**
67 * Back pointer to the tree node for this doc item.
68 * May be null if there is no associated tree.
69 */
70 protected TreePath treePath;
72 /**
73 * The complex comment object, lazily initialized.
74 */
75 private Comment comment;
77 /**
78 * The cached sort key, to take care of Natural Language Text sorting.
79 */
80 private CollationKey collationkey = null;
82 /**
83 * Raw documentation string.
84 */
85 protected String documentation; // Accessed in PackageDocImpl, RootDocImpl
87 /**
88 * Cached first sentence.
89 */
90 private Tag[] firstSentence;
92 /**
93 * Cached inline tags.
94 */
95 private Tag[] inlineTags;
97 /**
98 * Constructor.
99 */
100 DocImpl(DocEnv env, TreePath treePath) {
101 this.treePath = treePath;
102 this.documentation = getCommentText(treePath);
103 this.env = env;
104 }
106 private static String getCommentText(TreePath p) {
107 if (p == null)
108 return null;
110 JCCompilationUnit topLevel = (JCCompilationUnit) p.getCompilationUnit();
111 JCTree tree = (JCTree) p.getLeaf();
112 return topLevel.docComments.getCommentText(tree);
113 }
115 /**
116 * So subclasses have the option to do lazy initialization of
117 * "documentation" string.
118 */
119 protected String documentation() {
120 if (documentation == null) documentation = "";
121 return documentation;
122 }
124 /**
125 * For lazy initialization of comment.
126 */
127 Comment comment() {
128 if (comment == null) {
129 comment = new Comment(this, documentation());
130 }
131 return comment;
132 }
134 /**
135 * Return the text of the comment for this doc item.
136 * TagImpls have been removed.
137 */
138 public String commentText() {
139 return comment().commentText();
140 }
142 /**
143 * Return all tags in this Doc item.
144 *
145 * @return an array of TagImpl containing all tags on this Doc item.
146 */
147 public Tag[] tags() {
148 return comment().tags();
149 }
151 /**
152 * Return tags of the specified kind in this Doc item.
153 *
154 * @param tagname name of the tag kind to search for.
155 * @return an array of TagImpl containing all tags whose 'kind()'
156 * matches 'tagname'.
157 */
158 public Tag[] tags(String tagname) {
159 return comment().tags(tagname);
160 }
162 /**
163 * Return the see also tags in this Doc item.
164 *
165 * @return an array of SeeTag containing all @see tags.
166 */
167 public SeeTag[] seeTags() {
168 return comment().seeTags();
169 }
171 public Tag[] inlineTags() {
172 if (inlineTags == null) {
173 inlineTags = Comment.getInlineTags(this, commentText());
174 }
175 return inlineTags;
176 }
178 public Tag[] firstSentenceTags() {
179 if (firstSentence == null) {
180 //Parse all sentences first to avoid duplicate warnings.
181 inlineTags();
182 try {
183 env.setSilent(true);
184 firstSentence = Comment.firstSentenceTags(this, commentText());
185 } finally {
186 env.setSilent(false);
187 }
188 }
189 return firstSentence;
190 }
192 /**
193 * Utility for subclasses which read HTML documentation files.
194 */
195 String readHTMLDocumentation(InputStream input, FileObject filename) throws IOException {
196 byte[] filecontents = new byte[input.available()];
197 try {
198 DataInputStream dataIn = new DataInputStream(input);
199 dataIn.readFully(filecontents);
200 } finally {
201 input.close();
202 }
203 String encoding = env.getEncoding();
204 String rawDoc = (encoding!=null)
205 ? new String(filecontents, encoding)
206 : new String(filecontents);
207 Pattern bodyPat = Pattern.compile("(?is).*<body\\b[^>]*>(.*)</body\\b.*");
208 Matcher m = bodyPat.matcher(rawDoc);
209 if (m.matches()) {
210 return m.group(1);
211 } else {
212 String key = rawDoc.matches("(?is).*<body\\b.*")
213 ? "javadoc.End_body_missing_from_html_file"
214 : "javadoc.Body_missing_from_html_file";
215 env.error(SourcePositionImpl.make(filename, Position.NOPOS, null), key);
216 return "";
217 }
218 }
220 /**
221 * Return the full unprocessed text of the comment. Tags
222 * are included as text. Used mainly for store and retrieve
223 * operations like internalization.
224 */
225 public String getRawCommentText() {
226 return documentation();
227 }
229 /**
230 * Set the full unprocessed text of the comment. Tags
231 * are included as text. Used mainly for store and retrieve
232 * operations like internalization.
233 */
234 public void setRawCommentText(String rawDocumentation) {
235 treePath = null;
236 documentation = rawDocumentation;
237 comment = null;
238 }
240 /**
241 * Set the full unprocessed text of the comment and tree path.
242 */
243 void setTreePath(TreePath treePath) {
244 this.treePath = treePath;
245 documentation = getCommentText(treePath);
246 comment = null;
247 }
249 /**
250 * return a key for sorting.
251 */
252 CollationKey key() {
253 if (collationkey == null) {
254 collationkey = generateKey();
255 }
256 return collationkey;
257 }
259 /**
260 * Generate a key for sorting.
261 * <p>
262 * Default is name().
263 */
264 CollationKey generateKey() {
265 String k = name();
266 // System.out.println("COLLATION KEY FOR " + this + " is \"" + k + "\"");
267 return env.doclocale.collator.getCollationKey(k);
268 }
270 /**
271 * Returns a string representation of this Doc item.
272 */
273 @Override
274 public String toString() {
275 return qualifiedName();
276 }
278 /**
279 * Returns the name of this Doc item.
280 *
281 * @return the name
282 */
283 public abstract String name();
285 /**
286 * Returns the qualified name of this Doc item.
287 *
288 * @return the name
289 */
290 public abstract String qualifiedName();
292 /**
293 * Compares this Object with the specified Object for order. Returns a
294 * negative integer, zero, or a positive integer as this Object is less
295 * than, equal to, or greater than the given Object.
296 * <p>
297 * Included so that Doc item are java.lang.Comparable.
298 *
299 * @param obj the {@code Object} to be compared.
300 * @return a negative integer, zero, or a positive integer as this Object
301 * is less than, equal to, or greater than the given Object.
302 * @exception ClassCastException the specified Object's type prevents it
303 * from being compared to this Object.
304 */
305 public int compareTo(Object obj) {
306 // System.out.println("COMPARE \"" + this + "\" to \"" + obj + "\" = " + key().compareTo(((DocImpl)obj).key()));
307 return key().compareTo(((DocImpl)obj).key());
308 }
310 /**
311 * Is this Doc item a field? False until overridden.
312 *
313 * @return true if it represents a field
314 */
315 public boolean isField() {
316 return false;
317 }
319 /**
320 * Is this Doc item an enum constant? False until overridden.
321 *
322 * @return true if it represents an enum constant
323 */
324 public boolean isEnumConstant() {
325 return false;
326 }
328 /**
329 * Is this Doc item a constructor? False until overridden.
330 *
331 * @return true if it represents a constructor
332 */
333 public boolean isConstructor() {
334 return false;
335 }
337 /**
338 * Is this Doc item a method (but not a constructor or annotation
339 * type element)?
340 * False until overridden.
341 *
342 * @return true if it represents a method
343 */
344 public boolean isMethod() {
345 return false;
346 }
348 /**
349 * Is this Doc item an annotation type element?
350 * False until overridden.
351 *
352 * @return true if it represents an annotation type element
353 */
354 public boolean isAnnotationTypeElement() {
355 return false;
356 }
358 /**
359 * Is this Doc item a interface (but not an annotation type)?
360 * False until overridden.
361 *
362 * @return true if it represents a interface
363 */
364 public boolean isInterface() {
365 return false;
366 }
368 /**
369 * Is this Doc item a exception class? False until overridden.
370 *
371 * @return true if it represents a exception
372 */
373 public boolean isException() {
374 return false;
375 }
377 /**
378 * Is this Doc item a error class? False until overridden.
379 *
380 * @return true if it represents a error
381 */
382 public boolean isError() {
383 return false;
384 }
386 /**
387 * Is this Doc item an enum type? False until overridden.
388 *
389 * @return true if it represents an enum type
390 */
391 public boolean isEnum() {
392 return false;
393 }
395 /**
396 * Is this Doc item an annotation type? False until overridden.
397 *
398 * @return true if it represents an annotation type
399 */
400 public boolean isAnnotationType() {
401 return false;
402 }
404 /**
405 * Is this Doc item an ordinary class (i.e. not an interface,
406 * annotation type, enumeration, exception, or error)?
407 * False until overridden.
408 *
409 * @return true if it represents an ordinary class
410 */
411 public boolean isOrdinaryClass() {
412 return false;
413 }
415 /**
416 * Is this Doc item a class
417 * (and not an interface or annotation type)?
418 * This includes ordinary classes, enums, errors and exceptions.
419 * False until overridden.
420 *
421 * @return true if it represents a class
422 */
423 public boolean isClass() {
424 return false;
425 }
427 /**
428 * return true if this Doc is include in the active set.
429 */
430 public abstract boolean isIncluded();
432 /**
433 * Return the source position of the entity, or null if
434 * no position is available.
435 */
436 public SourcePosition position() { return null; }
437 }