io.github.konohiroaki.deepinitializer.DeepInitializer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of deep-initializer Show documentation
Show all versions of deep-initializer Show documentation
Initialize deep bean recursively filling with default values.
The newest version!
package io.github.konohiroaki.deepinitializer;
import java.lang.reflect.Field;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@SuppressWarnings("unchecked")
public class DeepInitializer {
private final List, BaseTypeInitializer>>> typeInitializer = new ArrayList<>();
private final List, BaseFieldInitializer>>> fieldInitializer = new ArrayList<>();
public DeepInitializer() {
addDefaultTypeInitializer();
}
private void addDefaultTypeInitializer() {
addTypeInitializer(Boolean.class, new BooleanTypeInitializer());
addTypeInitializer(Byte.class, new ByteTypeInitializer());
addTypeInitializer(Character.class, new CharacterTypeInitializer());
addTypeInitializer(Short.class, new ShortTypeInitializer());
addTypeInitializer(Integer.class, new IntegerTypeInitializer());
addTypeInitializer(Long.class, new LongTypeInitializer());
addTypeInitializer(Float.class, new FloatTypeInitializer());
addTypeInitializer(Double.class, new DoubleTypeInitializer());
addTypeInitializer(String.class, new StringTypeInitializer());
addTypeInitializer(Enum.class, new EnumTypeInitializer());
addTypeInitializer(List.class, new ListTypeInitializer());
addTypeInitializer(Set.class, new SetTypeInitializer());
addTypeInitializer(Map.class, new MapTypeInitializer());
}
public void addTypeInitializer(Class extends T> type, BaseTypeInitializer init) {
typeInitializer.add(new AbstractMap.SimpleImmutableEntry<>(type, init));
}
public void removeTypeInitializer(Class> type) {
List, BaseTypeInitializer>>> target = new ArrayList<>();
for (Map.Entry, BaseTypeInitializer>> entry : typeInitializer) {
if (entry.getKey() == type && !TypeUtils.isDefaultInitializer(entry.getValue())) {
target.add(entry);
}
}
typeInitializer.removeAll(target);
}
public void addFieldInitializer(Class extends T> type, BaseFieldInitializer init) {
fieldInitializer.add(new AbstractMap.SimpleImmutableEntry<>(type, init));
}
public void removeFieldInitializer(Class> type) {
List, BaseFieldInitializer>>> target = new ArrayList<>();
for (Map.Entry, BaseFieldInitializer>> entry : fieldInitializer) {
if (entry.getKey() == type) {
target.add(entry);
}
}
fieldInitializer.removeAll(target);
}
public T init(Class clazz) {
T value = getTypeValue(clazz);
if (value != null) {
return value;
}
return initFields(clazz);
}
public List init(Class clazz, int size) {
if (size <= 0) {
throw new IllegalArgumentException("size needs to be positive number but was " + size);
}
return Stream.generate(() -> init(clazz)).limit(size).collect(Collectors.toList());
}
private T initFields(Class clazz) {
T value;
try {
value = clazz.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new IllegalArgumentException(clazz + " type not supported");
}
for (Field field : ReflectionUtils.getAllFields(clazz)) {
ReflectionUtils.setProperty(value, field, initField(field));
}
return value;
}
private T initField(Field field) {
T value = getFieldValue((field));
if (value != null) {
return value;
}
return initFields((Class) field.getType());
}
private T getTypeValue(Class clazz) {
for (Map.Entry, BaseTypeInitializer>> entry : ListUtils.reverse(typeInitializer)) {
if (entry.getKey().isAssignableFrom(clazz) || TypeUtils.isAutoboxable(clazz, entry.getKey())) {
return (T) entry.getValue().init((Class) clazz);
}
}
return null;
}
private T getFieldValue(Field field) {
Class clazz = (Class) field.getType();
for (Map.Entry, BaseFieldInitializer>> entry : ListUtils.reverse(fieldInitializer)) {
if (entry.getKey().isAssignableFrom(clazz) || TypeUtils.isAutoboxable(clazz, entry.getKey())) {
return (T) entry.getValue().init(field);
}
}
return getTypeValue(clazz);
}
}