Skip to content

Commit

Permalink
Fixed a bug in Unwrappable
Browse files Browse the repository at this point in the history
  • Loading branch information
Aklakan committed Sep 14, 2023
1 parent c6cb88e commit 11a8a48
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,32 +31,32 @@ public class CacheView<KF, KB, V>
implements Cache<KF, V>
{
/** The delegate cache*/
protected Cache<KB, V> delegate;
protected Cache<KB, V> backend;

protected Converter<KF, KB> keyMapper;
protected Converter<KF, KB> keyConverter;

/**
* A predicate that hides cache entries unrelated to this cache view.
* Note that every backend key derived from this view must succeed the filter.
* This means:
* backendFilter.test(keyMapper.convert(frontendKey)) must always evaluate to true.
*/
protected Predicate<KB> backendFilter;
protected Predicate<KB> backendKeyFilter;

public CacheView(Cache<KB, V> delegate, Converter<KF, KB> keyMapper, Predicate<KB> backendFilter) {
public CacheView(Cache<KB, V> backend, Converter<KF, KB> keyConverter, Predicate<KB> backendFilter) {
super();
this.delegate = delegate;
this.keyMapper = keyMapper;
this.backendFilter = backendFilter;
this.backend = backend;
this.keyConverter = keyConverter;
this.backendKeyFilter = backendFilter;
}

public Cache<KB, V> getDelegate() {
return delegate;
public Cache<KB, V> getBackend() {
return backend;
}

protected KB safeToBackend(KF key) {
KB result = keyMapper.convert(key);
if (!backendFilter.test(result)) {
KB result = keyConverter.convert(key);
if (!backendKeyFilter.test(result)) {
throw new IllegalStateException("Converted key was rejected by filter. Input: " + key + " Output: " + result);
}
return result;
Expand All @@ -77,7 +77,7 @@ protected List<KB> convert(Object key) {

@Override
public V getIfPresent(Object key) {
Cache<KB, V> backend = getDelegate();
Cache<KB, V> backend = getBackend();
V result = null;
for (KB backendKey : convert(key)) {
result = backend.getIfPresent(backendKey);
Expand All @@ -87,91 +87,99 @@ public V getIfPresent(Object key) {

@Override
public V get(KF key, Callable<? extends V> loader) throws ExecutionException {
Cache<KB, V> backend = getDelegate();
KB backendKey = keyMapper.convert(key);
Cache<KB, V> backend = getBackend();
KB backendKey = keyConverter.convert(key);
V result = backend.get(backendKey, loader);
return result;
}

@Override
public ImmutableMap<KF, V> getAllPresent(Iterable<? extends Object> keys) {
Cache<KB, V> backend = getDelegate();
Cache<KB, V> backend = getBackend();

@SuppressWarnings("unchecked")
List<KB> backendKeys = Streams.stream(keys)
.map(k -> (KF)k)
.map(keyMapper::convert)
.map(keyConverter::convert)
.collect(Collectors.toList());

Builder<KF, V> mapBuilder = ImmutableMap.builder();

ImmutableMap<KB, V> tmp = backend.getAllPresent(backendKeys);
tmp.forEach((backendKey, value) -> {
KF frontendKey = keyMapper.reverse().convert(backendKey);
KF frontendKey = keyConverter.reverse().convert(backendKey);
mapBuilder.put(frontendKey, value);
});
ImmutableMap<KF, V> result = mapBuilder.build();
return result;
}
@Override
public void put(KF key, V value) {
Cache<KB, V> backend = getDelegate();
KB backendKey = keyMapper.convert(key);
Cache<KB, V> backend = getBackend();
KB backendKey = keyConverter.convert(key);
backend.put(backendKey, value);
}

@Override
public void putAll(Map<? extends KF, ? extends V> m) {
Cache<KB, V> backend = getDelegate();
Cache<KB, V> backend = getBackend();
Map<KB, V> map = m.entrySet().stream().collect(Collectors.toMap(e -> safeToBackend(e.getKey()), Entry::getValue));
backend.putAll(map);
}

@Override
public void invalidate(Object key) {
Cache<KB, V> backend = getDelegate();
Cache<KB, V> backend = getBackend();
for(KB backendKey : convert(key)) {
backend.invalidate(backendKey);
}
}

@Override
public void invalidateAll(Iterable<? extends Object> keys) {
Cache<KB, V> backend = getDelegate();
Cache<KB, V> backend = getBackend();
List<KB> backendKeys = Streams.stream(keys).flatMap(key -> convert(key).stream()).collect(Collectors.toList());
backend.invalidateAll(backendKeys);
}

@Override
public void invalidateAll() {
// Only invalidate the keys that match the filter
Cache<KB, V> backend = getDelegate();
Collection<KB> backendKeys = backend.asMap().keySet().stream().filter(backendFilter).collect(Collectors.toList());
Cache<KB, V> backend = getBackend();
Collection<KB> backendKeys = backend.asMap().keySet().stream().filter(backendKeyFilter).collect(Collectors.toList());
backend.invalidateAll(backendKeys);
}

@Override
public long size() {
Cache<KB, V> backend = getDelegate();
long result = backend.asMap().keySet().stream().filter(backendFilter).count();
Cache<KB, V> backend = getBackend();
long result = backend.asMap().keySet().stream().filter(backendKeyFilter).count();
return result;
}

@Override
public CacheStats stats() {
Cache<KB, V> backend = getDelegate();
Cache<KB, V> backend = getBackend();
CacheStats result = backend.stats();
return result;
}

@Override
public ConcurrentMap<KF, V> asMap() {

// TODO We could adapt our MapFromKeyConverter class but this one is in the collections module

// ConcurrentMap<KB, V> backendMap = delegate.asMap();
// Map<KB, V> filteredBackendMap = Maps.filterKeys(backendMap, backendFilter::test);
// Map<KF, V> frontendMap = MapFromKeyConverter();
// ConcurrentMap<KF, V> result = ConcurrentMapWrapper.wrap(frontendMap);

throw new UnsupportedOperationException();
}

@Override
public void cleanUp() {
Cache<KB, V> backend = getDelegate();
Cache<KB, V> backend = getBackend();
backend.cleanUp();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,41 @@
*/
public interface Unwrappable {

@SuppressWarnings("unchecked")
default public <X> Optional<X> unwrap(Class<X> clazz, boolean reflexive) {
Optional<X> result;
if(reflexive && clazz.isAssignableFrom(this.getClass())) {
result = Optional.of((X)this);
} else {
if(this instanceof Delegated) {
Object delegate = ((Delegated<?>)this).delegate();
result = delegate instanceof Unwrappable
? ((Unwrappable)delegate).unwrap(clazz, true)
: Optional.empty();
} else {
result = Optional.empty();
}
}
@SuppressWarnings("unchecked")
default public <X> Optional<X> unwrap(Class<X> clazz, boolean reflexive) {
Optional<X> result;
if(reflexive && clazz.isAssignableFrom(this.getClass())) {
result = Optional.of((X)this);
} else {
if(this instanceof Delegated) {
Object delegate = ((Delegated<?>)this).delegate();
result = unwrap(delegate, clazz, true);
// result = delegate instanceof Unwrappable
// ? ((Unwrappable)delegate).unwrap(clazz, true)
// : Optional.empty();
} else {
result = Optional.empty();
}
}

return result;
}
return result;
}

public static <X> Optional<X> unwrap(Object o, Class<X> clazz, boolean reflexive) {
Optional<X> result;
Class<?> oClass = o.getClass();
if(reflexive && clazz.isAssignableFrom(oClass)) {
result = Optional.of((X)o);
} else {
if (o instanceof Unwrappable) {
result = ((Unwrappable)o).unwrap(clazz, true);
} else if(o instanceof Delegated) {
Object delegate = ((Delegated<?>)o).delegate();
result = unwrap(delegate, clazz, true);
} else {
result = Optional.empty();
}
}
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import java.util.function.Consumer;

public class OutputStreamUtils {
public static String toStringUtf8(Consumer<OutputStream> action, Charset charset) {
public static String toStringUtf8(Consumer<OutputStream> action) {
return toString(action, StandardCharsets.UTF_8);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public boolean equals(Object obj) {

@Override
public String toString() {
return "EnrichedItem [item=" + item + ", classToInstanceMap=" + classToInstanceMap + "]";
return "Enriched [item=" + item + ", classToInstanceMap=" + classToInstanceMap + "]";
}


Expand Down

0 comments on commit 11a8a48

Please sign in to comment.