diff --git a/implementation/src/main/java/io/smallrye/config/ConfigMappingContext.java b/implementation/src/main/java/io/smallrye/config/ConfigMappingContext.java index d09afe7b0..a77e98dbf 100644 --- a/implementation/src/main/java/io/smallrye/config/ConfigMappingContext.java +++ b/implementation/src/main/java/io/smallrye/config/ConfigMappingContext.java @@ -132,31 +132,17 @@ private Converter getConverter(final Property property) { } @SuppressWarnings("unchecked") - public Converter getKeyConverter(Class enclosingType, String field, int degree) { + public Converter getKeyConverter(final Class enclosingType, final MapProperty mapProperty) { List, Map>>> list = this.keyConvertersByDegreeTypeAndField; - while (list.size() <= degree) { + while (list.size() < mapProperty.getLevels()) { list.add(new IdentityHashMap<>()); } - Map, Map>> map = list.get(degree); + Map, Map>> map = list.get(mapProperty.getLevels() - 1); return (Converter) map .computeIfAbsent(enclosingType, x -> new HashMap<>()) - .computeIfAbsent(field, x -> { - ConfigMappingInterface ci = getConfigurationInterface(enclosingType); - Property property = ci.getProperty(field); - MapProperty mapProperty; - if (property.isMap()) { - mapProperty = property.asMap(); - } else if (property.isCollection()) { - mapProperty = property.asCollection().getElement().asMap(); - } else { - throw new IllegalStateException(); - } - - while (degree + 1 < mapProperty.getLevels()) { - mapProperty = mapProperty.getValueProperty().asMap(); - } + .computeIfAbsent(mapProperty.getMemberName(), x -> { if (mapProperty.hasKeyConvertWith()) { - return getConverterInstance(mapProperty.getKeyConvertWith()); + return ConfigMappingContext.this.getConverterInstance(mapProperty.getKeyConvertWith()); } else { // todo: replace with generic converter lookup Class valueRawType = mapProperty.getKeyRawType(); diff --git a/implementation/src/main/java/io/smallrye/config/ConfigMappingInterface.java b/implementation/src/main/java/io/smallrye/config/ConfigMappingInterface.java index 2d645e2b8..2bd225f13 100644 --- a/implementation/src/main/java/io/smallrye/config/ConfigMappingInterface.java +++ b/implementation/src/main/java/io/smallrye/config/ConfigMappingInterface.java @@ -197,6 +197,10 @@ public String getPropertyName() { return hasPropertyName() && !propertyName.isEmpty() ? propertyName : method.getName(); } + public String getMemberName() { + return method.getName(); + } + public boolean hasPropertyName() { return propertyName != null; } diff --git a/implementation/src/main/java/io/smallrye/config/ConfigMappingProvider.java b/implementation/src/main/java/io/smallrye/config/ConfigMappingProvider.java index 757cf0c85..b8dd18262 100644 --- a/implementation/src/main/java/io/smallrye/config/ConfigMappingProvider.java +++ b/implementation/src/main/java/io/smallrye/config/ConfigMappingProvider.java @@ -166,24 +166,20 @@ private void processEagerGroup( } Class type = group.getInterfaceType(); - HashSet usedProperties = new HashSet<>(); for (int i = 0; i < group.getPropertyCount(); i++) { Property property = group.getProperty(i); - String memberName = property.getMethod().getName(); ArrayDeque propertyPath = new ArrayDeque<>(currentPath); - if (usedProperties.add(memberName)) { - // process by property type - if (!property.isParentPropertyName()) { - NameIterator ni = new NameIterator(property.hasPropertyName() ? property.getPropertyName() - : propertyName(property, group, namingStrategy)); - while (ni.hasNext()) { - propertyPath.add(ni.getNextSegment()); - ni.next(); - } + // process by property type + if (!property.isParentPropertyName()) { + NameIterator ni = new NameIterator(property.hasPropertyName() ? property.getPropertyName() + : propertyName(property, group, namingStrategy)); + while (ni.hasNext()) { + propertyPath.add(ni.getNextSegment()); + ni.next(); } - processProperty(propertyPath, matchActions, defaultValues, namingStrategy, group, getEnclosingFunction, type, - memberName, property); } + processProperty(propertyPath, matchActions, defaultValues, namingStrategy, group, getEnclosingFunction, type, + property); } } @@ -195,14 +191,13 @@ private void processProperty( final ConfigMappingInterface group, final BiFunction getEnclosingFunction, final Class type, - final String memberName, final Property property) { if (property.isOptional()) { // switch to lazy mode Property nestedProperty = property.asOptional().getNestedProperty(); processOptionalProperty(currentPath, matchActions, defaultValues, namingStrategy, group, getEnclosingFunction, type, - memberName, nestedProperty); + nestedProperty); } else if (property.isGroup()) { processEagerGroup(currentPath, matchActions, defaultValues, namingStrategy, property.asGroup().getGroupType(), new GetOrCreateEnclosingGroupInGroup(getEnclosingFunction, group, property.asGroup(), currentPath)); @@ -245,7 +240,7 @@ private void processProperty( CollectionProperty collectionProperty = property.asCollection(); currentPath.addLast(currentPath.removeLast() + "[*]"); processProperty(currentPath, matchActions, defaultValues, namingStrategy, group, getEnclosingFunction, type, - memberName, collectionProperty.getElement()); + collectionProperty.getElement()); } } @@ -257,7 +252,6 @@ private void processOptionalProperty( final ConfigMappingInterface group, final BiFunction getEnclosingFunction, final Class type, - final String memberName, final Property property) { if (property.isGroup()) { @@ -266,8 +260,7 @@ private void processOptionalProperty( GetOrCreateEnclosingGroupInGroup matchAction = new GetOrCreateEnclosingGroupInGroup( getEnclosingFunction, group, nestedGroup, currentPath); processLazyGroupInGroup(currentPath, matchActions, defaultValues, namingStrategy, nestedGroup.getGroupType(), - matchAction, - new HashSet<>()); + matchAction); } else if (property.isLeaf()) { LeafProperty leafProperty = property.asLeaf(); if (leafProperty.hasDefaultValue()) { @@ -286,7 +279,7 @@ private void processOptionalProperty( CollectionProperty collectionProperty = property.asCollection(); currentPath.addLast(currentPath.removeLast() + "[*]"); processProperty(currentPath, matchActions, defaultValues, namingStrategy, group, getEnclosingFunction, type, - memberName, collectionProperty.getElement()); + collectionProperty.getElement()); } } @@ -296,8 +289,7 @@ private void processLazyGroupInGroup( final Map defaultValues, final NamingStrategy namingStrategy, final ConfigMappingInterface group, - final BiConsumer matchAction, - final HashSet usedProperties) { + final BiConsumer matchAction) { int pc = group.getPropertyCount(); int pathLen = currentPath.size(); for (int i = 0; i < pc; i++) { @@ -310,11 +302,9 @@ private void processLazyGroupInGroup( ni.next(); } } - if (usedProperties.add(String.join(".", String.join(".", currentPath), property.getMethod().getName()))) { - boolean optional = property.isOptional(); - processLazyPropertyInGroup(currentPath, matchActions, defaultValues, matchAction, usedProperties, - namingStrategy, group, optional, property); - } + boolean optional = property.isOptional(); + processLazyPropertyInGroup(currentPath, matchActions, defaultValues, matchAction, namingStrategy, group, optional, + property); while (currentPath.size() > pathLen) { currentPath.removeLast(); } @@ -322,7 +312,7 @@ private void processLazyGroupInGroup( int sc = group.getSuperTypeCount(); for (int i = 0; i < sc; i++) { processLazyGroupInGroup(currentPath, matchActions, defaultValues, namingStrategy, group.getSuperType(i), - matchAction, usedProperties); + matchAction); } } @@ -331,7 +321,6 @@ private void processLazyPropertyInGroup( final KeyMap> matchActions, final Map defaultValues, final BiConsumer matchAction, - final HashSet usedProperties, final NamingStrategy namingStrategy, final ConfigMappingInterface group, final boolean optional, @@ -344,7 +333,7 @@ private void processLazyPropertyInGroup( : new ConsumeOneAndThenFn<>(new GetNestedEnclosing(matchAction)), group, nestedGroup, currentPath); processLazyGroupInGroup(currentPath, matchActions, defaultValues, namingStrategy, nestedGroup.getGroupType(), - nestedEnclosingFunction, new HashSet<>()); + nestedEnclosingFunction); } else if (property.isGroup()) { GroupProperty asGroup = property.asGroup(); GetOrCreateEnclosingGroupInGroup nestedEnclosingFunction = new GetOrCreateEnclosingGroupInGroup( @@ -352,7 +341,7 @@ private void processLazyPropertyInGroup( : new ConsumeOneAndThenFn<>(new GetNestedEnclosing(matchAction)), group, asGroup, currentPath); processLazyGroupInGroup(currentPath, matchActions, defaultValues, namingStrategy, asGroup.getGroupType(), - nestedEnclosingFunction, usedProperties); + nestedEnclosingFunction); } else if (property.isLeaf() || property.isPrimitive() || optional && property.asOptional().getNestedProperty().isLeaf()) { BiConsumer actualAction = property.isParentPropertyName() ? matchAction @@ -398,8 +387,8 @@ private void processLazyPropertyInGroup( CollectionProperty collectionProperty = optional ? property.asOptional().getNestedProperty().asCollection() : property.asCollection(); currentPath.addLast(currentPath.removeLast() + "[*]"); - processLazyPropertyInGroup(currentPath, matchActions, defaultValues, matchAction, usedProperties, namingStrategy, - group, false, collectionProperty.getElement()); + processLazyPropertyInGroup(currentPath, matchActions, defaultValues, matchAction, namingStrategy, group, false, + collectionProperty.getElement()); } } @@ -539,7 +528,7 @@ private void processLazyMapValue( GetOrCreateEnclosingGroupInMap ef = new GetOrCreateEnclosingGroupInMap(getEnclosingMap, mapProperty, keyUnnamed, enclosingGroup, property.asGroup(), currentPath); processLazyGroupInGroup(currentPath, matchActions, defaultValues, namingStrategy, property.asGroup().getGroupType(), - ef, new HashSet<>()); + ef); } else if (property.isCollection()) { CollectionProperty collectionProperty = property.asCollection(); Property element = collectionProperty.getElement(); @@ -561,8 +550,8 @@ private void addAction( KeyMap> current = matchActions.findOrAdd(currentPath); Property previous = properties.put(String.join(".", currentPath), property); if (current.hasRootValue() && current.getRootValue() != action && previous != null && !previous.equals(property)) { - throw ConfigMessages.msg.ambiguousMapping(String.join(".", currentPath), property.getMethod().toString(), - previous.getMethod().toString()); + throw ConfigMessages.msg.ambiguousMapping(String.join(".", currentPath), property.getMemberName(), + previous.getMemberName()); } current.putRootValue(action); } @@ -678,7 +667,7 @@ static class GetOrCreateEnclosingGroupInGroup public ConfigMappingObject apply(final ConfigMappingContext context, final NameIterator ni) { ConfigMappingObject ourEnclosing = delegate.apply(context, ni); Class enclosingType = enclosingGroup.getInterfaceType(); - String key = indexName(enclosedGroup.getMethod().getName(), groupPath, ni); + String key = indexName(enclosedGroup.getMemberName(), groupPath, ni); ConfigMappingObject val = (ConfigMappingObject) context.getEnclosedField(enclosingType, key, ourEnclosing); context.applyNamingStrategy( namingStrategy(enclosedGroup.getGroupType().getNamingStrategy(), enclosingGroup.getNamingStrategy())); @@ -789,8 +778,7 @@ private MapKey mapKey(final ConfigMappingContext context, final NameIterator ni, mapPath.next(); String pathKey = mapPath.getAllPreviousSegments(); mapPath.previous(); - Converter converterKey = context.getKeyConverter(enclosingGroup.getInterfaceType(), - enclosingMap.getMethod().getName(), enclosingMap.getLevels() - 1); + Converter converterKey = context.getKeyConverter(enclosingGroup.getInterfaceType(), enclosingMap); // This will be the key to use to store the value in the map String nameKey = normalizeIfIndexed(rawKey); @@ -876,7 +864,7 @@ static class GetOrCreateEnclosingMapInGroup implements BiFunction enclosingType = enclosingGroup.getInterfaceType(); - String key = indexName(enclosedGroup.getMethod().getName(), groupPath, ni); + String key = indexName(enclosedGroup.getMemberName(), groupPath, ni); Map val = (Map) context.getEnclosedField(enclosingType, key, ourEnclosing); context.applyNamingStrategy(enclosingGroup.getNamingStrategy()); if (val == null) { @@ -893,26 +881,6 @@ public void accept(final ConfigMappingContext context, final NameIterator ni) { } } - static class GetFieldOfEnclosing implements BiFunction { - private final BiFunction getEnclosingFunction; - private final Class type; - private final String memberName; - - GetFieldOfEnclosing(final BiFunction getEnclosingFunction, - final Class type, final String memberName) { - this.getEnclosingFunction = getEnclosingFunction; - this.type = type; - this.memberName = memberName; - } - - @Override - public ConfigMappingObject apply(final ConfigMappingContext context, final NameIterator ni) { - ConfigMappingObject outer = getEnclosingFunction.apply(context, ni); - // eagerly populated groups will always exist - return (ConfigMappingObject) context.getEnclosedField(type, memberName, outer); - } - } - // To recursively create Optional nested groups static class GetNestedEnclosing implements BiFunction { private final BiConsumer matchAction;