1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.rat.tools;
20
21 import java.io.File;
22 import java.util.ArrayList;
23 import java.util.HashMap;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Objects;
28 import java.util.Set;
29 import java.util.function.Supplier;
30 import java.util.stream.Collectors;
31
32 import org.apache.commons.cli.Option;
33 import org.apache.commons.text.StringEscapeUtils;
34 import org.apache.commons.text.WordUtils;
35 import org.apache.rat.OptionCollection;
36 import org.apache.rat.commandline.Arg;
37
38 import static java.lang.String.format;
39
40
41
42
43 public class AntOption extends AbstractOption {
44
45
46
47
48 private static final List<Option> UNSUPPORTED_LIST = new ArrayList<>();
49
50
51
52
53 private static final Map<Option, Option> ANT_CONVERSION_MAP = new HashMap<>();
54
55
56
57
58 private static final Map<OptionCollection.ArgumentType, BuildType> BUILD_TYPE_MAP = new HashMap<>();
59
60
61 private static final List<Class<?>> ATTRIBUTE_TYPES = new ArrayList<>();
62
63
64
65
66
67
68 private static void updateConversionMap(final Arg arg, final Arg actualArg) {
69 Option mapTo = actualArg.option();
70 for (Option option : arg.group().getOptions()) {
71 if (!option.equals(mapTo) && !option.isDeprecated()) {
72 ANT_CONVERSION_MAP.put(option, mapTo);
73 }
74 }
75 }
76
77 static {
78 ATTRIBUTE_TYPES.add(String.class);
79 ATTRIBUTE_TYPES.add(String[].class);
80 ATTRIBUTE_TYPES.add(Integer.class);
81 ATTRIBUTE_TYPES.add(Long.class);
82 ATTRIBUTE_TYPES.add(File.class);
83 Arg.getOptions().getOptions().stream().filter(o -> Objects.isNull(o.getLongOpt())).forEach(UNSUPPORTED_LIST::add);
84 UNSUPPORTED_LIST.addAll(Arg.LOG_LEVEL.group().getOptions());
85 UNSUPPORTED_LIST.addAll(Arg.DIR.group().getOptions());
86 UNSUPPORTED_LIST.add(OptionCollection.HELP);
87 UNSUPPORTED_LIST.addAll(Arg.SOURCE.group().getOptions());
88 updateConversionMap(Arg.LICENSES_APPROVED_FILE, Arg.LICENSES_APPROVED);
89 updateConversionMap(Arg.LICENSES_DENIED_FILE, Arg.LICENSES_DENIED);
90 updateConversionMap(Arg.FAMILIES_APPROVED_FILE, Arg.FAMILIES_APPROVED);
91 updateConversionMap(Arg.FAMILIES_DENIED_FILE, Arg.FAMILIES_DENIED);
92 updateConversionMap(Arg.INCLUDE_FILE, Arg.INCLUDE);
93 updateConversionMap(Arg.INCLUDE_STD, Arg.INCLUDE);
94 updateConversionMap(Arg.EXCLUDE_FILE, Arg.EXCLUDE);
95 updateConversionMap(Arg.EXCLUDE_STD, Arg.EXCLUDE);
96
97
98
99
100 BuildType buildType;
101 for (OptionCollection.ArgumentType type : OptionCollection.ArgumentType.values()) {
102 switch (type) {
103 case FILE:
104 case DIRORARCHIVE:
105 buildType = new BuildType(type, "filename") {
106 @Override
107 protected String getMultipleFormat(final AntOption antOption) {
108 return " <fileset file='%s' />\n";
109 }
110 };
111 BUILD_TYPE_MAP.put(type, buildType);
112 break;
113 case NONE:
114 buildType = new BuildType(type, "");
115 BUILD_TYPE_MAP.put(type, buildType);
116 break;
117 case COUNTERPATTERN:
118 buildType = new BuildType(type, "cntr");
119 BUILD_TYPE_MAP.put(type, buildType);
120 break;
121 case EXPRESSION:
122 buildType = new BuildType(type, "expr");
123 BUILD_TYPE_MAP.put(type, buildType);
124 break;
125 case STANDARDCOLLECTION:
126 buildType = new BuildType(type, "std");
127 BUILD_TYPE_MAP.put(type, buildType);
128 break;
129 case LICENSEID:
130 case FAMILYID:
131 buildType = new BuildType(type, "lst");
132 BUILD_TYPE_MAP.put(type, buildType);
133 break;
134 default:
135 buildType = new BuildType(type, type.getDisplayName()) {
136 protected String getMethodFormat(final AntOption antOption) {
137 return String.format("<%1$s>%%s</%1$s>\n", WordUtils.uncapitalize(antOption.getArgName()));
138 }
139 };
140 BUILD_TYPE_MAP.put(type, buildType);
141 }
142 }
143 }
144
145
146
147
148
149 public static List<Option> getUnsupportedOptions() {
150 return UNSUPPORTED_LIST;
151 }
152
153
154
155
156
157
158 public static Set<Option> getFilteredOptions() {
159 HashSet<Option> filteredOptions = new HashSet<>(UNSUPPORTED_LIST);
160 filteredOptions.addAll(ANT_CONVERSION_MAP.keySet());
161 return filteredOptions;
162 }
163
164
165
166
167
168
169 public AntOption(final Option option) {
170 super(option, AntGenerator.createName(option));
171 }
172
173
174
175
176
177
178 public boolean isAttribute() {
179 return (!option.hasArg() || option.getArgs() == 1) && ATTRIBUTE_TYPES.contains(option.getType())
180 && convertedFrom().isEmpty();
181
182 }
183
184
185
186
187
188
189 public boolean isElement() {
190 return !isAttribute();
191 }
192
193
194
195
196
197
198 public AntOption getActualAntOption() {
199 Option opt = ANT_CONVERSION_MAP.get(this.option);
200 return opt == null ? this : new AntOption(opt);
201 }
202
203
204
205
206
207 public Set<Option> convertedFrom() {
208 return ANT_CONVERSION_MAP.entrySet().stream().filter(e -> e.getValue().equals(option))
209 .map(Map.Entry::getKey)
210 .collect(Collectors.toSet());
211 }
212
213 protected String cleanupName(final Option option) {
214 AntOption antOption = new AntOption(option);
215 String fmt = antOption.isAttribute() ? "%s attribute" : "<%s>";
216 return format(fmt, AntGenerator.createName(option));
217 }
218
219
220
221
222
223
224
225 public String getComment(final boolean addParam) {
226 StringBuilder sb = new StringBuilder();
227 String desc = getDescription();
228 if (desc == null) {
229 throw new IllegalStateException(format("Description for %s may not be null", getName()));
230 }
231 if (!desc.contains(".")) {
232 throw new IllegalStateException(format("First sentence of description for %s must end with a '.'", getName()));
233 }
234 if (addParam) {
235 String arg;
236 if (option.hasArg()) {
237 arg = desc.substring(desc.indexOf(" ") + 1, desc.indexOf(".") + 1);
238 arg = WordUtils.capitalize(arg.substring(0, 1)) + arg.substring(1);
239 } else {
240 arg = "The state";
241 }
242 if (option.getArgName() != null) {
243 Supplier<String> sup = OptionCollection.getArgumentTypes().get(option.getArgName());
244 if (sup == null) {
245 throw new IllegalStateException(format("Argument type %s must be in OptionCollection.ARGUMENT_TYPES", option.getArgName()));
246 }
247 desc = format("%s Argument%s should be %s%s. (See Argument Types for clarification)", desc, option.hasArgs() ? "s" : "",
248 option.hasArgs() ? "" : "a ", option.getArgName());
249 }
250 sb.append(format(" /**%n * %s%n * @param %s %s%n", StringEscapeUtils.escapeHtml4(desc), getName(),
251 StringEscapeUtils.escapeHtml4(arg)));
252 } else {
253 sb.append(format(" /**%n * %s%n", StringEscapeUtils.escapeHtml4(desc)));
254 }
255 if (option.isDeprecated()) {
256 sb.append(format(" * @deprecated %s%n", StringEscapeUtils.escapeHtml4(getDeprecated())));
257 }
258 return sb.append(format(" */%n")).toString();
259 }
260
261
262
263
264
265
266
267 public String getAttributeFunctionName() {
268 return "set" +
269 WordUtils.capitalize(name) +
270 (option.hasArg() ? "(String " : "(boolean ") +
271 name +
272 ")";
273 }
274
275 @Override
276 public String getExample() {
277 return new ExampleGenerator().getExample();
278 }
279
280
281
282
283 private static class BuildType {
284
285 private final OptionCollection.ArgumentType type;
286
287 private final String tag;
288
289
290
291
292
293
294 BuildType(final OptionCollection.ArgumentType type, final String tag) {
295 this.type = type;
296 this.tag = tag;
297 }
298
299
300
301
302
303
304 protected String getMultipleFormat(final AntOption antOption) {
305 return String.format("<%1$s>%%s</%1$s>\n", tag);
306 }
307
308
309
310
311
312
313 protected String getMethodFormat(final AntOption antOption) {
314 return antOption.hasArgs() ? getMultipleFormat(antOption) : String.format("<%1$s>%%s</%1$s>\n", tag);
315 }
316
317
318
319
320
321
322
323
324 public String getPattern(final AntOption delegateOption, final AntOption antOption, final String data) {
325 String fmt = getMethodFormat(antOption);
326 String value = data == null ? WordUtils.uncapitalize(antOption.getArgName()) : data;
327 String inner = format(fmt, value);
328 return format("<%1$s>%2$s</%1$s>%n", delegateOption.getName(), inner);
329 }
330 }
331
332
333 private static final Map<String, Map<String, String>> REQUIRED_ATTRIBUTES = new HashMap<>();
334
335 static {
336 Map<String, String> attributes = new HashMap<>();
337 attributes.put("editLicense", "true");
338 REQUIRED_ATTRIBUTES.put("copyright", attributes);
339 REQUIRED_ATTRIBUTES.put("editCopyright", attributes);
340 REQUIRED_ATTRIBUTES.put("force", attributes);
341 REQUIRED_ATTRIBUTES.put("editOverwrite", attributes);
342 }
343
344
345
346
347 public class ExampleGenerator {
348
349
350
351
352 public ExampleGenerator() {
353 }
354
355
356
357
358
359 String getExample() {
360 return getExample("data", REQUIRED_ATTRIBUTES.get(getName()), null);
361 }
362
363
364
365
366
367
368
369
370 public String getExample(final String data, final Map<String, String> attributes, final List<String> childElements) {
371 if (UNSUPPORTED_LIST.contains(option)) {
372 return "-- not supported --";
373 }
374 return "<rat:report" +
375 getExampleAttributes(data, attributes) +
376 "> \n" +
377 getChildElements(data, childElements) +
378 "</rat:report>\n";
379 }
380
381
382
383
384
385
386
387 public String getExampleAttributes(final String data, final Map<String, String> attributes) {
388 AntOption actualOption = getActualAntOption();
389 StringBuilder result = new StringBuilder();
390 if (attributes != null) {
391 attributes.forEach((k, v) -> result.append(format(" %s=\"%s\"", k, v)));
392 }
393 if (actualOption.isAttribute()) {
394 result.append(format(" %s=\"%s\"", actualOption.getName(), actualOption.hasArg() ? data : "true"));
395 }
396 return result.toString();
397 }
398
399
400
401
402
403
404
405 public String getChildElements(final String data, final List<String> childElements) {
406 AntOption baseOption = AntOption.this;
407 AntOption actualOption = getActualAntOption();
408 StringBuilder result = new StringBuilder();
409 if (!actualOption.isAttribute()) {
410 String inner = BUILD_TYPE_MAP.get(getArgType()).getPattern(actualOption, baseOption, data);
411 result.append(inner);
412 }
413 if (childElements != null) {
414 childElements.forEach(x -> result.append(x).append("\n"));
415 }
416 return result.toString();
417 }
418 }
419 }