/** * Common core for the {@link #compute(String, BiFunction, NullaryFunction)} and {@link * #computeIfPresent(String, BiFunction, NullaryFunction)} methods. * * @param key the key of the entry to process * @param currentValue the existing value, if any, for {@code key} * @param mappingFunction the function that will produce the value. The function will be * supplied with the key and existing value (or null if no entry exists) as parameters. The * function should return the desired new value for the entry or null to remove the entry. * If the method throws an unchecked exception the Store will not be modified (the caller * will receive the exception) * @param replaceEqual If the existing value in the store is {@link * java.lang.Object#equals(Object)} to the value returned from the mappingFunction this * function will be invoked. If this function returns {@link java.lang.Boolean#FALSE} then * the existing entry in the store will not be replaced with a new entry and the existing * entry will have its access time updated * @return the new value associated with the key or null if none */ private FakeValueHolder computeInternal( final String key, final FakeValueHolder currentValue, final BiFunction<? super String, ? super String, ? extends String> mappingFunction, final NullaryFunction<Boolean> replaceEqual) { final String remappedValue = mappingFunction.apply(key, (currentValue == null ? null : currentValue.value())); FakeValueHolder newValue = (remappedValue == null ? null : new FakeValueHolder(remappedValue)); if (newValue == null) { /* Remove entry from store */ this.entries.remove(key); } else if (!newValue.equals(currentValue)) { /* New, remapped value is different */ this.entries.put(key, newValue); } else { /* New, remapped value is the same */ if (replaceEqual.apply()) { /* Replace existing equal value */ this.entries.put(key, newValue); } else { /* Update access time of current entry */ currentValue.lastAccessTime = System.currentTimeMillis(); newValue = currentValue; } } return newValue; }
@Override public ValueHolder<String> get(final String key) throws CacheAccessException { this.checkFailingKey(key); final FakeValueHolder valueHolder = this.entries.get(key); if (valueHolder != null) { valueHolder.lastAccessTime = System.currentTimeMillis(); } return valueHolder; }
@Override public ValueHolder<String> putIfAbsent(final String key, final String value) throws CacheAccessException { this.checkFailingKey(key); final FakeValueHolder currentValue = this.entries.get(key); if (currentValue == null) { this.entries.put(key, new FakeValueHolder(value)); return null; } currentValue.lastAccessTime = System.currentTimeMillis(); return currentValue; }
@Override public ValueHolder<String> computeIfAbsent( final String key, final Function<? super String, ? extends String> mappingFunction) throws CacheAccessException { this.checkFailingKey(key); FakeValueHolder currentValue = this.entries.get(key); if (currentValue == null) { final String newValue = mappingFunction.apply(key); if (newValue != null) { final FakeValueHolder newValueHolder = new FakeValueHolder(newValue); this.entries.put(key, newValueHolder); currentValue = newValueHolder; } } else { currentValue.lastAccessTime = System.currentTimeMillis(); } return currentValue; }