com.github.avarabyeu.jashing.utils.InstanceOfMap Maven / Gradle / Ivy
package com.github.avarabyeu.jashing.utils;
import com.google.common.base.Preconditions;
import com.google.common.collect.ForwardingMap;
import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* Contains object as values and it's classes as keys
* Extends default {@code {java.util.Map, T>}} map with {@link #getInstanceOf(Class)} method
* which first calls {@link #get(Object)} (and returns value if found) and after goes through entries and
* tries to find values using {@link java.lang.Class#isAssignableFrom(Class)} construction
*
* @author Andrei Varabyeu
*/
public final class InstanceOfMap extends ForwardingMap, T> {
private Map, T> delegate;
private InstanceOfMap(Map, T> delegate) {
this.delegate = delegate;
}
@Override
protected Map, T> delegate() {
return delegate;
}
@Override
public T put(@Nullable Class extends T> clazz, @Nullable T value) {
return delegate.put(clazz, value);
}
public T getInstanceOf(Class extends T> clazz) {
if (delegate.containsKey(clazz)) {
return delegate.get(clazz);
} else {
return delegate.entrySet().stream()
.filter(entry -> clazz.isAssignableFrom(entry.getKey()))
.map(Map.Entry::getValue)
.findFirst().orElse(null);
}
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
if (!super.equals(o))
return false;
InstanceOfMap> that = (InstanceOfMap>) o;
return Objects.equals(delegate, that.delegate);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), delegate);
}
@Override
public Collection values() {
return delegate.values();
}
public static Builder builder() {
return new Builder<>();
}
public static InstanceOfMap empty() {
return new InstanceOfMap<>(Collections.emptyMap());
}
public static class Builder {
@SuppressWarnings("unchecked")
public InstanceOfMap fromList(List extends T> list) {
Preconditions.checkNotNull(list, "Provided list is null!");
Map, T> map = new HashMap<>(list.size());
for (T item : list) {
map.put((Class extends T>) item.getClass(), item);
}
return new InstanceOfMap<>(map);
}
public InstanceOfMap fromArray(T... array) {
Preconditions.checkNotNull(array, "Provided array is null!");
return fromList(Arrays.asList(array));
}
public InstanceOfMap fromMap(Map, T> map) {
return new InstanceOfMap<>(map);
}
}
}