/*
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cache.support;
import org.springframework.cache.Cache;
import org.springframework.lang.Nullable;
Common base class for Cache
implementations that need to adapt null
values (and potentially other such special values) before passing them on to the underlying store. Transparently replaces given null
user values with an internal NullValue.INSTANCE
, if configured to support null
values (as indicated by isAllowNullValues()
.
Author: Juergen Hoeller Since: 4.2.2
/**
* Common base class for {@link Cache} implementations that need to adapt
* {@code null} values (and potentially other such special values) before
* passing them on to the underlying store.
*
* <p>Transparently replaces given {@code null} user values with an internal
* {@link NullValue#INSTANCE}, if configured to support {@code null} values
* (as indicated by {@link #isAllowNullValues()}.
*
* @author Juergen Hoeller
* @since 4.2.2
*/
public abstract class AbstractValueAdaptingCache implements Cache {
private final boolean allowNullValues;
Create an AbstractValueAdaptingCache
with the given setting. Params: - allowNullValues – whether to allow for
null
values
/**
* Create an {@code AbstractValueAdaptingCache} with the given setting.
* @param allowNullValues whether to allow for {@code null} values
*/
protected AbstractValueAdaptingCache(boolean allowNullValues) {
this.allowNullValues = allowNullValues;
}
Return whether null
values are allowed in this cache. /**
* Return whether {@code null} values are allowed in this cache.
*/
public final boolean isAllowNullValues() {
return this.allowNullValues;
}
@Override
@Nullable
public ValueWrapper get(Object key) {
Object value = lookup(key);
return toValueWrapper(value);
}
@Override
@SuppressWarnings("unchecked")
@Nullable
public <T> T get(Object key, @Nullable Class<T> type) {
Object value = fromStoreValue(lookup(key));
if (value != null && type != null && !type.isInstance(value)) {
throw new IllegalStateException(
"Cached value is not of required type [" + type.getName() + "]: " + value);
}
return (T) value;
}
Perform an actual lookup in the underlying store.
Params: - key – the key whose associated value is to be returned
Returns: the raw store value for the key, or null
if none
/**
* Perform an actual lookup in the underlying store.
* @param key the key whose associated value is to be returned
* @return the raw store value for the key, or {@code null} if none
*/
@Nullable
protected abstract Object lookup(Object key);
Convert the given value from the internal store to a user value returned from the get method (adapting null
). Params: - storeValue – the store value
Returns: the value to return to the user
/**
* Convert the given value from the internal store to a user value
* returned from the get method (adapting {@code null}).
* @param storeValue the store value
* @return the value to return to the user
*/
@Nullable
protected Object fromStoreValue(@Nullable Object storeValue) {
if (this.allowNullValues && storeValue == NullValue.INSTANCE) {
return null;
}
return storeValue;
}
Convert the given user value, as passed into the put method, to a value in the internal store (adapting null
). Params: - userValue – the given user value
Returns: the value to store
/**
* Convert the given user value, as passed into the put method,
* to a value in the internal store (adapting {@code null}).
* @param userValue the given user value
* @return the value to store
*/
protected Object toStoreValue(@Nullable Object userValue) {
if (userValue == null) {
if (this.allowNullValues) {
return NullValue.INSTANCE;
}
throw new IllegalArgumentException(
"Cache '" + getName() + "' is configured to not allow null values but null was provided");
}
return userValue;
}
Wrap the given store value with a SimpleValueWrapper
, also going through fromStoreValue
conversion. Useful for get(Object)
and Cache.putIfAbsent(Object, Object)
implementations. Params: - storeValue – the original value
Returns: the wrapped value
/**
* Wrap the given store value with a {@link SimpleValueWrapper}, also going
* through {@link #fromStoreValue} conversion. Useful for {@link #get(Object)}
* and {@link #putIfAbsent(Object, Object)} implementations.
* @param storeValue the original value
* @return the wrapped value
*/
@Nullable
protected Cache.ValueWrapper toValueWrapper(@Nullable Object storeValue) {
return (storeValue != null ? new SimpleValueWrapper(fromStoreValue(storeValue)) : null);
}
}