/******************************************************************************
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0.  If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/.
 * 
 * Software distributed under the License is distributed on an "AS IS" basis, 
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for 
 * the specific language governing rights and limitations under the License.
 *
 * The Original Code is: FetchMailAtt
 * The Initial Developer of the Original Code is: William Wong (williamw520@gmail.com)
 * Portions created by William Wong are Copyright (C) 2015 William Wong, All Rights Reserved.
 *
 ******************************************************************************/

package fetchmailatt;


import java.util.*;


/**
 * Shared thread local storage cache.  All instances shared the same TLS cache.
 * Using the same key, cached item can be accessed by different instances of the same namespace.
 */
public class TlsCache<K,V> {

    // Shared TLS map for all instances of TlsCache.
    private static final ThreadLocal<Map>   sTlsObj = new ThreadLocal<Map>() {
        protected Map initialValue() {
            return new HashMap();
        }
    };


    public static interface Factory<K,V> {
        public V create(K key, Object... createParams);
    }


    private String                  namespace;
    private TlsCache.Factory<K,V>   factory;

    /** Create a TlsCache access object, with no factory. */
    public TlsCache(String namespace) {
        this.namespace = namespace;
        sTlsObj.get().put(namespace, new HashMap<K,V>());
    }

    /** Create a TlsCache access object, with factory to create missing item. */
    public TlsCache(String namespace, TlsCache.Factory<K,V> factory) {
        this.namespace = namespace;
        this.factory = factory;
        sTlsObj.get().put(namespace, new HashMap<K,V>());
    }

    /** Get a cached item.  Return null if not exists. */
    public V get(K key) {
        return ((Map<K,V>)sTlsObj.get().get(namespace)).get(key);
    }

    /** Get a cached item.  Create and cache it if not exists. */
    public V val(K key, Object... createParams) {
        if (factory == null)
            throw new RuntimeException("No factory defined.");
    
        Map<K,V> map = (Map<K,V>)sTlsObj.get().get(namespace);
        V   value = map.get(key);
        if (value == null) {
            value = factory.create(key, createParams);
            map.put(key, value);
        }
        return value;
    }

    public void put(K key, V value) {
        ((Map<K,V>)sTlsObj.get().get(namespace)).put(key, value);
    }

    public V remove(K key) {
        return ((Map<K,V>)sTlsObj.get().get(namespace)).remove(key);
    }

    public void clear() {
        ((Map<K,V>)sTlsObj.get().get(namespace)).clear();
    }


    // Raw access on the shared TLS object.
    
	public static Object sget(Object key) {
		return sTlsObj.get().get(key);
	}

	public static <T> T sget(Object key, T defaultVal) {
        T   value = (T)sget(key);
        return value != null ? value : defaultVal;
	}

	public static void sput(Object key, Object value) {
		sTlsObj.get().put(key, value);
	}

	public static Object sremove(Object key) {
		return sTlsObj.get().remove(key);
	}

	public static void sclear()	{
		sTlsObj.remove();
	}

}


@@ -847,17 +847,16 @@
 ilatt;%0A%0A
-%0A
 import j
@@ -931,17 +931,16 @@
 es share
-d
  the sam
@@ -1026,18 +1026,20 @@
 stances 
-of
+with
  the sam
@@ -1089,61 +1089,8 @@
  %7B%0A%0A
-    // Shared TLS map for all instances of TlsCache.%0A
     
@@ -1255,17 +1255,16 @@
     %7D;%0A%0A
-%0A
     publ
@@ -1464,36 +1464,33 @@
    /** Create a 
-TlsC
+c
 ache access obje
@@ -1487,24 +1487,41 @@
 ccess object
+ on the namespace
 , with no fa
@@ -1688,20 +1688,17 @@
 reate a 
-TlsC
+c
 ache acc
@@ -1707,16 +1707,33 @@
 s object
+ on the namespace
 , with f
@@ -2585,32 +2585,58 @@
 n value;%0A    %7D%0A%0A
+    /** Cache an item. */%0A
     public void 
@@ -2722,32 +2722,70 @@
  value);%0A    %7D%0A%0A
+    /** Remove an item from cache. */%0A
     public V rem
@@ -2869,24 +2869,90 @@
 ey);%0A    %7D%0A%0A
+    /** Remove all items with the same namespace in the cache. */%0A
     public v
@@ -3034,507 +3034,7 @@
  %7D%0A%0A
-%0A    // Raw access on the shared TLS object.%0A    %0A%09public static Object sget(Object key) %7B%0A%09%09return sTlsObj.get().get(key);%0A%09%7D%0A%0A%09public static %3CT%3E T sget(Object key, T defaultVal) %7B%0A        T   value = (T)sget(key);%0A        return value != null ? value : defaultVal;%0A%09%7D%0A%0A%09public static void sput(Object key, Object value) %7B%0A%09%09sTlsObj.get().put(key, value);%0A%09%7D%0A%0A%09public static Object sremove(Object key) %7B%0A%09%09return sTlsObj.get().remove(key);%0A%09%7D%0A%0A%09public static void sclear()%09%7B%0A%09%09sTlsObj.remove();%0A%09%7D%0A%0A
 %7D%0A%0A

Clean up TlsCache.