1   package com.trendmicro.grid.acl.ds.cache.commands;
2   
3   import com.trendmicro.grid.acl.ds.cache.CacheSettings;
4   import com.trendmicro.grid.acl.ds.cache.CacheSource;
5   
6   import java.util.Collection;
7   import java.util.Iterator;
8   import java.util.Map;
9   
10  /**
11   * Retains only the keys that do not exist inside the cache.
12   * <p/>
13   * The purpose of this command is to differentiate between negative cache and un-cached values.
14   * Disabling the command disables negative caching.
15   *
16   * @author juergen_kellerer, 2011-03-24
17   * @version 1.0
18   */
19  public class RetainMissingKeysCommand<K, V> extends AbstractCommand<K, V> {
20  
21  	private CacheSource<K, V> cache;
22  
23  	/**
24  	 * Creates the command.
25  	 *
26  	 * @param keys  the keys to check.
27  	 * @param cache the cache source to check the keys against.
28  	 */
29  	public RetainMissingKeysCommand(Collection<K> keys, CacheSource<K, V> cache) {
30  		super(keys);
31  		this.cache = cache;
32  	}
33  
34  	/**
35  	 * Retains only the keys that do not exist inside the cache.
36  	 * <p/>
37  	 * Use this to reduce the key set by all keys that are negatively cached with a null value.
38  	 * <p/>
39  	 * A typical implementation is:<code><pre>
40  	 * for (Iterator i = keys.iterator(); i.hasNext();)
41  	 *   if (cached.containsKey(i.next()))
42  	 *     i.remove();
43  	 * </pre></code>
44  	 *
45  	 * @param keys the keys to filter.
46  	 */
47  	protected void retainMissingKeys(Collection<K> keys) {
48  		for (Iterator<K> iterator = keys.iterator(); iterator.hasNext();) {
49  			if (cache.containsKey(iterator.next())) iterator.remove();
50  		}
51  	}
52  
53  	/**
54  	 * {@inheritDoc}
55  	 */
56  	@Override
57  	public Map<K, V> call() throws Exception {
58  		if (!CacheSettings.NO_NEGATIVE_CACHING) retainMissingKeys(keys);
59  
60  		return keysToCallResult();
61  	}
62  }