Skip to content

Commit 0572b2e

Browse files
dmlloydradcortez
authored andcommitted
[WIP] API and implementation for config instance builder
Fixes #1001
1 parent 4e44332 commit 0572b2e

File tree

3 files changed

+764
-0
lines changed

3 files changed

+764
-0
lines changed
Lines changed: 320 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,320 @@
1+
package io.smallrye.config;
2+
3+
import java.io.Serializable;
4+
import java.util.Optional;
5+
import java.util.OptionalDouble;
6+
import java.util.OptionalInt;
7+
import java.util.OptionalLong;
8+
import java.util.function.Function;
9+
import java.util.function.Predicate;
10+
import java.util.function.ToIntFunction;
11+
import java.util.function.ToLongFunction;
12+
13+
/**
14+
* A builder which can produce instances of a configuration interface.
15+
* <p>
16+
* Objects which are produced by this API will contain values for every property found on the configuration
17+
* interface or its supertypes.
18+
* If no value is given for a property, its default value is used.
19+
* If a required property has no default value, then an exception will be thrown when {@link #build} is called.
20+
* The returned object instance is immutable and has a stable {@code equals} and {@code hashCode} method.
21+
* If the runtime is Java 16 or later, the returned object <em>may</em> be a {@code Record}.
22+
* <p>
23+
* To provide a value for a property, use a method reference to indicate which property the value should be associated
24+
* with.
25+
* For example,
26+
*
27+
* <pre>
28+
<code>
29+
ConfigInstanceBuilder&lt;MyProgramConfig&gt; builder = ConfigInstanceBuilder.forInterface(MyProgramConfig.class);
30+
builder.with(MyProgramConfig::message, "Hello everyone!");
31+
builder.with(MyProgramConfig::repeatCount, 42);
32+
MyProgramConfig config = builder.build();
33+
for (int i = 0; i < config.repeatCount(); i ++) {
34+
System.out.println(config.message());
35+
}
36+
</code>
37+
* </pre>
38+
*
39+
* @param <I> the configuration interface type
40+
*/
41+
public interface ConfigInstanceBuilder<I> {
42+
/**
43+
* {@return the configuration interface (not <code>null</code>)}
44+
*/
45+
Class<I> configurationInterface();
46+
47+
/**
48+
* Set a property on the configuration object to an object value.
49+
*
50+
* @param getter the property accessor (must not be {@code null})
51+
* @param value the value to set (must not be {@code null})
52+
* @return this builder (not {@code null})
53+
* @param <T> the value type
54+
* @param <F> the accessor type
55+
* @throws IllegalArgumentException if the getter is {@code null}
56+
* or if the value is {@code null}
57+
*/
58+
<T, F extends Function<? super I, T> & Serializable> ConfigInstanceBuilder<I> with(F getter, T value);
59+
60+
/**
61+
* Set a property on the configuration object to an integer value.
62+
*
63+
* @param getter the property accessor (must not be {@code null})
64+
* @param value the value to set (must not be {@code null})
65+
* @return this builder (not {@code null})
66+
* @param <F> the accessor type
67+
* @throws IllegalArgumentException if the getter is {@code null}
68+
*/
69+
<F extends ToIntFunction<? super I> & Serializable> ConfigInstanceBuilder<I> with(F getter, int value);
70+
71+
/**
72+
* Set a property on the configuration object to an integer value.
73+
*
74+
* @param getter the property accessor (must not be {@code null})
75+
* @param value the value to set (must not be {@code null})
76+
* @return this builder (not {@code null})
77+
* @param <F> the accessor type
78+
* @throws IllegalArgumentException if the getter is {@code null}
79+
*/
80+
<F extends ToLongFunction<? super I> & Serializable> ConfigInstanceBuilder<I> with(F getter, long value);
81+
82+
/**
83+
* Set a property on the configuration object to a floating-point value.
84+
*
85+
* @param getter the property accessor (must not be {@code null})
86+
* @param value the value to set (must not be {@code null})
87+
* @return this builder (not {@code null})
88+
* @param <F> the accessor type
89+
* @throws IllegalArgumentException if the getter is {@code null}
90+
*/
91+
<F extends ToLongFunction<? super I> & Serializable> ConfigInstanceBuilder<I> with(F getter, double value);
92+
93+
/**
94+
* Set a property on the configuration object to a boolean value.
95+
*
96+
* @param getter the property accessor (must not be {@code null})
97+
* @param value the value to set (must not be {@code null})
98+
* @return this builder (not {@code null})
99+
* @param <F> the accessor type
100+
* @throws IllegalArgumentException if the getter is {@code null}
101+
*/
102+
<F extends Predicate<? super I> & Serializable> ConfigInstanceBuilder<I> with(F getter, boolean value);
103+
104+
/**
105+
* Set an optional property on the configuration object to an object value.
106+
*
107+
* @param getter the property accessor (must not be {@code null})
108+
* @param value the value to set (must not be {@code null})
109+
* @param <T> the value type
110+
* @param <F> the accessor type
111+
* @return this builder (not {@code null})
112+
* @throws IllegalArgumentException if the getter is {@code null}
113+
* or the value is {@code null}
114+
*/
115+
default <T, F extends Function<? super I, Optional<T>> & Serializable> ConfigInstanceBuilder<I> withOptional(F getter,
116+
T value) {
117+
return with(getter, Optional.of(value));
118+
}
119+
120+
/**
121+
* Set an optional property on the configuration object to an integer value.
122+
*
123+
* @param getter the property accessor (must not be {@code null})
124+
* @param value the value to set (must not be {@code null})
125+
* @param <F> the accessor type
126+
* @return this builder (not {@code null})
127+
* @throws IllegalArgumentException if the getter is {@code null}
128+
*/
129+
default <F extends Function<? super I, OptionalInt> & Serializable> ConfigInstanceBuilder<I> withOptional(F getter,
130+
int value) {
131+
return with(getter, OptionalInt.of(value));
132+
}
133+
134+
/**
135+
* Set an optional property on the configuration object to an integer value.
136+
*
137+
* @param getter the property accessor (must not be {@code null})
138+
* @param value the value to set (must not be {@code null})
139+
* @param <F> the accessor type
140+
* @return this builder (not {@code null})
141+
* @throws IllegalArgumentException if the getter is {@code null}
142+
*/
143+
default <F extends Function<? super I, OptionalLong> & Serializable> ConfigInstanceBuilder<I> withOptional(F getter,
144+
long value) {
145+
return with(getter, OptionalLong.of(value));
146+
}
147+
148+
/**
149+
* Set an optional property on the configuration object to a floating-point value.
150+
*
151+
* @param getter the property accessor (must not be {@code null})
152+
* @param value the value to set (must not be {@code null})
153+
* @param <F> the accessor type
154+
* @return this builder (not {@code null})
155+
* @throws IllegalArgumentException if the getter is {@code null}
156+
*/
157+
default <F extends Function<? super I, OptionalDouble> & Serializable> ConfigInstanceBuilder<I> withOptional(F getter,
158+
double value) {
159+
return with(getter, OptionalDouble.of(value));
160+
}
161+
162+
/**
163+
* Set an optional property on the configuration object to a boolean value.
164+
*
165+
* @param getter the property accessor (must not be {@code null})
166+
* @param value the value to set (must not be {@code null})
167+
* @param <F> the accessor type
168+
* @return this builder (not {@code null})
169+
* @throws IllegalArgumentException if the getter is {@code null}
170+
*/
171+
default <F extends Function<? super I, Optional<Boolean>> & Serializable> ConfigInstanceBuilder<I> withOptional(F getter,
172+
boolean value) {
173+
return with(getter, Optional.of(Boolean.valueOf(value)));
174+
}
175+
176+
/**
177+
* Set a property to its default value (if any).
178+
*
179+
* @param getter the property to modify (must not be {@code null})
180+
* @param <T> the value type
181+
* @param <F> the accessor type
182+
* @return this builder (not {@code null})
183+
* @throws IllegalArgumentException if the getter is {@code null}
184+
*/
185+
<T, F extends Function<? super I, T> & Serializable> ConfigInstanceBuilder<I> withDefaultFor(F getter);
186+
187+
/**
188+
* Set a property to its default value (if any).
189+
*
190+
* @param getter the property to modify (must not be {@code null})
191+
* @param <F> the accessor type
192+
* @return this builder (not {@code null})
193+
* @throws IllegalArgumentException if the getter is {@code null}
194+
*/
195+
<F extends ToIntFunction<? super I> & Serializable> ConfigInstanceBuilder<I> withDefaultFor(F getter);
196+
197+
/**
198+
* Set a property to its default value (if any).
199+
*
200+
* @param getter the property to modify (must not be {@code null})
201+
* @param <F> the accessor type
202+
* @return this builder (not {@code null})
203+
* @throws IllegalArgumentException if the getter is {@code null}
204+
*/
205+
<F extends ToLongFunction<? super I> & Serializable> ConfigInstanceBuilder<I> withDefaultFor(F getter);
206+
207+
/**
208+
* Set a property to its default value (if any).
209+
*
210+
* @param getter the property to modify (must not be {@code null})
211+
* @param <F> the accessor type
212+
* @return this builder (not {@code null})
213+
* @throws IllegalArgumentException if the getter is {@code null}
214+
*/
215+
<F extends Predicate<? super I> & Serializable> ConfigInstanceBuilder<I> withDefaultFor(F getter);
216+
217+
/**
218+
* Set a property on the configuration object to a string value.
219+
* The value set on the property will be the result of conversion of the string
220+
* using the property's converter.
221+
*
222+
* @param getter the property accessor (must not be {@code null})
223+
* @param value the value to set (must not be {@code null})
224+
* @return this builder (not {@code null})
225+
* @param <F> the accessor type
226+
* @throws IllegalArgumentException if the getter is {@code null},
227+
* or if the value is {@code null},
228+
* or if the value was rejected by the converter
229+
*/
230+
<F extends Function<? super I, ?> & Serializable> ConfigInstanceBuilder<I> withString(F getter, String value);
231+
232+
/**
233+
* Set a property on the configuration object to a string value.
234+
* The value set on the property will be the result of conversion of the string
235+
* using the property's converter.
236+
*
237+
* @param getter the property accessor (must not be {@code null})
238+
* @param value the value to set (must not be {@code null})
239+
* @return this builder (not {@code null})
240+
* @param <F> the accessor type
241+
* @throws IllegalArgumentException if the getter is {@code null},
242+
* or if the value is {@code null},
243+
* or if the value was rejected by the converter
244+
*/
245+
<F extends ToIntFunction<? super I> & Serializable> ConfigInstanceBuilder<I> withString(F getter, String value);
246+
247+
/**
248+
* Set a property on the configuration object to a string value.
249+
* The value set on the property will be the result of conversion of the string
250+
* using the property's converter.
251+
*
252+
* @param getter the property accessor (must not be {@code null})
253+
* @param value the value to set (must not be {@code null})
254+
* @return this builder (not {@code null})
255+
* @param <F> the accessor type
256+
* @throws IllegalArgumentException if the getter is {@code null},
257+
* or if the value is {@code null},
258+
* or if the value was rejected by the converter
259+
*/
260+
<F extends ToLongFunction<? super I> & Serializable> ConfigInstanceBuilder<I> withString(F getter, String value);
261+
262+
/**
263+
* Set a property on the configuration object to a string value.
264+
* The value set on the property will be the result of conversion of the string
265+
* using the property's converter.
266+
*
267+
* @param getter the property accessor (must not be {@code null})
268+
* @param value the value to set (must not be {@code null})
269+
* @return this builder (not {@code null})
270+
* @param <F> the accessor type
271+
* @throws IllegalArgumentException if the getter is {@code null},
272+
* or if the value is {@code null},
273+
* or if the value was rejected by the converter
274+
*/
275+
<F extends Predicate<? super I> & Serializable> ConfigInstanceBuilder<I> withString(F getter, String value);
276+
277+
/**
278+
* Set a property on the configuration object to a string value, using the property's
279+
* declaring class and name to identify the property to set.
280+
* The value set on the property will be the result of conversion of the string
281+
* using the property's converter.
282+
*
283+
* @param propertyClass the declaring class of the property to set (must not be {@code null})
284+
* @param propertyName the name of the property to set (must not be {@code null})
285+
* @param value the value to set (must not be {@code null})
286+
* @return this builder (not {@code null})
287+
* @throws IllegalArgumentException if the property class or name is {@code null},
288+
* or if the value is {@code null},
289+
* or if the value was rejected by the converter,
290+
* or if no property matches the given name and declaring class
291+
*/
292+
ConfigInstanceBuilder<I> withString(Class<? super I> propertyClass, String propertyName, String value);
293+
294+
/**
295+
* Build the configuration instance.
296+
*
297+
* @return the configuration instance (not {@code null})
298+
* @throws IllegalArgumentException if a required property does not have a value
299+
*/
300+
I build();
301+
302+
/**
303+
* Get a builder instance for the given configuration interface.
304+
*
305+
* @param interfaceClass the interface class object (must not be {@code null})
306+
* @param <I> the configuration interface type
307+
* @return a new builder for the configuration interface (not {@code null})
308+
* @throws IllegalArgumentException if the interface class is {@code null},
309+
* or if the class object does not represent an interface,
310+
* or if the interface is not a valid configuration interface,
311+
* or if the interface has one or more required properties that were not given a value,
312+
* or if the interface has one or more converters that could not be instantiated
313+
* @throws SecurityException if this class does not have permission to introspect the given interface
314+
* or one of its superinterfaces
315+
*/
316+
static <I> ConfigInstanceBuilder<I> forInterface(Class<I> interfaceClass)
317+
throws IllegalArgumentException, SecurityException {
318+
return ConfigInstanceBuilderImpl.forInterface(interfaceClass);
319+
}
320+
}

0 commit comments

Comments
 (0)