Skip to content

Commit d9a9433

Browse files
authored
[CLI-329] Support "Deprecated" CLI Options (apache#252)
* [CLI-329] Support "Deprecated" CLI Options * [CLI-329] Support "Deprecated" CLI Options - HelpFormatter does not print deprecated options by default - HelpFormatter can show deprecated options: HelpFormatter.builder().setShowDeprecated(true).get(); * [CLI-329] Support "Deprecated" CLI Options Deprecated string looks like: "Option 'c': Deprecated for removal since 2.0: Use X."
1 parent 2a859c4 commit d9a9433

12 files changed

Lines changed: 923 additions & 94 deletions

src/main/java/org/apache/commons/cli/CommandLine.java

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Licensed to the Apache Software Foundation (ASF) under one or more
2626
import java.util.List;
2727
import java.util.Objects;
2828
import java.util.Properties;
29+
import java.util.function.Consumer;
2930
import java.util.function.Supplier;
3031

3132
/**
@@ -47,12 +48,22 @@ public class CommandLine implements Serializable {
4748
*/
4849
public static final class Builder {
4950

51+
/**
52+
* Prints an Option to {@link System#out}.
53+
*/
54+
static final Consumer<Option> DEPRECATED_HANDLER = o -> System.out.println(o.toDeprecatedString());
55+
5056
/** The unrecognized options/arguments */
5157
private final List<String> args = new LinkedList<>();
5258

5359
/** The processed options */
5460
private final List<Option> options = new ArrayList<>();
5561

62+
/**
63+
* Deprecated Option handler.
64+
*/
65+
private Consumer<Option> deprecatedHandler = DEPRECATED_HANDLER;
66+
5667
/**
5768
* Adds left-over unrecognized option/argument.
5869
*
@@ -82,15 +93,30 @@ public Builder addOption(final Option opt) {
8293
}
8394

8495
/**
85-
* Returns the new instance.
96+
* Creates the new instance.
8697
*
8798
* @return the new instance.
8899
*/
89100
public CommandLine build() {
90-
return new CommandLine(args, options);
101+
return new CommandLine(args, options, deprecatedHandler);
102+
}
103+
104+
/**
105+
* Sets the deprecated option handler.
106+
*
107+
* @param deprecatedHandler the deprecated option handler.
108+
* @return this.
109+
* @since 1.7.0
110+
*/
111+
public Builder setDeprecatedHandler(final Consumer<Option> deprecatedHandler) {
112+
this.deprecatedHandler = deprecatedHandler;
113+
return this;
91114
}
92115
}
93116

117+
/** The serial version UID. */
118+
private static final long serialVersionUID = 1L;
119+
94120
/**
95121
* Creates a new builder.
96122
*
@@ -101,28 +127,34 @@ public static Builder builder() {
101127
return new Builder();
102128
}
103129

104-
/** The serial version UID. */
105-
private static final long serialVersionUID = 1L;
106-
107130
/** The unrecognized options/arguments */
108131
private final List<String> args;
109132

110133
/** The processed options */
111134
private final List<Option> options;
112135

136+
/**
137+
* The deprecated option handler.
138+
* <p>
139+
* If you want to serialize this field, use a serialization proxy.
140+
* </p>
141+
*/
142+
private final transient Consumer<Option> deprecatedHandler;
143+
113144
/**
114145
* Creates a command line.
115146
*/
116147
protected CommandLine() {
117-
this(new LinkedList<>(), new ArrayList<>());
148+
this(new LinkedList<>(), new ArrayList<>(), Builder.DEPRECATED_HANDLER);
118149
}
119150

120151
/**
121152
* Creates a command line.
122153
*/
123-
private CommandLine(final List<String> args, final List<Option> options) {
154+
private CommandLine(final List<String> args, final List<Option> options, final Consumer<Option> deprecatedHandler) {
124155
this.args = Objects.requireNonNull(args, "args");
125156
this.options = Objects.requireNonNull(options, "options");
157+
this.deprecatedHandler = deprecatedHandler;
126158
}
127159

128160
/**
@@ -530,13 +562,14 @@ public <T> T getParsedOptionValue(final String opt, final T defaultValue) throws
530562
}
531563

532564
/**
533-
* Tests to see if an option has been set.
565+
* Handles deprecated options.
534566
*
535-
* @param opt character name of the option.
536-
* @return true if set, false if not.
567+
* @param option a deprecated option.
537568
*/
538-
public boolean hasOption(final char opt) {
539-
return hasOption(String.valueOf(opt));
569+
private void handleDeprecated(final Option option) {
570+
if (deprecatedHandler != null) {
571+
deprecatedHandler.accept(option);
572+
}
540573
}
541574

542575
/**
@@ -557,6 +590,16 @@ public boolean hasOption(final char opt) {
557590
* return buf.toString(); }
558591
*/
559592

593+
/**
594+
* Tests to see if an option has been set.
595+
*
596+
* @param opt character name of the option.
597+
* @return true if set, false if not.
598+
*/
599+
public boolean hasOption(final char opt) {
600+
return hasOption(String.valueOf(opt));
601+
}
602+
560603
/**
561604
* Tests to see if an option has been set.
562605
*
@@ -615,6 +658,9 @@ private Option resolveOption(final String opt) {
615658
if (actual != null) {
616659
for (final Option option : options) {
617660
if (actual.equals(option.getOpt()) || actual.equals(option.getLongOpt())) {
661+
if (option.isDeprecated()) {
662+
handleDeprecated(option);
663+
}
618664
return option;
619665
}
620666
}

src/main/java/org/apache/commons/cli/DefaultParser.java

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Licensed to the Apache Software Foundation (ASF) under one or more
2121
import java.util.Enumeration;
2222
import java.util.List;
2323
import java.util.Properties;
24+
import java.util.function.Consumer;
2425

2526
/**
2627
* Default parser.
@@ -48,6 +49,14 @@ public static final class Builder {
4849
/** Flag indicating if partial matching of long options is supported. */
4950
private boolean allowPartialMatching = true;
5051

52+
/**
53+
* The deprecated option handler.
54+
* <p>
55+
* If you want to serialize this field, use a serialization proxy.
56+
* </p>
57+
*/
58+
private Consumer<Option> deprecatedHandler = CommandLine.Builder.DEPRECATED_HANDLER;
59+
5160
/** Flag indicating if balanced leading and trailing double quotes should be stripped from option arguments. */
5261
private Boolean stripLeadingAndTrailingQuotes;
5362

@@ -67,7 +76,7 @@ private Builder() {
6776
* @since 1.5.0
6877
*/
6978
public DefaultParser build() {
70-
return new DefaultParser(allowPartialMatching, stripLeadingAndTrailingQuotes);
79+
return new DefaultParser(allowPartialMatching, stripLeadingAndTrailingQuotes, deprecatedHandler);
7180
}
7281

7382
/**
@@ -97,6 +106,18 @@ public Builder setAllowPartialMatching(final boolean allowPartialMatching) {
97106
return this;
98107
}
99108

109+
/**
110+
* Sets the deprecated option handler.
111+
*
112+
* @param deprecatedHandler the deprecated option handler.
113+
* @return this.
114+
* @since 1.7.0
115+
*/
116+
public Builder setDeprecatedHandler(final Consumer<Option> deprecatedHandler) {
117+
this.deprecatedHandler = deprecatedHandler;
118+
return this;
119+
}
120+
100121
/**
101122
* Sets if balanced leading and trailing double quotes should be stripped from option arguments.
102123
*
@@ -160,6 +181,14 @@ public static Builder builder() {
160181
* null represents the historic arbitrary behavior */
161182
private final Boolean stripLeadingAndTrailingQuotes;
162183

184+
/**
185+
* The deprecated option handler.
186+
* <p>
187+
* If you want to serialize this field, use a serialization proxy.
188+
* </p>
189+
*/
190+
private final Consumer<Option> deprecatedHandler;
191+
163192
/**
164193
* Creates a new DefaultParser instance with partial matching enabled.
165194
*
@@ -182,6 +211,7 @@ public static Builder builder() {
182211
public DefaultParser() {
183212
this.allowPartialMatching = true;
184213
this.stripLeadingAndTrailingQuotes = null;
214+
this.deprecatedHandler = CommandLine.Builder.DEPRECATED_HANDLER;
185215
}
186216

187217
/**
@@ -208,6 +238,7 @@ public DefaultParser() {
208238
public DefaultParser(final boolean allowPartialMatching) {
209239
this.allowPartialMatching = allowPartialMatching;
210240
this.stripLeadingAndTrailingQuotes = null;
241+
this.deprecatedHandler = CommandLine.Builder.DEPRECATED_HANDLER;
211242
}
212243

213244
/**
@@ -217,10 +248,10 @@ public DefaultParser(final boolean allowPartialMatching) {
217248
* @param allowPartialMatching if partial matching of long options shall be enabled
218249
* @param stripLeadingAndTrailingQuotes if balanced outer double quoutes should be stripped
219250
*/
220-
private DefaultParser(final boolean allowPartialMatching,
221-
final Boolean stripLeadingAndTrailingQuotes) {
251+
private DefaultParser(final boolean allowPartialMatching, final Boolean stripLeadingAndTrailingQuotes, final Consumer<Option> deprecatedHandler) {
222252
this.allowPartialMatching = allowPartialMatching;
223253
this.stripLeadingAndTrailingQuotes = stripLeadingAndTrailingQuotes;
254+
this.deprecatedHandler = deprecatedHandler;
224255
}
225256

226257
/**
@@ -671,28 +702,21 @@ public CommandLine parse(final Options options, final String[] arguments, final
671702
skipParsing = false;
672703
currentOption = null;
673704
expectedOpts = new ArrayList<>(options.getRequiredOptions());
674-
675705
// clear the data from the groups
676706
for (final OptionGroup group : options.getOptionGroups()) {
677707
group.setSelected(null);
678708
}
679-
680-
cmd = CommandLine.builder().build();
681-
709+
cmd = CommandLine.builder().setDeprecatedHandler(deprecatedHandler).build();
682710
if (arguments != null) {
683711
for (final String argument : arguments) {
684712
handleToken(argument);
685713
}
686714
}
687-
688715
// check the arguments of the last option
689716
checkRequiredArgs();
690-
691717
// add the default options
692718
handleProperties(properties);
693-
694719
checkRequiredOptions();
695-
696720
return cmd;
697721
}
698722

0 commit comments

Comments
 (0)