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