Skip to content

Commit cf45b0f

Browse files
committed
value api: javadoc for ValueFactory
1 parent 4dcc96c commit cf45b0f

File tree

3 files changed

+112
-24
lines changed

3 files changed

+112
-24
lines changed

jooby/src/main/java/io/jooby/QueryString.java

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,6 @@ public interface QueryString extends Value {
2626
*/
2727
String queryString();
2828

29-
/**
30-
* Query string produces always a non-null result even if no property matches. This is bc the
31-
* query string run with {@link io.jooby.value.ConversionHint#Empty}. It fits better for empty
32-
* query string when target object has some default properties.
33-
*
34-
* <pre>{@code
35-
* var factory = ctx.getValueFactory();
36-
* var nullable = factory.convert(MyBean.class, ctx.query(), ConversionHint.Nullable);
37-
* }</pre>
38-
*
39-
* @param type Type to convert.
40-
* @return Non null result.
41-
* @param <T> Type result.
42-
*/
43-
@Nullable <T> T toNullable(@NonNull Class<T> type);
44-
4529
/**
4630
* Query string produces always a non-null result even if no property matches. This is bc the
4731
* query string run with {@link io.jooby.value.ConversionHint#Empty}. It fits better for empty

jooby/src/main/java/io/jooby/internal/SingleValue.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public class SingleValue implements Value {
2424

2525
private final String name;
2626

27-
private String value;
27+
private final String value;
2828

2929
public SingleValue(ValueFactory factory, String name, String value) {
3030
this.factory = factory;

jooby/src/main/java/io/jooby/value/ValueFactory.java

Lines changed: 111 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,27 @@
1414
import edu.umd.cs.findbugs.annotations.NonNull;
1515
import edu.umd.cs.findbugs.annotations.Nullable;
1616
import io.jooby.SneakyThrows;
17+
import io.jooby.exception.ProvisioningException;
1718
import io.jooby.exception.TypeMismatchException;
1819
import io.jooby.internal.converter.ReflectiveBeanConverter;
1920
import io.jooby.internal.converter.StandardConverter;
2021
import io.jooby.internal.reflect.$Types;
2122

23+
/**
24+
* Keep track of existing {@link Converter} and convert values to a more concrete type. This class
25+
* resolve all the <code>toXXX</code> calls from {@link Value}.
26+
*
27+
* <ul>
28+
* <li>{@link Value#to(Class)}: convert to request type using {@link ConversionHint#Strict}
29+
* <li>{@link Value#toNullable(Class)}: convert to request type using {@link
30+
* ConversionHint#Nullable}
31+
* <li>{@link io.jooby.QueryString#toEmpty(Class)}: convert to request type using {@link
32+
* ConversionHint#Empty}
33+
* </ul>
34+
*
35+
* @author edgar
36+
* @since 4.0.0
37+
*/
2238
public class ValueFactory {
2339

2440
private final Map<Type, Converter> converterMap = new HashMap<>();
@@ -29,42 +45,134 @@ public class ValueFactory {
2945

3046
private Converter fallback;
3147

48+
/**
49+
* Creates a new instance.
50+
*
51+
* @param lookup Lookup to use.
52+
*/
3253
public ValueFactory(@NonNull MethodHandles.Lookup lookup) {
3354
this.lookup = lookup;
3455
this.fallback = new ReflectiveBeanConverter(lookup);
3556
StandardConverter.register(this);
3657
}
3758

59+
/** Creates a new instance with public lookup. */
3860
public ValueFactory() {
3961
this(MethodHandles.publicLookup());
4062
}
4163

64+
/**
65+
* Set lookup to use. Required by:
66+
*
67+
* <ul>
68+
* <li>valueOf(String) converter
69+
* <li>constructor(String) converter
70+
* <li>fallback/reflective bean converter
71+
* </ul>
72+
*
73+
* @param lookup Look up to use.
74+
* @return This instance.
75+
*/
4276
public @NonNull ValueFactory lookup(@NonNull MethodHandles.Lookup lookup) {
4377
this.lookup = lookup;
4478
this.fallback = new ReflectiveBeanConverter(lookup);
4579
return this;
4680
}
4781

82+
/**
83+
* Set default conversion hint to use. Defaults is {@link ConversionHint#Strict}.
84+
*
85+
* @param defaultHint Default conversion hint.
86+
* @return This instance.
87+
*/
4888
public @NonNull ValueFactory hint(@NonNull ConversionHint defaultHint) {
4989
this.defaultHint = defaultHint;
5090
return this;
5191
}
5292

93+
/**
94+
* Get a converter for the given type. This is an exact lookup, no inheritance rule applies here.
95+
*
96+
* @param type The requested type.
97+
* @return A converter or <code>null</code>.
98+
*/
5399
public @Nullable Converter get(Type type) {
54100
return converterMap.get(type);
55101
}
56102

103+
/**
104+
* Set a custom converter for type.
105+
*
106+
* @param type Target type.
107+
* @param converter Converter.
108+
* @return This instance.
109+
*/
57110
public @NonNull ValueFactory put(@NonNull Type type, @NonNull Converter converter) {
58111
converterMap.put(type, converter);
59112
return this;
60113
}
61114

62-
public <T> T convert(@NonNull Type type, @NonNull Value value) {
115+
/**
116+
* Convert a value to target type using the default {@link #hint(ConversionHint)}. Conversion
117+
* steps:
118+
*
119+
* <ul>
120+
* <li>Find a converter by type and use it. If no converter is found:
121+
* <li>Find a factory method <code>valueOf(String)</code> for {@link Value#isSingle()} values
122+
* and use it. If no converter is found:
123+
* <li>Find a <code>constructor(String)</code> for {@link Value#isSingle()} values. If no
124+
* converter is found:
125+
* <li>Fallback to reflective converter.
126+
* </ul>
127+
*
128+
* @param type Target type.
129+
* @param value Value.
130+
* @param <T> Target type.
131+
* @return New instance.
132+
* @throws TypeMismatchException when convert returns <code>null</code> and hint is set to {@link
133+
* ConversionHint#Strict}.
134+
* @throws ProvisioningException when convert target type constructor requires a non-null value
135+
* and value is missing or null.
136+
*/
137+
public <T> T convert(@NonNull Type type, @NonNull Value value)
138+
throws TypeMismatchException, ProvisioningException {
63139
return convert(type, value, defaultHint);
64140
}
65141

142+
/**
143+
* Convert a value to target type using a hint. Conversion steps:
144+
*
145+
* <ul>
146+
* <li>Find a converter by type and use it. If no converter is found:
147+
* <li>Find a factory method <code>valueOf(String)</code> for {@link Value#isSingle()} values
148+
* and use it. If no converter is found:
149+
* <li>Find a <code>constructor(String)</code> for {@link Value#isSingle()} values. If no
150+
* converter is found:
151+
* <li>Fallback to reflective converter.
152+
* </ul>
153+
*
154+
* @param type Target type.
155+
* @param value Value.
156+
* @param hint Conversion hint.
157+
* @param <T> Target type.
158+
* @return New instance.
159+
* @throws TypeMismatchException when convert returns <code>null</code> and hint is set to {@link
160+
* ConversionHint#Strict}.
161+
* @throws ProvisioningException when convert target type constructor requires a non-null value
162+
* and value is missing or null.
163+
*/
164+
public <T> T convert(@NonNull Type type, @NonNull Value value, @NonNull ConversionHint hint)
165+
throws TypeMismatchException, ProvisioningException {
166+
T result = convertInternal(type, value, hint);
167+
if (result == null && hint == ConversionHint.Strict) {
168+
throw new TypeMismatchException(value.name(), type);
169+
}
170+
return result;
171+
}
172+
66173
@SuppressWarnings("unchecked")
67-
public <T> T convert(@NonNull Type type, @NonNull Value value, @NonNull ConversionHint hint) {
174+
private <T> T convertInternal(
175+
@NonNull Type type, @NonNull Value value, @NonNull ConversionHint hint) {
68176
var converter = converterMap.get(type);
69177
if (converter != null) {
70178
// Specific converter at type level.
@@ -95,11 +203,7 @@ public <T> T convert(@NonNull Type type, @NonNull Value value, @NonNull Conversi
95203
}
96204
}
97205
// anything else fallback to reflective
98-
var result = (T) fallback.convert(type, value, hint);
99-
if (result == null && hint == ConversionHint.Strict) {
100-
throw new TypeMismatchException(value.name(), type);
101-
}
102-
return result;
206+
return (T) fallback.convert(type, value, hint);
103207
}
104208
}
105209

0 commit comments

Comments
 (0)