1 /*
2  * Copyright (c) 1997, 2020, 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 
26 package jdk.javadoc.internal.doclets.toolkit;
27 
28 import java.io.ByteArrayOutputStream;
29 import java.io.IOException;
30 import java.io.OutputStream;
31 import java.io.OutputStreamWriter;
32 import java.io.UnsupportedEncodingException;
33 import java.util.ArrayList;
34 import java.util.Arrays;
35 import java.util.HashSet;
36 import java.util.LinkedHashSet;
37 import java.util.List;
38 import java.util.MissingResourceException;
39 import java.util.Set;
40 import java.util.StringTokenizer;
41 import java.util.TreeSet;
42 
43 import jdk.javadoc.doclet.Doclet;
44 import jdk.javadoc.doclet.Reporter;
45 import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
46 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
47 
48 import static javax.tools.Diagnostic.Kind.ERROR;
49 
50 /**
51  * Storage for the format-independent options supported by the toolkit.
52  * The objects to handle command-line options, and to initialize this
53  * object, are all subtypes of {@link BaseOptions.Option},
54  * returned by {@link BaseOptions#getSupportedOptions()}.
55  *
56  * <p>Some of the methods used to access the values of options
57  * have names that begin with a verb, such as {@link #copyDocfileSubdirs}
58  * or {@link #showVersion}. Unless otherwise stated,
59  * these methods should all be taken as just accessing the value
60  * of the associated option.
61  */
62 public abstract class BaseOptions {
63 
64     //<editor-fold desc="Option values">
65 
66     /**
67      * Argument for command-line option {@code --allow-script-in-comments}.
68      * Allow JavaScript in doc comments.
69      */
70     private boolean allowScriptInComments = false;
71 
72     /**
73      * Argument for command-line option {@code -docfilessubdirs}.
74      * True if we should recursively copy the doc-file subdirectories
75      */
76     private boolean copyDocfileSubdirs = false;
77 
78     /**
79      * Arguments for command-line option {@code -tag} and {@code -taglet}.
80      */
81     private final LinkedHashSet<List<String>> customTagStrs = new LinkedHashSet<>();
82 
83     /**
84      * Argument for command-line option {@code -d}.
85      * Destination directory name, in which doclet will generate the entire
86      * documentation. Default is current directory.
87      */
88     private String destDirName = "";
89 
90     /**
91      * Argument for command-line option {@code --disable-javafx-strict-checks}.
92      * Primarily used to disable strict checks in the regression
93      * tests allowing those tests to be executed successfully, for
94      * instance, with OpenJDK builds which may not contain FX libraries.
95      */
96     private boolean disableJavaFxStrictChecks = false;
97 
98     /**
99      * Argument for command-line option {@code -docencoding}.
100      * Encoding for this document. Default is default encoding for this
101      * platform.
102      */
103     private String docEncoding = null;
104 
105     /**
106      * Argument for command-line option {@code ???}.
107      * Destination directory name, in which doclet will copy the doc-files to.
108      */
109     private String docFileDestDirName = "";
110 
111     /**
112      * Argument for hidden command-line option {@code --dump-on-error}.
113      */
114     private boolean dumpOnError = false;
115 
116     /**
117      * Argument for command-line option {@code -encoding}.
118      * Encoding for this document. Default is default encoding for this
119      * platform.
120      */
121     private String encoding = null;
122 
123     /**
124      * Argument for command-line option {@code -excludedocfilessubdir}.
125      * The set of doc-file subdirectories to exclude.
126      */
127     private Set<String> excludedDocFileDirs;
128 
129     /**
130      * Argument for command-line option {@code -noqualifier}.
131      * The set of qualifiers to exclude.
132      */
133     private Set<String> excludedQualifiers;
134 
135     /**
136      * Arguments for command-line option {@code -group}
137      */
138     private List<Utils.Pair<String, String>> groupPairs;
139 
140     /**
141      * Argument for command-line option {@code --javafx} or {@code -javafx}.
142      * Generate documentation for JavaFX getters and setters automatically
143      * by copying it from the appropriate property definition.
144      */
145     private boolean javafx = false;
146 
147     /**
148      * Argument for command-line option {@code -keywords}.
149      * True if user wants to add member names as meta keywords.
150      * Set to false because meta keywords are ignored in general
151      * by most Internet search engines.
152      */
153     private boolean keywords = false;
154 
155     /**
156      * Arguments for command-line option {@code -link}.
157      */
158     // A list containing urls
159     private final List<String> linkList = new ArrayList<>();
160 
161     /**
162      * Arguments for command-line option {@code -linkoffline}.
163      */
164     // A list of pairs containing urls and package list
165     private final List<Utils.Pair<String, String>> linkOfflineList = new ArrayList<>();
166 
167     /**
168      * Argument for command-line option {@code -linksource}.
169      * True if we should generate browsable sources.
170      */
171     private boolean linkSource = false;
172 
173     /**
174      * Argument for command-line option {@code -nocomment}.
175      * True if user wants to suppress descriptions and tags.
176      */
177     private boolean noComment = false;
178 
179     /**
180      * Argument for command-line option {@code -nodeprecated}.
181      * Don't generate deprecated API information at all, if -nodeprecated
182      * option is used. <code>nodeprecated</code> is set to true if
183      * -nodeprecated option is used. Default is generate deprecated API
184      * information.
185      */
186     private boolean noDeprecated = false;
187 
188     /**
189      * Argument for command-line option {@code -nosince}.
190      * True if command-line option "-nosince" is used. Default value is
191      * false.
192      */
193     private boolean noSince = false;
194 
195     /**
196      * Argument for command-line option {@code -notimestamp}.
197      * True if user wants to suppress time stamp in output.
198      * Default is false.
199      */
200     private boolean noTimestamp = false;
201 
202     /**
203      * Argument for command-line option {@code -quiet}.
204      * Suppress all messages
205      */
206     private boolean quiet = false;
207 
208     /**
209      * Argument for command-line option {@code -serialwarn}.
210      * This is true if option "-serialwarn" is used. Default value is false to
211      * suppress excessive warnings about serial tag.
212      */
213     private boolean serialWarn = false;
214 
215     /**
216      * Argument for command-line option {@code -author}.
217      * Generate author specific information for all the classes if @author
218      * tag is used in the doc comment and if -author option is used.
219      * <code>showauthor</code> is set to true if -author option is used.
220      * Default is don't show author information.
221      */
222     private boolean showAuthor = false;
223 
224     /**
225      * Argument for command-line option {@code --show-taglets}.
226      * Show taglets (internal debug switch)
227      */
228     private boolean showTaglets = false;
229 
230     /**
231      * Argument for command-line option {@code -version}.
232      * Generate version specific information for the all the classes
233      * if @version tag is used in the doc comment and if -version option is
234      * used. {@code showVersion} is set to true if -version option is
235      * used. Default is don't show version information.
236      */
237     private boolean showVersion = false;
238 
239     /**
240      * Argument for command-line option {@code -sourcetab}.
241      * The specified amount of space between tab stops.
242      */
243     private int sourceTabSize;
244 
245     /**
246      * Value for command-line option {@code --override-methods summary}
247      * or  {@code --override-methods detail}.
248      * Specifies whether those methods that override a super-type's method
249      * with no changes to the API contract should be summarized in the
250      * footnote section.
251      */
252     private boolean summarizeOverriddenMethods = false;
253 
254     /**
255      * Argument for command-line option {@code -tagletpath}.
256      * The path to Taglets
257      */
258     private String tagletPath = null;
259 
260     //</editor-fold>
261 
262     private final BaseConfiguration config;
263 
BaseOptions(BaseConfiguration config)264     protected BaseOptions(BaseConfiguration config) {
265         this.config = config;
266 
267         excludedDocFileDirs = new HashSet<>();
268         excludedQualifiers = new HashSet<>();
269         sourceTabSize = DocletConstants.DEFAULT_TAB_STOP_LENGTH;
270         groupPairs = new ArrayList<>(0);
271     }
272 
getSupportedOptions()273     public Set<? extends Option> getSupportedOptions() {
274         Resources resources = config.getDocResources();
275         Messages messages = config.getMessages();
276         Reporter reporter = config.getReporter();
277 
278         List<Option> options = List.of(
279                 new Option(resources, "-author") {
280                     @Override
281                     public boolean process(String opt, List<String> args) {
282                         showAuthor = true;
283                         return true;
284                     }
285                 },
286 
287                 new Option(resources, "-d", 1) {
288                     @Override
289                     public boolean process(String opt, List<String> args) {
290                         destDirName = addTrailingFileSep(args.get(0));
291                         return true;
292                     }
293                 },
294 
295                 new Option(resources, "-docencoding", 1) {
296                     @Override
297                     public boolean process(String opt, List<String> args) {
298                         docEncoding = args.get(0);
299                         return true;
300                     }
301                 },
302 
303                 new Option(resources, "-docfilessubdirs") {
304                     @Override
305                     public boolean process(String opt, List<String> args) {
306                         copyDocfileSubdirs = true;
307                         return true;
308                     }
309                 },
310 
311                 new Hidden(resources, "-encoding", 1) {
312                     @Override
313                     public boolean process(String opt, List<String> args) {
314                         encoding = args.get(0);
315                         return true;
316                     }
317                 },
318 
319                 new Option(resources, "-excludedocfilessubdir", 1) {
320                     @Override
321                     public boolean process(String opt, List<String> args) {
322                         addToSet(excludedDocFileDirs, args.get(0));
323                         return true;
324                     }
325                 },
326 
327                 new Option(resources, "-group", 2) {
328                     @Override
329                     public boolean process(String opt, List<String> args) {
330                         groupPairs.add(new Utils.Pair<>(args.get(0), args.get(1)));
331                         return true;
332                     }
333                 },
334 
335                 new Option(resources, "--javafx -javafx") {
336                     @Override
337                     public boolean process(String opt, List<String> args) {
338                         javafx = true;
339                         return true;
340                     }
341                 },
342 
343                 new Option(resources, "-keywords") {
344                     @Override
345                     public boolean process(String opt, List<String> args) {
346                         keywords = true;
347                         return true;
348                     }
349                 },
350 
351                 new Option(resources, "-link", 1) {
352                     @Override
353                     public boolean process(String opt, List<String> args) {
354                         linkList.add(args.get(0));
355                         return true;
356                     }
357                 },
358 
359                 new Option(resources, "-linksource") {
360                     @Override
361                     public boolean process(String opt, List<String> args) {
362                         linkSource = true;
363                         return true;
364                     }
365                 },
366 
367                 new Option(resources, "-linkoffline", 2) {
368                     @Override
369                     public boolean process(String opt, List<String> args) {
370                         linkOfflineList.add(new Utils.Pair<>(args.get(0), args.get(1)));
371                         return true;
372                     }
373                 },
374                 new Option(resources, "-nocomment") {
375                     @Override
376                     public boolean process(String opt, List<String> args) {
377                         noComment = true;
378                         return true;
379                     }
380                 },
381 
382                 new Option(resources, "-nodeprecated") {
383                     @Override
384                     public boolean process(String opt, List<String> args) {
385                         noDeprecated = true;
386                         return true;
387                     }
388                 },
389 
390                 new Option(resources, "-nosince") {
391                     @Override
392                     public boolean process(String opt, List<String> args) {
393                         noSince = true;
394                         return true;
395                     }
396                 },
397 
398                 new Option(resources, "-notimestamp") {
399                     @Override
400                     public boolean process(String opt, List<String> args) {
401                         noTimestamp = true;
402                         return true;
403                     }
404                 },
405 
406                 new Option(resources, "-noqualifier", 1) {
407                     @Override
408                     public boolean process(String opt, List<String> args) {
409                         addToSet(excludedQualifiers, args.get(0));
410                         return true;
411                     }
412                 },
413 
414                 new Option(resources, "--override-methods", 1) {
415                     @Override
416                     public boolean process(String opt,  List<String> args) {
417                         String o = args.get(0);
418                         switch (o) {
419                             case "summary":
420                                 summarizeOverriddenMethods = true;
421                                 break;
422                             case "detail":
423                                 summarizeOverriddenMethods = false;
424                                 break;
425                             default:
426                                 reporter.print(ERROR,
427                                         resources.getText("doclet.Option_invalid",o, "--override-methods"));
428                                 return false;
429                         }
430                         return true;
431                     }
432                 },
433 
434                 new Hidden(resources, "-quiet") {
435                     @Override
436                     public boolean process(String opt, List<String> args) {
437                         quiet = true;
438                         return true;
439                     }
440                 },
441 
442                 new Option(resources, "-serialwarn") {
443                     @Override
444                     public boolean process(String opt, List<String> args) {
445                         serialWarn = true;
446                         return true;
447                     }
448                 },
449 
450                 new Option(resources, "-sourcetab", 1) {
451                     @Override
452                     public boolean process(String opt, List<String> args) {
453                         linkSource = true;
454                         try {
455                             sourceTabSize = Integer.parseInt(args.get(0));
456                         } catch (NumberFormatException e) {
457                             //Set to -1 so that warning will be printed
458                             //to indicate what is valid argument.
459                             sourceTabSize = -1;
460                         }
461                         if (sourceTabSize <= 0) {
462                             messages.warning("doclet.sourcetab_warning");
463                             sourceTabSize = DocletConstants.DEFAULT_TAB_STOP_LENGTH;
464                         }
465                         return true;
466                     }
467                 },
468 
469                 new Option(resources, "-tag", 1) {
470                     @Override
471                     public boolean process(String opt, List<String> args) {
472                         ArrayList<String> list = new ArrayList<>();
473                         list.add(opt);
474                         list.add(args.get(0));
475                         customTagStrs.add(list);
476                         return true;
477                     }
478                 },
479 
480                 new Option(resources, "-taglet", 1) {
481                     @Override
482                     public boolean process(String opt, List<String> args) {
483                         ArrayList<String> list = new ArrayList<>();
484                         list.add(opt);
485                         list.add(args.get(0));
486                         customTagStrs.add(list);
487                         return true;
488                     }
489                 },
490 
491                 new Option(resources, "-tagletpath", 1) {
492                     @Override
493                     public boolean process(String opt, List<String> args) {
494                         tagletPath = args.get(0);
495                         return true;
496                     }
497                 },
498 
499                 new Option(resources, "-version") {
500                     @Override
501                     public boolean process(String opt, List<String> args) {
502                         showVersion = true;
503                         return true;
504                     }
505                 },
506 
507                 new Hidden(resources, "--dump-on-error") {
508                     @Override
509                     public boolean process(String opt, List<String> args) {
510                         dumpOnError = true;
511                         return true;
512                     }
513                 },
514 
515                 new Option(resources, "--allow-script-in-comments") {
516                     @Override
517                     public boolean process(String opt, List<String> args) {
518                         allowScriptInComments = true;
519                         return true;
520                     }
521                 },
522 
523                 new Hidden(resources, "--disable-javafx-strict-checks") {
524                     @Override
525                     public boolean process(String opt, List<String> args) {
526                         disableJavaFxStrictChecks = true;
527                         return true;
528                     }
529                 },
530 
531                 new Hidden(resources, "--show-taglets") {
532                     @Override
533                     public boolean process(String opt, List<String> args) {
534                         showTaglets = true;
535                         return true;
536                     }
537                 }
538         );
539         return new TreeSet<>(options);
540     }
541 
542     /**
543      * This checks for the validity of the options used by the user.
544      * As of this writing, this checks only docencoding.
545      *
546      * @return true if all the options are valid.
547      */
generalValidOptions()548     protected boolean generalValidOptions() {
549         if (docEncoding != null) {
550             if (!checkOutputFileEncoding(docEncoding)) {
551                 return false;
552             }
553         }
554         if (docEncoding == null && (encoding != null && !encoding.isEmpty())) {
555             if (!checkOutputFileEncoding(encoding)) {
556                 return false;
557             }
558         }
559         return true;
560     }
561 
562     /**
563      * Check the validity of the given Source or Output File encoding on this
564      * platform.
565      *
566      * @param docencoding output file encoding.
567      */
checkOutputFileEncoding(String docencoding)568     private boolean checkOutputFileEncoding(String docencoding) {
569         OutputStream ost = new ByteArrayOutputStream();
570         OutputStreamWriter osw = null;
571         try {
572             osw = new OutputStreamWriter(ost, docencoding);
573         } catch (UnsupportedEncodingException exc) {
574             config.reporter.print(ERROR,
575                     config.getDocResources().getText("doclet.Encoding_not_supported", docencoding));
576             return false;
577         } finally {
578             try {
579                 if (osw != null) {
580                     osw.close();
581                 }
582             } catch (IOException exc) {
583             }
584         }
585         return true;
586     }
587 
addToSet(Set<String> s, String str)588     private void addToSet(Set<String> s, String str) {
589         StringTokenizer st = new StringTokenizer(str, ":");
590         String current;
591         while (st.hasMoreTokens()) {
592             current = st.nextToken();
593             s.add(current);
594         }
595     }
596 
597     /**
598      * Add a trailing file separator, if not found. Remove superfluous
599      * file separators if any. Preserve the front double file separator for
600      * UNC paths.
601      *
602      * @param path Path under consideration.
603      * @return String Properly constructed path string.
604      */
addTrailingFileSep(String path)605     protected static String addTrailingFileSep(String path) {
606         String fs = System.getProperty("file.separator");
607         String dblfs = fs + fs;
608         int indexDblfs;
609         while ((indexDblfs = path.indexOf(dblfs, 1)) >= 0) {
610             path = path.substring(0, indexDblfs) +
611                     path.substring(indexDblfs + fs.length());
612         }
613         if (!path.endsWith(fs))
614             path += fs;
615         return path;
616     }
617 
618     /**
619      * Argument for command-line option {@code --allow-script-in-comments}.
620      * Allow JavaScript in doc comments.
621      */
allowScriptInComments()622     boolean allowScriptInComments() {
623         return allowScriptInComments;
624     }
625 
626     /**
627      * Argument for command-line option {@code -docfilessubdirs}.
628      * True if we should recursively copy the doc-file subdirectories
629      */
copyDocfileSubdirs()630     public boolean copyDocfileSubdirs() {
631         return copyDocfileSubdirs;
632     }
633 
634     /**
635      * Arguments for command-line option {@code -tag} and {@code -taglet}.
636      */
customTagStrs()637     LinkedHashSet<List<String>> customTagStrs() {
638         return customTagStrs;
639     }
640 
641     /**
642      * Argument for command-line option {@code -d}.
643      * Destination directory name, in which doclet will generate the entire
644      * documentation. Default is current directory.
645      */
destDirName()646     String destDirName() {
647         return destDirName;
648     }
649 
650     /**
651      * Argument for command-line option {@code --disable-javafx-strict-checks}.
652      * Primarily used to disable strict checks in the regression
653      * tests allowing those tests to be executed successfully, for
654      * instance, with OpenJDK builds which may not contain FX libraries.
655      */
disableJavaFxStrictChecks()656     boolean disableJavaFxStrictChecks() {
657         return disableJavaFxStrictChecks;
658     }
659 
660     /**
661      * Argument for command-line option {@code -docencoding}.
662      * Encoding for this document. Default is default encoding for this
663      * platform.
664      */
docEncoding()665     public String docEncoding() {
666         return docEncoding;
667     }
668 
setDocEncoding(String docEncoding)669     public void setDocEncoding(String docEncoding) {
670         this.docEncoding = docEncoding;
671     }
672 
673 
674     /**
675      * Argument for command-line option {@code ???}.
676      * Destination directory name, in which doclet will copy the doc-files to.
677      */
docFileDestDirName()678     String docFileDestDirName() {
679         return docFileDestDirName;
680     }
681 
682     /**
683      * Argument for hidden command-line option {@code --dump-on-error}.
684      */
dumpOnError()685     boolean dumpOnError() {
686         return dumpOnError;
687     }
688 
689     /**
690      * Argument for command-line option {@code -encoding}.
691      * Encoding for this document. Default is default encoding for this
692      * platform.
693      */
encoding()694     public String encoding() {
695         return encoding;
696     }
697 
698     /**
699      * Argument for command-line option {@code -excludedocfilessubdir}.
700      * The set of doc-file subdirectories to exclude.
701      */
excludedDocFileDirs()702     Set<String> excludedDocFileDirs() {
703         return excludedDocFileDirs;
704     }
705 
706     /**
707      * Argument for command-line option {@code -noqualifier}.
708      * The set of qualifiers to exclude.
709      */
excludedQualifiers()710     Set<String> excludedQualifiers() {
711         return excludedQualifiers;
712     }
713 
714     /**
715      * Arguments for command-line option {@code -group}
716      */
groupPairs()717     List<Utils.Pair<String, String>> groupPairs() {
718         return groupPairs;
719     }
720 
721     /**
722      * Argument for command-line option {@code --javafx} or {@code -javafx}.
723      * Generate documentation for JavaFX getters and setters automatically
724      * by copying it from the appropriate property definition.
725      */
javafx()726     public boolean javafx() {
727         return javafx;
728     }
729 
setJavaFX(boolean javafx)730     public void setJavaFX(boolean javafx) {
731         this.javafx = javafx;
732     }
733 
734     /**
735      * Argument for command-line option {@code -keywords}.
736      * True if user wants to add member names as meta keywords.
737      * Set to false because meta keywords are ignored in general
738      * by most Internet search engines.
739      */
keywords()740     public boolean keywords() {
741         return keywords;
742     }
743 
744     /**
745      * Arguments for command-line option {@code -link}.
746      */
linkList()747     List<String> linkList() {
748         return linkList;
749     }
750 
751     /**
752      * Arguments for command-line option {@code -linkoffline}.
753      */
linkOfflineList()754     List<Utils.Pair<String, String>> linkOfflineList() {
755         return linkOfflineList;
756     }
757 
758     /**
759      * Argument for command-line option {@code -linksource}.
760      * True if we should generate browsable sources.
761      */
linkSource()762     public boolean linkSource() {
763         return linkSource;
764     }
765 
766     /**
767      * Argument for command-line option {@code -nocomment}.
768      * True if user wants to suppress descriptions and tags.
769      */
noComment()770     public boolean noComment() {
771         return noComment;
772     }
773 
774     /**
775      * Argument for command-line option {@code -nodeprecated}.
776      * Don't generate deprecated API information at all if -nodeprecated
777      * option is used. {@code noDeprecated} is set to {@code true} if
778      * {@code -nodeprecated} option is used.
779      * Default is generate deprecated API information.
780      */
noDeprecated()781     public boolean noDeprecated() {
782         return noDeprecated;
783     }
784 
785     /**
786      * Argument for command-line option {@code -nosince}.
787      * True if command-line option {@code -nosince"} is used.
788      * Default value is false.
789      */
noSince()790     public boolean noSince() {
791         return noSince;
792     }
793 
794     /**
795      * Argument for command-line option {@code -notimestamp}.
796      * True if user wants to suppress time stamp in output.
797      * Default is false.
798      */
noTimestamp()799     public boolean noTimestamp() {
800         return noTimestamp;
801     }
802 
803     /**
804      * Argument for command-line option {@code -quiet}.
805      * Suppress all messages
806      */
quiet()807     boolean quiet() {
808         return quiet;
809     }
810 
811     /**
812      * Argument for command-line option {@code -serialwarn}.
813      * This is true if option "-serialwarn" is used. Default value is false to
814      * suppress excessive warnings about serial tag.
815      */
serialWarn()816     public boolean serialWarn() {
817         return serialWarn;
818     }
819 
820     /**
821      * Argument for command-line option {@code -author}.
822      * Generate author specific information for all the classes if @author
823      * tag is used in the doc comment and if -author option is used.
824      * <code>showauthor</code> is set to true if -author option is used.
825      * Default is don't show author information.
826      */
showAuthor()827     public boolean showAuthor() {
828         return showAuthor;
829     }
830 
831     /**
832      * Argument for command-line option {@code --show-taglets}.
833      * Show taglets (internal debug switch)
834      */
showTaglets()835     public boolean showTaglets() {
836         return showTaglets;
837     }
838 
839     /**
840      * Argument for command-line option {@code -version}.
841      * Generate version specific information for the all the classes
842      * if @version tag is used in the doc comment and if -version option is
843      * used. {@code showVersion} is set to true if -version option is
844      * used. Default is don't show version information.
845      */
showVersion()846     public boolean showVersion() {
847         return showVersion;
848     }
849 
850     /**
851      * Argument for command-line option {@code -sourcetab}.
852      * The specified amount of space between tab stops.
853      */
sourceTabSize()854     public int sourceTabSize() {
855         return sourceTabSize;
856     }
857 
858     /**
859      * Value for command-line option {@code --override-methods summary}
860      * or  {@code --override-methods detail}.
861      * Specifies whether those methods that override a super-type's method
862      * with no changes to the API contract should be summarized in the
863      * footnote section.
864      */
summarizeOverriddenMethods()865     public boolean summarizeOverriddenMethods() {
866         return summarizeOverriddenMethods;
867     }
868 
869     /**
870      * Argument for command-line option {@code -tagletpath}.
871      * The path to Taglets
872      */
tagletPath()873     public String tagletPath() {
874         return tagletPath;
875     }
876 
877     protected abstract static class Option implements Doclet.Option, Comparable<Option> {
878         private final String[] names;
879         private final String parameters;
880         private final String description;
881         private final int argCount;
882 
Option(Resources resources, String name, int argCount)883         protected Option(Resources resources, String name, int argCount) {
884             this(resources, null, name, argCount);
885         }
886 
Option(Resources resources, String keyBase, String name, int argCount)887         protected Option(Resources resources, String keyBase, String name, int argCount) {
888             this.names = name.trim().split("\\s+");
889             if (keyBase == null) {
890                 keyBase = "doclet.usage." + names[0].toLowerCase().replaceAll("^-+", "");
891             }
892             String desc = getOptionsMessage(resources, keyBase + ".description");
893             if (desc.isEmpty()) {
894                 this.description = "<MISSING KEY>";
895                 this.parameters = "<MISSING KEY>";
896             } else {
897                 this.description = desc;
898                 this.parameters = getOptionsMessage(resources, keyBase + ".parameters");
899             }
900             this.argCount = argCount;
901         }
902 
Option(Resources resources, String name)903         protected Option(Resources resources, String name) {
904             this(resources, name, 0);
905         }
906 
getOptionsMessage(Resources resources, String key)907         private String getOptionsMessage(Resources resources, String key) {
908             try {
909                 return resources.getText(key);
910             } catch (MissingResourceException ignore) {
911                 return "";
912             }
913         }
914 
915         @Override
getDescription()916         public String getDescription() {
917             return description;
918         }
919 
920         @Override
getKind()921         public Kind getKind() {
922             return Kind.STANDARD;
923         }
924 
925         @Override
getNames()926         public List<String> getNames() {
927             return Arrays.asList(names);
928         }
929 
930         @Override
getParameters()931         public String getParameters() {
932             return parameters;
933         }
934 
935         @Override
toString()936         public String toString() {
937             return Arrays.toString(names);
938         }
939 
940         @Override
getArgumentCount()941         public int getArgumentCount() {
942             return argCount;
943         }
944 
matches(String option)945         public boolean matches(String option) {
946             for (String name : names) {
947                 boolean matchCase = name.startsWith("--");
948                 if (option.startsWith("--") && option.contains("=")) {
949                     return name.equals(option.substring(option.indexOf("=") + 1));
950                 } else if (matchCase) {
951                     return name.equals(option);
952                 }
953                 return name.toLowerCase().equals(option.toLowerCase());
954             }
955             return false;
956         }
957 
958         @Override
compareTo(Option that)959         public int compareTo(Option that) {
960             return this.getNames().get(0).compareTo(that.getNames().get(0));
961         }
962     }
963 
964     protected abstract static class XOption extends Option {
965 
XOption(Resources resources, String prefix, String name, int argCount)966         public XOption(Resources resources, String prefix, String name, int argCount) {
967             super(resources, prefix, name, argCount);
968         }
969 
XOption(Resources resources, String name, int argCount)970         public XOption(Resources resources, String name, int argCount) {
971             super(resources, name, argCount);
972         }
973 
XOption(Resources resources, String name)974         public XOption(Resources resources, String name) {
975             this(resources, name, 0);
976         }
977 
978         @Override
getKind()979         public Option.Kind getKind() {
980             return Kind.EXTENDED;
981         }
982     }
983 
984     protected abstract static class Hidden extends Option {
985 
Hidden(Resources resources, String name, int argCount)986         public Hidden(Resources resources, String name, int argCount) {
987             super(resources, name, argCount);
988         }
989 
Hidden(Resources resources, String name)990         public Hidden(Resources resources, String name) {
991             this(resources, name, 0);
992         }
993 
994         @Override
getKind()995         public Option.Kind getKind() {
996             return Kind.OTHER;
997         }
998     }
999 }
1000