package eu.dnetlib.enabling.resultset.push; import java.util.ArrayList; import java.util.List; import javax.annotation.Resource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Required; import eu.dnetlib.enabling.resultset.push.ResultSetDescriptor.Range; import eu.dnetlib.miscutils.cache.Cache; import eu.dnetlib.miscutils.factory.Factory; /** * implement a resultset dao. * * @author marko * */ public class CacheTransientResultSetDaoImpl implements TransientPushResultSetDao { /** * logger. */ private static final Log log = LogFactory.getLog(CacheTransientResultSetDaoImpl.class); // NOPMD by marko on 11/24/08 5:02 PM /** * range cache. Keys are "rsid-rangenumber". */ private Cache> cache; /** * resultsets */ private Cache resultSetCache; /** * resultset descriptor factory. */ @Resource private Factory resultSetDescriptorFactory; /** * {@inheritDoc} * * @see eu.dnetlib.enabling.resultset.push.TransientPushResultSetDao#getSize(java.lang.String) */ @Override public int getSize(final String key) { final ResultSetDescriptor desc = resultSetCache.get(key); if (desc == null) return 0; return (desc.getRanges() - 1) * desc.getRangeLength() + cache.get(key + "-" + desc.getLastRange()).size(); } /** * {@inheritDoc} * * @see eu.dnetlib.enabling.resultset.push.TransientPushResultSetDao#addElements(java.lang.String, java.util.List) */ @Override public void addElements(final String key, final List elements) { // TODO: huuuuu, chaos, fix this please! synchronized (cache) { ResultSetDescriptor desc = resultSetCache.get(key); log.debug("got desc: " + desc); if (desc == null) { desc = resultSetDescriptorFactory.newInstance(); resultSetCache.put(key, desc); } log.debug("desc now is desc: " + desc); if (elements.size() > desc.getRangeLength()) throw new IllegalArgumentException("The current implementation of the push resultset doesn't accept pages longer than " + desc.getRangeLength() + ", got: " + elements.size()); int lastRangeIndex = desc.getLastRange(); if (lastRangeIndex < 0) lastRangeIndex = 0; log.debug("last range: " + lastRangeIndex); List lastRange = cache.get(key + "-" + lastRangeIndex); log.debug("stored last range: " + lastRange); if (lastRange == null) { lastRange = new ArrayList(); desc.setRanges(desc.getRanges() + 1); } log.debug("last range is: " + lastRange); final int free = desc.getRangeLength() - lastRange.size(); log.debug("free: " + free); log.debug("desc range length: " + desc.getRangeLength()); log.debug("last range size: " + lastRange.size()); int toElements = free; if (toElements > elements.size()) { toElements = elements.size(); } else { final List nextRange = new ArrayList(elements.subList(free, elements.size())); log.debug("next range: " + nextRange); cache.put(key + "-" + (lastRangeIndex + 1), nextRange); log.debug("next range stored at: " + key + "-" + (lastRangeIndex + 1)); desc.setRanges(desc.getRanges() + 1); } lastRange.addAll(elements.subList(0, toElements)); log.debug("LAST RANGE SIZE: " + lastRange.size() + " range index " + lastRangeIndex); log.debug("after add: " + lastRange); cache.put(key + "-" + lastRangeIndex, lastRange); log.debug("range stored at: " + key + "-" + lastRangeIndex); resultSetCache.put(key, desc); } } /** * {@inheritDoc} * * @see eu.dnetlib.enabling.resultset.push.TransientPushResultSetDao#getElements(java.lang.String, int, int) */ @Override public List getElements(final String key, final int fromPosition, final int toPosition) { ResultSetDescriptor desc = resultSetCache.get(key); log.debug("got desc: " + desc); if (desc == null) desc = resultSetDescriptorFactory.newInstance(); final List res = new ArrayList(); log.debug("ranges containing " + fromPosition + " to " + toPosition); for (final Range range : desc.getRangesContaining(fromPosition, toPosition)) { log.debug("reading range " + key + "-" + range.getRange() + " begin: " + range.getBegin() + " end: " + range.getEnd()); res.addAll(cache.get(key + "-" + range.getRange()).subList(range.getBegin(), range.getEnd())); } return res; } public Cache> getCache() { return cache; } @Required public void setCache(final Cache> cache) { this.cache = cache; } public Cache getResultSetCache() { return resultSetCache; } @Required public void setResultSetCache(final Cache resultSetCache) { this.resultSetCache = resultSetCache; } public Factory getResultSetDescriptorFactory() { return resultSetDescriptorFactory; } public void setResultSetDescriptorFactory(final Factory resultSetDescriptorFactory) { this.resultSetDescriptorFactory = resultSetDescriptorFactory; } }