/*
* Copyright 2010, Andrew M Gibson
*
* www.andygibson.net
*
* This file is part of DataValve.
*
* DataValve is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DataValve is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
*
* You should have received a copy of the GNU Lesser General Public License
* along with DataValve. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.fluttercode.datavalve.util;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.fluttercode.datavalve.DataProvider;
import org.fluttercode.datavalve.Paginator;
/**
* Implementation of a data cache that is used to keep hold of a limited set of
* result values, and uses a LRU mechanism to eject older items. This is
* designed for use with random access mechanisms for accessing data by index.
* it can perform a look ahead prefetch so the next set of results are probably
* loaded in.
* <p>
* The {@link IndexedDataProviderCache#loadValues(Integer, int)} method is used
* as a template to load the values with a look ahead.
*
*
* @author Andy Gibson
*
* @param <V>
* Value type used in the map
*/
public class IndexedDataProviderCache<V> {
private final DataProvider<V> provider;
private final Paginator paginator;
private final int maximumSize;
private Map<Integer, V> map;
public IndexedDataProviderCache(DataProvider<V> provider,
Paginator paginator) {
this(provider, paginator, 100, 25);
}
public IndexedDataProviderCache(DataProvider<V> provider,
Paginator paginator, int maxEntries, int initialSize) {
this.provider = provider;
this.maximumSize = maxEntries;
this.paginator = paginator;
map = new LinkedHashMap<Integer, V>(initialSize, 0.75f, true) {
protected boolean removeEldestEntry(Map.Entry<Integer, V> eldest) {
return size() > maximumSize;
};
};
}
public V get(Integer key) {
if (map.containsKey(key)) {
return map.get(key);
}
List<V> values = loadValues(key, 10);
if (values == null || values.size() == 0) {
return null;
}
for (int i = 0; i < values.size(); i++) {
map.put(key + i, values.get(i));
}
return values.get(0);
}
protected void put(Integer key, V value) {
map.put(key, value);
}
protected void putAll(Map<Integer, V> map) {
map.putAll(map);
}
/**
* Load the item indicated by the key and return it.
*
* @param key
* Key of the value to load
* @return the item to load
*/
protected List<V> loadValues(Integer key, int batchSize) {
// load ahead
paginator.setFirstResult(key);
paginator.setMaxRows(10);
return getProvider().fetchResults(paginator);
}
public DataProvider<V> getProvider() {
return provider;
}
public void clear() {
map.clear();
}
}