Skip to content

Commit 0f59f42

Browse files
authored
Merge pull request #158 from rvesse/parse-from-charsequence
Parse from charsequence (#156)
2 parents 4bd6079 + f1de9d8 commit 0f59f42

File tree

20 files changed

+160
-72
lines changed

20 files changed

+160
-72
lines changed

CHANGELOG.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,17 @@ positional argument support, better DI framework integration, that are not possi
77
breaking changes. You can see progress on 4.x by following the `4x` branch and its `CHANGELOG.md` and `Migrating.md`
88
files.
99

10-
### 3.1.1
10+
### 3.2.0
1111

12+
- Type Conversion improvements:
13+
- When converting to types `DefaultTypeConverter` now considers overloads of `valueOf()`, `fromString()` and
14+
constructors that take a `CharSequence` argument
1215
- Code Modernisation
1316
- Applied a variety of code modernisation PRs (#136, #138, #140, #143) (thanks to @khmarbaise)
17+
- Build Cleanup
18+
- The Maven Plugin build dependencies were updated to avoid warnings during the build process (#152) (thanks to
19+
@khmarbaise)
20+
- Various other build warnings eliminated (thanks to @khmarbaise)
1421
- Dependency Updates
1522
- Apache Commons Lang upgraded to 3.18.0
1623

airline-backcompat-javaxinject/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<parent>
44
<artifactId>airline-parent</artifactId>
55
<groupId>com.github.rvesse</groupId>
6-
<version>3.1.1-SNAPSHOT</version>
6+
<version>3.2.0-SNAPSHOT</version>
77
</parent>
88
<modelVersion>4.0.0</modelVersion>
99
<artifactId>airline-backcompat-javaxinject</artifactId>

airline-core/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<parent>
55
<groupId>com.github.rvesse</groupId>
66
<artifactId>airline-parent</artifactId>
7-
<version>3.1.1-SNAPSHOT</version>
7+
<version>3.2.0-SNAPSHOT</version>
88
</parent>
99

1010
<artifactId>airline</artifactId>

airline-core/src/main/java/com/github/rvesse/airline/types/DefaultTypeConverter.java

Lines changed: 97 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,28 @@
2727
/**
2828
* The default type converter
2929
* <p>
30-
* This converter supports all the basic Java types plus types. Additionally it
31-
* supports any class that defines a static {@code fromString(String)} or
32-
* {@code valueOf(String)} method. Finally it supports any class that defines a
30+
* This converter supports all the basic Java types plus types. Additionally it supports any class that defines a static
31+
* {@code fromString(String)} or {@code valueOf(String)} method. Finally it supports any class that defines a
3332
* constructor that takes a string.
3433
* </p>
3534
*/
36-
public class DefaultTypeConverter extends DefaultTypeConverterProvider implements TypeConverter {
35+
public class DefaultTypeConverter extends DefaultTypeConverterProvider implements TypeConverter {
3736

3837
private NumericTypeConverter numericConverter;
3938

39+
/**
40+
* Creates a new instance of the default type converter with the default {@link NumericTypeConverter} configured
41+
*/
4042
public DefaultTypeConverter() {
4143
this(null);
4244
}
4345

46+
/**
47+
* Creates a new instance of the default type converter
48+
*
49+
* @param numericConverter Numeric type converter to use, if {@code null} then {@link DefaultNumericConverter} is
50+
* used
51+
*/
4452
public DefaultTypeConverter(NumericTypeConverter numericConverter) {
4553
this.numericConverter = numericConverter != null ? numericConverter : new DefaultNumericConverter();
4654
}
@@ -51,88 +59,104 @@ public Object convert(String name, Class<?> type, String value) {
5159

5260
// Firstly try the standard Java types
5361
ConvertResult result = tryConvertBasicTypes(name, type, value);
54-
if (result.wasSuccessful())
62+
if (result.wasSuccessful()) {
5563
return result.getConvertedValue();
64+
}
5665

5766
// Then look for a static fromString(String) method
5867
result = tryConvertFromString(name, type, value);
59-
if (result.wasSuccessful())
68+
if (result.wasSuccessful()) {
6069
return result.getConvertedValue();
70+
}
6171

6272
// Then look for a static valueOf(String) method
6373
// This covers enums which have a valueOf method
6474
result = tryConvertFromValueOf(name, type, value);
65-
if (result.wasSuccessful())
75+
if (result.wasSuccessful()) {
6676
return result.getConvertedValue();
77+
}
6778

6879
// Finally look for a constructor taking a string
6980
result = tryConvertStringConstructor(name, type, value);
70-
if (result.wasSuccessful())
81+
if (result.wasSuccessful()) {
7182
return result.getConvertedValue();
83+
}
7284

7385
throw new ParseOptionConversionException(name, value, type.getSimpleName());
7486
}
7587

7688
/**
7789
* Checks that the arguments are all non-null
78-
*
79-
* @param name
80-
* Option/Argument name
81-
* @param type
82-
* Target type
83-
* @param value
84-
* String to convert
90+
*
91+
* @param name Option/Argument name
92+
* @param type Target type
93+
* @param value String to convert
8594
*/
8695
public static void checkArguments(String name, Class<?> type, String value) {
87-
if (name == null)
96+
if (name == null) {
8897
throw new NullPointerException("name is null");
89-
if (type == null)
98+
}
99+
if (type == null) {
90100
throw new NullPointerException("type is null");
91-
if (value == null)
101+
}
102+
if (value == null) {
92103
throw new NullPointerException("value is null");
104+
}
93105
}
94106

95107
/**
96-
* Tries to convert the value by invoking a constructor that takes a string
97-
* on the type
98-
*
99-
* @param type
100-
* Type
101-
* @param value
102-
* value
108+
* Tries to convert the value by invoking a constructor that takes a string on the type
109+
* <p>
110+
* Considers two variants of the constructor, one which takes {@link String} as its parameter type and if that doesn't
111+
* exist one that takes {@link CharSequence} as it's parameter type
112+
* </p>
113+
*
114+
* @param type Type
115+
* @param value value
103116
* @return Conversion result
104117
*/
105118
protected final ConvertResult tryConvertStringConstructor(String name, Class<?> type, String value) {
119+
ConvertResult result = tryConvertConstructor(name, type, value, String.class);
120+
if (result.wasSuccessful()) {
121+
return result;
122+
} else {
123+
return tryConvertConstructor(name, type, value, CharSequence.class);
124+
}
125+
}
126+
127+
/**
128+
* Tries to convert the value by invoking a constructor that takes a string on the type
129+
*
130+
* @param type Type
131+
* @param value value
132+
* @return Conversion result
133+
*/
134+
protected final <T> ConvertResult tryConvertConstructor(String name, Class<?> type, String value,
135+
Class<T> parameterType) {
106136
try {
107-
Constructor<?> constructor = type.getConstructor(String.class);
137+
Constructor<?> constructor = type.getConstructor(parameterType);
108138
return new ConvertResult(constructor.newInstance(value));
109139
} catch (Throwable ignored) {
110140
}
111141
return ConvertResult.FAILURE;
112142
}
113143

114144
/**
115-
* Tries to convert the value by invoking a static {@code valueOf(String)}
116-
* method on the type
117-
*
118-
* @param type
119-
* Type
120-
* @param value
121-
* Value
145+
* Tries to convert the value by invoking a static {@code valueOf(String)} method on the type
146+
*
147+
* @param type Type
148+
* @param value Value
122149
* @return Conversion result
123150
*/
124151
protected final ConvertResult tryConvertFromValueOf(String name, Class<?> type, String value) {
125152
return tryConvertStringMethod(name, type, value, "valueOf");
126153
}
127154

128155
/**
129-
* Tries to convert the value by invoking a static
130-
* {@code fromString(String)} method on the type
131-
*
132-
* @param type
133-
* Type
134-
* @param value
135-
* Value
156+
* Tries to convert the value by invoking a static {@code fromString(String)} method on the type
157+
*
158+
* @param type Type
159+
* @param value Value
136160
* @return Conversion result
137161
*/
138162
protected final ConvertResult tryConvertFromString(String name, Class<?> type, String value) {
@@ -141,34 +165,53 @@ protected final ConvertResult tryConvertFromString(String name, Class<?> type, S
141165
}
142166

143167
/**
144-
* Tries to convert the value by invoking a static method on the type
145-
*
146-
* @param type
147-
* Type
148-
* @param value
149-
* Value
150-
* @param methodName
151-
* Name of the method to invoke
168+
* Tries to convert the value by invoking a static method on the
169+
* <p>
170+
* Considers two variants of the method, one which takes {@link String} as its parameter type and if that doesn't
171+
* exist one that takes {@link CharSequence} as it's parameter type
172+
* </p>
173+
*
174+
* @param type Type
175+
* @param value Value
176+
* @param methodName Name of the method to invoke
152177
* @return Conversion Result
153178
*/
179+
@SuppressWarnings("unused")
154180
protected final ConvertResult tryConvertStringMethod(String name, Class<?> type, String value, String methodName) {
181+
ConvertResult result = tryConvertStringMethod(type, value, methodName, String.class);
182+
if (result.wasSuccessful()) {
183+
return result;
184+
} else {
185+
return tryConvertStringMethod(type, value, methodName, CharSequence.class);
186+
}
187+
}
188+
189+
/**
190+
* Tries to convert the value by invoking a static method on the type
191+
*
192+
* @param type Type
193+
* @param value Value
194+
* @param methodName Name of the method to invoke
195+
* @return Conversion Result
196+
*/
197+
protected final ConvertResult tryConvertStringMethod(Class<?> type, String value,
198+
String methodName, Class<?> parameterType) {
155199
try {
156-
Method method = type.getMethod(methodName, String.class);
200+
Method method = type.getMethod(methodName, parameterType);
157201
if (method.getReturnType().isAssignableFrom(type)) {
158202
return new ConvertResult(method.invoke(null, value));
159203
}
160204
} catch (Throwable ignored) {
205+
161206
}
162207
return ConvertResult.FAILURE;
163208
}
164209

165210
/**
166211
* Tries to convert the value if it is one of the common Java types
167-
*
168-
* @param type
169-
* Type
170-
* @param value
171-
* Value
212+
*
213+
* @param type Type
214+
* @param value Value
172215
* @return Conversion result
173216
*/
174217
protected final ConvertResult tryConvertBasicTypes(String name, Class<?> type, String value) {

airline-core/src/test/java/com/github/rvesse/airline/tests/parser/TestDefaultTypeConverter.java

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
public class TestDefaultTypeConverter {
2626

2727
private static final String OPTION_NAME = "--test";
28-
private TypeConverter converter = new DefaultTypeConverter();
28+
private final TypeConverter converter = new DefaultTypeConverter();
2929

3030
@Test(expectedExceptions = NullPointerException.class)
3131
public void convert_null_value() {
@@ -191,4 +191,35 @@ public void convert_enum() {
191191
Assert.assertEquals(converted, item);
192192
}
193193
}
194+
195+
public static class FromCharSequence extends ConversionExample {
196+
197+
private FromCharSequence(CharSequence value) {
198+
super((String)value);
199+
}
200+
201+
public static FromCharSequence fromString(CharSequence value) {
202+
return new FromCharSequence(value);
203+
}
204+
}
205+
206+
@Test
207+
public void convert_static_fromCharSequence() {
208+
String value = "test";
209+
FromCharSequence converted = testConvert(FromCharSequence.class, value);
210+
Assert.assertEquals(converted.value, value);
211+
}
212+
213+
public static class CharSequenceConstructor extends ConversionExample {
214+
public CharSequenceConstructor(CharSequence value) {
215+
super((String)value);
216+
}
217+
}
218+
219+
@Test
220+
public void convert_constructor_fromCharSequence() {
221+
String value = "test";
222+
CharSequenceConstructor converted = testConvert(CharSequenceConstructor.class, value);
223+
Assert.assertEquals(converted.value, value);
224+
}
194225
}

airline-examples/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<parent>
44
<groupId>com.github.rvesse</groupId>
55
<artifactId>airline-parent</artifactId>
6-
<version>3.1.1-SNAPSHOT</version>
6+
<version>3.2.0-SNAPSHOT</version>
77
</parent>
88
<artifactId>airline-examples</artifactId>
99
<name>Airline - Examples</name>

airline-help/airline-help-bash/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<parent>
44
<groupId>com.github.rvesse</groupId>
55
<artifactId>airline-help</artifactId>
6-
<version>3.1.1-SNAPSHOT</version>
6+
<version>3.2.0-SNAPSHOT</version>
77
</parent>
88
<artifactId>airline-help-bash</artifactId>
99
<name>Airline - Help - Bash</name>

airline-help/airline-help-external/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<parent>
44
<groupId>com.github.rvesse</groupId>
55
<artifactId>airline-help</artifactId>
6-
<version>3.1.1-SNAPSHOT</version>
6+
<version>3.2.0-SNAPSHOT</version>
77
</parent>
88
<artifactId>airline-help-external</artifactId>
99
<name>Airline - External Help</name>

airline-help/airline-help-html/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<parent>
44
<groupId>com.github.rvesse</groupId>
55
<artifactId>airline-help</artifactId>
6-
<version>3.1.1-SNAPSHOT</version>
6+
<version>3.2.0-SNAPSHOT</version>
77
</parent>
88
<artifactId>airline-help-html</artifactId>
99
<name>Airline - Help - HTML</name>

airline-help/airline-help-man/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<parent>
44
<groupId>com.github.rvesse</groupId>
55
<artifactId>airline-help</artifactId>
6-
<version>3.1.1-SNAPSHOT</version>
6+
<version>3.2.0-SNAPSHOT</version>
77
</parent>
88
<artifactId>airline-help-man</artifactId>
99
<name>Airline - Help - Man Page (Troff)</name>

0 commit comments

Comments
 (0)