io.scalecube.config.ObjectPropertyField Maven / Gradle / Ivy
package io.scalecube.config;
import io.scalecube.config.utils.ThrowableUtil;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
/**
* Helper holder class. Contains parsed field of the corresponding object class, associated property
* name and computed {@link #valueParser} function.
*/
class ObjectPropertyField {
private final Field field;
private final String propertyName;
private final Function valueParser;
ObjectPropertyField(Field field, String propertyName) {
int modifiers = field.getModifiers();
if (Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers)) {
throw new IllegalArgumentException(
"ObjectPropertyField: 'static' or 'final' declaration is not supported (field: "
+ field
+ ")");
}
this.field = field;
field.setAccessible(true); // set accessible to overcome 'private' declaration
this.propertyName = propertyName;
if (field.getGenericType() instanceof ParameterizedType) {
ParameterizedType paramType = (ParameterizedType) field.getGenericType();
if (isList(paramType)) {
Type type = paramType.getActualTypeArguments()[0];
this.valueParser = ListConfigPropertyImpl.toListPropertyParser(getValueParser(type));
} else if (isMultimap(paramType)) {
Type[] typeArguments = paramType.getActualTypeArguments();
ParameterizedType valueType = ((ParameterizedType) typeArguments[1]);
Type type = valueType.getActualTypeArguments()[0];
this.valueParser =
MultimapConfigPropertyImpl.toMultimapPropertyParser(getValueParser(type));
} else {
throw new IllegalArgumentException(
"ObjectPropertyField: unsupported type on field: " + field);
}
} else {
this.valueParser = getValueParser(field.getType());
}
}
private boolean isList(ParameterizedType paramType) {
return paramType.getRawType() == List.class;
}
private boolean isMultimap(ParameterizedType paramType) {
boolean result = false;
if (paramType.getRawType() == Map.class) {
Type[] typeArguments = paramType.getActualTypeArguments();
Type keyType = typeArguments[0];
Type valueType = typeArguments[1];
if (keyType == String.class && valueType instanceof ParameterizedType) {
ParameterizedType parameterizedValueType = ((ParameterizedType) valueType);
if (parameterizedValueType.getRawType() == List.class) {
result = true;
}
}
}
return result;
}
private Function getValueParser(Type type) {
if (type == String.class) {
return str -> str;
} else if (type == Duration.class) {
return DurationParser::parseDuration;
} else if (type == Integer.TYPE || type == Integer.class) {
return Integer::parseInt;
} else if (type == Double.TYPE || type == Double.class) {
return Double::parseDouble;
} else if (type == Boolean.TYPE || type == Boolean.class) {
return Boolean::parseBoolean;
} else if (type == Long.TYPE || type == Long.class) {
return Long::parseLong;
} else {
return Function.identity();
}
}
String getPropertyName() {
return propertyName;
}
void applyValueParser(Object instance, String value) {
try {
field.set(instance, valueParser.apply(value));
} catch (IllegalAccessException e) {
throw ThrowableUtil.propagate(e);
}
}
}