WeakCacheMap.java Source code

Java tutorial

Introduction

Here is the source code for WeakCacheMap.java

Source

/*
 * This file is part of aion-emu <aion-emu.com>.
 *
 *  aion-emu is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  aion-emu is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with aion-emu.  If not, see <http://www.gnu.org/licenses/>.
 */
//package com.aionemu.gameserver.utils.collections.cachemap;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;

/**
 * This class is a simple map implementation for cache usage.<br>
 * <br>
 * Values from the map will be removed after the first garbage collector run if there isn't any strong reference to the
 * value object.
 * 
 * @author Luno
 * 
 */
class WeakCacheMap<K, V> extends AbstractCacheMap<K, V> implements CacheMap<K, V> {
    /**
     * This class is a {@link WeakReference} with additional responsibility of holding key object
     * 
     * @author Luno
     */
    private class Entry extends WeakReference<V> {
        private K key;

        Entry(K key, V referent, ReferenceQueue<? super V> q) {
            super(referent, q);
            this.key = key;
        }

        K getKey() {
            return key;
        }
    }

    WeakCacheMap(String cacheName, String valueName) {
        super(cacheName, valueName);
    }

    @SuppressWarnings("unchecked")
    @Override
    protected synchronized void cleanQueue() {
        Entry en = null;
        while ((en = (Entry) refQueue.poll()) != null) {
            K key = en.getKey();
            cacheMap.remove(key);
        }
    }

    @Override
    protected Reference<V> newReference(K key, V value, ReferenceQueue<V> vReferenceQueue) {
        return new Entry(key, value, vReferenceQueue);
    }
}

/**
 * Base class for {@link WeakCacheMap} and {@link SoftCacheMap}
 * 
 * @author Luno
 * 
 * @param <K>
 * @param <V>
 */
abstract class AbstractCacheMap<K, V> implements CacheMap<K, V> {
    protected final String cacheName;
    protected final String valueName;

    /** Map storing references to cached objects */
    protected final Map<K, Reference<V>> cacheMap = new HashMap<K, Reference<V>>();

    protected final ReferenceQueue<V> refQueue = new ReferenceQueue<V>();

    /**
     * @param cacheName
     * @param valueName
     */
    AbstractCacheMap(String cacheName, String valueName) {
        this.cacheName = "#CACHE  [" + cacheName + "]#  ";
        this.valueName = valueName;
    }

    /** {@inheritDoc} */
    @Override
    public void put(K key, V value) {
        cleanQueue();

        if (cacheMap.containsKey(key))
            throw new IllegalArgumentException("Key: " + key + " already exists in map");

        Reference<V> entry = newReference(key, value, refQueue);

        cacheMap.put(key, entry);
    }

    /** {@inheritDoc} */
    @Override
    public V get(K key) {
        cleanQueue();

        Reference<V> reference = cacheMap.get(key);

        if (reference == null)
            return null;

        V res = reference.get();
        return res;
    }

    @Override
    public boolean contains(K key) {
        cleanQueue();
        return cacheMap.containsKey(key);
    }

    protected abstract void cleanQueue();

    @Override
    public void remove(K key) {
        cacheMap.remove(key);
    }

    protected abstract Reference<V> newReference(K key, V value, ReferenceQueue<V> queue);
}

interface CacheMap<K, V> {

    /**
     * Adds a pair <key,value> to cache map.<br>
     * <br>
     * 
     * <font color='red'><b>NOTICE:</b> </font> if there is already a value with given id in the map,
     * {@link IllegalArgumentException} will be thrown.
     * 
     * @param key
     * @param value
     */
    public void put(K key, V value);

    /**
     * Returns cached value correlated to given key.
     * 
     * @param key
     * @return V
     */
    public V get(K key);

    /**
     * Checks whether this map contains a value related to given key.
     * @param key
     * @return true or false
     */
    public boolean contains(K key);

    /**
     * Removes an entry from the map, that has given key.
     * @param key
     */
    public void remove(K key);
}