es.iti.wakamiti.api.imconfig.internal.ApacheConfiguration2 Maven / Gradle / Ivy
The newest version!
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package es.iti.wakamiti.api.imconfig.internal;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.type.TypeFactory;
import es.iti.wakamiti.api.imconfig.Configuration;
import es.iti.wakamiti.api.imconfig.ConfigurationFactory;
import es.iti.wakamiti.api.imconfig.PropertyDefinition;
import org.apache.commons.configuration2.BaseConfiguration;
import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class ApacheConfiguration2 extends AbstractConfiguration {
protected final org.apache.commons.configuration2.Configuration conf;
private final Map, BiFunction> CONVERTER = Map.of(
List.class, (key, ct) -> getList(key, rawTypes(ct, 1)[0]),
Set.class, (key, ct) -> getSet(key, rawTypes(ct, 1)[0]),
Stream.class, (key, ct) -> getStream(key, rawTypes(ct, 1)[0]),
Map.class, (key, ct) -> {
Class>[] types = rawTypes(ct, 2);
return inner(key).asMap().entrySet().stream()
.collect(Collectors.toMap(
e -> convert(e.getKey(), types[0]),
e -> convert(e.getValue(), types[1]))
);
}
);
protected ApacheConfiguration2(
ConfigurationFactory builder,
Map definitions,
org.apache.commons.configuration2.Configuration conf
) {
super(builder, definitions);
this.conf = conf;
}
protected ApacheConfiguration2(
ConfigurationFactory builder,
org.apache.commons.configuration2.Configuration conf
) {
super(builder, Map.of());
this.conf = conf;
}
@Override
public Configuration withPrefix(String keyPrefix) {
BaseConfiguration innerConf = prepare(new BaseConfiguration());
conf.getKeys().forEachRemaining(key -> innerConf.addProperty(keyPrefix + "." + key, conf.getProperty(key)));
return new ApacheConfiguration2(builder, definitions, innerConf);
}
@Override
public Configuration filtered(String keyPrefix) {
BaseConfiguration innerConf = prepare(new BaseConfiguration());
conf.getKeys(keyPrefix).forEachRemaining(key -> {
if (key.startsWith(keyPrefix)) {
innerConf.addProperty(key, conf.getProperty(key));
}
});
return new ApacheConfiguration2(builder, definitions, innerConf);
}
@Override
public Configuration inner(String keyPrefix) {
if (keyPrefix == null || keyPrefix.isEmpty()) {
return this;
}
return new ApacheConfiguration2(builder, definitions, conf.subset(keyPrefix));
}
@Override
public boolean isEmpty() {
return conf.isEmpty();
}
@Override
public boolean hasProperty(String key) {
return conf.containsKey(key);
}
@Override
public Iterable keys() {
return keyList();
}
@Override
public Iterator keyIterator() {
return conf.getKeys();
}
@Override
public Stream keyStream() {
return keyList().stream();
}
private List keyList() {
List keys = new ArrayList<>();
conf.getKeys().forEachRemaining(keys::add);
return keys;
}
@Override
public Optional get(String key, Class type) {
var definition = definitions.get(key);
String raw = conf.getString(key);
boolean empty = (raw == null || raw.isEmpty());
if (definition != null) {
var value = empty ? definition.defaultValue().orElse(null) : raw;
if (value != null) {
return Optional.of(convert(value, type));
} else {
return Optional.empty();
}
} else {
return Optional.ofNullable(empty ? null : conf.get(type, key));
}
}
@Override
@SuppressWarnings("unchecked")
public Optional get(String key, TypeReference type) {
JavaType jt = TypeFactory.defaultInstance().constructType(type.getType());
JavaType[] containedTypes = IntStream.range(0, jt.containedTypeCount())
.mapToObj(jt::containedType)
.toArray(JavaType[]::new);
return (Optional) Optional.ofNullable(CONVERTER.getOrDefault(jt.getRawClass(),
(k, ct) -> get(k, jt.getRawClass()).orElse(null)))
.map(f -> f.apply(key, containedTypes));
}
private Class>[] rawTypes(JavaType[] jt, int length) {
Class>[] types = new Class[length];
for (int i = 0; i < length; i++) {
try {
types[i] = jt[i].getRawClass();
} catch (ArrayIndexOutOfBoundsException e) {
types[i] = String.class;
}
}
return types;
}
@Override
public List getList(String key, Class type) {
return Optional.ofNullable(conf.getList(type, key)).orElse(Collections.emptyList());
}
@Override
public Set getSet(String key, Class type) {
return new HashSet<>(getList(key, type));
}
@Override
public Stream getStream(String key, Class type) {
return getList(key, type).stream();
}
@Override
public Properties asProperties() {
Properties properties = new Properties();
conf.getKeys().forEachRemaining(key -> properties.put(key, conf.getString(key)));
return properties;
}
@Override
public Map asMap() {
Map map = new LinkedHashMap<>();
conf.getKeys().forEachRemaining(key -> map.put(key, conf.getString(key)));
return map;
}
@Override
public String toString() {
StringBuilder string = new StringBuilder("configuration:\n---------------\n");
conf.getKeys().forEachRemaining(key -> {
final String[] values = conf.getStringArray(key);
String value = "";
if (values.length == 1) {
value = values[0];
} else if (values.length > 1) {
value = Arrays.toString(values);
}
string
.append(key)
.append(" : ")
.append(value)
.append("\n");
});
return string.append("---------------").toString();
}
@Override
public void forEach(BiConsumer consumer) {
conf.getKeys().forEachRemaining(key -> consumer.accept(key, conf.get(String.class, key)));
}
private T convert(String raw, Class type) {
var abstractConf = (org.apache.commons.configuration2.AbstractConfiguration) conf;
return abstractConf.getConversionHandler().to(raw, type, abstractConf.getInterpolator());
}
private T prepare(T abstractConfiguration) {
if (builder.hasMultiValueSeparator()) {
abstractConfiguration.setListDelimiterHandler(new DefaultListDelimiterHandler(builder.multiValueSeparator()));
}
return abstractConfiguration;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy