TempStateCacheView.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one
  3.  * or more contributor license agreements.  See the NOTICE file
  4.  * distributed with this work for additional information
  5.  * regarding copyright ownership.  The ASF licenses this file
  6.  * to you under the Apache License, Version 2.0 (the
  7.  * "License"); you may not use this file except in compliance
  8.  * with the License.  You may obtain a copy of the License at
  9.  *
  10.  *   http://www.apache.org/licenses/LICENSE-2.0
  11.  *
  12.  * Unless required by applicable law or agreed to in writing,
  13.  * software distributed under the License is distributed on an
  14.  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15.  * KIND, either express or implied.  See the License for the
  16.  * specific language governing permissions and limitations
  17.  * under the License.
  18.  */
  19. package org.apache.commons.jcs3.jcache;

  20. import javax.cache.Cache;
  21. import javax.cache.CacheManager;
  22. import javax.cache.configuration.CacheEntryListenerConfiguration;
  23. import javax.cache.configuration.CompleteConfiguration;
  24. import javax.cache.configuration.Configuration;
  25. import javax.cache.integration.CompletionListener;
  26. import javax.cache.processor.EntryProcessor;
  27. import javax.cache.processor.EntryProcessorException;
  28. import javax.cache.processor.EntryProcessorResult;

  29. import static org.apache.commons.jcs3.jcache.Asserts.assertNotNull;

  30. import java.util.Collection;
  31. import java.util.HashMap;
  32. import java.util.HashSet;
  33. import java.util.Iterator;
  34. import java.util.LinkedList;
  35. import java.util.Map;
  36. import java.util.Set;

  37. // kind of transactional view for a Cache<K, V>, to use with EntryProcessor
  38. public class TempStateCacheView<K, V> implements Cache<K, V>
  39. {
  40.     private final JCSCache<K, V> cache;
  41.     private final Map<K, V> put = new HashMap<>();
  42.     private final Collection<K> remove = new LinkedList<>();
  43.     private boolean removeAll;
  44.     private boolean clear;

  45.     public TempStateCacheView(final JCSCache<K, V> entries)
  46.     {
  47.         this.cache = entries;
  48.     }

  49.     @Override
  50.     public V get(final K key)
  51.     {
  52.         if (ignoreKey(key))
  53.         {
  54.             return null;
  55.         }

  56.         final V v = put.get(key);
  57.         if (v != null)
  58.         {
  59.             return v;
  60.         }

  61.         // for an EntryProcessor we already incremented stats - to enhance
  62.         // surely
  63.         if (cache.getConfiguration(CompleteConfiguration.class).isStatisticsEnabled())
  64.         {
  65.             final Statistics statistics = cache.getStatistics();
  66.             if (cache.containsKey(key))
  67.             {
  68.                 statistics.increaseHits(-1);
  69.             }
  70.             else
  71.             {
  72.                 statistics.increaseMisses(-1);
  73.             }
  74.         }
  75.         return cache.get(key);
  76.     }

  77.     private boolean ignoreKey(final K key)
  78.     {
  79.         return removeAll || clear || remove.contains(key);
  80.     }

  81.     @Override
  82.     public Map<K, V> getAll(final Set<? extends K> keys)
  83.     {
  84.         final Map<K, V> v = new HashMap<>(keys.size());
  85.         final Set<K> missing = new HashSet<>();
  86.         for (final K k : keys)
  87.         {
  88.             final V value = put.get(k);
  89.             if (value != null)
  90.             {
  91.                 v.put(k, value);
  92.             }
  93.             else if (!ignoreKey(k))
  94.             {
  95.                 missing.add(k);
  96.             }
  97.         }
  98.         if (!missing.isEmpty())
  99.         {
  100.             v.putAll(cache.getAll(missing));
  101.         }
  102.         return v;
  103.     }

  104.     @Override
  105.     public boolean containsKey(final K key)
  106.     {
  107.         return !ignoreKey(key) && (put.containsKey(key) || cache.containsKey(key));
  108.     }

  109.     @Override
  110.     public void loadAll(final Set<? extends K> keys, final boolean replaceExistingValues, final CompletionListener completionListener)
  111.     {
  112.         cache.loadAll(keys, replaceExistingValues, completionListener);
  113.     }

  114.     @Override
  115.     public void put(final K key, final V value)
  116.     {
  117.         assertNotNull(key, "key");
  118.         assertNotNull(value, "value");
  119.         put.put(key, value);
  120.         remove.remove(key);
  121.     }

  122.     @Override
  123.     public V getAndPut(final K key, final V value)
  124.     {
  125.         final V v = get(key);
  126.         put(key, value);
  127.         return v;
  128.     }

  129.     @Override
  130.     public void putAll(final Map<? extends K, ? extends V> map)
  131.     {
  132.         put.putAll(map);
  133.         for (final K k : map.keySet())
  134.         {
  135.             remove.remove(k);
  136.         }
  137.     }

  138.     @Override
  139.     public boolean putIfAbsent(final K key, final V value)
  140.     {
  141.         if (!put.containsKey(key))
  142.         {
  143.             put.put(key, value);
  144.             remove.remove(key);
  145.             return true;
  146.         }
  147.         return false;
  148.     }

  149.     @Override
  150.     public boolean remove(final K key)
  151.     {
  152.         final boolean noop = put.containsKey(key);
  153.         put.remove(key);
  154.         if (!ignoreKey(key))
  155.         {
  156.             if (!noop)
  157.             {
  158.                 remove.add(key);
  159.             }
  160.             return true;
  161.         }
  162.         return false;
  163.     }

  164.     @Override
  165.     public boolean remove(final K key, final V oldValue)
  166.     {
  167.         put.remove(key);
  168.         if (!ignoreKey(key) && oldValue.equals(cache.get(key)))
  169.         {
  170.             remove.add(key);
  171.             return true;
  172.         }
  173.         return false;
  174.     }

  175.     @Override
  176.     public V getAndRemove(final K key)
  177.     {
  178.         final V v = get(key);
  179.         remove.add(key);
  180.         put.remove(key);
  181.         return v;
  182.     }

  183.     @Override
  184.     public boolean replace(final K key, final V oldValue, final V newValue)
  185.     {
  186.         if (oldValue.equals(get(key)))
  187.         {
  188.             put(key, newValue);
  189.             return true;
  190.         }
  191.         return false;
  192.     }

  193.     @Override
  194.     public boolean replace(final K key, final V value)
  195.     {
  196.         if (containsKey(key))
  197.         {
  198.             remove(key);
  199.             return true;
  200.         }
  201.         return false;
  202.     }

  203.     @Override
  204.     public V getAndReplace(final K key, final V value)
  205.     {
  206.         if (containsKey(key))
  207.         {
  208.             final V oldValue = get(key);
  209.             put(key, value);
  210.             return oldValue;
  211.         }
  212.         return null;
  213.     }

  214.     @Override
  215.     public void removeAll(final Set<? extends K> keys)
  216.     {
  217.         remove.addAll(keys);
  218.         for (final K k : keys)
  219.         {
  220.             put.remove(k);
  221.         }
  222.     }

  223.     @Override
  224.     public void removeAll()
  225.     {
  226.         removeAll = true;
  227.         put.clear();
  228.         remove.clear();
  229.     }

  230.     @Override
  231.     public void clear()
  232.     {
  233.         clear = true;
  234.         put.clear();
  235.         remove.clear();
  236.     }

  237.     @Override
  238.     public <C extends Configuration<K, V>> C getConfiguration(final Class<C> clazz)
  239.     {
  240.         return cache.getConfiguration(clazz);
  241.     }

  242.     @Override
  243.     public <T> T invoke(final K key, final EntryProcessor<K, V, T> entryProcessor, final Object... arguments) throws EntryProcessorException
  244.     {
  245.         return cache.invoke(key, entryProcessor, arguments);
  246.     }

  247.     @Override
  248.     public <T> Map<K, EntryProcessorResult<T>> invokeAll(final Set<? extends K> keys, final EntryProcessor<K, V, T> entryProcessor,
  249.             final Object... arguments)
  250.     {
  251.         return cache.invokeAll(keys, entryProcessor, arguments);
  252.     }

  253.     @Override
  254.     public String getName()
  255.     {
  256.         return cache.getName();
  257.     }

  258.     @Override
  259.     public CacheManager getCacheManager()
  260.     {
  261.         return cache.getCacheManager();
  262.     }

  263.     @Override
  264.     public void close()
  265.     {
  266.         cache.close();
  267.     }

  268.     @Override
  269.     public boolean isClosed()
  270.     {
  271.         return cache.isClosed();
  272.     }

  273.     @Override
  274.     public <T> T unwrap(final Class<T> clazz)
  275.     {
  276.         return cache.unwrap(clazz);
  277.     }

  278.     @Override
  279.     public void registerCacheEntryListener(final CacheEntryListenerConfiguration<K, V> cacheEntryListenerConfiguration)
  280.     {
  281.         cache.registerCacheEntryListener(cacheEntryListenerConfiguration);
  282.     }

  283.     @Override
  284.     public void deregisterCacheEntryListener(final CacheEntryListenerConfiguration<K, V> cacheEntryListenerConfiguration)
  285.     {
  286.         cache.deregisterCacheEntryListener(cacheEntryListenerConfiguration);
  287.     }

  288.     @Override
  289.     public Iterator<Entry<K, V>> iterator()
  290.     {
  291.         return cache.iterator();
  292.     }

  293.     public void merge()
  294.     {
  295.         if (removeAll)
  296.         {
  297.             cache.removeAll();
  298.         }
  299.         if (clear)
  300.         {
  301.             cache.clear();
  302.         }

  303.         for (final Map.Entry<K, V> entry : put.entrySet())
  304.         {
  305.             cache.put(entry.getKey(), entry.getValue());
  306.         }
  307.         put.clear();
  308.         for (final K entry : remove)
  309.         {
  310.             cache.remove(entry);
  311.         }
  312.         remove.clear();
  313.     }
  314. }