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.ByteArrayOutputStream;
22 import java.io.File;
23 import java.io.FileWriter;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.InputStreamReader;
27 import java.io.OutputStreamWriter;
28 import java.io.Writer;
29 import java.nio.charset.StandardCharsets;
30 import java.util.HashMap;
31 import java.util.HashSet;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Set;
35
36 import org.apache.commons.cli.Option;
37 import org.apache.commons.io.IOUtils;
38 import org.apache.commons.io.LineIterator;
39 import org.apache.commons.lang3.StringUtils;
40 import org.apache.commons.text.WordUtils;
41 import org.apache.rat.OptionCollection;
42 import org.apache.rat.documentation.options.AntOption;
43 import org.apache.rat.utils.CasedString;
44 import org.apache.rat.utils.CasedString.StringCase;
45
46 import static java.lang.String.format;
47
48
49
50
51 public final class AntGenerator {
52
53
54
55
56 private static final Map<OptionCollection.ArgumentType, GenerateType> GENERATE_TYPE_MAP = new HashMap<>();
57
58 static {
59 String defaultFmt = " public void add%$1s(String %2$s) {%n" +
60 " addArg(%%1$s, %2$s);%n" +
61 " }%n%n";
62 GenerateType generateType;
63 for (OptionCollection.ArgumentType type : OptionCollection.ArgumentType.values()) {
64 switch (type) {
65 case FILE:
66 case DIRORARCHIVE:
67 generateType = new GenerateType("fileset") {
68 protected String getMethodFormat(final AntOption antOption) {
69 return """
70 public void addConfiguredFileset(FileSet fileSet) {
71 for (Resource resource : fileSet) {
72 if (resource.isFilesystemOnly()) {
73 addArg(%1$s, ((FileResource) resource).getFile().getAbsolutePath());
74 }
75 }
76 }
77 """;
78 }
79 };
80 break;
81 case NONE:
82 generateType = new GenerateType("") {
83 protected String getMethodFormat(final AntOption antOption) {
84 return "";
85 }
86 };
87 break;
88 case STANDARDCOLLECTION:
89 generateType = new GenerateType("Std");
90 break;
91 case EXPRESSION:
92 generateType = new GenerateType("Expr");
93 break;
94 case COUNTERPATTERN:
95 generateType = new GenerateType("Cntr");
96 break;
97 case LICENSEID:
98 case FAMILYID:
99 generateType = new GenerateType("Lst");
100 break;
101 default:
102 generateType = new GenerateType(type.getDisplayName()) {
103
104 protected String getMethodFormat(final AntOption antOption) {
105 return String.format(defaultFmt, innerClass, WordUtils.uncapitalize(antOption.getArgName()));
106 }
107 };
108 }
109 GENERATE_TYPE_MAP.put(type, generateType);
110 }
111 }
112
113 private AntGenerator() { }
114
115
116
117
118
119
120 private static String argsKey(final Option option) {
121 return StringUtils.defaultIfEmpty(option.getLongOpt(), option.getOpt());
122 }
123
124
125
126
127
128
129
130
131
132
133
134
135 public static void main(final String[] args) throws IOException {
136 if (args == null || args.length < 3) {
137 System.err.println("At least three arguments are required: package, simple class name, target directory.");
138 return;
139 }
140
141 String packageName = args[0];
142 String className = args[1];
143 String destDir = args[2];
144
145 List<AntOption> options = AntOption.getAntOptions();
146
147 String pkgName = String.join(File.separator, new CasedString(StringCase.DOT, packageName).getSegments());
148 File file = new File(new File(new File(destDir), pkgName), className + ".java");
149 file.getParentFile().mkdirs();
150 try (InputStream template = AntGenerator.class.getResourceAsStream("/Ant.tpl");
151 FileWriter writer = new FileWriter(file, StandardCharsets.UTF_8);
152 ByteArrayOutputStream bos = new ByteArrayOutputStream();
153 OutputStreamWriter customClasses = new OutputStreamWriter(bos, StandardCharsets.UTF_8);) {
154 if (template == null) {
155 throw new RuntimeException("Template /Ant.tpl not found");
156 }
157 LineIterator iter = IOUtils.lineIterator(new InputStreamReader(template, StandardCharsets.UTF_8));
158 while (iter.hasNext()) {
159 String line = iter.next();
160 switch (line.trim()) {
161 case "${static}":
162 for (Map.Entry<String, String> entry : AntOption.getRenameMap().entrySet()) {
163 writer.append(format(" xlateName.put(\"%s\", \"%s\");%n", entry.getKey(), entry.getValue()));
164 }
165 for (Option option : AntOption.getFilteredOptions()) {
166 writer.append(format(" unsupportedArgs.add(\"%s\");%n", argsKey(option)));
167 }
168 for (AntOption option : options) {
169 if (option.isDeprecated()) {
170 writer.append(format(" deprecatedArgs.put(\"%s\", \"%s\");%n", argsKey(option.getOption()),
171 format("Use of deprecated option '%s'. %s", option.getName(), option.getDeprecated())));
172 }
173 }
174 break;
175 case "${methods}":
176 writeMethods(writer, options, customClasses);
177 break;
178 case "${package}":
179 writer.append(format("package %s;%n", packageName));
180 break;
181 case "${constructor}":
182 writer.append(format("""
183 protected %s() {
184 setDeprecationReporter();
185 }%n""", className));
186 break;
187 case "${class}":
188 writer.append(format("public abstract class %s extends Task {%n", className));
189 break;
190 case "${classes}":
191 customClasses.flush();
192 customClasses.close();
193 writer.write(bos.toString());
194 break;
195 case "${commonArgs}":
196 try (InputStream argsTpl = MavenGenerator.class.getResourceAsStream("/Args.tpl")) {
197 if (argsTpl == null) {
198 throw new RuntimeException("Args.tpl not found");
199 }
200 IOUtils.copy(argsTpl, writer, StandardCharsets.UTF_8);
201 }
202 break;
203 default:
204 writer.append(line).append(System.lineSeparator());
205 break;
206 }
207 }
208 }
209 }
210
211 private static void writeMethods(final FileWriter writer, final List<AntOption> options, final Writer customClasses) throws IOException {
212 for (AntOption option : options) {
213
214 if (option.isAttribute()) {
215 writer.append(option.getComment(true));
216 writer.append(format(" public void %s {%n%s%n }%n%n", option.getAttributeFunctionName(), getAttributeBody(option)));
217 } else {
218 customClasses.append(option.getComment(false));
219 customClasses.append(format(" public %1$s create%1$s() {%n return new %1$s();%n }%n%n",
220 WordUtils.capitalize(option.getName())));
221 customClasses.append(getElementClass(option));
222 }
223 }
224 }
225
226 private static String getAttributeBody(final AntOption option) {
227 return option.hasArg() ? format(" setArg(%s, %s);%n", option.keyValue(), option.getName())
228 : format(" if (%1$s) { setArg(%2$s, null); } else { removeArg(%2$s); }", option.getName(), option.keyValue());
229 }
230
231 private static String getElementClass(final AntOption option) {
232
233 String elementConstructor =
234 """
235 public class %1$s {
236 %1$s() { }%n""";
237
238 String funcName = WordUtils.capitalize(option.getName());
239 StringBuilder result = new StringBuilder(format(elementConstructor, funcName));
240 Set<AntOption> implementedOptions = new HashSet<>();
241 implementedOptions.add(option);
242 option.convertedFrom().stream().filter(o -> !AntOption.getUnsupportedOptions().contains(o)).forEach(opt -> implementedOptions.add(new AntOption(opt)));
243 implementedOptions.forEach(o -> result.append(GENERATE_TYPE_MAP.get(o.getArgType()).getPattern(option, o)));
244 result.append(format(" }%n"));
245
246 return result.toString();
247 }
248
249 public static class GenerateType {
250
251 protected final String innerClass;
252
253 GenerateType(final String innerClass) {
254 this.innerClass = innerClass;
255 }
256
257 protected String getMethodFormat(final AntOption antOption) {
258 return String.format("""
259 public void addConfigured%1$s(%1$s %%2$s) {
260 addArg(%%1$s, %%2$s.value);
261 }%n""", innerClass);
262 }
263
264 public String getPattern(final AntOption delegateOption, final AntOption antOption) {
265 if (delegateOption.isAttribute()) {
266 String fmt = "<rat:report %s='%s' />";
267 return format(fmt, delegateOption.getName(), antOption.hasArg() ? antOption.getArgName() : "true");
268 } else {
269 return format(getMethodFormat(antOption), antOption.keyValue(),
270 WordUtils.uncapitalize(antOption.getArgName()));
271 }
272 }
273 }
274
275 }