Skip to content

Commit

Permalink
Use separate MapResolver for map resolving
Browse files Browse the repository at this point in the history
  • Loading branch information
AntonOellerer committed Apr 13, 2022
1 parent 0d27dcb commit 090b918
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 45 deletions.
3 changes: 1 addition & 2 deletions src/main/java/com/docutools/jocument/MapPlaceholderData.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
import java.util.Map;
import java.util.stream.Stream;

public record MapPlaceholderData(Map<String, PlaceholderData> map)
implements PlaceholderData {
public record MapPlaceholderData(Map<String, PlaceholderData> map) implements PlaceholderData {

@Override
public PlaceholderType getType() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import com.docutools.jocument.CustomPlaceholderRegistry;
import com.docutools.jocument.GenerationOptions;
import com.docutools.jocument.GenerationOptionsBuilder;
import com.docutools.jocument.MapPlaceholderData;
import com.docutools.jocument.PlaceholderData;
import com.docutools.jocument.PlaceholderResolver;
import java.lang.reflect.InvocationTargetException;
Expand All @@ -17,7 +16,6 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
import org.apache.commons.lang3.ClassUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

Expand Down Expand Up @@ -77,19 +75,9 @@ public Optional<PlaceholderData> doReflectiveResolve(String placeholderName, Loc
logger.debug("Placeholder {} resolved to simple placeholder", placeholderName);
return simplePlaceholder;
} else {
if (property instanceof Map<?, ?> valueMap) {
if (property instanceof Map valueMap) {
logger.debug("Placeholder {} resolved to map", placeholderName);
Map<String, PlaceholderData> dataMap = valueMap.entrySet()
.stream()
.map(entry -> {
var mapValue = entry.getValue();
var scalarType = ClassUtils.isPrimitiveOrWrapper(entry.getValue().getClass()) || mapValue instanceof String;
PlaceholderData placeholderData = scalarType ? new ScalarPlaceholderData<>(entry.getValue()) :
new IterablePlaceholderData(new ReflectionResolver(entry.getValue(), customPlaceholderRegistry, options, this));
return Map.entry(entry.getKey().toString().toLowerCase(), placeholderData);
})
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
return Optional.of(new MapPlaceholderData(dataMap));
return Optional.of(new IterablePlaceholderData(new MapResolver(valueMap, customPlaceholderRegistry, this, options), valueMap.size()));
} else if (property instanceof Collection<?> collection) {
logger.debug("Placeholder {} resolved to collection", placeholderName);
List<PlaceholderResolver> list = collection.stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@

public class IterablePlaceholderData implements PlaceholderData {

public static IterablePlaceholderData of(PlaceholderResolver...resolvers) {
public IterablePlaceholderData(PlaceholderResolver resolver, int size) {
this.iterable = List.of(resolver);
this.count = size;
}

public static IterablePlaceholderData of(PlaceholderResolver... resolvers) {
return new IterablePlaceholderData(Arrays.asList(resolvers), resolvers.length);
}

Expand Down
51 changes: 51 additions & 0 deletions src/main/java/com/docutools/jocument/impl/MapResolver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.docutools.jocument.impl;

import com.docutools.jocument.CustomPlaceholderRegistry;
import com.docutools.jocument.GenerationOptions;
import com.docutools.jocument.PlaceholderData;
import com.docutools.jocument.PlaceholderResolver;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import org.apache.commons.lang3.ClassUtils;

public class MapResolver extends PlaceholderResolver {

private final Map<String, Object> map;
private final CustomPlaceholderRegistry customPlaceholderRegistry; //TODO this should be refactored to a separate resolver or class-adjacent methods
private final PlaceholderResolver parent; //FIXME add this field to FutureReflectionResolver
private final GenerationOptions generationOptions;

/**
* Create a new {@link PlaceholderResolver} to resolve from {@link Map}s.
*
* @param map The {@link Map} to resolve from
* @param customPlaceholderRegistry The custom placeholder registry to check for custom placeholders
* @param parent The parent registry
* @param generationOptions the {@link GenerationOptions}
*/
public MapResolver(Map<String, Object> map, CustomPlaceholderRegistry customPlaceholderRegistry, PlaceholderResolver parent,
GenerationOptions generationOptions) {
this.map = map;
this.customPlaceholderRegistry = customPlaceholderRegistry;
this.parent = parent;
this.generationOptions = generationOptions;
}

@Override
protected Optional<PlaceholderData> doResolve(String placeholderName, Locale locale) {
if (map.containsKey(placeholderName)) {
var value = map.get(placeholderName);
if (value instanceof Map childMap) {
return Optional.of(new IterablePlaceholderData(new MapResolver(childMap, customPlaceholderRegistry, this, generationOptions)));
} else if (ClassUtils.isPrimitiveOrWrapper(value.getClass()) || value instanceof String) {
return Optional.of(new ScalarPlaceholderData<>(value));
} else {
var futureResolver =
new FutureReflectionResolver(value, customPlaceholderRegistry, options, 10L); //TODO find way to decouple timout time from resolver
return futureResolver.doResolve(placeholderName, locale);
}
}
return Optional.empty();
}
}
31 changes: 3 additions & 28 deletions src/main/java/com/docutools/jocument/impl/ReflectionResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@
import com.docutools.jocument.CustomPlaceholderRegistry;
import com.docutools.jocument.GenerationOptions;
import com.docutools.jocument.GenerationOptionsBuilder;
import com.docutools.jocument.MapPlaceholderData;
import com.docutools.jocument.PlaceholderData;
import com.docutools.jocument.PlaceholderMapper;
import com.docutools.jocument.PlaceholderResolver;
import com.docutools.jocument.PlaceholderType;
import com.docutools.jocument.annotations.Format;
import com.docutools.jocument.annotations.Image;
import com.docutools.jocument.annotations.MatchPlaceholder;
Expand Down Expand Up @@ -35,9 +33,7 @@
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import org.apache.commons.beanutils.PropertyUtilsBean;
import org.apache.commons.lang3.ClassUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

Expand Down Expand Up @@ -231,13 +227,6 @@ private Optional<PlaceholderData> matchPattern(String placeholderName, Locale lo
private Optional<PlaceholderData> resolveAccessor(String placeholderName, Locale locale) {
Optional<PlaceholderData> result = Optional.empty();
for (String property : placeholderName.split("\\.")) {
if (bean instanceof Map<?, ?> map) {
var object = map.get(property);
if (object instanceof PlaceholderData placeholderData) {
result = Optional.of(placeholderData);
continue;
}
}
result = result.isEmpty()
? doReflectiveResolve(property, locale).or(() -> tryResolveInParent(placeholderName, locale))
: result.map(placeholderData -> resolveChild(placeholderData, property, locale));
Expand All @@ -246,11 +235,7 @@ private Optional<PlaceholderData> resolveAccessor(String placeholderName, Locale
}

private PlaceholderData resolveChild(PlaceholderData placeholderData, String property, Locale locale) {
if (placeholderData.getType().equals(PlaceholderType.MAP)) {
return ((Map<String, PlaceholderData>) placeholderData.getRawValue()).get(property.toLowerCase());
} else {
return placeholderData.stream().findAny().flatMap(r -> r.resolve(property, locale)).orElse(null);
}
return placeholderData.stream().findAny().flatMap(r -> r.resolve(property, locale)).orElse(null);
}

private Optional<PlaceholderData> tryResolveInParent(String placeholderName, Locale locale) {
Expand Down Expand Up @@ -287,19 +272,9 @@ public Optional<PlaceholderData> doReflectiveResolve(String placeholderName, Loc
logger.debug("Placeholder {} resolved to simple placeholder", placeholderName);
return simplePlaceholder;
} else {
if (property instanceof Map<?, ?> valueMap) {
if (property instanceof Map valueMap) {
logger.debug("Placeholder {} resolved to map", placeholderName);
Map<String, PlaceholderData> dataMap = valueMap.entrySet()
.stream()
.map(entry -> {
var mapValue = entry.getValue();
var scalarType = ClassUtils.isPrimitiveOrWrapper(entry.getValue().getClass()) || mapValue instanceof String;
PlaceholderData placeholderData = scalarType ? new ScalarPlaceholderData<>(entry.getValue()) :
new IterablePlaceholderData(new ReflectionResolver(entry.getValue(), customPlaceholderRegistry, options, this));
return Map.entry(entry.getKey().toString().toLowerCase(), placeholderData);
})
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
return Optional.of(new MapPlaceholderData(dataMap));
return Optional.of(new IterablePlaceholderData(new MapResolver(valueMap, customPlaceholderRegistry, this, options), valueMap.size()));
} else if (property instanceof Collection<?> collection) {
logger.debug("Placeholder {} resolved to collection", placeholderName);
List<PlaceholderResolver> list = collection.stream()
Expand Down
19 changes: 19 additions & 0 deletions src/test/java/com/docutools/jocument/ReflectionResolvingTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -227,4 +227,23 @@ void shouldResolveNestedMapKey() {
// Assert
assertThat(cook.getRawValue(), equalTo(SampleModelData.ENTERPRISE.staff().get("cook")));
}

@Test
@DisplayName("Resolve map block")
void shouldResolveMapBlock() {
// Assemble
resolver = new ReflectionResolver(SampleModelData.ENTERPRISE);

// Act
var cook = resolver.resolve("staff")
.map(data -> data.stream()
.map(r -> r.resolve("cook")
.map(PlaceholderData::toString)
.orElseThrow())
.collect(Collectors.toList()))
.orElseThrow();
// Act
assertThat(cook, contains("Puro Okin"));
}

}

0 comments on commit 090b918

Please sign in to comment.