grails.plugin.cache.GrailsConcurrentLinkedMapCache.java Source code

Java tutorial

Introduction

Here is the source code for grails.plugin.cache.GrailsConcurrentLinkedMapCache.java

Source

/* Copyright 2012-2013 SpringSource.
 *
 * 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 grails.plugin.cache;

import java.io.Serializable;
import java.util.Collection;
import java.util.concurrent.ConcurrentMap;

import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap.Builder;

import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;
import org.springframework.util.Assert;

/**
 * @author Jakob Drangmeister
 */
public class GrailsConcurrentLinkedMapCache implements GrailsCache {

    private static final Object NULL_HOLDER = new NullHolder();
    private String name;
    private long capacity;
    private final ConcurrentLinkedHashMap<Object, Object> store;
    private final boolean allowNullValues;

    /**
     * Create a new GrailsConcurrentLinkedMapCache with the specified name 
     * and capacity
     * @param name the name of the cache
     * @param capacity of the map
     * @param allowNullValues null values (default is true)
     */
    public GrailsConcurrentLinkedMapCache(String name, long capacity, boolean allowNullValues) {
        this.name = name;
        this.capacity = capacity;
        this.allowNullValues = allowNullValues;
        this.store = new ConcurrentLinkedHashMap.Builder<Object, Object>().maximumWeightedCapacity(capacity)
                .build();
    }

    /**
     * Create a new GrailsConcurrentLinkedMapCache with the specified name 
     * and capacity
     * @param name the name of the cache
     * @param capacity of the map
     */
    public GrailsConcurrentLinkedMapCache(String name, long capacity) {
        this(name, capacity, true);
    }

    public final long getCapacity() {
        return this.store.capacity();
    }

    @Override
    public final String getName() {
        return this.name;
    }

    @Override
    public final ConcurrentMap<Object, Object> getNativeCache() {
        return this.store;
    }

    public final int getSize() {
        return this.store.size();
    }

    public final boolean isAllowNullValues() {
        return this.allowNullValues;
    }

    @Override
    public GrailsValueWrapper get(Object key) {
        Object value = getNativeCache().get(key);
        return value == null ? null : new GrailsValueWrapper(fromStoreValue(value), null);
    }

    @Override
    public <T> T get(Object key, Class<T> type) {
        Object value = getNativeCache().get(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;
    }

    @SuppressWarnings("unchecked")
    public Collection<Object> getAllKeys() {
        return getNativeCache().keySet();
    }

    public Collection<Object> getHottestKeys() {
        return this.store.descendingKeySet();
    }

    @Override
    public void put(Object key, Object value) {
        this.store.put(key, toStoreValue(value));
    }

    public ValueWrapper putIfAbsent(Object key, Object value) {
        Object existing = this.store.putIfAbsent(key, value);
        return toWrapper(existing);
    }

    @Override
    public void evict(Object key) {
        this.store.remove(key);
    }

    @Override
    public void clear() {
        this.store.clear();
    }

    /**
     * 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
     */
    protected Object fromStoreValue(Object storeValue) {
        if (this.allowNullValues && storeValue == NULL_HOLDER) {
            return null;
        }
        return storeValue;
    }

    /**
     * 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(Object userValue) {
        if (this.allowNullValues && userValue == null) {
            return NULL_HOLDER;
        }
        return userValue;
    }

    private ValueWrapper toWrapper(Object value) {
        return (value != null ? new SimpleValueWrapper(fromStoreValue(value)) : null);
    }

    @SuppressWarnings("serial")

    private static class NullHolder implements Serializable {
    }
}