
io.smallrye.config.KeyMap Maven / Gradle / Ivy
package io.smallrye.config;
import java.io.Serializable;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
import io.smallrye.common.function.Functions;
/**
* A multi-level key map.
*/
public final class KeyMap extends HashMap> {
private static final Object NO_VALUE = new Serializable() {
private static final long serialVersionUID = -6072559389176920349L;
};
private static final long serialVersionUID = 3584966224369608557L;
private KeyMap any;
@SuppressWarnings("unchecked")
private V rootValue = (V) NO_VALUE;
public KeyMap(final int initialCapacity, final float loadFactor) {
super(initialCapacity, loadFactor);
}
public KeyMap(final int initialCapacity) {
super(initialCapacity);
}
public KeyMap() {
}
public KeyMap get(final String key, int offs, int len) {
return get(key.substring(offs, offs + len));
}
public KeyMap getAny() {
return any;
}
public KeyMap getOrCreateAny() {
KeyMap any = this.any;
if (any == null) {
any = this.any = new KeyMap<>();
}
return any;
}
public KeyMap putAny(KeyMap any) {
KeyMap oldAny = this.any;
this.any = any;
return oldAny;
}
public KeyMap putAnyIfAbsent(KeyMap any) {
KeyMap oldAny = this.any;
if (oldAny == null) {
this.any = any;
return null;
} else {
return oldAny;
}
}
public boolean hasRootValue() {
return rootValue != NO_VALUE;
}
public V getRootValue() {
return getRootValueOrDefault(null);
}
public V getRootValueOrDefault(final V defaultVal) {
V rootValue = this.rootValue;
return rootValue == NO_VALUE ? defaultVal : rootValue;
}
public V getOrComputeRootValue(final Supplier supplier) {
V rootValue = this.rootValue;
if (rootValue == NO_VALUE) {
this.rootValue = rootValue = supplier.get();
}
return rootValue;
}
@SuppressWarnings("unchecked")
public V removeRootValue() {
V rootValue = this.rootValue;
if (rootValue != NO_VALUE) {
this.rootValue = (V) NO_VALUE;
}
return rootValue;
}
public V putRootValue(final V rootValue) {
V old = this.rootValue;
this.rootValue = rootValue;
return old == NO_VALUE ? null : old;
}
public KeyMap find(final String path) {
return find(new NameIterator(path));
}
public KeyMap find(final NameIterator ni) {
if (!ni.hasNext()) {
return this;
}
String seg = ni.getNextSegment();
ni.next();
KeyMap next = getOrDefault(seg, any);
return next == null ? null : next.find(ni);
}
public KeyMap find(final Iterator iter) {
if (!iter.hasNext()) {
return this;
}
String seg = iter.next();
KeyMap next = seg.equals("*") ? any : getOrDefault(seg, any);
return next == null ? null : next.find(iter);
}
public KeyMap find(final Iterable i) {
return find(i.iterator());
}
public KeyMap findOrAdd(final String path) {
return findOrAdd(new NameIterator(path));
}
public KeyMap findOrAdd(final NameIterator ni) {
if (!ni.hasNext()) {
return this;
}
String seg = ni.getNextSegment();
ni.next();
try {
KeyMap next = seg.equals("*") ? getOrCreateAny() : computeIfAbsent(seg, k -> new KeyMap<>());
return next.findOrAdd(ni);
} finally {
ni.previous();
}
}
public KeyMap findOrAdd(final Iterator iter) {
if (!iter.hasNext()) {
return this;
}
String seg = iter.next();
KeyMap next = seg.equals("*") ? getOrCreateAny() : computeIfAbsent(seg, k -> new KeyMap<>());
return next.findOrAdd(iter);
}
public KeyMap findOrAdd(final Iterable i) {
return findOrAdd(i.iterator());
}
public KeyMap findOrAdd(final String... keys) {
return findOrAdd(keys, 0, keys.length);
}
public KeyMap findOrAdd(final String[] keys, int off, int len) {
String seg = keys[off];
KeyMap next = seg.equals("*") ? getOrCreateAny() : computeIfAbsent(seg, k -> new KeyMap<>());
return off + 1 > len - 1 ? next : next.findOrAdd(keys, off + 1, len);
}
public V findRootValue(final String path) {
return findRootValue(new NameIterator(path));
}
public V findRootValue(final NameIterator ni) {
KeyMap result = find(ni);
return result == null ? null : result.getRootValue();
}
public boolean hasRootValue(final String path) {
return hasRootValue(new NameIterator(path));
}
public boolean hasRootValue(final NameIterator ni) {
KeyMap result = find(ni);
return result != null && result.hasRootValue();
}
public KeyMap map(P param, BiFunction conversion) {
return map(param, conversion, new IdentityHashMap<>());
}
public KeyMap map(Function conversion) {
return map(conversion, Functions.functionBiFunction());
}
KeyMap map(P param, BiFunction conversion, IdentityHashMap, KeyMap> cached) {
if (cached.containsKey(this)) {
return cached.get(this);
}
KeyMap newMap = new KeyMap<>(size());
cached.put(this, newMap);
Set>> entries = entrySet();
for (Entry> entry : entries) {
newMap.put(entry.getKey(), entry.getValue().map(param, conversion, cached));
}
KeyMap any = getAny();
if (any != null) {
newMap.putAny(any.map(param, conversion, cached));
}
if (hasRootValue()) {
newMap.putRootValue(conversion.apply(param, getRootValue()));
}
return newMap;
}
@SuppressWarnings("ResultOfMethodCallIgnored")
public StringBuilder toString(StringBuilder b) {
b.append("KeyMap(");
V rootValue = this.rootValue;
if (rootValue == NO_VALUE) {
b.append("no value");
} else {
b.append("value=").append(rootValue);
}
b.append(") {");
final Iterator>> iterator = entrySet().iterator();
KeyMap any = this.any;
if (iterator.hasNext()) {
Entry> entry = iterator.next();
b.append(entry.getKey()).append("=>");
entry.getValue().toString(b);
while (iterator.hasNext()) {
entry = iterator.next();
b.append(',').append(entry.getKey()).append("=>");
entry.getValue().toString(b);
}
if (any != null) {
b.append(',').append("(any)=>");
any.toString(b);
}
} else {
if (any != null) {
b.append("(any)=>");
any.toString(b);
}
}
b.append('}');
return b;
}
public String toString() {
return toString(new StringBuilder()).toString();
}
}