Skip to content

Commit 9556f6a

Browse files
author
Thomas Stieglmaier
committed
add configuration container
1 parent 7ebf9bd commit 9556f6a

File tree

14 files changed

+323
-218
lines changed

14 files changed

+323
-218
lines changed

pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,12 @@
174174
<scope>system</scope>
175175
<systemPath>${java.home}/../lib/tools.jar</systemPath>
176176
</dependency>
177+
<dependency>
178+
<groupId>org.projectlombok</groupId>
179+
<artifactId>lombok</artifactId>
180+
<version>1.16.20</version>
181+
<scope>provided</scope>
182+
</dependency>
177183
</dependencies>
178184

179185
<build>

src/main/java/com/manoelcampos/javadoc/coverage/CoverageDoclet.java

Lines changed: 17 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,10 @@
1515
*/
1616
package com.manoelcampos.javadoc.coverage;
1717

18-
import java.io.*;
19-
18+
import com.manoelcampos.javadoc.coverage.configuration.Configuration;
2019
import com.manoelcampos.javadoc.coverage.exporter.*;
20+
import com.manoelcampos.javadoc.coverage.stats.JavaDocsStats;
2121
import com.sun.javadoc.*;
22-
import com.sun.tools.doclets.standard.Standard;
2322

2423
/**
2524
* A {@link Doclet} that computes coverage of JavaDoc documentation.
@@ -37,31 +36,17 @@
3736
* @since 1.0.0
3837
*/
3938
public class CoverageDoclet {
40-
/**
41-
* A command line parameter to enable defining the name of the coverage report.
42-
* The first value is the long version of the parameter name and the second
43-
* is the short one.
44-
*/
45-
public static final String OUTPUT_NAME_OPTION[] = {"-outputName", "-o"};
46-
47-
/**
48-
* A command line parameter to enable coverage reports only for certain visibility modifiers. The first value is the long version of the
49-
* parameter name and the second is the short one. Values for this option are public (only public stuff is used) and private (everything
50-
* is used)
51-
*/
52-
public static final String COVERAGE_ONLY_FOR_PUBLIC_OPTION[] = { "-modifiers", "-m" };
53-
5439
/**
5540
* The {@link DataExporter} object to export the coverage report to a file
5641
* in a specific format.
5742
*/
5843
private final DataExporter exporter;
5944
private final RootDoc rootDoc;
60-
private final boolean computeOnlyForPublicModifier;
45+
private final Configuration config;
6146

6247
/**
63-
* Starts the actual parsing or JavaDoc documentation and generation of the coverage report.
64-
* This is the entry point for the JavaDoc tool to start the Doclet.
48+
* Starts the actual parsing or JavaDoc documentation and generation of the coverage report. This is the entry point
49+
* for the JavaDoc tool to start the Doclet.
6550
*
6651
* @param rootDoc root element which enables reading JavaDoc documentation
6752
* @return true if the Doclet was started successfully, false otherwise
@@ -78,58 +63,12 @@ public static boolean start(final RootDoc rootDoc) {
7863
*/
7964
public CoverageDoclet(final RootDoc rootDoc) {
8065
this.rootDoc = rootDoc;
81-
computeOnlyForPublicModifier = "public".equals(getOptionValue(COVERAGE_ONLY_FOR_PUBLIC_OPTION));
66+
this.config = new Configuration(rootDoc.options());
8267

83-
// this needs to be the last part as it already accesses some stuff from the doclet
84-
this.exporter = new HtmlExporter(this);
85-
}
86-
87-
public final boolean computeOnlyForPublicModifier() {
88-
return computeOnlyForPublicModifier;
89-
}
68+
JavaDocsStats stats = new JavaDocsStats(rootDoc, config);
9069

91-
/**
92-
* Checks if a given parameter is a valid custom parameter accepted by this doclet.
93-
* @param paramName the name of the parameter to check
94-
* @return true if it's a valid custom parameter, false otherwise
95-
*/
96-
private static boolean isCustomParameter(final String paramName) {
97-
return isParameter(paramName, OUTPUT_NAME_OPTION) || isParameter(paramName, COVERAGE_ONLY_FOR_PUBLIC_OPTION);
98-
}
99-
100-
/**
101-
* Checks if the name of a given parameter corresponds to either its long or short form.
102-
*
103-
* @param paramName the name of the parameter to check
104-
* @param validNames the list of accepted names for that parameter
105-
* @return true if the given name corresponds to one of the valid names, false otherwise
106-
*/
107-
private static boolean isParameter(final String paramName, final String[] validNames) {
108-
for (String validName : validNames) {
109-
if (validName.equalsIgnoreCase(paramName)) {
110-
return true;
111-
}
112-
}
113-
114-
return false;
115-
}
116-
117-
/**
118-
* Validates command line options.
119-
*
120-
* @param options the array of given options
121-
* @param errorReporter an object that allows printing error messages for invalid options
122-
* @return true if the options are valid, false otherwise
123-
* @see Doclet#validOptions(String[][], DocErrorReporter)
124-
*/
125-
public static boolean validOptions(final String[][] options, final DocErrorReporter errorReporter) {
126-
for (final String[] opt : options) {
127-
if (isCustomParameter(opt[0])) {
128-
return true;
129-
}
130-
}
131-
132-
return Standard.validOptions(options, errorReporter);
70+
// this needs to be the last part as it already accesses some stuff from the doclet
71+
this.exporter = new HtmlExporter(config, stats);
13372
}
13473

13574
/**
@@ -140,32 +79,19 @@ public static boolean validOptions(final String[][] options, final DocErrorRepor
14079
* @see Doclet#optionLength(String)
14180
*/
14281
public static int optionLength(final String option) {
143-
/*The custom outputName parameter accepts one argument.
144-
* The name of the param counts as the one argument.*/
145-
if (isCustomParameter(option)) {
146-
return 2;
147-
}
148-
149-
return Standard.optionLength(option);
82+
return Configuration.getOptionLength(option);
15083
}
15184

15285
/**
153-
* Gets the values associated to a given command line option.
86+
* Checks that all given option are valid
15487
*
155-
* @param optionNames an array containing the valid names for the command line option to get its associated values.
156-
* This array may include the long and short versions of the option name,
157-
* for instance {@code {-outputName, -o}}.
158-
* @return the values associated to the option, where the 0th element is the option itself;
159-
* or an empty array if the option is invalid.
88+
* @param options the options to be checked on validity
89+
* @param errorReporter
90+
* @return true if the options are valid
91+
* @see Doclet#validOptions(String[][], DocErrorReporter)
16092
*/
161-
public String getOptionValue(final String[] optionNames) {
162-
for (final String[] optionValues : rootDoc.options()) {
163-
if (isParameter(optionValues[0], optionNames)) {
164-
return optionValues[1];
165-
}
166-
}
167-
168-
return null;
93+
public static boolean validOptions(final String[][] options, final DocErrorReporter errorReporter) {
94+
return Configuration.areValidOptions(options, errorReporter);
16995
}
17096

17197
/**
@@ -196,44 +122,4 @@ private boolean render() {
196122
public RootDoc getRootDoc() {
197123
return rootDoc;
198124
}
199-
200-
/**
201-
* Gets a {@link PrintWriter} used by the {@link #exporter} to write
202-
* the coverage report to.
203-
*
204-
* @param file the file to which the coverage report will be saved to
205-
*/
206-
public PrintWriter getWriter(final File file) throws FileNotFoundException {
207-
return new PrintWriter(new OutputStreamWriter(new FileOutputStream(file)));
208-
}
209-
210-
/**
211-
* Gets a {@link File} object from a given file name.
212-
*
213-
* @param fileName the name of the file to get a {@link File} object.
214-
* @return the {@link File} object
215-
*/
216-
public File getOutputFile(final String fileName) {
217-
final File dir = new File(getOutputDir());
218-
if (!dir.exists() && !dir.mkdirs()) {
219-
throw new RuntimeException("The directory '" + getOutputDir() + "' was not created due to unknown reason.");
220-
}
221-
222-
return new File(dir, fileName);
223-
}
224-
225-
/**
226-
* Gets the output directory passed as a command line argument to javadoc tool.
227-
*
228-
* @return the output directory to export the JavaDocs
229-
*/
230-
private String getOutputDir() {
231-
for (final String[] option : rootDoc.options()) {
232-
if (option.length == 2 && option[0].equals("-d")) {
233-
return Utils.includeTrailingDirSeparator(option[1]);
234-
}
235-
}
236-
237-
return "";
238-
}
239125
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package com.manoelcampos.javadoc.coverage.configuration;
2+
3+
import java.util.*;
4+
5+
import com.manoelcampos.javadoc.coverage.Utils;
6+
import com.sun.javadoc.DocErrorReporter;
7+
import com.sun.tools.doclets.standard.Standard;
8+
9+
public class Configuration {
10+
11+
private static final NoValueOption computePublicCoverageOnly = new NoValueOption("-po", "-publicOnly",
12+
"Indicates if coverage should be computed only for the public parts of a project.");
13+
private static final StringOption coverageFileName = new StringOption("-o", "-outputName",
14+
"Set the filename for the created coverage file. If nothing is given, the default is \"javadoc-coverage\".",
15+
Optional.of("javadoc-coverage"));
16+
17+
private static final List<Option<?>> ALL_OPTIONS = new ArrayList<>();
18+
19+
/**
20+
* Static constructor for initializing the options list
21+
*/
22+
static {
23+
ALL_OPTIONS.add(computePublicCoverageOnly);
24+
ALL_OPTIONS.add(coverageFileName);
25+
}
26+
27+
/**
28+
* The raw options which need to be parsed to our configuration
29+
*/
30+
private final String[][] rawOptions;
31+
32+
public Configuration(String[][] rawOptions) {
33+
this.rawOptions = rawOptions;
34+
}
35+
36+
public boolean computePublicCoverageOnly() {
37+
return isOptionContained(computePublicCoverageOnly);
38+
}
39+
40+
public String getCoverageFileName() {
41+
if (isOptionContained(coverageFileName)) {
42+
return getOptionValue(coverageFileName);
43+
}
44+
return coverageFileName.getDefaultValue();
45+
}
46+
47+
/**
48+
* Gets the output directory passed as a command line argument to javadoc tool.
49+
*
50+
* @return the output directory to export the JavaDocs
51+
*/
52+
public String getOutputDirectory() {
53+
// This is no option of the doclet, but instead of the javadoc tool
54+
// so we don't declare it as an option here directly)
55+
56+
for (final String[] option : rawOptions) {
57+
if (option.length == 2 && option[0].equals("-d")) {
58+
return Utils.includeTrailingDirSeparator(option[1]);
59+
}
60+
}
61+
62+
return "";
63+
}
64+
65+
private boolean isOptionContained(Option<?> option) {
66+
for (final String[] opt : rawOptions) {
67+
if (option.isOption(opt[0])) {
68+
return true;
69+
}
70+
}
71+
return false;
72+
}
73+
74+
private <T> T getOptionValue(Option<T> option) {
75+
if (!isOptionContained(option) && !option.hasDefaultValue()) {
76+
throw new IllegalStateException("Option is not contained and has no default value");
77+
}
78+
79+
if (!isOptionContained(option)) {
80+
return option.getDefaultValue();
81+
}
82+
83+
for (final String[] opt: rawOptions) {
84+
if (option.isOption(opt[0])) {
85+
return option.parseValue(opt);
86+
}
87+
}
88+
89+
throw new IllegalStateException("no valid option found although it should be there");
90+
}
91+
92+
/**
93+
* This method is necessary for validating the doclet parameters, which happens before instantiating the
94+
* CoverageDoclet and the configuration container.
95+
*
96+
* @param option
97+
* @return the length of the option
98+
*/
99+
public static int getOptionLength(final String option) {
100+
Optional<Option<?>> opt = ALL_OPTIONS.stream().filter(o -> o.isOption(option)).findFirst();
101+
if (opt.isPresent()) {
102+
return opt.get().getLength();
103+
}
104+
return Standard.optionLength(option);
105+
}
106+
107+
/**
108+
* This method is necessary for validating the doclet parameters, which happens before instantiating the
109+
* CoverageDoclet and the configuration container.
110+
*
111+
* @param options
112+
* @param errorReporter
113+
* @return indicates if the given options are valid
114+
*/
115+
public static boolean areValidOptions(final String[][] options, final DocErrorReporter errorReporter) {
116+
for (final String[] opt : options) {
117+
if (ALL_OPTIONS.stream().anyMatch(o -> o.isOption(opt[0]))) {
118+
return true;
119+
}
120+
}
121+
122+
return Standard.validOptions(options, errorReporter);
123+
}
124+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.manoelcampos.javadoc.coverage.configuration;
2+
3+
import lombok.NonNull;
4+
5+
class NoValueOption extends Option<Void> {
6+
7+
public NoValueOption(@NonNull String shortName, @NonNull String longName, @NonNull String description) {
8+
super(shortName, longName, description, 1);
9+
}
10+
11+
@Override
12+
public Void parseValue(String[] value) {
13+
throw new UnsupportedOperationException("NoValueOption does not have a value.");
14+
}
15+
16+
@Override
17+
public Void getDefaultValue() {
18+
throw new UnsupportedOperationException("NoValueOption does not have a default value.");
19+
}
20+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.manoelcampos.javadoc.coverage.configuration;
2+
3+
import lombok.*;
4+
5+
@ToString
6+
@Getter
7+
@AllArgsConstructor
8+
abstract class Option<T> {
9+
@NonNull
10+
private final String shortName;
11+
@NonNull
12+
private final String longName;
13+
@NonNull
14+
private final String description;
15+
private final int length;
16+
17+
public abstract T parseValue(String[] opt);
18+
19+
public final boolean isOption(String name) {
20+
return shortName.equals(name) || longName.equals(name);
21+
}
22+
23+
public boolean hasDefaultValue() {
24+
return false;
25+
}
26+
27+
public abstract T getDefaultValue();
28+
29+
public int getLength() {
30+
return length;
31+
}
32+
}

0 commit comments

Comments
 (0)