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.CharArrayWriter;
22 import java.io.FileWriter;
23 import java.io.IOException;
24 import java.io.OutputStreamWriter;
25 import java.io.PrintWriter;
26 import java.io.Writer;
27 import java.nio.charset.StandardCharsets;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.Deque;
31 import java.util.LinkedList;
32 import java.util.List;
33 import java.util.function.Function;
34 import java.util.function.Predicate;
35
36 import org.apache.commons.cli.CommandLine;
37 import org.apache.commons.cli.DefaultParser;
38 import org.apache.commons.cli.HelpFormatter;
39 import org.apache.commons.cli.Option;
40 import org.apache.commons.cli.Options;
41 import org.apache.commons.cli.ParseException;
42 import org.apache.commons.csv.CSVFormat;
43 import org.apache.commons.csv.CSVPrinter;
44 import org.apache.commons.csv.QuoteMode;
45 import org.apache.commons.lang3.StringUtils;
46 import org.apache.rat.OptionCollection;
47 import org.apache.rat.help.AbstractHelp;
48
49 import static java.lang.String.format;
50
51
52
53
54
55
56
57
58
59
60
61
62 public final class Naming {
63
64 private Naming() { }
65
66 private static final Option WIDTH = Option.builder().longOpt("width").type(Integer.class)
67 .desc("Set the display width of the output").hasArg().build();
68
69 private static final Option MAVEN = Option.builder().longOpt("maven").desc("Produce Maven name mapping").build();
70
71 private static final Option ANT = Option.builder().longOpt("ant").desc("Produce Ant name mapping").build();
72
73 private static final Option CSV = Option.builder().longOpt("csv").desc("Produce CSV format").build();
74
75 private static final Option CLI = Option.builder().longOpt("cli").desc("Produce CLI name mapping").build();
76
77 private static final Option INCLUDE_DEPRECATED = Option.builder().longOpt("include-deprecated")
78 .desc("Include deprecated options.").build();
79
80 private static final Options OPTIONS = new Options().addOption(MAVEN).addOption(ANT).addOption(CLI)
81 .addOption(CSV)
82 .addOption(INCLUDE_DEPRECATED)
83 .addOption(WIDTH);
84
85
86
87
88
89
90
91
92
93
94 public static void main(final String[] args) throws IOException, ParseException {
95 if (args == null || args.length < 1) {
96 System.err.println("At least one argument is required: path to file is missing.");
97 return;
98 }
99 CommandLine cl = DefaultParser.builder().build().parse(OPTIONS, args);
100 int width = Math.max(cl.getParsedOptionValue(WIDTH, AbstractHelp.HELP_WIDTH), AbstractHelp.HELP_WIDTH);
101
102 Predicate<Option> mavenFilter = cl.hasOption(MAVEN) ? MavenGenerator.getFilter() : null;
103
104 Predicate<Option> antFilter = cl.hasOption(ANT) ? AntGenerator.getFilter() : null;
105 boolean includeDeprecated = cl.hasOption(INCLUDE_DEPRECATED);
106 Predicate<Option> filter = o -> o.hasLongOpt() && (!o.isDeprecated() || includeDeprecated);
107
108 List<String> columns = new ArrayList<>();
109
110 if (cl.hasOption(CLI)) {
111 columns.add("CLI");
112 }
113
114 if (antFilter != null) {
115 columns.add("Ant");
116 }
117
118 if (mavenFilter != null) {
119 columns.add("Maven");
120 }
121 columns.add("Description");
122 columns.add("Argument Type");
123
124 Function<Option, String> descriptionFunction;
125
126 if (cl.hasOption(CLI) || antFilter != null && mavenFilter != null) {
127 descriptionFunction = o -> {
128 StringBuilder desc = new StringBuilder();
129 if (o.isDeprecated()) {
130 desc.append("[").append(o.getDeprecated().toString()).append("] ");
131 }
132 return desc.append(StringUtils.defaultIfEmpty(o.getDescription(), "")).toString();
133 };
134 } else if (antFilter != null) {
135 descriptionFunction = o -> {
136 StringBuilder desc = new StringBuilder();
137 AntOption antOption = new AntOption(o);
138 if (antOption.isDeprecated()) {
139 desc.append("[").append(antOption.getDeprecated()).append("] ");
140 }
141 return desc.append(StringUtils.defaultIfEmpty(antOption.getDescription(), "")).toString();
142 };
143 } else {
144 descriptionFunction = o -> {
145 StringBuilder desc = new StringBuilder();
146 MavenOption mavenOption = new MavenOption(o);
147 if (mavenOption.isDeprecated()) {
148 desc.append("[").append(mavenOption.getDeprecated()).append("] ");
149 }
150 return desc.append(StringUtils.defaultIfEmpty(mavenOption.getDescription(), "")).toString();
151 };
152 }
153
154 try (Writer underWriter = cl.getArgs().length != 0 ? new FileWriter(cl.getArgs()[0]) : new OutputStreamWriter(System.out, StandardCharsets.UTF_8)) {
155 if (cl.hasOption(CSV)) {
156 printCSV(columns, filter, cl.hasOption(CLI), mavenFilter, antFilter, descriptionFunction, underWriter);
157 }
158 else {
159 printText(columns, filter, cl.hasOption(CLI), mavenFilter, antFilter, descriptionFunction, underWriter, width);
160 }
161 }
162 }
163
164 private static List<String> fillColumns(final List<String> columns, final Option option, final boolean addCLI, final Predicate<Option> mavenFilter,
165 final Predicate<Option> antFilter, final Function<Option, String> descriptionFunction) {
166 if (addCLI) {
167 if (option.hasLongOpt()) {
168 columns.add("--" + option.getLongOpt());
169 } else {
170 columns.add("-" + option.getOpt());
171 }
172 }
173 if (antFilter != null) {
174 columns.add(antFilter.test(option) ? antFunctionName(option) : "-- not supported --");
175 }
176 if (mavenFilter != null) {
177 columns.add(mavenFilter.test(option) ? mavenFunctionName(option) : "-- not supported --");
178 }
179
180 columns.add(descriptionFunction.apply(option));
181 columns.add(option.hasArgName() ? option.getArgName() : option.hasArgs() ? "Strings" : option.hasArg() ? "String" : "-- none --");
182 columns.add(option.hasArgName() ? option.getArgName() : option.hasArgs() ? "Strings" : option.hasArg() ? "String" : "-- none --");
183 columns.add(option.hasArgName() ? option.getArgName() : option.hasArgs() ? "Strings" : option.hasArg() ? "String" : "-- none --");
184 return columns;
185 }
186
187 private static void printCSV(final List<String> columns, final Predicate<Option> filter, final boolean addCLI, final Predicate<Option> mavenFilter,
188 final Predicate<Option> antFilter, final Function<Option, String> descriptionFunction,
189 final Writer underWriter) throws IOException {
190 try (CSVPrinter printer = new CSVPrinter(underWriter, CSVFormat.DEFAULT.builder().setQuoteMode(QuoteMode.ALL).build())) {
191 printer.printRecord(columns);
192 for (Option option : OptionCollection.buildOptions().getOptions()) {
193 if (filter.test(option)) {
194 columns.clear();
195 printer.printRecord(fillColumns(columns, option, addCLI, mavenFilter, antFilter, descriptionFunction));
196 }
197 }
198 }
199 }
200
201 private static int[] calculateColumnWidth(final int width, final int columnCount, final List<List<String>> page) {
202 int[] columnWidth = new int[columnCount];
203 for (List<String> row : page) {
204 for (int i = 0; i < columnCount; i++) {
205 columnWidth[i] = Math.max(columnWidth[i], row.get(i).length());
206 }
207 }
208 int extra = 0;
209 int averageWidth = (width - ((columnCount - 1) * 2)) / columnCount;
210 int[] overage = new int[columnCount];
211 int totalOverage = 0;
212 for (int i = 0; i < columnCount; i++) {
213 if (columnWidth[i] < averageWidth) {
214 extra += averageWidth - columnWidth[i];
215 } else if (columnWidth[i] > averageWidth) {
216 overage[i] = columnWidth[i] - averageWidth;
217 totalOverage += overage[i];
218 }
219 }
220
221 for (int i = 0; i < columnCount; i++) {
222 if (overage[i] > 0) {
223 int addl = (int) (extra * overage[i] * 1.0 / totalOverage);
224 columnWidth[i] = averageWidth + addl;
225 }
226 }
227 return columnWidth;
228 }
229
230 private static void printText(final List<String> columns, final Predicate<Option> filter, final boolean addCLI,
231 final Predicate<Option> mavenFilter, final Predicate<Option> antFilter,
232 final Function<Option, String> descriptionFunction, final Writer underWriter, final int width) throws IOException {
233 List<List<String>> page = new ArrayList<>();
234
235 int columnCount = columns.size();
236 page.add(columns);
237
238 for (Option option : OptionCollection.buildOptions().getOptions()) {
239 if (filter.test(option)) {
240 page.add(fillColumns(new ArrayList<>(), option, addCLI, mavenFilter, antFilter, descriptionFunction));
241 }
242 }
243 int[] columnWidth = calculateColumnWidth(width, columnCount, page);
244 HelpFormatter helpFormatter;
245 helpFormatter = new HelpFormatter.Builder().get();
246 helpFormatter.setWidth(width);
247
248
249 List<Deque<String>> entries = new ArrayList<>();
250 CharArrayWriter cWriter = new CharArrayWriter();
251
252
253 for (List<String> cols : page) {
254 entries.clear();
255 PrintWriter writer = new PrintWriter(cWriter);
256
257 for (int i = 0; i < columnCount; i++) {
258 String col = cols.get(i);
259
260 for (String line : col.split("\\v")) {
261 helpFormatter.printWrapped(writer, columnWidth[i], 2, line);
262 }
263 writer.flush();
264
265 Deque<String> entryLines = new LinkedList<>(Arrays.asList(cWriter.toString().split("\\v")));
266
267 entries.add(entryLines);
268 cWriter.reset();
269 }
270
271 boolean cont = true;
272 while (cont) {
273 cont = false;
274 for (int columnNumber = 0; columnNumber < entries.size(); columnNumber++) {
275 Deque<String> queue = entries.get(columnNumber);
276 if (queue.isEmpty()) {
277 underWriter.append(AbstractHelp.createPadding(columnWidth[columnNumber] + 2));
278 } else {
279 String ln = queue.pop();
280 underWriter.append(ln);
281 underWriter.append(AbstractHelp.createPadding(columnWidth[columnNumber] - ln.length() + 2));
282 if (!queue.isEmpty()) {
283 cont = true;
284 }
285 }
286 }
287 underWriter.append(System.lineSeparator());
288 }
289 underWriter.append(System.lineSeparator());
290 }
291 }
292
293 public static String mavenFunctionName(final Option option) {
294 MavenOption mavenOption = new MavenOption(option);
295 StringBuilder sb = new StringBuilder();
296 if (mavenOption.isDeprecated()) {
297 sb.append("@Deprecated").append(System.lineSeparator());
298 }
299 return sb.append(format("<%s>", mavenOption.getName())).toString();
300 }
301
302 private static String antFunctionName(final Option option) {
303 StringBuilder sb = new StringBuilder();
304 AntOption antOption = new AntOption(option);
305 if (option.isDeprecated()) {
306 sb.append("@Deprecated").append(System.lineSeparator());
307 }
308 if (option.hasArgs()) {
309 sb.append(format("<rat:report>%n <%1$s>text</%1$s>%n</rat:report>", antOption.getName()));
310 } else {
311 sb.append(format("<rat:report %s = 'text'/>", antOption.getName()));
312 }
313 return sb.toString();
314 }
315 }