io.polyglotted.common.model.Builder Maven / Gradle / Ivy
package io.polyglotted.common.model;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.util.Map;
import static io.polyglotted.common.util.NullUtil.nonNullFn;
import static io.polyglotted.common.util.ReflectionUtil.annotation;
import static io.polyglotted.common.util.ReflectionUtil.create;
import static io.polyglotted.common.util.ReflectionUtil.declaredField;
import static io.polyglotted.common.util.ReflectionUtil.declaredMethod;
import static io.polyglotted.common.util.ReflectionUtil.detectValueClass;
import static io.polyglotted.common.util.ReflectionUtil.safeInvoke;
import static io.polyglotted.common.util.Sanitizer.sanitize;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@SuppressWarnings("unchecked")
public interface Builder {
T build();
@Documented @Retention(RUNTIME)
@Target(FIELD) @interface Name {
String value();
}
static > T buildWith(Map result, Class clazz) { return buildWith(result, (C) create(clazz)); }
static > T buildWith(Map result, C builder) {
return builder(result, (Class) builder.getClass(), builder).build();
}
static > C builder(Map result, Class clazz) { return builder(result, clazz, (C) create(clazz)); }
static > C builder(Map result, Class clazz, C builder) {
for (Field field : clazz.getDeclaredFields()) {
Object value = result.get(field.getName());
if (value == null) { value = result.get(nonNullFn(annotation(field, Builder.Name.class), Builder.Name::value, "_$")); }
if (value != null) {
Class> valueClass = detectValueClass(value, () -> declaredField(clazz, field.getName()));
try {
safeInvoke(declaredMethod(clazz, field.getName(), new Class[]{valueClass}), builder, sanitize(valueClass, value));
} catch (Exception ex) { throw new RuntimeException("failed invoke " + field.getName(), ex); }
}
}
return builder;
}
}