DocTreeScanner.java revision 4278:a6cee0419f93
1/*
2 * Copyright (c) 2011, 2017, 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 */
25
26package com.sun.source.util;
27
28import com.sun.source.doctree.*;
29
30
31/**
32 * A TreeVisitor that visits all the child tree nodes.
33 * To visit nodes of a particular type, just override the
34 * corresponding visitXYZ method.
35 * Inside your method, call super.visitXYZ to visit descendant
36 * nodes.
37 *
38 * <p>The default implementation of the visitXYZ methods will determine
39 * a result as follows:
40 * <ul>
41 * <li>If the node being visited has no children, the result will be {@code null}.
42 * <li>If the node being visited has one child, the result will be the
43 * result of calling {@code scan} on that child. The child may be a simple node
44 * or itself a list of nodes.
45 * <li> If the node being visited has more than one child, the result will
46 * be determined by calling {@code scan} each child in turn, and then combining the
47 * result of each scan after the first with the cumulative result
48 * so far, as determined by the {@link #reduce} method. Each child may be either
49 * a simple node of a list of nodes. The default behavior of the {@code reduce}
50 * method is such that the result of the visitXYZ method will be the result of
51 * the last child scanned.
52 * </ul>
53 *
54 * <p>Here is an example to count the number of erroneous nodes in a tree:
55 * <pre>
56 *   class CountErrors extends DocTreeScanner&lt;Integer,Void&gt; {
57 *      {@literal @}Override
58 *      public Integer visitErroneous(ErroneousTree node, Void p) {
59 *          return 1;
60 *      }
61 *      {@literal @}Override
62 *      public Integer reduce(Integer r1, Integer r2) {
63 *          return (r1 == null ? 0 : r1) + (r2 == null ? 0 : r2);
64 *      }
65 *   }
66 * </pre>
67 *
68 * @since 1.8
69 */
70public class DocTreeScanner<R,P> implements DocTreeVisitor<R,P> {
71
72    /**
73     * Scans a single node.
74     * @param node the node to be scanned
75     * @param p a parameter value passed to the visit method
76     * @return the result value from the visit method
77     */
78    public R scan(DocTree node, P p) {
79        return (node == null) ? null : node.accept(this, p);
80    }
81
82    private R scanAndReduce(DocTree node, P p, R r) {
83        return reduce(scan(node, p), r);
84    }
85
86    /**
87     * Scans a sequence of nodes.
88     * @param nodes the nodes to be scanned
89     * @param p a parameter value to be passed to the visit method for each node
90     * @return the combined return value from the visit methods.
91     *      The values are combined using the {@link #reduce reduce} method.
92     */
93    public R scan(Iterable<? extends DocTree> nodes, P p) {
94        R r = null;
95        if (nodes != null) {
96            boolean first = true;
97            for (DocTree node : nodes) {
98                r = (first ? scan(node, p) : scanAndReduce(node, p, r));
99                first = false;
100            }
101        }
102        return r;
103    }
104
105    private R scanAndReduce(Iterable<? extends DocTree> nodes, P p, R r) {
106        return reduce(scan(nodes, p), r);
107    }
108
109    /**
110     * Reduces two results into a combined result.
111     * The default implementation is to return the first parameter.
112     * The general contract of the method is that it may take any action whatsoever.
113     * @param r1 the first of the values to be combined
114     * @param r2 the second of the values to be combined
115     * @return the result of combining the two parameters
116     */
117    public R reduce(R r1, R r2) {
118        return r1;
119    }
120
121
122/* ***************************************************************************
123 * Visitor methods
124 ****************************************************************************/
125
126    /**
127     * {@inheritDoc} This implementation returns {@code null}.
128     *
129     * @param node  {@inheritDoc}
130     * @param p  {@inheritDoc}
131     * @return the result of scanning
132     */
133    @Override
134    public R visitAttribute(AttributeTree node, P p) {
135        return null;
136    }
137
138    /**
139     * {@inheritDoc} This implementation scans the children in left to right order.
140     *
141     * @param node  {@inheritDoc}
142     * @param p  {@inheritDoc}
143     * @return the result of scanning
144     */
145    @Override
146    public R visitAuthor(AuthorTree node, P p) {
147        return scan(node.getName(), p);
148    }
149
150    /**
151     * {@inheritDoc} This implementation returns {@code null}.
152     *
153     * @param node  {@inheritDoc}
154     * @param p  {@inheritDoc}
155     * @return the result of scanning
156     */
157    @Override
158    public R visitComment(CommentTree node, P p) {
159        return null;
160    }
161
162    /**
163     * {@inheritDoc} This implementation scans the children in left to right order.
164     *
165     * @param node  {@inheritDoc}
166     * @param p  {@inheritDoc}
167     * @return the result of scanning
168     */
169    @Override
170    public R visitDeprecated(DeprecatedTree node, P p) {
171        return scan(node.getBody(), p);
172    }
173
174    /**
175     * {@inheritDoc} This implementation scans the children in left to right order.
176     *
177     * @param node  {@inheritDoc}
178     * @param p  {@inheritDoc}
179     * @return the result of scanning
180     */
181    @Override
182    public R visitDocComment(DocCommentTree node, P p) {
183        R r = scan(node.getFirstSentence(), p);
184        r = scanAndReduce(node.getBody(), p, r);
185        r = scanAndReduce(node.getBlockTags(), p, r);
186        return r;
187    }
188
189    /**
190     * {@inheritDoc} This implementation returns {@code null}.
191     *
192     * @param node  {@inheritDoc}
193     * @param p  {@inheritDoc}
194     * @return the result of scanning
195     */
196    @Override
197    public R visitDocRoot(DocRootTree node, P p) {
198        return null;
199    }
200
201    /**
202     * {@inheritDoc} This implementation returns {@code null}.
203     *
204     * @param node  {@inheritDoc}
205     * @param p  {@inheritDoc}
206     * @return the result of scanning
207     */
208    @Override
209    public R visitEndElement(EndElementTree node, P p) {
210        return null;
211    }
212
213    /**
214     * {@inheritDoc} This implementation returns {@code null}.
215     *
216     * @param node  {@inheritDoc}
217     * @param p  {@inheritDoc}
218     * @return the result of scanning
219     */
220    @Override
221    public R visitEntity(EntityTree node, P p) {
222        return null;
223    }
224
225    /**
226     * {@inheritDoc} This implementation returns {@code null}.
227     *
228     * @param node  {@inheritDoc}
229     * @param p  {@inheritDoc}
230     * @return the result of scanning
231     */
232    @Override
233    public R visitErroneous(ErroneousTree node, P p) {
234        return null;
235    }
236
237    /**
238     * {@inheritDoc} This implementation scans the children in left to right order.
239     *
240     * @param node  {@inheritDoc}
241     * @param p  {@inheritDoc}
242     * @return the result of scanning
243     */
244    @Override
245    public R visitHidden(HiddenTree node, P p) {
246        return scan(node.getBody(), p);
247    }
248
249    /**
250     * {@inheritDoc} This implementation returns {@code null}.
251     *
252     * @param node  {@inheritDoc}
253     * @param p  {@inheritDoc}
254     * @return the result of scanning
255     */
256    @Override
257    public R visitIdentifier(IdentifierTree node, P p) {
258        return null;
259    }
260
261    /**
262     * {@inheritDoc} This implementation returns {@code null}.
263     *
264     * @param node  {@inheritDoc}
265     * @param p  {@inheritDoc}
266     * @return the result of scanning
267     */
268    @Override
269    public R visitIndex(IndexTree node, P p) {
270        R r = scan(node.getSearchTerm(), p);
271        r = scanAndReduce(node.getDescription(), p, r);
272        return r;
273    }
274
275    /**
276     * {@inheritDoc} This implementation returns {@code null}.
277     *
278     * @param node  {@inheritDoc}
279     * @param p  {@inheritDoc}
280     * @return the result of scanning
281     */
282    @Override
283    public R visitInheritDoc(InheritDocTree node, P p) {
284        return null;
285    }
286
287    /**
288     * {@inheritDoc} This implementation scans the children in left to right order.
289     *
290     * @param node  {@inheritDoc}
291     * @param p  {@inheritDoc}
292     * @return the result of scanning
293     */
294    @Override
295    public R visitLink(LinkTree node, P p) {
296        R r = scan(node.getReference(), p);
297        r = scanAndReduce(node.getLabel(), p, r);
298        return r;
299    }
300
301    /**
302     * {@inheritDoc} This implementation returns {@code null}.
303     *
304     * @param node  {@inheritDoc}
305     * @param p  {@inheritDoc}
306     * @return the result of scanning
307     */
308    @Override
309    public R visitLiteral(LiteralTree node, P p) {
310        return null;
311    }
312
313    /**
314     * {@inheritDoc} This implementation scans the children in left to right order.
315     *
316     * @param node  {@inheritDoc}
317     * @param p  {@inheritDoc}
318     * @return the result of scanning
319     */
320    @Override
321    public R visitParam(ParamTree node, P p) {
322        R r = scan(node.getName(), p);
323        r = scanAndReduce(node.getDescription(), p, r);
324        return r;
325    }
326
327    /**
328     * {@inheritDoc} This implementation scans the children in left to right order.
329     *
330     * @param node  {@inheritDoc}
331     * @param p  {@inheritDoc}
332     * @return the result of scanning
333     */
334    @Override
335    public R visitProvides(ProvidesTree node, P p) {
336        R r = scan(node.getServiceType(), p);
337        r = scanAndReduce(node.getDescription(), p, r);
338        return r;
339    }
340
341    /**
342     * {@inheritDoc} This implementation returns {@code null}.
343     *
344     * @param node  {@inheritDoc}
345     * @param p  {@inheritDoc}
346     * @return the result of scanning
347     */
348    @Override
349    public R visitReference(ReferenceTree node, P p) {
350        return null;
351    }
352
353    /**
354     * {@inheritDoc} This implementation scans the children in left to right order.
355     *
356     * @param node  {@inheritDoc}
357     * @param p  {@inheritDoc}
358     * @return the result of scanning
359     */
360    @Override
361    public R visitReturn(ReturnTree node, P p) {
362        return scan(node.getDescription(), p);
363    }
364
365    /**
366     * {@inheritDoc} This implementation scans the children in left to right order.
367     *
368     * @param node  {@inheritDoc}
369     * @param p  {@inheritDoc}
370     * @return the result of scanning
371     */
372    @Override
373    public R visitSee(SeeTree node, P p) {
374        return scan(node.getReference(), p);
375    }
376
377    /**
378     * {@inheritDoc} This implementation scans the children in left to right order.
379     *
380     * @param node  {@inheritDoc}
381     * @param p  {@inheritDoc}
382     * @return the result of scanning
383     */
384    @Override
385    public R visitSerial(SerialTree node, P p) {
386        return scan(node.getDescription(), p);
387    }
388
389    /**
390     * {@inheritDoc} This implementation scans the children in left to right order.
391     *
392     * @param node  {@inheritDoc}
393     * @param p  {@inheritDoc}
394     * @return the result of scanning
395     */
396    @Override
397    public R visitSerialData(SerialDataTree node, P p) {
398        return scan(node.getDescription(), p);
399    }
400
401    /**
402     * {@inheritDoc} This implementation scans the children in left to right order.
403     *
404     * @param node  {@inheritDoc}
405     * @param p  {@inheritDoc}
406     * @return the result of scanning
407     */
408    @Override
409    public R visitSerialField(SerialFieldTree node, P p) {
410        R r = scan(node.getName(), p);
411        r = scanAndReduce(node.getType(), p, r);
412        r = scanAndReduce(node.getDescription(), p, r);
413        return r;
414    }
415
416    /**
417     * {@inheritDoc} This implementation scans the children in left to right order.
418     *
419     * @param node  {@inheritDoc}
420     * @param p  {@inheritDoc}
421     * @return the result of scanning
422     */
423    @Override
424    public R visitSince(SinceTree node, P p) {
425        return scan(node.getBody(), p);
426    }
427
428    /**
429     * {@inheritDoc} This implementation scans the children in left to right order.
430     *
431     * @param node  {@inheritDoc}
432     * @param p  {@inheritDoc}
433     * @return the result of scanning
434     */
435    @Override
436    public R visitStartElement(StartElementTree node, P p) {
437        return scan(node.getAttributes(), p);
438    }
439
440    /**
441     * {@inheritDoc} This implementation scans the children in left to right order.
442     *
443     * @param node  {@inheritDoc}
444     * @param p  {@inheritDoc}
445     * @return the result of scanning
446     * @since 10
447     */
448    @Override
449    public R visitSummary(SummaryTree node, P p) {
450        R r = scan(node.getSummary(), p);
451        return r;
452    }
453
454    /**
455     * {@inheritDoc} This implementation returns {@code null}.
456     *
457     * @param node  {@inheritDoc}
458     * @param p  {@inheritDoc}
459     * @return the result of scanning
460     */
461    @Override
462    public R visitText(TextTree node, P p) {
463        return null;
464    }
465
466    /**
467     * {@inheritDoc} This implementation scans the children in left to right order.
468     *
469     * @param node  {@inheritDoc}
470     * @param p  {@inheritDoc}
471     * @return the result of scanning
472     */
473    @Override
474    public R visitThrows(ThrowsTree node, P p) {
475        R r = scan(node.getExceptionName(), p);
476        r = scanAndReduce(node.getDescription(), p, r);
477        return r;
478    }
479
480    /**
481     * {@inheritDoc} This implementation scans the children in left to right order.
482     *
483     * @param node  {@inheritDoc}
484     * @param p  {@inheritDoc}
485     * @return the result of scanning
486     */
487    @Override
488    public R visitUnknownBlockTag(UnknownBlockTagTree node, P p) {
489        return scan(node.getContent(), p);
490    }
491
492    /**
493     * {@inheritDoc} This implementation scans the children in left to right order.
494     *
495     * @param node  {@inheritDoc}
496     * @param p  {@inheritDoc}
497     * @return the result of scanning
498     */
499    @Override
500    public R visitUnknownInlineTag(UnknownInlineTagTree node, P p) {
501        return scan(node.getContent(), p);
502    }
503
504    /**
505     * {@inheritDoc} This implementation scans the children in left to right order.
506     *
507     * @param node  {@inheritDoc}
508     * @param p  {@inheritDoc}
509     * @return the result of scanning
510     */
511    @Override
512    public R visitUses(UsesTree node, P p) {
513        R r = scan(node.getServiceType(), p);
514        r = scanAndReduce(node.getDescription(), p, r);
515        return r;
516    }
517
518    /**
519     * {@inheritDoc} This implementation scans the children in left to right order.
520     *
521     * @param node  {@inheritDoc}
522     * @param p  {@inheritDoc}
523     * @return the result of scanning
524     */
525    @Override
526    public R visitValue(ValueTree node, P p) {
527        return scan(node.getReference(), p);
528    }
529
530    /**
531     * {@inheritDoc} This implementation scans the children in left to right order.
532     *
533     * @param node  {@inheritDoc}
534     * @param p  {@inheritDoc}
535     * @return the result of scanning
536     */
537    @Override
538    public R visitVersion(VersionTree node, P p) {
539        return scan(node.getBody(), p);
540    }
541
542    /**
543     * {@inheritDoc} This implementation returns {@code null}.
544     *
545     * @param node  {@inheritDoc}
546     * @param p  {@inheritDoc}
547     * @return the result of scanning
548     */
549    @Override
550    public R visitOther(DocTree node, P p) {
551        return null;
552    }
553
554}
555