Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Config instance builder #1021

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,320 @@
package io.smallrye.config;

import java.io.Serializable;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.OptionalLong;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;

/**
* A builder which can produce instances of a configuration interface.
* <p>
* Objects which are produced by this API will contain values for every property found on the configuration
* interface or its supertypes.
* If no value is given for a property, its default value is used.
* If a required property has no default value, then an exception will be thrown when {@link #build} is called.
* The returned object instance is immutable and has a stable {@code equals} and {@code hashCode} method.
* If the runtime is Java 16 or later, the returned object <em>may</em> be a {@code Record}.
* <p>
* To provide a value for a property, use a method reference to indicate which property the value should be associated
* with.
* For example,
*
* <pre>
<code>
ConfigInstanceBuilder&lt;MyProgramConfig&gt; builder = ConfigInstanceBuilder.forInterface(MyProgramConfig.class);
builder.with(MyProgramConfig::message, "Hello everyone!");
builder.with(MyProgramConfig::repeatCount, 42);
MyProgramConfig config = builder.build();
for (int i = 0; i < config.repeatCount(); i ++) {
System.out.println(config.message());
}
</code>
* </pre>
*
* @param <I> the configuration interface type
*/
public interface ConfigInstanceBuilder<I> {
/**
* {@return the configuration interface (not <code>null</code>)}
*/
Class<I> configurationInterface();

/**
* Set a property on the configuration object to an object value.
*
* @param getter the property accessor (must not be {@code null})
* @param value the value to set (must not be {@code null})
* @return this builder (not {@code null})
* @param <T> the value type
* @param <F> the accessor type
* @throws IllegalArgumentException if the getter is {@code null}
* or if the value is {@code null}
*/
<T, F extends Function<? super I, T> & Serializable> ConfigInstanceBuilder<I> with(F getter, T value);

/**
* Set a property on the configuration object to an integer value.
*
* @param getter the property accessor (must not be {@code null})
* @param value the value to set (must not be {@code null})
* @return this builder (not {@code null})
* @param <F> the accessor type
* @throws IllegalArgumentException if the getter is {@code null}
*/
<F extends ToIntFunction<? super I> & Serializable> ConfigInstanceBuilder<I> with(F getter, int value);

/**
* Set a property on the configuration object to an integer value.
*
* @param getter the property accessor (must not be {@code null})
* @param value the value to set (must not be {@code null})
* @return this builder (not {@code null})
* @param <F> the accessor type
* @throws IllegalArgumentException if the getter is {@code null}
*/
<F extends ToLongFunction<? super I> & Serializable> ConfigInstanceBuilder<I> with(F getter, long value);

/**
* Set a property on the configuration object to a floating-point value.
*
* @param getter the property accessor (must not be {@code null})
* @param value the value to set (must not be {@code null})
* @return this builder (not {@code null})
* @param <F> the accessor type
* @throws IllegalArgumentException if the getter is {@code null}
*/
<F extends ToLongFunction<? super I> & Serializable> ConfigInstanceBuilder<I> with(F getter, double value);

/**
* Set a property on the configuration object to a boolean value.
*
* @param getter the property accessor (must not be {@code null})
* @param value the value to set (must not be {@code null})
* @return this builder (not {@code null})
* @param <F> the accessor type
* @throws IllegalArgumentException if the getter is {@code null}
*/
<F extends Predicate<? super I> & Serializable> ConfigInstanceBuilder<I> with(F getter, boolean value);

/**
* Set an optional property on the configuration object to an object value.
*
* @param getter the property accessor (must not be {@code null})
* @param value the value to set (must not be {@code null})
* @param <T> the value type
* @param <F> the accessor type
* @return this builder (not {@code null})
* @throws IllegalArgumentException if the getter is {@code null}
* or the value is {@code null}
*/
default <T, F extends Function<? super I, Optional<T>> & Serializable> ConfigInstanceBuilder<I> withOptional(F getter,
T value) {
return with(getter, Optional.of(value));
}

/**
* Set an optional property on the configuration object to an integer value.
*
* @param getter the property accessor (must not be {@code null})
* @param value the value to set (must not be {@code null})
* @param <F> the accessor type
* @return this builder (not {@code null})
* @throws IllegalArgumentException if the getter is {@code null}
*/
default <F extends Function<? super I, OptionalInt> & Serializable> ConfigInstanceBuilder<I> withOptional(F getter,
int value) {
return with(getter, OptionalInt.of(value));
}

/**
* Set an optional property on the configuration object to an integer value.
*
* @param getter the property accessor (must not be {@code null})
* @param value the value to set (must not be {@code null})
* @param <F> the accessor type
* @return this builder (not {@code null})
* @throws IllegalArgumentException if the getter is {@code null}
*/
default <F extends Function<? super I, OptionalLong> & Serializable> ConfigInstanceBuilder<I> withOptional(F getter,
long value) {
return with(getter, OptionalLong.of(value));
}

/**
* Set an optional property on the configuration object to a floating-point value.
*
* @param getter the property accessor (must not be {@code null})
* @param value the value to set (must not be {@code null})
* @param <F> the accessor type
* @return this builder (not {@code null})
* @throws IllegalArgumentException if the getter is {@code null}
*/
default <F extends Function<? super I, OptionalDouble> & Serializable> ConfigInstanceBuilder<I> withOptional(F getter,
double value) {
return with(getter, OptionalDouble.of(value));
}

/**
* Set an optional property on the configuration object to a boolean value.
*
* @param getter the property accessor (must not be {@code null})
* @param value the value to set (must not be {@code null})
* @param <F> the accessor type
* @return this builder (not {@code null})
* @throws IllegalArgumentException if the getter is {@code null}
*/
default <F extends Function<? super I, Optional<Boolean>> & Serializable> ConfigInstanceBuilder<I> withOptional(F getter,
boolean value) {
return with(getter, Optional.of(Boolean.valueOf(value)));
}

/**
* Set a property to its default value (if any).
*
* @param getter the property to modify (must not be {@code null})
* @param <T> the value type
* @param <F> the accessor type
* @return this builder (not {@code null})
* @throws IllegalArgumentException if the getter is {@code null}
*/
<T, F extends Function<? super I, T> & Serializable> ConfigInstanceBuilder<I> withDefaultFor(F getter);

/**
* Set a property to its default value (if any).
*
* @param getter the property to modify (must not be {@code null})
* @param <F> the accessor type
* @return this builder (not {@code null})
* @throws IllegalArgumentException if the getter is {@code null}
*/
<F extends ToIntFunction<? super I> & Serializable> ConfigInstanceBuilder<I> withDefaultFor(F getter);

/**
* Set a property to its default value (if any).
*
* @param getter the property to modify (must not be {@code null})
* @param <F> the accessor type
* @return this builder (not {@code null})
* @throws IllegalArgumentException if the getter is {@code null}
*/
<F extends ToLongFunction<? super I> & Serializable> ConfigInstanceBuilder<I> withDefaultFor(F getter);

/**
* Set a property to its default value (if any).
*
* @param getter the property to modify (must not be {@code null})
* @param <F> the accessor type
* @return this builder (not {@code null})
* @throws IllegalArgumentException if the getter is {@code null}
*/
<F extends Predicate<? super I> & Serializable> ConfigInstanceBuilder<I> withDefaultFor(F getter);

/**
* Set a property on the configuration object to a string value.
* The value set on the property will be the result of conversion of the string
* using the property's converter.
*
* @param getter the property accessor (must not be {@code null})
* @param value the value to set (must not be {@code null})
* @return this builder (not {@code null})
* @param <F> the accessor type
* @throws IllegalArgumentException if the getter is {@code null},
* or if the value is {@code null},
* or if the value was rejected by the converter
*/
<F extends Function<? super I, ?> & Serializable> ConfigInstanceBuilder<I> withString(F getter, String value);

/**
* Set a property on the configuration object to a string value.
* The value set on the property will be the result of conversion of the string
* using the property's converter.
*
* @param getter the property accessor (must not be {@code null})
* @param value the value to set (must not be {@code null})
* @return this builder (not {@code null})
* @param <F> the accessor type
* @throws IllegalArgumentException if the getter is {@code null},
* or if the value is {@code null},
* or if the value was rejected by the converter
*/
<F extends ToIntFunction<? super I> & Serializable> ConfigInstanceBuilder<I> withString(F getter, String value);

/**
* Set a property on the configuration object to a string value.
* The value set on the property will be the result of conversion of the string
* using the property's converter.
*
* @param getter the property accessor (must not be {@code null})
* @param value the value to set (must not be {@code null})
* @return this builder (not {@code null})
* @param <F> the accessor type
* @throws IllegalArgumentException if the getter is {@code null},
* or if the value is {@code null},
* or if the value was rejected by the converter
*/
<F extends ToLongFunction<? super I> & Serializable> ConfigInstanceBuilder<I> withString(F getter, String value);

/**
* Set a property on the configuration object to a string value.
* The value set on the property will be the result of conversion of the string
* using the property's converter.
*
* @param getter the property accessor (must not be {@code null})
* @param value the value to set (must not be {@code null})
* @return this builder (not {@code null})
* @param <F> the accessor type
* @throws IllegalArgumentException if the getter is {@code null},
* or if the value is {@code null},
* or if the value was rejected by the converter
*/
<F extends Predicate<? super I> & Serializable> ConfigInstanceBuilder<I> withString(F getter, String value);

/**
* Set a property on the configuration object to a string value, using the property's
* declaring class and name to identify the property to set.
* The value set on the property will be the result of conversion of the string
* using the property's converter.
*
* @param propertyClass the declaring class of the property to set (must not be {@code null})
* @param propertyName the name of the property to set (must not be {@code null})
* @param value the value to set (must not be {@code null})
* @return this builder (not {@code null})
* @throws IllegalArgumentException if the property class or name is {@code null},
* or if the value is {@code null},
* or if the value was rejected by the converter,
* or if no property matches the given name and declaring class
*/
ConfigInstanceBuilder<I> withString(Class<? super I> propertyClass, String propertyName, String value);

/**
* Build the configuration instance.
*
* @return the configuration instance (not {@code null})
* @throws IllegalArgumentException if a required property does not have a value
*/
I build();

/**
* Get a builder instance for the given configuration interface.
*
* @param interfaceClass the interface class object (must not be {@code null})
* @param <I> the configuration interface type
* @return a new builder for the configuration interface (not {@code null})
* @throws IllegalArgumentException if the interface class is {@code null},
* or if the class object does not represent an interface,
* or if the interface is not a valid configuration interface,
* or if the interface has one or more required properties that were not given a value,
* or if the interface has one or more converters that could not be instantiated
* @throws SecurityException if this class does not have permission to introspect the given interface
* or one of its superinterfaces
*/
static <I> ConfigInstanceBuilder<I> forInterface(Class<I> interfaceClass)
throws IllegalArgumentException, SecurityException {
return ConfigInstanceBuilderImpl.forInterface(interfaceClass);
}
}
Loading
Loading