package com.datdo.mobilib.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import junit.framework.Assert;

import com.datdo.mobilib.util.MblUtils;

/**
 * <pre>
 * TBD
 * </pre>
 *
 * @param <T>
 */
@SuppressWarnings("rawtypes")
public class MblMemCache<T> {

    private static class CacheItem<V> {

        V mObject;
        long mPutAt;

        CacheItem(V object, long putAt) {
            mObject = object;
            mPutAt = putAt;
        }
    }

    private static final Map<String, CacheItem> sMap = new HashMap<String, CacheItem>();

    private String getCacheId(String id) {
        return mTypeName + "#" + id;
    }

    private String mTypeName;
    private long mDuration;

    public MblMemCache(Class<T> type, long duration) {
        Assert.assertNotNull(type);
        mTypeName = type.getName();
        mDuration = duration;
    }

    /**
     * <pre>
     * TBD
     * </pre>
     * @param id
     * @param object
     */
    @SuppressWarnings("unchecked")
    public void put(String id, T object) {
        synchronized (MblMemCache.class) {
            String cachId = getCacheId(id);
            CacheItem<T> cacheItem = sMap.get(cachId);
            if (cacheItem == null) {
                cacheItem = new CacheItem<T>(object, System.currentTimeMillis());
            } else {
                cacheItem.mObject = object;
                cacheItem.mPutAt = System.currentTimeMillis();
            }
            sMap.put(cachId, cacheItem);
        }
    }

    /**
     * <pre>
     * TBD
     * </pre>
     * @param id
     * @return
     */
    @SuppressWarnings("unchecked")
    public T get(String id) {
        synchronized (MblMemCache.class) {
            String cachId = getCacheId(id);
            CacheItem<T> cacheItem = sMap.get(cachId);
            if (cacheItem == null) {
                return null;
            } else {
                if (mDuration <= 0 || cacheItem.mPutAt + mDuration > System.currentTimeMillis()) {
                    return cacheItem.mObject;
                } else {
                    sMap.remove(cachId);
                    return null;
                }
            }
        }
    }

    /**
     * <pre>
     * TBD
     * </pre>
     * @param ids
     * @return
     */
    public List<T> get(List<String> ids) {

        if (MblUtils.isEmpty(ids)) {
            return new ArrayList<T>();
        }

        synchronized (MblMemCache.class) {
            List<T> ret = new ArrayList<T>();
            for (String id : ids) {
                T object = get(id);
                if (object != null) {
                    ret.add(object);
                }
            }
            return ret;
        }
    }

    /**
     * <pre>
     * TBD
     * </pre>
     * @param id
     * @return
     */
    public boolean containsKey(String id) {
        synchronized (MblMemCache.class) {
            return get(id) != null;
        }
    }

    /**
     * <pre>
     * TBD
     * </pre>
     */
    public void clear() {
        synchronized (MblMemCache.class) {
            List<String> removedIds = new ArrayList<String>();
            for (String mapId : sMap.keySet()) {
                if (mapId.startsWith(mTypeName)) {
                    removedIds.add(mapId);
                }
            }
            for (String id : removedIds) {
                sMap.remove(id);
            }
        }
    }
}

@@ -124,16 +124,38 @@
 til.Map;
+%0Aimport java.util.Set;
 %0A%0Aimport
@@ -184,49 +184,8 @@
 t;%0A%0A
-import com.datdo.mobilib.util.MblUtils;%0A%0A
 /**%0A
@@ -483,32 +483,130 @@
        %7D%0A    %7D%0A%0A
+    public static interface IterateCallback%3CT%3E %7B%0A        public void onInterate(T object);%0A    %7D%0A%0A
     private stat
@@ -2812,32 +2812,1095 @@
        %7D%0A    %7D%0A%0A
+    /**%0A     * %3Cpre%3ETBD%3C/pre%3E%0A     * @param id%0A     * @return%0A     */%0A    @SuppressWarnings(%22unchecked%22)%0A    public T remove(String id) %7B%0A        synchronized (MblMemCache.class) %7B%0A            String cachId = getCacheId(id);%0A            CacheItem%3CT%3E cacheItem = sMap.get(cachId);%0A            if (cacheItem == null) %7B%0A                return null;%0A            %7D else %7B%0A                sMap.remove(cachId);%0A                return cacheItem.mObject;%0A            %7D%0A        %7D%0A    %7D%0A%0A    /**%0A     * %3Cpre%3ETBD%3C/pre%3E%0A     * @param cb%0A     */%0A    public void iterateWithCallback(IterateCallback%3CT%3E cb) %7B%0A%0A        if (cb == null) %7B%0A            return;%0A        %7D%0A%0A        synchronized (MblMemCache.class) %7B%0A            Set%3CString%3E cacheIds = sMap.keySet();%0A            String prefix = mTypeName + %22#%22;%0A            for (String cid : cacheIds) %7B%0A                if (cid.startsWith(prefix)) %7B%0A                    T o = get(cid);%0A                    if (o != null) %7B%0A                        cb.onInterate(o);%0A                    %7D%0A                %7D%0A            %7D%0A        %7D%0A    %7D%0A%0A
     /**%0A     * %3C

add 2 methods remove() and iterateWithCallback()