77
88import io .jooby .TypeMismatchException ;
99
10+ /**
11+ * Contains the {@link ValueConverter}s loaded via the ServiceLoader. It is is a
12+ * singleton and an instance can be retrieved with {@link #getInstance()}. The
13+ * ValueConverters are stored in an ordered collection and thus resolution of
14+ * type to be converted is based on the order of the converters.
15+ *
16+ * @author agentgt
17+ *
18+ */
1019public final class ValueConverters {
20+
1121 // Allow thread safe adding of ValueConverters.
1222 private final CopyOnWriteArrayList <ValueConverter > valueConverters ;
13-
23+
1424 // Initialization on demand
1525 private static final class Hidden {
26+
1627 private static final ValueConverters INSTANCE = ValueConverters .create ().fromServiceLoader ();
1728 }
18-
29+
1930 private ValueConverters (CopyOnWriteArrayList <ValueConverter > valueConverters ) {
2031 super ();
2132 this .valueConverters = valueConverters ;
2233 }
23-
34+
2435 static ValueConverters create () {
2536 return new ValueConverters (new CopyOnWriteArrayList <>());
2637 }
27-
38+
39+ /**
40+ * Attempts to convert values to an object based on the provided type.
41+ *
42+ * @param v
43+ * value
44+ * @param c
45+ * desired type
46+ * @return the type if converted or null if conversion was not possible.
47+ * @throws TypeMismatchException failure in a converter
48+ */
2849 public @ Nullable Object convert (ValueContainer v , Class <?> c ) throws TypeMismatchException {
2950 Object result = null ;
3051 for (ValueConverter vc : valueConverters ) {
@@ -37,33 +58,37 @@ static ValueConverters create() {
3758 }
3859 return result ;
3960 }
40-
41- final ValueConverters fromServiceLoader () {
61+
62+ ValueConverters fromServiceLoader () {
4263 ServiceLoader <ValueConverter > sl = ServiceLoader .load (ValueConverter .class );
43- //If any failes to load we will fail entirely.
44- //The value converters found earlier in the classpath take precedence.
64+ // If any failes to load we will fail entirely.
65+ // The value converters found earlier in the classpath take precedence.
4566 sl .forEach (this ::add );
4667 return this ;
4768 }
69+
4870 /**
49- * You can add value converters programmatic. For now its protected.
50- * Its also to aid unit testing since serviceloader is inherently static singleton.
71+ * You can add value converters programmatic. For now its protected. Its also
72+ * to aid unit testing since serviceloader is inherently static singleton.
73+ *
5174 * @param vc
5275 * @return
5376 */
54- /* private */ final ValueConverters add (ValueConverter vc ) {
77+ /* private */ ValueConverters add (ValueConverter vc ) {
5578 valueConverters .add (vc );
5679 return this ;
5780 }
58-
59- final ValueConverters clear () {
81+
82+ ValueConverters clear () {
6083 valueConverters .clear ();
6184 return this ;
6285 }
63-
64-
65-
66- public static final ValueConverters getInstance () {
86+
87+ /**
88+ * The ValueConverters singleton usually preloaded by the ServiceLoader.
89+ * @return the shared singleton used by Jooby
90+ */
91+ public static ValueConverters getInstance () {
6792 return ValueConverters .Hidden .INSTANCE ;
6893 }
6994
0 commit comments