001/*
002 * (C) Copyright 2006-2009 Nuxeo SAS (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Nuxeo - initial API and implementation
016 *
017 * $Id$
018 */
019
020package org.nuxeo.ecm.platform.ui.web.cache;
021
022import java.io.Serializable;
023import java.util.Calendar;
024import java.util.Map;
025import java.util.concurrent.locks.ReentrantReadWriteLock;
026
027import org.nuxeo.ecm.core.api.DocumentModel;
028import org.nuxeo.ecm.core.api.DocumentRef;
029
030public class ThreadSafeCacheHolder<T extends Serializable> implements Serializable {
031
032    public static final int DEFAULT_SIZE = 20;
033
034    private static final long serialVersionUID = 1L;
035
036    protected final Map<String, T> cacheMap;
037
038    protected final ReentrantReadWriteLock cacheLock = new ReentrantReadWriteLock();
039
040    public ThreadSafeCacheHolder() {
041        this(DEFAULT_SIZE);
042    }
043
044    public ThreadSafeCacheHolder(int maxSize) {
045        cacheMap = new LRUCachingMap<String, T>(maxSize);
046    }
047
048    protected String getKey(DocumentRef docRef, String key) {
049        if (docRef == null) {
050            if (key == null) {
051                return "default";
052            } else {
053                return key;
054            }
055        } else {
056            if (key == null) {
057                return docRef.toString();
058            } else {
059                return docRef.toString() + "-" + key;
060            }
061        }
062    }
063
064    protected String getKey(DocumentModel doc, String key) {
065        DocumentRef docRef = doc.getRef();
066        Calendar modified = (Calendar) doc.getProperty("dublincore", "modified");
067        if (key == null) {
068            if (modified != null) {
069                key = modified.toString();
070            }
071        } else {
072            key = key + "-" + key;
073        }
074
075        return getKey(docRef, key);
076    }
077
078    // Adders
079    protected void doAdd(String key, T value) {
080        try {
081            cacheLock.writeLock().lock();
082            cacheMap.put(key, value);
083        } finally {
084            cacheLock.writeLock().unlock();
085        }
086    }
087
088    public void addToCache(String key, T value) {
089        doAdd(key, value);
090    }
091
092    public void addToCache(DocumentRef docRef, String key, T value) {
093        doAdd(getKey(docRef, key), value);
094    }
095
096    public void addToCache(DocumentModel doc, String key, T value) {
097        doAdd(getKey(doc, key), value);
098    }
099
100    // Getters
101    protected T doGet(String key) {
102        try {
103            cacheLock.readLock().lock();
104            return cacheMap.get(key);
105        } finally {
106            cacheLock.readLock().unlock();
107        }
108    }
109
110    public T getFromCache(String key) {
111        return doGet(key);
112    }
113
114    public T getFromCache(DocumentRef docRef, String key) {
115        return doGet(getKey(docRef, key));
116    }
117
118    public T getFromCache(DocumentModel doc, String key) {
119        return doGet(getKey(doc, key));
120    }
121
122    // Removers
123    protected void doRemove(String key) {
124        try {
125            cacheLock.writeLock().lock();
126            cacheMap.remove(key);
127        } finally {
128            cacheLock.writeLock().unlock();
129        }
130    }
131
132    public void removeFromCache(DocumentRef docRef, String key) {
133        doRemove(getKey(docRef, key));
134    }
135
136    public void removeFromCache(DocumentModel doc, String key) {
137        doRemove(getKey(doc, key));
138    }
139
140    public void removeFromCache(String key) {
141        doRemove(key);
142    }
143
144}