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