Skip to content

Commit

Permalink
Remove references to Property classes from runtime (#1027)
Browse files Browse the repository at this point in the history
  • Loading branch information
radcortez authored Oct 17, 2023
1 parent 27b00d0 commit 75cd073
Show file tree
Hide file tree
Showing 5 changed files with 435 additions and 340 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
package io.smallrye.config;

import static io.smallrye.config.ConfigMappingInterface.LeafProperty;
import static io.smallrye.config.ConfigMappingInterface.MapProperty;
import static io.smallrye.config.ConfigMappingInterface.PrimitiveProperty;
import static io.smallrye.config.ConfigMappingInterface.Property;
import static io.smallrye.config.ConfigMappingInterface.getConfigurationInterface;
import static io.smallrye.config.ConfigMappingInterface.rawTypeOf;
import static io.smallrye.config.ConfigMappingInterface.typeOfParameter;
import static io.smallrye.config.ConfigValidationException.Problem;
import static io.smallrye.config.common.utils.StringUtil.replaceNonAlphanumericByUnderscores;

Expand All @@ -26,7 +19,6 @@

import org.eclipse.microprofile.config.spi.Converter;

import io.smallrye.config.ConfigMappingInterface.CollectionProperty;
import io.smallrye.config.ConfigMappingInterface.NamingStrategy;
import io.smallrye.config._private.ConfigMessages;
import io.smallrye.config.common.utils.StringUtil;
Expand All @@ -38,8 +30,6 @@
public final class ConfigMappingContext {
private final Map<Class<?>, Map<String, Map<Object, Object>>> enclosedThings = new IdentityHashMap<>();
private final Map<Class<?>, Map<String, ConfigMappingObject>> roots = new IdentityHashMap<>();
private final Map<Class<?>, Map<String, Converter<?>>> convertersByTypeAndField = new IdentityHashMap<>();
private final List<Map<Class<?>, Map<String, Converter<?>>>> keyConvertersByDegreeTypeAndField = new ArrayList<>();
private final Map<Class<?>, Converter<?>> converterInstances = new IdentityHashMap<>();
private final List<ConfigMappingObject> allInstances = new ArrayList<>();
private final SmallRyeConfig config;
Expand Down Expand Up @@ -85,83 +75,6 @@ public <T> T constructGroup(Class<T> interfaceType) {
return mappingObject;
}

@SuppressWarnings({ "unchecked", "unused" })
public <T> Converter<T> getValueConverter(Class<?> enclosingType, String field) {
return (Converter<T>) convertersByTypeAndField
.computeIfAbsent(enclosingType, x -> new HashMap<>())
.computeIfAbsent(field, x -> {
ConfigMappingInterface ci = getConfigurationInterface(enclosingType);
Property property = ci.getProperty(field);
return getConverter(property);
});
}

private Converter<?> getConverter(final Property property) {
boolean optional = property.isOptional();
if (property.isLeaf() || optional && property.asOptional().getNestedProperty().isLeaf()) {
LeafProperty leafProperty = optional ? property.asOptional().getNestedProperty().asLeaf()
: property.asLeaf();
if (leafProperty.hasConvertWith()) {
Class<? extends Converter<?>> convertWith = leafProperty.getConvertWith();
// todo: generics
return getConverterInstance(convertWith);
} else {
// todo: replace with generic converter lookup
Class<?> valueRawType = leafProperty.getValueRawType();
if (valueRawType == List.class) {
return config.requireConverter(rawTypeOf(typeOfParameter(leafProperty.getValueType(), 0)));
} else if (valueRawType == Set.class) {
return config.requireConverter(rawTypeOf(typeOfParameter(leafProperty.getValueType(), 0)));
} else {
return config.requireConverter(valueRawType);
}
}
} else if (property.isPrimitive()) {
PrimitiveProperty primitiveProperty = property.asPrimitive();
if (primitiveProperty.hasConvertWith()) {
return getConverterInstance(primitiveProperty.getConvertWith());
} else {
return config.requireConverter(primitiveProperty.getBoxType());
}
} else if (property.isCollection() || optional && property.asOptional().getNestedProperty().isCollection()) {
CollectionProperty collectionProperty = optional ? property.asOptional().getNestedProperty().asCollection()
: property.asCollection();
return getConverter(collectionProperty.getElement());
} else {
throw new IllegalStateException();
}
}

@SuppressWarnings("unchecked")
public <T> Converter<T> getKeyConverter(final Class<?> enclosingType, final MapProperty mapProperty) {
List<Map<Class<?>, Map<String, Converter<?>>>> list = this.keyConvertersByDegreeTypeAndField;
while (list.size() < mapProperty.getLevels()) {
list.add(new IdentityHashMap<>());
}
Map<Class<?>, Map<String, Converter<?>>> map = list.get(mapProperty.getLevels() - 1);
return (Converter<T>) map
.computeIfAbsent(enclosingType, x -> new HashMap<>())
.computeIfAbsent(mapProperty.getMemberName(), x -> {
if (mapProperty.hasKeyConvertWith()) {
return ConfigMappingContext.this.getConverterInstance(mapProperty.getKeyConvertWith());
} else {
// todo: replace with generic converter lookup
Class<?> valueRawType = mapProperty.getKeyRawType();
if (valueRawType == List.class) {
return Converters.newCollectionConverter(
config.requireConverter(rawTypeOf(typeOfParameter(mapProperty.getKeyType(), 0))),
ArrayList::new);
} else if (valueRawType == Set.class) {
return Converters.newCollectionConverter(
config.requireConverter(rawTypeOf(typeOfParameter(mapProperty.getKeyType(), 0))),
HashSet::new);
} else {
return config.requireConverter(valueRawType);
}
}
});
}

@SuppressWarnings("unchecked")
public <T> Converter<T> getConverterInstance(Class<? extends Converter<? extends T>> converterType) {
return (Converter<T>) converterInstances.computeIfAbsent(converterType, t -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
import org.objectweb.asm.Type;

import io.smallrye.config.ConfigMappingInterface.CollectionProperty;
import io.smallrye.config.ConfigMappingInterface.LeafProperty;
import io.smallrye.config.ConfigMappingInterface.MapProperty;
import io.smallrye.config.ConfigMappingInterface.PrimitiveProperty;
import io.smallrye.config.ConfigMappingInterface.Property;
Expand Down Expand Up @@ -406,6 +407,8 @@ private static void addProperties(

// now handle each possible type
if (property.isCollection() || realProperty.isCollection() && optional) {
CollectionProperty collectionProperty = realProperty.asCollection();

ctor.visitVarInsn(ALOAD, V_THIS);
// append property name
boolean restoreLength = appendPropertyName(ctor, property);
Expand All @@ -414,11 +417,10 @@ private static void addProperties(
ctor.visitMethodInsn(INVOKEVIRTUAL, I_MAPPING_CONTEXT, "getConfig", "()L" + I_SMALLRYE_CONFIG + ';', false);
ctor.visitVarInsn(ALOAD, V_STRING_BUILDER);
ctor.visitMethodInsn(INVOKEVIRTUAL, I_STRING_BUILDER, "toString", "()L" + I_STRING + ';', false);
// stack config key

// For Both Group and Optional Group
if (realProperty.asCollection().getElement().isGroup() || realProperty.asCollection().getElement().isMap()) {
CollectionProperty collectionProperty = realProperty.asCollection();

// get properties indexes
ctor.visitMethodInsn(INVOKEVIRTUAL, I_SMALLRYE_CONFIG, "getIndexedPropertiesIndexes",
"(L" + I_STRING + ";)L" + I_LIST + ';', false);
Expand Down Expand Up @@ -568,17 +570,25 @@ private static void addProperties(
}

} else if (optional) {
ctor.visitVarInsn(Opcodes.ALOAD, V_MAPPING_CONTEXT);
ctor.visitLdcInsn(getType(mapping.getInterfaceType()));
ctor.visitLdcInsn(memberName);
ctor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, I_MAPPING_CONTEXT, "getValueConverter",
"(L" + I_CLASS + ";L" + I_STRING + ";)L" + I_CONVERTER + ';', false);

ctor.visitLdcInsn(getType(realProperty.asCollection().getCollectionRawType()));
ctor.visitMethodInsn(INVOKESTATIC, I_MAPPING_CONTEXT, "createCollectionFactory",
"(L" + I_CLASS + ";)L" + I_INT_FUNCTION + ";", false);
ctor.visitMethodInsn(INVOKEVIRTUAL, I_SMALLRYE_CONFIG, "getOptionalValues",
"(L" + I_STRING + ";L" + I_CONVERTER + ";L" + I_INT_FUNCTION + ";)L" + I_OPTIONAL + ';', false);
LeafProperty collectionElementProperty = collectionProperty.getElement().asLeaf();
if (collectionElementProperty.hasConvertWith()) {
ctor.visitVarInsn(ALOAD, V_MAPPING_CONTEXT);
ctor.visitLdcInsn(getType(collectionElementProperty.getConvertWith()));
ctor.visitMethodInsn(INVOKEVIRTUAL, I_MAPPING_CONTEXT, "getConverterInstance",
"(L" + I_CLASS + ";)L" + I_CONVERTER + ';', false);
ctor.visitLdcInsn(getType(realProperty.asCollection().getCollectionRawType()));
ctor.visitMethodInsn(INVOKESTATIC, I_MAPPING_CONTEXT, "createCollectionFactory",
"(L" + I_CLASS + ";)L" + I_INT_FUNCTION + ";", false);
ctor.visitMethodInsn(INVOKEVIRTUAL, I_SMALLRYE_CONFIG, "getOptionalValues",
"(L" + I_STRING + ";L" + I_CONVERTER + ";L" + I_INT_FUNCTION + ";)L" + I_OPTIONAL + ';', false);
} else {
ctor.visitLdcInsn(getType(collectionElementProperty.getValueRawType()));
ctor.visitLdcInsn(getType(collectionProperty.getCollectionRawType()));
ctor.visitMethodInsn(INVOKESTATIC, I_MAPPING_CONTEXT, "createCollectionFactory",
"(L" + I_CLASS + ";)L" + I_INT_FUNCTION + ";", false);
ctor.visitMethodInsn(INVOKEVIRTUAL, I_SMALLRYE_CONFIG, "getOptionalValues",
"(L" + I_STRING + ";L" + I_CLASS + ";L" + I_INT_FUNCTION + ";)L" + I_OPTIONAL + ';', false);
}
ctor.visitFieldInsn(Opcodes.PUTFIELD, className, memberName, fieldDesc);

if (restoreLength) {
Expand All @@ -589,18 +599,29 @@ private static void addProperties(
Label _catch = new Label();
Label _continue = new Label();
ctor.visitLabel(_try);
ctor.visitVarInsn(Opcodes.ALOAD, V_MAPPING_CONTEXT);
ctor.visitLdcInsn(getType(mapping.getInterfaceType()));
ctor.visitLdcInsn(memberName);
ctor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, I_MAPPING_CONTEXT, "getValueConverter",
"(L" + I_CLASS + ";L" + I_STRING + ";)L" + I_CONVERTER + ';', false);

ctor.visitLdcInsn(getType(fieldDesc));
ctor.visitMethodInsn(INVOKESTATIC, I_MAPPING_CONTEXT, "createCollectionFactory",
"(L" + I_CLASS + ";)L" + I_INT_FUNCTION + ";", false);
ctor.visitMethodInsn(INVOKEVIRTUAL, I_SMALLRYE_CONFIG, "getValues",
"(L" + I_STRING + ";L" + I_CONVERTER + ";L" + I_INT_FUNCTION + ";)L" + I_COLLECTION + ';', false);
LeafProperty collectionElementProperty = collectionProperty.getElement().asLeaf();
if (collectionElementProperty.hasConvertWith()) {
ctor.visitVarInsn(ALOAD, V_MAPPING_CONTEXT);
ctor.visitLdcInsn(getType(collectionElementProperty.getConvertWith()));
ctor.visitMethodInsn(INVOKEVIRTUAL, I_MAPPING_CONTEXT, "getConverterInstance",
"(L" + I_CLASS + ";)L" + I_CONVERTER + ';', false);
ctor.visitLdcInsn(getType(realProperty.asCollection().getCollectionRawType()));
ctor.visitMethodInsn(INVOKESTATIC, I_MAPPING_CONTEXT, "createCollectionFactory",
"(L" + I_CLASS + ";)L" + I_INT_FUNCTION + ";", false);
ctor.visitMethodInsn(INVOKEVIRTUAL, I_SMALLRYE_CONFIG, "getValues",
"(L" + I_STRING + ";L" + I_CONVERTER + ";L" + I_INT_FUNCTION + ";)L" + I_COLLECTION + ';',
false);
} else {
ctor.visitLdcInsn(getType(collectionElementProperty.getValueRawType()));
ctor.visitLdcInsn(getType(collectionProperty.getCollectionRawType()));
ctor.visitMethodInsn(INVOKESTATIC, I_MAPPING_CONTEXT, "createCollectionFactory",
"(L" + I_CLASS + ";)L" + I_INT_FUNCTION + ";", false);
ctor.visitMethodInsn(INVOKEVIRTUAL, I_SMALLRYE_CONFIG, "getValues",
"(L" + I_STRING + ";L" + I_CLASS + ";L" + I_INT_FUNCTION + ";)L" + I_COLLECTION + ';', false);
}
ctor.visitFieldInsn(Opcodes.PUTFIELD, className, memberName, fieldDesc);

ctor.visitJumpInsn(Opcodes.GOTO, _continue);
ctor.visitLabel(_catch);
ctor.visitVarInsn(Opcodes.ALOAD, V_MAPPING_CONTEXT);
Expand Down Expand Up @@ -746,37 +767,58 @@ private static void addProperties(
ctor.visitVarInsn(Opcodes.ALOAD, V_STRING_BUILDER);
ctor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, I_STRING_BUILDER, "toString", "()L" + I_STRING + ';', false);
// stack: this config key
// get the converter to use
ctor.visitVarInsn(Opcodes.ALOAD, V_MAPPING_CONTEXT);
ctor.visitLdcInsn(getType(mapping.getInterfaceType()));
ctor.visitLdcInsn(memberName);
ctor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, I_MAPPING_CONTEXT, "getValueConverter",
"(L" + I_CLASS + ";L" + I_STRING + ";)L" + I_CONVERTER + ';', false);
// stack: this config key converter
Label _try = new Label();
Label _catch = new Label();
Label _continue = new Label();
ctor.visitLabel(_try);
if (property.isOptional()) {
ctor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, I_SMALLRYE_CONFIG, "getOptionalValue",
"(L" + I_STRING + ";L" + I_CONVERTER + ";)L" + I_OPTIONAL + ';', false);
} else {
ctor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, I_SMALLRYE_CONFIG, "getValue",
"(L" + I_STRING + ";L" + I_CONVERTER + ";)L" + I_OBJECT + ';', false);
}
// stack: this value
if (property.isPrimitive()) {
PrimitiveProperty prim = property.asPrimitive();
// unbox it
// stack: this box
String boxType = getInternalName(prim.getBoxType());
ctor.visitTypeInsn(Opcodes.CHECKCAST, boxType);
ctor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, boxType, prim.getUnboxMethodName(),
prim.getUnboxMethodDescriptor(), false);
// stack: this value
} else if (!property.isOptional()) {
assert property.isLeaf();
LeafProperty leafProperty = property.asOptional().getNestedProperty().asLeaf();
if (leafProperty.hasConvertWith()) {
ctor.visitVarInsn(ALOAD, V_MAPPING_CONTEXT);
ctor.visitLdcInsn(getType(leafProperty.getConvertWith()));
ctor.visitMethodInsn(INVOKEVIRTUAL, I_MAPPING_CONTEXT, "getConverterInstance",
"(L" + I_CLASS + ";)L" + I_CONVERTER + ';', false);
ctor.visitMethodInsn(INVOKEVIRTUAL, I_SMALLRYE_CONFIG, "getOptionalValue",
"(L" + I_STRING + ";L" + I_CONVERTER + ";)L" + I_OPTIONAL + ';', false);
} else {
ctor.visitLdcInsn(getType(leafProperty.getValueRawType()));
ctor.visitMethodInsn(INVOKEVIRTUAL, I_SMALLRYE_CONFIG, "getOptionalValue",
"(L" + I_STRING + ";L" + I_CLASS + ";)L" + I_OPTIONAL + ';', false);
}
ctor.visitTypeInsn(Opcodes.CHECKCAST, fieldType);
} else if (property.isLeaf()) {
LeafProperty leafProperty = property.asLeaf();
if (leafProperty.hasConvertWith()) {
ctor.visitVarInsn(ALOAD, V_MAPPING_CONTEXT);
ctor.visitLdcInsn(getType(leafProperty.getConvertWith()));
ctor.visitMethodInsn(INVOKEVIRTUAL, I_MAPPING_CONTEXT, "getConverterInstance",
"(L" + I_CLASS + ";)L" + I_CONVERTER + ';', false);
ctor.visitMethodInsn(INVOKEVIRTUAL, I_SMALLRYE_CONFIG, "getValue",
"(L" + I_STRING + ";L" + I_CONVERTER + ";)L" + I_OBJECT + ';', false);
} else {
ctor.visitLdcInsn(getType(leafProperty.getValueRawType()));
ctor.visitMethodInsn(INVOKEVIRTUAL, I_SMALLRYE_CONFIG, "getValue",
"(L" + I_STRING + ";L" + I_CLASS + ";)L" + I_OBJECT + ';', false);
}
ctor.visitTypeInsn(Opcodes.CHECKCAST, fieldType);
} else if (property.isPrimitive()) {
PrimitiveProperty primitiveProperty = property.asPrimitive();
if (primitiveProperty.hasConvertWith()) {
ctor.visitVarInsn(ALOAD, V_MAPPING_CONTEXT);
ctor.visitLdcInsn(getType(primitiveProperty.getConvertWith()));
ctor.visitMethodInsn(INVOKEVIRTUAL, I_MAPPING_CONTEXT, "getConverterInstance",
"(L" + I_CLASS + ";)L" + I_CONVERTER + ';', false);
ctor.visitMethodInsn(INVOKEVIRTUAL, I_SMALLRYE_CONFIG, "getValue",
"(L" + I_STRING + ";L" + I_CONVERTER + ";)L" + I_OBJECT + ';', false);
} else {
ctor.visitLdcInsn(getType(primitiveProperty.getBoxType()));
ctor.visitMethodInsn(INVOKEVIRTUAL, I_SMALLRYE_CONFIG, "getValue",
"(L" + I_STRING + ";L" + I_CLASS + ";)L" + I_OBJECT + ';', false);
}
String boxType = getInternalName(primitiveProperty.getBoxType());
ctor.visitTypeInsn(Opcodes.CHECKCAST, boxType);
ctor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, boxType, primitiveProperty.getUnboxMethodName(),
primitiveProperty.getUnboxMethodDescriptor(), false);
}
// stack: this value
ctor.visitFieldInsn(Opcodes.PUTFIELD, className, memberName, fieldDesc);
Expand Down
Loading

0 comments on commit 75cd073

Please sign in to comment.