Add ValueCache.compute method (#4704)
Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>pull/4849/head
parent
f695acfc4c
commit
98e3b13c71
|
@ -25,6 +25,7 @@ import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
@ -176,6 +177,12 @@ public class CacheScriptExtension implements ScriptExtensionProvider {
|
||||||
return Objects.requireNonNull(cache.computeIfAbsent(key, k -> supplier.get()));
|
return Objects.requireNonNull(cache.computeIfAbsent(key, k -> supplier.get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public Object compute(String key, BiFunction<String, @Nullable Object, @Nullable Object> remappingFunction) {
|
||||||
|
return cache.compute(key, (k, v) -> remappingFunction.apply(k, v));
|
||||||
|
}
|
||||||
|
|
||||||
private Collection<Object> values() {
|
private Collection<Object> values() {
|
||||||
return cache.values();
|
return cache.values();
|
||||||
}
|
}
|
||||||
|
@ -244,6 +251,24 @@ public class CacheScriptExtension implements ScriptExtensionProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public Object compute(String key, BiFunction<String, @Nullable Object, @Nullable Object> remappingFunction) {
|
||||||
|
cacheLock.lock();
|
||||||
|
try {
|
||||||
|
Object value = sharedCache.compute(key, (k, v) -> remappingFunction.apply(k, v));
|
||||||
|
if (value == null) {
|
||||||
|
sharedCacheKeyAccessors.remove(key);
|
||||||
|
} else {
|
||||||
|
rememberAccessToKey(key);
|
||||||
|
}
|
||||||
|
logger.trace("COMPUTE to cache from '{}': '{}' -> '{}'", scriptIdentifier, key, value);
|
||||||
|
return value;
|
||||||
|
} finally {
|
||||||
|
cacheLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void rememberAccessToKey(String key) {
|
private void rememberAccessToKey(String key) {
|
||||||
Objects.requireNonNull(sharedCacheKeyAccessors.computeIfAbsent(key, k -> new HashSet<>()))
|
Objects.requireNonNull(sharedCacheKeyAccessors.computeIfAbsent(key, k -> new HashSet<>()))
|
||||||
.add(scriptIdentifier);
|
.add(scriptIdentifier);
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.core.automation.module.script.rulesupport.shared;
|
package org.openhab.core.automation.module.script.rulesupport.shared;
|
||||||
|
|
||||||
|
import java.util.function.BiFunction;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
@ -62,4 +63,17 @@ public interface ValueCache {
|
||||||
* @return the value associated with the key
|
* @return the value associated with the key
|
||||||
*/
|
*/
|
||||||
Object get(String key, Supplier<Object> supplier);
|
Object get(String key, Supplier<Object> supplier);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to compute a mapping for the specified key and its current mapped value
|
||||||
|
* (or null if there is no current mapping).
|
||||||
|
*
|
||||||
|
* See {@code java.util.Map.compute()} for details.
|
||||||
|
*
|
||||||
|
* @param key the key of the requested value.
|
||||||
|
* @param remappingFunction the remapping function to compute a value.
|
||||||
|
* @return the new value associated with the specified key, or null if none
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
Object compute(String key, BiFunction<String, @Nullable Object, @Nullable Object> remappingFunction);
|
||||||
}
|
}
|
||||||
|
|
|
@ -206,6 +206,28 @@ public class CacheScriptExtensionTest {
|
||||||
cache.put(KEY2, VALUE2);
|
cache.put(KEY2, VALUE2);
|
||||||
assertThat(cache.get(KEY1), is(VALUE1));
|
assertThat(cache.get(KEY1), is(VALUE1));
|
||||||
assertThat(cache.get(KEY2), is(VALUE2));
|
assertThat(cache.get(KEY2), is(VALUE2));
|
||||||
|
|
||||||
|
// computed value is returned
|
||||||
|
assertThat(cache.compute(KEY1, (k, v) -> VALUE1), is(VALUE1));
|
||||||
|
assertThat(cache.get(KEY1), is(VALUE1));
|
||||||
|
assertThat(cache.compute(KEY1, (k, v) -> VALUE2), is(VALUE2));
|
||||||
|
assertThat(cache.get(KEY1), is(VALUE2));
|
||||||
|
assertThat(cache.compute(KEY1, (k, v) -> null), nullValue());
|
||||||
|
assertThat(cache.get(KEY1), nullValue());
|
||||||
|
|
||||||
|
// remappingFunction is called with key and old value
|
||||||
|
cache.remove(KEY1);
|
||||||
|
cache.compute(KEY1, (k, v) -> {
|
||||||
|
assertThat(k, is(KEY1));
|
||||||
|
assertThat(v, nullValue());
|
||||||
|
return VALUE2;
|
||||||
|
});
|
||||||
|
cache.put(KEY1, VALUE1);
|
||||||
|
cache.compute(KEY1, (k, v) -> {
|
||||||
|
assertThat(k, is(KEY1));
|
||||||
|
assertThat(v, is(VALUE1));
|
||||||
|
return VALUE2;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private ValueCache getCache(CacheScriptExtension se, String scriptIdentifier, String type) {
|
private ValueCache getCache(CacheScriptExtension se, String scriptIdentifier, String type) {
|
||||||
|
|
Loading…
Reference in New Issue