Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSetFactory.java	(revision 45117)
@@ -0,0 +1,26 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * Create a new resultset which takes each record of the input resultset and counts them.
+ * 
+ * @author claudio
+ * 
+ */
+public class CountingResultSetFactory extends MappedResultSetFactory {
+
+	/**
+	 * Create a new resultset which takes each record of the input resultset and counts them.
+	 * 
+	 * @param source
+	 *            source resultset epr
+	 * @param mapper
+	 *            mapper function
+	 * @return mapped resultset epr
+	 */
+	public W3CEndpointReference createCountingResultSet(final W3CEndpointReference source) {
+		return getResultSetFactory().createResultSet(new CountingResultSet(source, getServiceResolver()));
+	}
+
+}

Property changes on: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSetFactory.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetListener.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetListener.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetListener.java	(revision 45117)
@@ -0,0 +1,15 @@
+package eu.dnetlib.enabling.resultset;
+
+
+/**
+ * A ResultSetListener is a pull interface to a ResultSet.
+ * 
+ * The Resultset will call method of ResultSetListener implementors whenever it needs to pull some data and provide it
+ * to clients. The ResultSet service acts as a decouple point between the producer and the consumer.
+ * 
+ * @author marko
+ * 
+ */
+public interface ResultSetListener extends TypedResultSetListener<String> {
+
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/SizedIterable.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/SizedIterable.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/SizedIterable.java	(revision 45117)
@@ -0,0 +1,7 @@
+package eu.dnetlib.enabling.resultset;
+
+public interface SizedIterable<T> extends Iterable<T> {
+
+	public int getNumberOfElements();
+	
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSet.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSet.java	(revision 45117)
@@ -0,0 +1,22 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import java.util.List;
+
+import eu.dnetlib.enabling.resultset.ResultSet;
+
+/**
+ * resultset which receive data through the "push" interface, i.e. data is directly appended to it.
+ * 
+ * @author marko
+ *
+ */
+public interface PushResultSet extends ResultSet {
+
+	/**
+	 * add a list of elements at the end of the resultset.
+	 * 
+	 * @param elements list of elements
+	 */
+	void addElements(List<String> elements);
+
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/AbstractResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/AbstractResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/AbstractResultSetFactory.java	(revision 45117)
@@ -0,0 +1,38 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * Resultset factories bound to a resultset service, from which it takes the resultset registry and the epr builder.
+ *
+ * @author marko
+ *
+ */
+public abstract class AbstractResultSetFactory implements ResultSetFactory {
+
+	/**
+	 * resultset service.
+	 */
+	private ResultSetServiceImpl resultSetService;
+
+	/**
+	 * Register a resultset instance to the underlying resultset registry and returns
+	 * and EPR to accessible through the resultset service.
+	 *
+	 * @param resultSet resultset instance
+	 * @return epr to the newly created resultset
+	 */
+	public W3CEndpointReference registerResultSet(final ResultSet resultSet) {
+		resultSetService.getResultsetRegistry().addResultSet(resultSet);
+		return resultSetService.getEprBuilder().getEndpointReference(resultSetService.getEndpoint(), resultSet.getIdentifier());
+	}
+
+	public ResultSetServiceImpl getResultSetService() {
+		return resultSetService;
+	}
+
+	public void setResultSetService(final ResultSetServiceImpl resultSetService) {
+		this.resultSetService = resultSetService;
+	}
+
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetFactory.java	(revision 45117)
@@ -0,0 +1,19 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * Creates a resultset service from a producer.
+ * 
+ * @author marko
+ *
+ */
+public interface ResultSetFactory {
+	/**
+	 * TODO other parameters like expiration time etc.
+	 * 
+	 * @param provider a resultset listener which provides the data
+	 * @return an EPR to the resultset.
+	 */
+	W3CEndpointReference createResultSet(ResultSetListener provider);
+}
Index: modules/cnr-resultset-service/trunk/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.xml
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.xml	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.xml	(revision 45117)
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
+	xmlns:sec="http://cxf.apache.org/configuration/security" xmlns:wsa="http://cxf.apache.org/ws/addressing"
+	xmlns:p="http://www.springframework.org/schema/p" xmlns:http="http://cxf.apache.org/transports/http/configuration"
+	xmlns:t="http://dnetlib.eu/springbeans/t" xmlns:template="http://dnetlib.eu/springbeans/template"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+                                    http://cxf.apache.org/ws/addressing http://cxf.apache.org/schemas/ws-addr-conf.xsd
+                                    http://cxf.apache.org/configuration/security http://cxf.apache.org/schemas/configuration/security.xsd
+                                    http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd
+                            http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
+                            http://dnetlib.eu/springbeans/template http://dnetlib.eu/springbeans/template.xsd">
+
+	<!-- beans -->
+	<bean id="resultSetCacheManager"
+		class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" />
+	<!-- p:configLocation="classpath:eu/dnetlib/enabling/resultset/ehcache.xml" -->
+
+	<bean id="resultSetRegistryCache" class="eu.dnetlib.miscutils.cache.EhCache">
+		<property name="cache">
+			<bean id="resultSetRegistryCacheCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"
+				p:cacheManager-ref="resultSetCacheManager" p:cacheName="resultSetFactoryCache"
+				p:eternal="false" p:timeToLive="${services.is.resultset.resultSetRegistryCache.timeToIdle}"
+				p:timeToIdle="${services.is.resultset.resultSetRegistryCache.timeToIdle}" />
+		</property>
+	</bean>
+
+	<bean id="resultSetRegistryMaxIdleTimeCache" class="eu.dnetlib.miscutils.cache.EhCache">
+		<property name="cache">
+			<bean id="resultSetRegistryMaxIdleTimeCacheCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"
+				p:cacheManager-ref="resultSetCacheManager" p:cacheName="resultSetFactoryMaxIdleTimeCache"
+				p:eternal="false" p:timeToLive="${services.is.resultset.resultSetRegistryMaxIdleTimeCache.timeToIdle}"
+				p:timeToIdle="${services.is.resultset.resultSetRegistryMaxIdleTimeCache.timeToIdle}" />
+		</property>
+	</bean>
+
+	<!-- backing store for the pushResultSetDao -->
+	<bean id="pushResultSetStoreCache" class="eu.dnetlib.miscutils.cache.EhCache">
+		<property name="cache">
+			<bean id="pushResultSetStoreCacheCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"
+				p:eternal="false" p:timeToLive="${services.is.resultset.push.timeToIdle}" p:timeToIdle="${services.is.resultset.push.timeToIdle}" 
+				p:overflowToDisk="true"
+				p:maxElementsInMemory="${services.is.resultset.push.maxElementsInMemory}" 
+				p:maxElementsOnDisk="${services.is.resultset.push.maxElementsOnDisk}"
+				p:cacheManager-ref="resultSetCacheManager" p:cacheName="pushResultSetStoreCache" />
+		</property>
+	</bean>
+
+	<!-- resultset descriptor store for the pushResultSetDao -->
+	<bean id="pushResultSetDescriptorCache" class="eu.dnetlib.miscutils.cache.EhCache">
+		<property name="cache">
+			<bean id="pushResultSetDescriptorCacheCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"
+				p:eternal="false" p:timeToLive="1800" p:timeToIdle="1800"
+				p:cacheManager-ref="resultSetCacheManager" p:cacheName="pushResultSetDescriptorCache" />
+		</property>
+	</bean>
+
+	<bean id="resultSetDescriptorFactory" class="eu.dnetlib.springutils.beans.factory.PrototypeFactory">
+		<lookup-method name="newInstance" bean="resultSetDescriptorPrototype" />
+	</bean>
+
+	<bean id="resultSetDescriptorPrototype" class="eu.dnetlib.enabling.resultset.push.ResultSetDescriptor"
+		p:rangeLength="100" scope="prototype" />
+
+	<bean id="resultSetRegistry" class="eu.dnetlib.enabling.resultset.ResultSetRegistryImpl"
+		p:cache-ref="resultSetRegistryCache" p:maxIdleTimeCache-ref="resultSetRegistryMaxIdleTimeCache" />
+
+<!--
+  <bean id="resultSetEPRPool" class="eu.dnetlib.enabling.resultset.ResultSetEPRPool"
+   p:resultSetService-ref="resultSetService" />
+-->
+
+	<!-- <bean id="resultSetFactory" class="eu.dnetlib.enabling.resultset.LocalResultSetFactoryImpl" -->
+	<!-- <bean id="resultSetFactory" class="eu.dnetlib.enabling.resultset.EPRPoolingLocalResultSetFactoryImpl" p:pool-ref="resultSetEPRPool" 
+		p:resultSetService-ref="resultSetService" /> -->
+
+  <bean id="resultSetFactory" class="eu.dnetlib.enabling.resultset.LocalResultSetFactoryImpl" 
+		p:resultSetService-ref="resultSetService" /> 
+
+	<bean id="openResultSetFactory"
+		class="eu.dnetlib.enabling.resultset.LocalOpenResultSetFactoryImpl"
+		p:resultSetService-ref="resultSetService" />
+		
+<!--
+	<bean id="openResultSetFactory"
+		class="eu.dnetlib.enabling.resultset.EPRPoolingLocalOpenResultSetFactoryImpl" p:pool-ref="resultSetEPRPool"
+		p:resultSetService-ref="resultSetService" />
+-->
+	<bean id="mappedResultSetFactory" class="eu.dnetlib.enabling.resultset.MappedResultSetFactory"
+		p:serviceResolver-ref="serviceResolver" p:resultSetFactory-ref="resultSetFactory" />
+		
+	<bean id="parallelMappedResultSetFactory" class="eu.dnetlib.enabling.resultset.ParallelMappedResultSetFactory"
+		p:serviceResolver-ref="serviceResolver" p:resultSetFactory-ref="resultSetFactory" />		
+
+	<bean id="xsltResultSetFactory"
+		class="eu.dnetlib.enabling.resultset.XSLTMappedResultSetFactory"
+		p:serviceResolver-ref="serviceResolver" p:resultSetFactory-ref="resultSetFactory" />
+
+	<bean id="countingResultSetFactory" class="eu.dnetlib.enabling.resultset.CountingResultSetFactory"
+		p:serviceResolver-ref="serviceResolver" p:resultSetFactory-ref="resultSetFactory" />
+
+	<bean id="streamingResultSetFactory" class="eu.dnetlib.enabling.resultset.StreamingResultSetFactory"
+		p:resultSetFactory-ref="resultSetFactory" />
+
+	<bean id="cachingResultSetFactory" class="eu.dnetlib.enabling.resultset.CachingResultSetFactory"
+		p:resultSetFactory-ref="resultSetFactory" />
+
+	<bean id="pushResultSetFactory"
+		class="eu.dnetlib.enabling.resultset.push.TransientPushResultSetFactory"
+		p:dao-ref="pushResultSetDao" p:resultSetService-ref="resultSetService" />
+
+	<bean id="iterableResultSetFactory" class="eu.dnetlib.enabling.resultset.IterableResultSetFactory"
+		p:fetchSize="10" p:resultSetFactory-ref="openResultSetFactory"
+		lazy-init="true" />
+
+
+	<bean id="pushResultSetDao"
+		class="eu.dnetlib.enabling.resultset.push.CacheTransientResultSetDaoImpl"
+		p:cache-ref="pushResultSetStoreCache" p:resultSetCache-ref="pushResultSetDescriptorCache" />
+
+	<bean id="customResultSetPropertyDao" class="eu.dnetlib.enabling.resultset.ResultSetPropertyDaoImpl" />
+
+	<bean id="resultSetService" class="eu.dnetlib.enabling.resultset.ResultSetServiceImpl"
+		init-method="start" p:resultsetRegistry-ref="resultSetRegistry"
+		p:pushFactory-ref="pushResultSetFactory" p:endpoint-ref="resultSetServiceEndpoint"
+		p:eprBuilder-ref="jaxwsEndpointReferenceBuilder" p:customPropertyDao-ref="customResultSetPropertyDao" />
+		
+	<!-- endpoints -->
+	<jaxws:endpoint id="resultSetServiceEndpoint"
+		implementor="#resultSetService" implementorClass="eu.dnetlib.enabling.resultset.rmi.ResultSetService"
+		address="/resultSet" />
+
+	<template:instance name="serviceRegistrationManager"
+		t:serviceRegistrationManagerClass="eu.dnetlib.enabling.tools.registration.ValidatingServiceRegistrationManagerImpl"
+		t:name="resultSetServiceRegistrationManager" t:service="resultSetService"
+		t:endpoint="resultSetServiceEndpoint" t:jobScheduler="jobScheduler" />
+
+</beans>
Index: modules/cnr-resultset-service/trunk/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.properties
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.properties	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.properties	(revision 45117)
@@ -0,0 +1,10 @@
+services.is.resultset.resultSetRegistryCache.timeToIdle = 240
+services.is.resultset.resultSetRegistryMaxIdleTimeCache.timeToIdle = 240
+
+# jaxwsEndpointReferenceBuilder | staticResultSetServiceEprBuilder
+services.resultset.eprbuilder.bean = jaxwsEndpointReferenceBuilder
+services.resultset.endpoint.static.address = ${transport.soap.baseAddress}/resultSet
+
+services.is.resultset.push.timeToIdle=36000
+services.is.resultset.push.maxElementsInMemory=500
+services.is.resultset.push.maxElementsOnDisk=5000000
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetServiceImpl.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetServiceImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetServiceImpl.java	(revision 45117)
@@ -0,0 +1,259 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import javax.jws.WebService;
+import javax.xml.ws.Endpoint;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.common.rmi.UnimplementedException;
+import eu.dnetlib.enabling.resultset.push.PushResultSet;
+import eu.dnetlib.enabling.resultset.push.PushResultSetFactory;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
+import eu.dnetlib.enabling.tools.AbstractBaseService;
+import eu.dnetlib.soap.EndpointReferenceBuilder;
+
+/**
+ * This component dispatches the service method calls to stateful datastructure instances and to the singleton core.
+ * 
+ * @author marko
+ * 
+ */
+@WebService(targetNamespace = "http://services.dnetlib.eu/")
+public class ResultSetServiceImpl extends AbstractBaseService implements ResultSetService {
+
+	/**
+	 * logger.
+	 */
+	private static final Log log = LogFactory.getLog(ResultSetServiceImpl.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	/**
+	 * Maps resultset identifiers to resultsets and manages expiration etc.
+	 */
+	private ResultSetRegistry resultsetRegistry;
+
+	/**
+	 * push resultset factory.
+	 */
+	private PushResultSetFactory pushFactory;
+
+	/**
+	 * Service endpoint.
+	 */
+	private Endpoint endpoint;
+
+	/**
+	 * injected epr builder.
+	 */
+	private EndpointReferenceBuilder<Endpoint> eprBuilder;
+
+	/**
+	 * custom resultset properties.
+	 */
+	private ResultSetPropertyDao customPropertyDao;
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#closeRS(java.lang.String)
+	 */
+	@Override
+	public void closeRS(final String rsId) {
+		try {
+			final ResultSet resultSet = getResultSetById(rsId);
+			resultSet.close();
+		} catch (ResultSetException e) {
+			log.warn("should throw checked exception but wasn't declared in cnr-rmi-api", e);
+			throw new IllegalStateException(e);
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#createPullRS(java.lang.String, java.lang.String, int, int, java.lang.String,
+	 *      java.lang.Integer, java.lang.Integer)
+	 */
+	@Override
+	public W3CEndpointReference createPullRS(final String providerAddress,
+			final String bdId,
+			final int initialPageSize,
+			final int expiryTime,
+			final String styleSheet,
+			final Integer keepAliveTime,
+			final Integer total) {
+		throw new UnimplementedException();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#createPullRSEPR(javax.xml.ws.wsaddressing.W3CEndpointReference,
+	 *      java.lang.String, int, int, java.lang.String, java.lang.Integer, java.lang.Integer)
+	 */
+	@Override
+	public W3CEndpointReference createPullRSEPR(final W3CEndpointReference dataProviderEPR,
+			final String bdId,
+			final int initialPageSize,
+			final int expiryTime,
+			final String styleSheet,
+			final Integer keepAliveTime,
+			final Integer total) {
+		throw new UnimplementedException();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#getNumberOfElements(java.lang.String)
+	 */
+	@Override
+	public int getNumberOfElements(final String rsId) throws ResultSetException {
+		final ResultSet resultSet = getResultSetById(rsId); // NOPMD
+		return resultSet.getNumberOfResults();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#getResult(java.lang.String, int, int, java.lang.String)
+	 */
+	@Override
+	public List<String> getResult(final String rsId, final int fromPosition, final int toPosition, final String requestMode) throws ResultSetException {
+		final ResultSet resultSet = getResultSetById(rsId); // NOPMD
+		return resultSet.getResults(fromPosition, toPosition);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#createPushRS(int, int)
+	 */
+	@Override
+	public W3CEndpointReference createPushRS(final int expiryTime, final int keepAliveTime) throws ResultSetException {
+		return pushFactory.createPushResultSet(expiryTime);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#getProperty(java.lang.String, java.lang.String)
+	 */
+	@Override
+	public String getProperty(final String rsId, final String name) throws ResultSetException {
+		final ResultSet resultSet = getResultSetById(rsId); // NOPMD
+
+		if ("rsId".equals(name)) return resultSet.getIdentifier();
+		else if ("total".equals(name)) return Integer.toString(resultSet.getNumberOfResults());
+		else if ("maxExpiryTime".equals(name)) return Integer.toString(resultsetRegistry.getMaxIdleTimeById(rsId));
+		else if ("expiryTime".equals(name)) return Integer.toString(resultsetRegistry.getMaxIdleTimeById(rsId));
+		else if ("keepAliveTime".equals(name)) return Integer.toString(resultsetRegistry.getMaxIdleTimeById(rsId));
+		else if ("classSimpleName".equals(name)) return resultSet.getClass().getSimpleName();
+		// ...
+
+		return customPropertyDao.getProperties(resultSet).get(name);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#getRSStatus(java.lang.String)
+	 */
+	@Override
+	public String getRSStatus(final String rsId) throws ResultSetException {
+		final ResultSet resultSet = getResultSetById(rsId); // NOPMD
+		if (resultSet.isOpen()) return "open";
+		return "closed";
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#populateRS(java.lang.String, java.util.List)
+	 */
+	@Override
+	public String populateRS(final String rsId, final List<String> elements) throws ResultSetException {
+		final ResultSet resultSet = getResultSetById(rsId); // NOPMD
+		if (resultSet instanceof PushResultSet) {
+			((PushResultSet) resultSet).addElements(elements);
+		} else throw new ResultSetException("ResultSet '" + rsId + "' is not a push resultset");
+
+		return "1";
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.common.rmi.BaseService#start()
+	 */
+	@Override
+	public void start() {
+		// TODO Auto-generated method stub
+
+	}
+
+	/**
+	 * obtain the resultset object for a given id.
+	 * 
+	 * @param rsId
+	 *            resultset id
+	 * @return resultset object, never null
+	 * @throws ResultSetException
+	 *             thrown when the id doesn't exist;
+	 */
+	private ResultSet getResultSetById(final String rsId) throws ResultSetException {
+		final ResultSet resultSet = resultsetRegistry.getResultSetById(rsId); // NOPMD
+		if (resultSet == null) throw new ResultSetException("resultset with id '" + rsId + "' doesn't exist");
+		return resultSet;
+	}
+
+	public ResultSetRegistry getResultsetRegistry() {
+		return resultsetRegistry;
+	}
+
+	@Required
+	public void setResultsetRegistry(final ResultSetRegistry resultsetRegistry) {
+		this.resultsetRegistry = resultsetRegistry;
+	}
+
+	public EndpointReferenceBuilder<Endpoint> getEprBuilder() {
+		return eprBuilder;
+	}
+
+	@Required
+	public void setEprBuilder(final EndpointReferenceBuilder<Endpoint> eprBuilder) {
+		this.eprBuilder = eprBuilder;
+	}
+
+	public Endpoint getEndpoint() {
+		return endpoint;
+	}
+
+	@Required
+	public void setEndpoint(final Endpoint endpoint) {
+		this.endpoint = endpoint;
+	}
+
+	public PushResultSetFactory getPushFactory() {
+		return pushFactory;
+	}
+
+	@Required
+	public void setPushFactory(final PushResultSetFactory pushFactory) {
+		this.pushFactory = pushFactory;
+	}
+
+	public ResultSetPropertyDao getCustomPropertyDao() {
+		return customPropertyDao;
+	}
+
+	public void setCustomPropertyDao(final ResultSetPropertyDao customPropertyDao) {
+		this.customPropertyDao = customPropertyDao;
+	}
+
+}
Index: modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest.java	(revision 45117)
@@ -0,0 +1,36 @@
+package eu.dnetlib.enabling.resultset.push;
+
+
+import static org.junit.Assert.*;
+
+import javax.annotation.Resource;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import eu.dnetlib.miscutils.factory.Factory;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration
+public class ResultSetDescriptorFactoryTest {
+
+	@Resource
+	Factory<ResultSetDescriptor> factory;
+
+	@Before
+	public void setUp() throws Exception {
+	}
+
+	@Test
+	public void testFactory() {
+		ResultSetDescriptor desc1 = factory.newInstance();
+		ResultSetDescriptor desc2 = factory.newInstance();
+
+		assertTrue("check different instances", desc1 != desc2);
+		assertEquals("check that it's a spring prototype", 200, desc1.getRangeLength());
+		assertEquals("check that it's a spring prototype", 200, desc2.getRangeLength());
+	}
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/FetchList.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/FetchList.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/FetchList.java	(revision 45117)
@@ -0,0 +1,105 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+
+/**
+ * a LinkedList populated by a given iterable, which provides a fetch window of elements
+ *
+ * @author claudio
+ *
+ * @param <T>
+ *            The FetchList type
+ */
+public class FetchList<T> extends LinkedList<T> {
+
+	/**
+	 *
+	 */
+	private static final long serialVersionUID = 7135272008563693321L;
+
+	/**
+	 * represents the number of elements ready to be pulled out of the list
+	 */
+	private int fetchSize;
+
+	/**
+	 * represents the number of elements already consumed by a poll call
+	 */
+	private int consumedElements;
+
+	/**
+	 * the given itarable used to populate the list
+	 */
+	private Iterator<T> iter;
+
+	/**
+	 * @param iter
+	 * @param fetchSize
+	 */
+	public FetchList(final Iterator<T> iter, final int fetchSize) {
+		super();
+		this.consumedElements = 0;
+		this.fetchSize = fetchSize;
+		this.iter = iter;
+	}
+
+	/**
+	 * used to fill the list
+	 */
+	public synchronized void fill() {
+		for (int i = 0; i < fetchSize; i++) {
+			if (!iter.hasNext()) {
+				break;
+			}
+			this.add(iter.next());
+		}
+	}
+
+	/**
+	 * return the first element and makes the list to be filled in case its size is zero
+	 */
+	@Override
+	public T poll() {
+		if (this.isEmpty()) {
+			fill();
+		}
+
+		if (this.size() > 0) {
+			consumedElements++;
+			return super.poll();
+		}
+		return null;
+	}
+
+	/**
+	 * @return the number of elements already consumed by a "poll"
+	 */
+	public int getConsumedElements() {
+		return consumedElements;
+	}
+
+	/**
+	 * @return the actual number of elements of the list
+	 */
+	public int getTotalElements() {
+		return consumedElements + this.size();
+	}
+
+	/**
+	 * to provide an actual size, fills the list if there are elements to fill it
+	 */
+	@Override
+	public int size() {
+		if (this.isEmpty() && iter.hasNext()) {
+			fill();
+		}
+		return super.size();
+	}
+
+	@Override
+	public boolean isEmpty() {
+		return super.size() == 0;
+	}
+
+}
Index: modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/push/AbstractTransientPushResultSetDaoTest.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/push/AbstractTransientPushResultSetDaoTest.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/push/AbstractTransientPushResultSetDaoTest.java	(revision 45117)
@@ -0,0 +1,223 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import static org.junit.Assert.*; // NOPMD
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.miscutils.cache.Cache;
+
+/**
+ * subclass this unit test class and provide a concrete transient push resultset dao implementation.
+ *
+ * @author marko
+ *
+ */
+@Ignore
+public abstract class AbstractTransientPushResultSetDaoTest {
+	/**
+	 * logger.
+	 */
+	private static final Log log = LogFactory.getLog(AbstractTransientPushResultSetDaoTest.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	/**
+	 * test first element.
+	 */
+	private static final String TWO = "two";
+
+	/**
+	 * test second element.
+	 */
+	private static final String ONE = "one";
+
+	/**
+	 * some key.
+	 */
+	private static final String RS_ID = "123";
+
+	/**
+	 * instance under test.
+	 */
+	private TransientPushResultSetDao dao;
+
+	/**
+	 * prepare the instance under test.
+	 *
+	 */
+	@Before
+	public void setUp() {
+		setDao(newInstance());
+	}
+
+	/**
+	 * specific unit tests will override this method and provide a concrete instance to test.
+	 *
+	 * @return new transient push resultset dao instance
+	 */
+	protected abstract TransientPushResultSetDao newInstance();
+
+	/**
+	 * test add elements.
+	 */
+	@Test
+	public void testAddElements() {
+		final List<String> freshGet = getDao().getElements(RS_ID, 1, 0);
+		assertNotNull("fresh get", freshGet);
+		assertEquals("fresh get", 0, freshGet.size());
+
+		final List<String> list = new ArrayList<String>();
+		list.add(ONE);
+
+		getDao().addElements(RS_ID, list);
+
+		final List<String> firstGet = getDao().getElements(RS_ID, 1, 1);
+		assertEquals("first get", 1, firstGet.size());
+		assertEquals("first get", ONE, firstGet.get(0));
+
+		final List<String> listAppend = new ArrayList<String>();
+		listAppend.add(TWO);
+
+		getDao().addElements(RS_ID, listAppend);
+
+		final List<String> secondGet = getDao().getElements(RS_ID, 1, 2);
+		assertEquals("second get", 2, secondGet.size());
+		assertEquals("second get", ONE, secondGet.get(0));
+		assertEquals("second get", TWO, secondGet.get(1));
+
+		final List<String> listBig = new ArrayList<String>();
+		for (int i = 0; i < 90; i++)
+			listBig.add(Integer.toString(i));
+
+		getDao().addElements(RS_ID, listBig);
+
+		final List<String> thirdGet = getDao().getElements(RS_ID, 3, 90);
+		assertEquals("third get", 88, thirdGet.size());
+		assertEquals("third get", "0", thirdGet.get(0));
+		assertEquals("third get", "1", thirdGet.get(1));
+	}
+
+	/**
+	 * check get elements.
+	 */
+	@Test
+	public void testGetElements() {
+		final List<String> list = new ArrayList<String>();
+		list.add(ONE);
+
+		getDao().addElements(RS_ID, list);
+
+		final List<String> res = getDao().getElements(RS_ID, 1, 1);
+		assertEquals("check size", 1, res.size());
+		assertEquals("check element", ONE, res.get(0));
+	}
+
+	/**
+	 * introduced for reproducing of #904. Thanks to Jochen for this one.
+	 */
+	@Test(expected = IllegalArgumentException.class)
+	public void testAddElementsDifferentSize() {
+		List<Integer> sizes = Lists.newArrayList(100, 200, 300, 99);
+		int run = 0;
+		int total = 0;
+
+		List<String> records = new LinkedList<String>();
+		for (int size : sizes) {
+			for (int i = 0; i < size; i++)
+				records.add("bla-" + run + "-" + i);
+
+			dao.addElements(RS_ID, records);
+			records.clear();
+
+			total += size;
+			run++;
+		}
+
+		assertEquals("check size", total, dao.getSize(RS_ID));
+	}
+
+	/**
+	 * introduced for reproducing of #904. with correct size (limited by 100)
+	 */
+	@Test
+	public void testAddElementsDifferentSizeCorrectSize() {
+		List<Integer> sizes = Lists.newArrayList(51, 51, 51, 51);
+
+		int total = 0;
+		int run = 0;
+		String lastName = null;
+
+		List<String> records = new LinkedList<String>();
+		for (int size : sizes) {
+			for (int i = 0; i < size; i++) {
+				lastName = "bla-" + run + "-" + i;
+				records.add(lastName);
+			}
+
+			dao.addElements(RS_ID, records);
+			records.clear();
+
+			total += size;
+			run++;
+		}
+
+		inspect();
+
+		assertEquals("check size", total, dao.getSize(RS_ID));
+		assertEquals("check last", lastName, dao.getElements(RS_ID, total, total).get(0));
+
+		assertEquals("check first page", "bla-0-11", dao.getElements(RS_ID, 12, 12).get(0));
+		assertEquals("check last page", "bla-1-11", dao.getElements(RS_ID, 51 + 12, 51 + 12).get(0));
+
+		assertEquals("check range", 10, dao.getElements(RS_ID, 1, 10).size());
+		assertEquals("check range", 10, dao.getElements(RS_ID, 51 + 1, 51 + 10).size());
+		assertEquals("check range", 51, dao.getElements(RS_ID, 1, 51).size());
+		assertEquals("check range", 52, dao.getElements(RS_ID, 1, 52).size());
+		assertEquals("check range", 51, dao.getElements(RS_ID, 2, 52).size());
+
+		assertEquals("check range", 100, dao.getElements(RS_ID, 1, 100).size());
+		assertEquals("check range", 99, dao.getElements(RS_ID, 2, 100).size());
+		assertEquals("check range", 100, dao.getElements(RS_ID, 2, 101).size());
+
+		assertEquals("check range", 200, dao.getElements(RS_ID, 2, 201).size());
+	}
+
+	private void inspect() {
+		CacheTransientResultSetDaoImpl dao = (CacheTransientResultSetDaoImpl) this.dao;
+		ResultSetDescriptor desc = dao.getResultSetCache().get(RS_ID);
+		Cache<String, List<String>> cache = dao.getCache();
+
+		log.debug("----------------");
+		log.debug("ranges: " + desc.getRanges());
+		log.debug("last range index: " + desc.getLastRange());
+		for (int i = 0; i < desc.getRanges(); i++) {
+			final List<String> range = cache.get(RS_ID + "-" + i);
+			log.debug("range: " + i + " has " + range.size() + " elements");
+			log.debug(" " + range);
+		}
+
+		log.debug("----------------");
+	}
+
+	@Test
+	public void testSizeOfEmpty() {
+		assertEquals("empty size", 0, dao.getSize(RS_ID));
+	}
+
+	public TransientPushResultSetDao getDao() {
+		return dao;
+	}
+
+	public void setDao(final TransientPushResultSetDao dao) {
+		this.dao = dao;
+	}
+
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/JaxbResultsetListenerWrapper.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/JaxbResultsetListenerWrapper.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/JaxbResultsetListenerWrapper.java	(revision 45117)
@@ -0,0 +1,68 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import javax.xml.bind.JAXBException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.miscutils.collections.MappedCollection;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+import eu.dnetlib.miscutils.jaxb.JaxbFactory;
+
+/**
+ * Given a jaxb factory for a given type, wraps TypedResultsetListeners to ResultSetListeners, serializing objects
+ * according to the jaxb factory.
+ * 
+ * @author marko
+ * 
+ * @param <T>
+ */
+public class JaxbResultsetListenerWrapper<T> {
+	private static final Log log = LogFactory.getLog(JaxbResultsetListenerWrapper.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	private JaxbFactory<T> factory;
+
+	/**
+	 * Returns a listener which serializes each item according to the jaxb factory.
+	 * 
+	 * @param listener
+	 *            listener which returns T
+	 * @return listener which returns strings
+	 */
+	public ResultSetListener wrap(final TypedResultSetListener<T> listener) {
+		return new ResultSetListener() {
+
+			@Override
+			public List<String> getResult(final int fromPosition, final int toPosition) {
+				return Lists.newArrayList(new MappedCollection<String, T>(listener.getResult(fromPosition, toPosition), new UnaryFunction<String, T>() {
+					@Override
+					public String evaluate(final T value) {
+						try {
+							return factory.serialize(value);
+						} catch (final JAXBException e) {
+							log.warn("cannot serialize", e);
+							throw new RuntimeException(e);
+						}
+					}
+				}));
+			}
+
+			@Override
+			public int getSize() {
+				return listener.getSize();
+			}
+		};
+	}
+
+	public JaxbFactory<T> getFactory() {
+		return factory;
+	}
+
+	public void setFactory(final JaxbFactory<T> factory) {
+		this.factory = factory;
+	}
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetEPRPool.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetEPRPool.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetEPRPool.java	(revision 45117)
@@ -0,0 +1,137 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import javax.annotation.PostConstruct;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.enabling.tools.UniqueIdentifierGenerator;
+import eu.dnetlib.enabling.tools.UniqueIdentifierGeneratorImpl;
+
+public class ResultSetEPRPool {
+	private static final Log log = LogFactory.getLog(ResultSetEPRPool.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	static class PreparedResultSet {
+		private String rsId;
+		private W3CEndpointReference epr;
+
+		public PreparedResultSet(final String rsId, final W3CEndpointReference epr) {
+			super();
+			this.rsId = rsId;
+			this.epr = epr;
+		}
+
+		public String getRsId() {
+			return rsId;
+		}
+
+		public void setRsId(final String rsId) {
+			this.rsId = rsId;
+		}
+
+		public W3CEndpointReference getEpr() {
+			return epr;
+		}
+
+		public void setEpr(final W3CEndpointReference epr) {
+			this.epr = epr;
+		}
+	}
+
+	class PoolFiller implements Runnable {
+
+		@Override
+		public void run() {
+			while (true)
+				try {
+					final PreparedResultSet resultSet = prepareResultSet();
+					pool.put(resultSet);
+				} catch (final InterruptedException e) {
+					// eat this exception
+					log.debug("cannot add resultset to pool", e);
+				}
+		}
+
+		private PreparedResultSet prepareResultSet() {
+			final String rsId = idGenerator.generateIdentifier();
+			return new PreparedResultSet(rsId, createEPR(rsId));
+		}
+
+		private W3CEndpointReference createEPR(final String rsId) {
+			return getResultSetService().getEprBuilder().getEndpointReference(getResultSetService().getEndpoint(), rsId);
+		}
+	}
+
+	/**
+	 * resultset service.
+	 */
+	private ResultSetServiceImpl resultSetService;
+
+	private int capacity = 1000;
+	private int fillerThreads = 10;
+	private final BlockingQueue<PreparedResultSet> pool = new LinkedBlockingQueue<PreparedResultSet>(capacity);
+
+	/**
+	 * identifier generator.
+	 */
+	private UniqueIdentifierGenerator idGenerator = new UniqueIdentifierGeneratorImpl("rs-");
+
+	@PostConstruct
+	public void init() {
+		log.info("-------<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>> Starting fill threads");
+		for (int i = 0; i < fillerThreads; i++)
+			startFillter();
+	}
+
+	protected void startFillter() {
+		final Thread filler = new Thread(new PoolFiller());
+		filler.setDaemon(true);
+		filler.start();
+	}
+
+	public W3CEndpointReference registerResultSet(final ResultSet resultSet) {
+		final PreparedResultSet prepared = nextPreparedResultSet();
+		if (prepared == null) {
+			log.info("EPR cache is empty, creating EPR in caller thread");
+			return getResultSetService().getEprBuilder().getEndpointReference(getResultSetService().getEndpoint(), idGenerator.generateIdentifier());
+		}
+
+		getResultSetService().getResultsetRegistry().addResultSet(resultSet, prepared.getRsId());
+		return prepared.getEpr();
+	}
+
+	private PreparedResultSet nextPreparedResultSet() {
+		log.info(">>>> fetching a prepared resultset from the pool");
+		return pool.poll();
+	}
+
+	public int getCapacity() {
+		return capacity;
+	}
+
+	public void setCapacity(int capacity) {
+		this.capacity = capacity;
+	}
+
+	public UniqueIdentifierGenerator getIdGenerator() {
+		return idGenerator;
+	}
+
+	public void setIdGenerator(UniqueIdentifierGenerator idGenerator) {
+		this.idGenerator = idGenerator;
+	}
+
+	public ResultSetServiceImpl getResultSetService() {
+		return resultSetService;
+	}
+
+	@Required
+	public void setResultSetService(ResultSetServiceImpl resultSetService) {
+		this.resultSetService = resultSetService;
+	}
+}
Index: modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImplTest.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImplTest.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImplTest.java	(revision 45117)
@@ -0,0 +1,184 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.matches;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import net.sf.ehcache.Cache;
+import net.sf.ehcache.CacheManager;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+import eu.dnetlib.miscutils.cache.EhCache;
+
+/**
+ * Test ResultSetRegistryImpl.
+ * 
+ * @author marko
+ * 
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class ResultSetRegistryImplTest {
+
+	/**
+	 * max in memory elements.
+	 */
+	private static final int MAX_IN_MEM = 100;
+
+	/**
+	 * default time.
+	 */
+	private static final int DEFAULT_TTI = 1000;
+
+	/**
+	 * default time to live.
+	 */
+	private static final int DEFAULT_TTL = 1000;
+
+	/**
+	 * class under test.
+	 */
+	private transient ResultSetRegistryImpl registry;
+
+	/**
+	 * mock of a resultset object.
+	 */
+	@Mock
+	private transient ResultSet resultSet;
+
+	/**
+	 * ehcache manager.
+	 */
+	private final transient CacheManager cacheManager = CacheManager.create();
+
+	/**
+	 * Set up basic mocks.
+	 */
+	@Before
+	public void setUp() {
+		final Cache ehCache = new net.sf.ehcache.Cache("testCache", MAX_IN_MEM, false, false, DEFAULT_TTL, DEFAULT_TTI);
+		cacheManager.addCache(ehCache);
+
+		final Cache mtEhCache = new net.sf.ehcache.Cache("testMTCache", MAX_IN_MEM, false, false, DEFAULT_TTL, DEFAULT_TTI);
+		cacheManager.addCache(mtEhCache);
+
+		final EhCache<String, ResultSet> cache = new EhCache<String, ResultSet>(ehCache);
+		cache.setCache(ehCache);
+
+		final EhCache<String, Integer> mtCache = new EhCache<String, Integer>(mtEhCache);
+		mtCache.setCache(mtEhCache);
+
+		registry = new ResultSetRegistryImpl();
+		registry.setCache(cache);
+		registry.setMaxIdleTimeCache(mtCache);
+
+		when(resultSet.getIdentifier()).thenReturn("123456");
+		when(resultSet.isOpen()).thenReturn(true);
+	}
+
+	/**
+	 * remove ehcache from ehcachemanager.
+	 */
+	@After
+	public void tearDown() {
+		cacheManager.removeAllCaches();
+	}
+
+	/**
+	 * Test that registered resultsets are really registered.
+	 */
+	@Test
+	public void testAddResultSet() {
+
+		final String rsId = resultSet.getIdentifier();
+		assertNotNull("the resultset should not be null", rsId);
+
+		registry.addResultSet(resultSet);
+		verify(resultSet).setIdentifier(matches("rs-" + registry.getIdGenerator().getRegEx()));
+
+		final ResultSet res = registry.getResultSetById(rsId); // NOPMD
+		assertNotNull("the resultset is not found", res);
+		assertEquals("the resultsets don't have the same id", rsId, res.getIdentifier());
+		assertEquals("the resultsets are not the same instance", resultSet, res);
+	}
+
+	/**
+	 * Test that registered resultsets are really registered.
+	 */
+	@Test
+	public void testAddResultSetWithId() {
+		resultSet = mock(ResultSet.class);
+		when(resultSet.getIdentifier()).thenReturn("123");
+
+		final String rsId = resultSet.getIdentifier();
+
+		registry.addResultSet(resultSet, rsId);
+		verify(resultSet).setIdentifier(rsId);
+
+		final ResultSet res = registry.getResultSetById(rsId); // NOPMD
+		assertNotNull("the resultset is not found", res);
+		assertEquals("the resultsets don't have the same id", rsId, res.getIdentifier());
+		assertEquals("the resultsets are not the same instance", resultSet, res);
+	}
+
+	/**
+	 * try to obtain a inexistent resultset.
+	 */
+	@Test
+	public void testInexistentResultSet() {
+		final String rsId = resultSet.getIdentifier();
+		assertNull("inexisten resultset returns null", registry.getResultSetById(rsId));
+	}
+
+	/**
+	 * test closing of resultset and its pruning from the registry.
+	 */
+	@Test
+	public void testResultSetClose() {
+		final String rsId = resultSet.getIdentifier();
+
+		assertTrue("check if resultset is open", resultSet.isOpen());
+
+		registry.addResultSet(resultSet);
+		verify(resultSet).addObserver(registry);
+
+		// simulate a resultset close on the mock
+		when(resultSet.isOpen()).thenReturn(false);
+		registry.update(resultSet, null);
+
+		assertFalse("check if resultset is closed", resultSet.isOpen());
+		assertNull("check if the object is pruned from the registry", registry.getResultSetById(rsId));
+	}
+
+	/**
+	 * same as testResultSetClose() but with a real observer/observable mechanism, i.e. without resultset mock class.
+	 * 
+	 */
+	@Test
+	public void testWithRealObservable() {
+		final LocalResultSetImpl rset = new LocalResultSetImpl(null);
+		rset.setIdentifier("123456");
+		resultSet = rset;
+
+		final String rsId = resultSet.getIdentifier();
+
+		assertFalse("check if resultset is not destroyed", resultSet.isDestroyed());
+
+		registry.addResultSet(resultSet);
+		resultSet.destroy();
+
+		assertTrue("check if resultset is destroyed", resultSet.isDestroyed());
+		assertNull("check if the object is pruned from the registry", registry.getResultSetById(rsId));
+	}
+
+}
Index: modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactoryTest.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactoryTest.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactoryTest.java	(revision 45117)
@@ -0,0 +1,139 @@
+package eu.dnetlib.enabling.resultset; // NOPMD
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.List;
+
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
+import eu.dnetlib.enabling.tools.ServiceResolver;
+
+/**
+ * test xslt resultset.
+ *
+ * @author marko
+ *
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class XSLTMappedResultSetFactoryTest {
+
+	/**
+	 * instance under test.
+	 */
+	private transient XSLTMappedResultSetFactory factory;
+
+	/**
+	 * resultset factory mock.
+	 */
+	@Mock
+	private transient ResultSetFactory resultSetFactory;
+
+	/**
+	 * service resolver.
+	 */
+	@Mock
+	private transient ServiceResolver serviceResolver;
+
+	/**
+	 * resultset service mock.
+	 */
+	@Mock
+	private transient ResultSetService resultSetService;
+	
+	/**
+	 * underlying resultSet mock
+	 */
+	@Mock
+	private transient ResultSet resultSet;
+
+	/**
+	 * Common setup.
+	 *
+	 */
+	@Before
+	public void setUp() {
+		factory = new XSLTMappedResultSetFactory();
+		factory.setResultSetFactory(resultSetFactory);
+		factory.setServiceResolver(serviceResolver);
+	}
+
+	/**
+	 * test invalid xslt.
+	 *
+	 * @throws TransformerConfigurationException
+	 *             could happen
+	 */
+	@Test(expected = IllegalStateException.class)
+	public void testInvalidXslt() throws TransformerConfigurationException {
+		factory.createMappedResultSet(null, "<bla/>");
+	}
+
+	/**
+	 * test xslt.
+	 *
+	 * @throws TransformerConfigurationException
+	 *             could happen
+	 * @throws IOException
+	 *             could happen
+	 * @throws ResultSetException mock
+	 */
+	@Test
+	public void testXslt() throws TransformerConfigurationException, IOException, ResultSetException {
+		when(serviceResolver.getService(eq(ResultSetService.class), (W3CEndpointReference) anyObject())).thenReturn(resultSetService);
+		when(serviceResolver.getResourceIdentifier((W3CEndpointReference) anyObject())).thenReturn("123");
+
+		when(resultSetService.getNumberOfElements(anyString())).thenReturn(1);
+		when(resultSetService.getResult("123", 1, 1, "waiting")).thenReturn(Lists.newArrayList("<first>something</first>"));
+		when(resultSetService.getRSStatus("123")).thenReturn("closed");
+		
+		when(resultSet.isOpen()).thenReturn(true);
+		
+		final StringWriter xsltSource = new StringWriter();
+		IOUtils.copy(getClass().getResourceAsStream("test.xsl"), xsltSource);
+		factory.createMappedResultSet(null, xsltSource.toString());
+
+		verify(resultSetFactory, times(1)).createResultSet(argThat(new ArgumentMatcher<ResultSetListener>() {
+
+			@Override
+			public boolean matches(final Object argument) {
+				final MappedResultSet listener = (MappedResultSet) argument;
+				listener.setResultSet(resultSet);
+				final List<String> res = listener.getResult(1, 1);
+
+				assertNotNull("null result", res);
+				assertFalse("empty result", res.isEmpty());
+
+				assertNotNull("null element", res.get(0));
+
+				assertTrue("transformed correctly", res.get(0).contains("<second>something</second>"));
+
+				return true;
+			}
+		}));
+	}
+
+}
Index: modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/StreamingResultSetListenerTest.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/StreamingResultSetListenerTest.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/StreamingResultSetListenerTest.java	(revision 45117)
@@ -0,0 +1,62 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.*;
+
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+public class StreamingResultSetListenerTest {
+
+	private StreamingResultSetListener listener;
+	private List<String> data;
+
+	@Before
+	public void setUp() throws Exception {
+		data = Lists.newArrayList("uno", "due", "tre", "quattro");
+		listener = new StreamingResultSetListener(data.iterator(), data.size());
+	}
+
+	@Test
+	public void testGetResult() {
+		assertEquals(data.size(), listener.getSize());
+
+		final List<String> res = listener.getResult(1, 2);
+		assertEquals(2, res.size());
+		assertEquals("uno", res.get(0));
+		assertEquals("due", res.get(1));
+	}
+
+	@Test
+	public void testGetResult2() {
+		listener.getResult(1, 2);
+		final List<String> res = listener.getResult(3, 4);
+		assertEquals(2, res.size());
+		assertEquals("tre", res.get(0));
+		assertEquals("quattro", res.get(1));
+	}
+
+	@Test
+	public void testGetResult_retry() {
+		listener.getResult(1, 2);
+		final List<String> res = listener.getResult(1, 2);
+		assertEquals(2, res.size());
+		assertEquals("uno", res.get(0));
+		assertEquals("due", res.get(1));
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testGetResult_random() {
+		listener.getResult(1, 2);
+		listener.getResult(2, 3);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testGetResult_skip() {
+		listener.getResult(1, 2);
+		listener.getResult(4, 4);
+	}
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSetFactory.java	(revision 45117)
@@ -0,0 +1,49 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+public class ParallelMappedResultSetFactory extends MappedResultSetFactory {
+
+	private ExecutorService executor;
+
+	private static final int QUEUE_SIZE = 40;
+
+	private int queueSize = QUEUE_SIZE;
+
+	private int cpus = 0;
+
+	public ParallelMappedResultSetFactory() {
+		super();
+
+		if (cpus == 0)
+			cpus = getNumberOfCPUs();
+		executor = new ThreadPoolExecutor(cpus, cpus, 5, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(queueSize),
+				new ThreadPoolExecutor.CallerRunsPolicy());
+	}
+
+	@Override
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final UnaryFunction<String, String> mapper) {
+		return getResultSetFactory().createResultSet(new ParallelMappedResultSet(source, mapper, getServiceResolver(), executor));
+	}
+
+	private int getNumberOfCPUs() {
+		return Runtime.getRuntime().availableProcessors();
+	}
+
+	public int getCpus() {
+		return cpus;
+	}
+
+	public void setCpus(int cpus) {
+		if(cpus > 0)
+			this.cpus = cpus;
+	}
+
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSet.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSet.java	(revision 45117)
@@ -0,0 +1,60 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.enabling.tools.ServiceResolver;
+import eu.dnetlib.miscutils.functional.IdentityFunction;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+/**
+ * A resultset record counter.
+ * 
+ * @author claudio
+ * 
+ */
+public class CountingResultSet extends MappedResultSet {
+
+	/**
+	 * counter.
+	 */
+	private int count;
+
+
+	/**
+	 * @param epr
+	 * @param serviceResolver
+	 */
+	public CountingResultSet(final W3CEndpointReference epr, final ServiceResolver serviceResolver) {
+		this(epr, new IdentityFunction<String>(), serviceResolver);
+	}
+
+	/**
+	 * @param epr
+	 * @param mapper
+	 * @param serviceResolver
+	 */
+	public CountingResultSet(final W3CEndpointReference epr, final UnaryFunction<String, String> mapper, final ServiceResolver serviceResolver) {
+		super(epr, mapper, serviceResolver);
+		count = 0;
+	}
+
+	/**
+	 * method sets the counter to the higher allowed value of toPosition.
+	 */
+	@Override
+	public List<String> getResult(int fromPosition, int toPosition) {
+
+		if (toPosition > count)
+			count = toPosition;
+		if (toPosition > super.getSize())
+			count = super.getSize();
+
+		return super.getResult(fromPosition, toPosition);
+	}
+
+	public int getCount() {
+		return count;
+	}
+}

Property changes on: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSet.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetListener.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetListener.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetListener.java	(revision 45117)
@@ -0,0 +1,61 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
+import eu.dnetlib.enabling.tools.ServiceResolver;
+
+public class CachingResultSetListener implements ResultSetListener {
+	private static final Log log = LogFactory.getLog(CachingResultSetListener.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	
+	private ResultSetService service;
+	private String rsId;
+
+	private ArrayList<String> storage = new ArrayList<String>();
+
+	public CachingResultSetListener(W3CEndpointReference epr, ServiceResolver serviceResolver) {
+		this.service = serviceResolver.getService(ResultSetService.class, epr);
+		this.rsId = serviceResolver.getResourceIdentifier(epr);
+	}
+
+	@Override
+	public List<String> getResult(int fromPosition, int toPosition) {
+		if (storage.get(fromPosition) != null)
+			return cached(fromPosition, toPosition);
+		try {
+			List<String> data = service.getResult(rsId, fromPosition, toPosition, "waiting");
+			cache(data, fromPosition, toPosition);
+			return data;
+		} catch (ResultSetException e) {
+			throw new IllegalStateException(e);
+		}
+	}
+
+	private void cache(List<String> data, int fromPosition, int toPosition) {
+		for(String value : data)
+			storage.set(fromPosition++, value);
+	}
+
+	private List<String> cached(int fromPosition, int toPosition) {
+		log.info("found cached page " + fromPosition + ", " + toPosition);
+		return storage.subList(fromPosition-1, toPosition);
+	}
+
+	@Override
+	public int getSize() {
+		try {
+			return service.getNumberOfElements(rsId);
+		} catch (ResultSetException e) {
+			throw new IllegalStateException(e);
+		}
+	}
+
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetFactory.java	(revision 45117)
@@ -0,0 +1,32 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+public class StreamingResultSetFactory {
+	/**
+	 * underlying resultset factory, which exposes local resultsets to the world.
+	 */
+	private ResultSetFactory resultSetFactory;
+
+	/**
+	 * @param items
+	 * @param size the size of the iterable
+	 * @return
+	 */
+	public W3CEndpointReference createStreamingResultSet(final Iterable<String> items, int size) {
+		return resultSetFactory.createResultSet(new StreamingResultSetListener(items.iterator(), size));
+	}
+
+	
+	public ResultSetFactory getResultSetFactory() {
+		return resultSetFactory;
+	}
+
+	@Required
+	public void setResultSetFactory(ResultSetFactory resultSetFactory) {
+		this.resultSetFactory = resultSetFactory;
+	}
+
+}
Index: modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/IterableResultSetTest.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/IterableResultSetTest.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/IterableResultSetTest.java	(revision 45117)
@@ -0,0 +1,150 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+/**
+ * tests the IterableResult class
+ * 
+ * @author claudio
+ *
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class IterableResultSetTest {
+
+	/**
+	 * number of total elements 
+	 */
+	private static int NUM_ELEM = 100;
+	
+	/**
+	 * number of elements available to fetch
+	 */
+	private static int FETCH_SIZE = 10;
+	
+	@Mock
+	private ResultSet mockResultSet;
+	
+	/**
+	 * a list used to compare elements.
+	 */
+	private List<String> list;
+	
+	/**
+	 * Iterator associated with the test list.
+	 */
+	private Iterator<String> iter;
+	
+	/**
+	 * Object to test.
+	 */
+	private IterableResultSet iterResultSet;
+
+	@Before
+	public void setUp() {
+		list = new ArrayList<String>();
+		for (int i=0; i< NUM_ELEM; i++)
+			list.add("XXXXX " + i);
+				
+		iter = list.iterator();
+		when(mockResultSet.isOpen()).thenReturn(iter.hasNext());
+		
+		iterResultSet = new IterableResultSet(list, FETCH_SIZE);
+		iterResultSet.setResultSet(mockResultSet);
+	}
+	
+	@Test
+	public void testIterableResultSet() {
+		assertNotNull(iterResultSet);
+		assertTrue(iterResultSet.getSize() > 0);
+	}
+
+	@Test(expected=RuntimeException.class)
+	public void testGetResult_fail_1() {
+		iterResultSet.getResult(0, 5);
+	}
+
+	@Test(expected=RuntimeException.class)
+	public void testGetResult_fail_2() {
+		iterResultSet.getResult(1, 5);
+		iterResultSet.getResult(1, 5);
+	}
+	
+	@Test(expected=RuntimeException.class)
+	public void testGetResult_fail_3() {
+		iterResultSet.getResult(1, 5);
+		iterResultSet.getResult(6, 5);
+	}
+	
+	@Test(expected=RuntimeException.class)
+	public void testGetResult_fail_4() {
+		iterResultSet.getResult(1, 5);
+		iterResultSet.getResult(7, 10);
+	}
+	
+	@Test
+	public void testGetResult_success_1() {
+		List<String> result = iterResultSet.getResult(1, NUM_ELEM);
+		for (int i=0; i<NUM_ELEM; i++) {
+			assertEquals(list.get(i), result.get(i));
+		}
+	}
+	
+	@Test
+	public void testGetResult_success_2() {
+		List<String> result = iterResultSet.getResult(1, NUM_ELEM);
+		
+		for (int i=0; i<NUM_ELEM; i++) {
+			assertEquals(list.get(i), result.get(i));
+			iter.next();
+		}
+		verify(mockResultSet).close();
+	}
+
+	@Test
+	public void testGetResult_success_3() {
+		for (int i = 1; i < NUM_ELEM; i+= FETCH_SIZE)
+			iterResultSet.getResult(i, i + FETCH_SIZE-1);
+		verify(mockResultSet, times(1)).close();
+	}
+	
+	@Test
+	public void testGetResult_success_4() {
+		iterResultSet.getResult(1, NUM_ELEM + 1);
+		verify(mockResultSet, times(1)).close();
+	}
+	
+	@Test
+	public void testGetResultSet_success_1() {
+		assertNotNull(iterResultSet.getResultSet());
+	}
+
+	@Test
+	public void testGetSize_fail_1() {
+		iterResultSet.getResult(1, 8);
+		assertNotSame(7, iterResultSet.getSize());
+		assertNotSame(9, iterResultSet.getSize());
+	}
+	
+	@Test
+	public void testGetSize_success_1() {
+		iterResultSet.getResult(1, 8);
+		assertEquals(FETCH_SIZE, iterResultSet.getSize());
+	}
+
+}
Index: modules/cnr-resultset-service/trunk/src/test/resources/eu/dnetlib/enabling/resultset/test.xsl
===================================================================
--- modules/cnr-resultset-service/trunk/src/test/resources/eu/dnetlib/enabling/resultset/test.xsl	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/test/resources/eu/dnetlib/enabling/resultset/test.xsl	(revision 45117)
@@ -0,0 +1,6 @@
+<xsl:stylesheet version="1.0"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+	<xsl:template match="first">
+		<second><xsl:value-of select="."/></second>
+	</xsl:template>
+</xsl:stylesheet>
\ No newline at end of file
Index: modules/cnr-resultset-service/trunk/src/test/resources/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest-context.xml
===================================================================
--- modules/cnr-resultset-service/trunk/src/test/resources/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest-context.xml	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/test/resources/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest-context.xml	(revision 45117)
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
+	xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
+
+	<bean id="resultSetDescriptorPrototype" class="eu.dnetlib.enabling.resultset.push.ResultSetDescriptor"
+		p:rangeLength="200" scope="prototype" />
+
+	<bean id="resultSetDescriptorFactory" class="eu.dnetlib.springutils.beans.factory.PrototypeFactory">
+		<lookup-method name="newInstance" bean="resultSetDescriptorPrototype" />
+	</bean>
+</beans>
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/LocalOpenResultSetFactoryImpl.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/LocalOpenResultSetFactoryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/LocalOpenResultSetFactoryImpl.java	(revision 45117)
@@ -0,0 +1,23 @@
+package eu.dnetlib.enabling.resultset;
+
+/**
+ * Creates an "open" (unbounded, unfreezed) local resultset.
+ * 
+ * @author marko
+ *
+ */
+public class LocalOpenResultSetFactoryImpl extends LocalResultSetFactoryImpl {
+
+	/** 
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.LocalResultSetFactoryImpl#createInstance(eu.dnetlib.enabling.resultset.ResultSetListener)
+	 */
+	@Override
+	protected LocalResultSetImpl createInstance(final ResultSetListener provider) {
+		final LocalResultSetImpl instance = super.createInstance(provider);
+		instance.setOpen(true);
+		return instance;
+	}
+
+
+}
Index: modules/cnr-resultset-service/trunk/deploy.info
===================================================================
--- modules/cnr-resultset-service/trunk/deploy.info	(nonexistent)
+++ modules/cnr-resultset-service/trunk/deploy.info	(revision 45117)
@@ -0,0 +1 @@
+{"type_source": "SVN", "goal": "package -U -T 4C source:jar", "url": "http://svn-public.driver.research-infrastructures.eu/driver/dnet40/modules/cnr-resultset-service/trunk/", "deploy_repository": "dnet4-snapshots", "version": "4", "mail": "sandro.labruzzo@isti.cnr.it,michele.artini@isti.cnr.it, claudio.atzori@isti.cnr.it, alessia.bardi@isti.cnr.it", "deploy_repository_url": "http://maven.research-infrastructures.eu/nexus/content/repositories/dnet4-snapshots", "name": "cnr-resultset-service"}
\ No newline at end of file
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactory.java	(revision 45117)
@@ -0,0 +1,75 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.Map;
+import java.util.UUID;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.core.io.Resource;
+
+import eu.dnetlib.miscutils.functional.xml.ApplyXslt;
+
+/**
+ * Create a mapped resultset using a given XSLT.
+ * 
+ * @author marko
+ * 
+ */
+public class XSLTMappedResultSetFactory extends MappedResultSetFactory {
+
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final String xslt) {
+		return createMappedResultSet(source, new ApplyXslt(xslt));
+	}
+
+	/**
+	 * Create a mapped resultset using a given XSLT.
+	 * 
+	 * @param source
+	 *            source
+	 * @param xslt
+	 *            XSLT source
+	 * @return epr of mapped resultset
+	 * @throws TransformerConfigurationException
+	 *             could happen
+	 */
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final String xslt, final String name)
+			throws TransformerConfigurationException {
+		return createMappedResultSet(source, new ApplyXslt(xslt, name));
+	}
+
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final Resource xslt) {
+		return createMappedResultSet(source, new ApplyXslt(xslt));
+	}
+
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final Source xslt) {
+		return createMappedResultSet(source, new ApplyXslt(xslt));
+	}
+	
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final Resource xslt, final Map<String, String> parameters) {
+		return createMappedResultSet(source, new ApplyXslt(xslt, parameters));
+	}
+	
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final String xslt, final Map<String, String> parameters) {
+		return createMappedResultSet(source, new ApplyXslt(xslt, "rs-" + UUID.randomUUID(), parameters));
+	}
+
+	/**
+	 * Create a mapped resultset using a given XSLT.
+	 * 
+	 * @param source
+	 *            source
+	 * @param xslt
+	 *            XSLT
+	 * @return epr of mapped resultset
+	 * @throws TransformerFactoryConfigurationError
+	 * @throws TransformerConfigurationException
+	 *             could happen
+	 */
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final Source xslt, final String name) {
+		return createMappedResultSet(source, new ApplyXslt(xslt, name));
+	}
+
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSet.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSet.java	(revision 45117)
@@ -0,0 +1,151 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
+import eu.dnetlib.enabling.tools.ServiceResolver;
+import eu.dnetlib.miscutils.collections.MappedCollection;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+/**
+ * A resultset filter. Applies a transformation for every resultset record.
+ * 
+ * @author marko
+ * 
+ */
+public class MappedResultSet implements ResultSetListener, ResultSetAware {
+
+	/**
+	 * input resultset.
+	 */
+	private ResultSetService resultSetService;
+
+	/**
+	 * input resultset id.
+	 */
+	private String rsId;
+
+	/**
+	 * mapper function.
+	 */
+	private UnaryFunction<String, String> mapper;
+
+	/**
+	 * service resolver.
+	 */
+	private ServiceResolver serviceResolver;
+
+	private ResultSet resultSet;
+
+	/**
+	 * Create a new mapped resultset.
+	 * 
+	 * @param epr
+	 *            input resultset epr
+	 * @param mapper
+	 *            mapper function
+	 * @param serviceResolver
+	 *            service resolver
+	 */
+	public MappedResultSet(final W3CEndpointReference epr, final UnaryFunction<String, String> mapper, final ServiceResolver serviceResolver) {
+		super();
+
+		this.resultSetService = serviceResolver.getService(ResultSetService.class, epr);
+		this.rsId = serviceResolver.getResourceIdentifier(epr);
+
+		this.mapper = mapper;
+
+		this.serviceResolver = serviceResolver;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSetListener#getResult(int, int)
+	 */
+	@Override
+	public List<String> getResult(final int fromPosition, final int toPosition) {
+		return MappedCollection.listMap(getResultFromSource(fromPosition, toPosition), mapper);
+
+	}
+
+	protected List<String> getResultFromSource(final int fromPosition, final int toPosition) {
+		try {
+			List<String> res = resultSetService.getResult(rsId, fromPosition, toPosition, "waiting");
+			checkStatus();
+			return res;
+		} catch (final ResultSetException e) {
+			throw new IllegalStateException(e);
+		}
+	}
+
+	private void checkStatus() throws ResultSetException {
+		if (getResultSet().isOpen() && resultSetService.getRSStatus(rsId).equals("closed")) {
+			getResultSet().close();
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSetListener#getSize()
+	 */
+	@Override
+	public int getSize() {
+		try {
+			int numberOfElements = resultSetService.getNumberOfElements(rsId);
+			checkStatus();		
+			return numberOfElements;
+		} catch (final ResultSetException e) {
+			throw new IllegalStateException(e);
+		}
+	}
+
+	public ResultSetService getResultSetService() {
+		return resultSetService;
+	}
+
+	public void setResultSetService(final ResultSetService resultSetService) {
+		this.resultSetService = resultSetService;
+	}
+
+	public UnaryFunction<String, String> getMapper() {
+		return mapper;
+	}
+
+	public void setMapper(final UnaryFunction<String, String> mapper) {
+		this.mapper = mapper;
+	}
+
+	public ServiceResolver getServiceResolver() {
+		return serviceResolver;
+	}
+
+	@Required
+	public void setServiceResolver(final ServiceResolver serviceResolver) {
+		this.serviceResolver = serviceResolver;
+	}
+
+	@Override
+	public void setResultSet(ResultSet resultSet) {
+		this.resultSet = resultSet;
+	}
+
+	public ResultSet getResultSet() {
+		return resultSet;
+	}
+
+	public String getRsId() {
+		return rsId;
+	}
+
+	public void setRsId(String rsId) {
+		this.rsId = rsId;
+	}
+
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/observer/ResultSetObserver.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/observer/ResultSetObserver.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/observer/ResultSetObserver.java	(revision 45117)
@@ -0,0 +1,23 @@
+package eu.dnetlib.enabling.resultset.observer;
+
+import eu.dnetlib.enabling.resultset.ResultSet;
+
+
+/**
+ * Implement the same interface as JDK java.util.Observer as java interface (not as a class) and introduce static type
+ * safeness through generics.
+ * 
+ * @author marko, claudio, alessia, michele
+ * 
+ */
+public interface ResultSetObserver {
+	/**
+	 * gets notified when an observed object is updated.
+	 * 
+	 * @param observed
+	 *            observed object which modification triggered this call.
+	 * @param arg
+	 *            arg
+	 */
+	void update(ResultSet observed, Object arg);
+}

Property changes on: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/observer/ResultSetObserver.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/pom.xml
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/pom.xml	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/pom.xml	(revision 45117)
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<parent>
+		<groupId>eu.dnetlib</groupId>
+		<artifactId>dnet-parent</artifactId>
+		<version>1.0.0</version>
+		<relativePath />
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>eu.dnetlib</groupId>
+	<artifactId>cnr-resultset-service</artifactId>
+	<packaging>jar</packaging>
+	<version>2.0.2</version>
+	<scm>
+	  <developerConnection>scm:svn:https://svn.driver.research-infrastructures.eu/driver/dnet40/modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2</developerConnection>
+	</scm>
+	<dependencies>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>${junit.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>com.google.guava</groupId>
+			<artifactId>guava</artifactId>
+			<version>${google.guava.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>cglib</groupId>
+			<artifactId>cglib-nodep</artifactId>
+			<version>2.2</version>
+		</dependency>
+		<dependency>
+			<groupId>org.mockito</groupId>
+			<artifactId>mockito-core</artifactId>
+			<version>1.6</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-test</artifactId>
+			<version>${spring.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-context-support</artifactId>
+			<version>${spring.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>eu.dnetlib</groupId>
+			<artifactId>cnr-rmi-api</artifactId>
+			<version>[2.0.0,3.0.0)</version>
+		</dependency>
+		<dependency>
+			<groupId>eu.dnetlib</groupId>
+			<artifactId>cnr-spring-utils</artifactId>
+			<version>[1.0.0,2.0.0)</version>
+		</dependency>
+		<dependency>
+			<groupId>eu.dnetlib</groupId>
+			<artifactId>cnr-service-common</artifactId>
+			<version>[2.0.0,3.0.0)</version>
+		</dependency>
+	</dependencies>
+</project>
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/observer/DelegationObserver.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/observer/DelegationObserver.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/observer/DelegationObserver.java	(revision 45117)
@@ -0,0 +1,29 @@
+package eu.dnetlib.enabling.resultset.observer;
+
+import eu.dnetlib.enabling.resultset.ResultSet;
+import eu.dnetlib.enabling.resultset.ResultSetRegistry;
+
+/**
+ * This class delegates an observation event from the java.util.Observable producer to the real consumer which is not a
+ * java.util.Observer (as expected by java.util.Observable) but instead a miscutils Observer.
+ * 
+ * @author marko, claudio, alessia, michele
+ * 
+ */
+public class DelegationObserver implements java.util.Observer {
+	/**
+	 * 
+	 */
+	private transient final ResultSet observable;
+	private transient final ResultSetRegistry observer;
+
+	public DelegationObserver(final ResultSet observable, final ResultSetRegistry observer) {
+		this.observable = observable;
+		this.observer = observer;
+	}
+
+	@Override
+	public void update(final java.util.Observable ignored, final Object arg) {
+		observer.update(observable, arg);
+	}
+}
\ No newline at end of file

Property changes on: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/observer/DelegationObserver.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/observer/Observable.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/observer/Observable.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/observer/Observable.java	(revision 45117)
@@ -0,0 +1,18 @@
+package eu.dnetlib.enabling.resultset.observer;
+
+import eu.dnetlib.enabling.resultset.ResultSetRegistry;
+
+/**
+ * Declares the JDK-like standard observable pattern as a java interface.
+ * 
+ * @author marko, claudio, alessia, michele
+ */
+public interface Observable {
+	/**
+	 * add a given observer to this object.
+	 * 
+	 * @param observer
+	 *            observer
+	 */
+	void addObserver(ResultSetRegistry observer);
+}

Property changes on: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/observer/Observable.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/FetchList.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/FetchList.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/FetchList.java	(revision 45117)
@@ -0,0 +1,105 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+
+/**
+ * a LinkedList populated by a given iterable, which provides a fetch window of elements
+ *
+ * @author claudio
+ *
+ * @param <T>
+ *            The FetchList type
+ */
+public class FetchList<T> extends LinkedList<T> {
+
+	/**
+	 *
+	 */
+	private static final long serialVersionUID = 7135272008563693321L;
+
+	/**
+	 * represents the number of elements ready to be pulled out of the list
+	 */
+	private int fetchSize;
+
+	/**
+	 * represents the number of elements already consumed by a poll call
+	 */
+	private int consumedElements;
+
+	/**
+	 * the given itarable used to populate the list
+	 */
+	private Iterator<T> iter;
+
+	/**
+	 * @param iter
+	 * @param fetchSize
+	 */
+	public FetchList(final Iterator<T> iter, final int fetchSize) {
+		super();
+		this.consumedElements = 0;
+		this.fetchSize = fetchSize;
+		this.iter = iter;
+	}
+
+	/**
+	 * used to fill the list
+	 */
+	public synchronized void fill() {
+		for (int i = 0; i < fetchSize; i++) {
+			if (!iter.hasNext()) {
+				break;
+			}
+			this.add(iter.next());
+		}
+	}
+
+	/**
+	 * return the first element and makes the list to be filled in case its size is zero
+	 */
+	@Override
+	public T poll() {
+		if (this.isEmpty()) {
+			fill();
+		}
+
+		if (this.size() > 0) {
+			consumedElements++;
+			return super.poll();
+		}
+		return null;
+	}
+
+	/**
+	 * @return the number of elements already consumed by a "poll"
+	 */
+	public int getConsumedElements() {
+		return consumedElements;
+	}
+
+	/**
+	 * @return the actual number of elements of the list
+	 */
+	public int getTotalElements() {
+		return consumedElements + this.size();
+	}
+
+	/**
+	 * to provide an actual size, fills the list if there are elements to fill it
+	 */
+	@Override
+	public int size() {
+		if (this.isEmpty() && iter.hasNext()) {
+			fill();
+		}
+		return super.size();
+	}
+
+	@Override
+	public boolean isEmpty() {
+		return super.size() == 0;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactory.java	(revision 45117)
@@ -0,0 +1,75 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.Map;
+import java.util.UUID;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.core.io.Resource;
+
+import eu.dnetlib.miscutils.functional.xml.ApplyXslt;
+
+/**
+ * Create a mapped resultset using a given XSLT.
+ * 
+ * @author marko
+ * 
+ */
+public class XSLTMappedResultSetFactory extends MappedResultSetFactory {
+
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final String xslt) {
+		return createMappedResultSet(source, new ApplyXslt(xslt));
+	}
+
+	/**
+	 * Create a mapped resultset using a given XSLT.
+	 * 
+	 * @param source
+	 *            source
+	 * @param xslt
+	 *            XSLT source
+	 * @return epr of mapped resultset
+	 * @throws TransformerConfigurationException
+	 *             could happen
+	 */
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final String xslt, final String name)
+			throws TransformerConfigurationException {
+		return createMappedResultSet(source, new ApplyXslt(xslt, name));
+	}
+
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final Resource xslt) {
+		return createMappedResultSet(source, new ApplyXslt(xslt));
+	}
+
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final Source xslt) {
+		return createMappedResultSet(source, new ApplyXslt(xslt));
+	}
+	
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final Resource xslt, final Map<String, String> parameters) {
+		return createMappedResultSet(source, new ApplyXslt(xslt, parameters));
+	}
+	
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final String xslt, final Map<String, String> parameters) {
+		return createMappedResultSet(source, new ApplyXslt(xslt, "rs-" + UUID.randomUUID(), parameters));
+	}
+
+	/**
+	 * Create a mapped resultset using a given XSLT.
+	 * 
+	 * @param source
+	 *            source
+	 * @param xslt
+	 *            XSLT
+	 * @return epr of mapped resultset
+	 * @throws TransformerFactoryConfigurationError
+	 * @throws TransformerConfigurationException
+	 *             could happen
+	 */
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final Source xslt, final String name) {
+		return createMappedResultSet(source, new ApplyXslt(xslt, name));
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/observer/ResultSetObserver.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/observer/ResultSetObserver.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/observer/ResultSetObserver.java	(revision 45117)
@@ -0,0 +1,23 @@
+package eu.dnetlib.enabling.resultset.observer;
+
+import eu.dnetlib.enabling.resultset.ResultSet;
+
+
+/**
+ * Implement the same interface as JDK java.util.Observer as java interface (not as a class) and introduce static type
+ * safeness through generics.
+ * 
+ * @author marko, claudio, alessia, michele
+ * 
+ */
+public interface ResultSetObserver {
+	/**
+	 * gets notified when an observed object is updated.
+	 * 
+	 * @param observed
+	 *            observed object which modification triggered this call.
+	 * @param arg
+	 *            arg
+	 */
+	void update(ResultSet observed, Object arg);
+}

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/observer/ResultSetObserver.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/observer/DelegationObserver.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/observer/DelegationObserver.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/observer/DelegationObserver.java	(revision 45117)
@@ -0,0 +1,29 @@
+package eu.dnetlib.enabling.resultset.observer;
+
+import eu.dnetlib.enabling.resultset.ResultSet;
+import eu.dnetlib.enabling.resultset.ResultSetRegistry;
+
+/**
+ * This class delegates an observation event from the java.util.Observable producer to the real consumer which is not a
+ * java.util.Observer (as expected by java.util.Observable) but instead a miscutils Observer.
+ * 
+ * @author marko, claudio, alessia, michele
+ * 
+ */
+public class DelegationObserver implements java.util.Observer {
+	/**
+	 * 
+	 */
+	private transient final ResultSet observable;
+	private transient final ResultSetRegistry observer;
+
+	public DelegationObserver(final ResultSet observable, final ResultSetRegistry observer) {
+		this.observable = observable;
+		this.observer = observer;
+	}
+
+	@Override
+	public void update(final java.util.Observable ignored, final Object arg) {
+		observer.update(observable, arg);
+	}
+}
\ No newline at end of file

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/observer/DelegationObserver.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetAware.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetAware.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetAware.java	(revision 45117)
@@ -0,0 +1,16 @@
+package eu.dnetlib.enabling.resultset;
+
+/**
+ * ResultSet listeners can add this interface in order to receive the ResultSet they are bound to.
+ * 
+ * @author marko
+ *
+ */
+public interface ResultSetAware {
+	/**
+	 * sets the resultset instance.
+	 * 
+	 * @param resultSet the resultset instance
+	 */
+	void setResultSet(ResultSet resultSet);
+}
Index: modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/push/CacheTransientPushResultSetDaoTest.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/push/CacheTransientPushResultSetDaoTest.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/push/CacheTransientPushResultSetDaoTest.java	(revision 45117)
@@ -0,0 +1,78 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import java.util.List;
+
+import net.sf.ehcache.CacheManager;
+
+import org.junit.After;
+
+import eu.dnetlib.miscutils.cache.Cache;
+import eu.dnetlib.miscutils.cache.EhCache;
+import eu.dnetlib.miscutils.factory.Factory;
+
+/**
+ * concrete push resultset dao test.
+ * 
+ * @author marko
+ * 
+ */
+public class CacheTransientPushResultSetDaoTest extends AbstractTransientPushResultSetDaoTest { // NOPMD
+
+	/**
+	 * max in memory elements.
+	 */
+	private static final int MAX_IN_MEM = 100;
+
+	/**
+	 * default time.
+	 */
+	private static final int DEFAULT_TTI = 1000;
+
+	/**
+	 * default time to live.
+	 */
+	private static final int DEFAULT_TTL = 1000;
+
+	/**
+	 * cache manager.
+	 */
+	private final transient CacheManager cacheManager = CacheManager.create();
+
+	/**
+	 * clean cache after test.
+	 */
+	@After
+	public void cleanCache() {
+		cacheManager.removeAllCaches();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.push.AbstractTransientPushResultSetDaoTest#newInstance()
+	 */
+	@Override
+	protected TransientPushResultSetDao newInstance() {
+		final net.sf.ehcache.Cache ehcache = new net.sf.ehcache.Cache("testCache", MAX_IN_MEM, false, false, DEFAULT_TTL, DEFAULT_TTI);
+		cacheManager.addCache(ehcache);
+
+		final net.sf.ehcache.Cache rsehcache = new net.sf.ehcache.Cache("rsetCache", MAX_IN_MEM, false, false, DEFAULT_TTL, DEFAULT_TTI);
+		cacheManager.addCache(rsehcache);
+
+		final CacheTransientResultSetDaoImpl resultSet = new CacheTransientResultSetDaoImpl();
+		final Cache<String, List<String>> cache = new EhCache<String, List<String>>(ehcache);
+		final Cache<String, ResultSetDescriptor> rscache = new EhCache<String, ResultSetDescriptor>(rsehcache);
+		resultSet.setCache(cache);
+		resultSet.setResultSetCache(rscache);
+
+		resultSet.setResultSetDescriptorFactory(new Factory<ResultSetDescriptor>() {
+
+			@Override
+			public ResultSetDescriptor newInstance() {
+				return new ResultSetDescriptor();
+			}
+		});
+		return resultSet;
+	}
+
+}
Index: modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorTest.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorTest.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorTest.java	(revision 45117)
@@ -0,0 +1,44 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.junit.Before;
+import org.junit.Test;
+
+import eu.dnetlib.enabling.resultset.push.ResultSetDescriptor.Range;
+
+public class ResultSetDescriptorTest {
+
+	private static final Log log = LogFactory.getLog(ResultSetDescriptorTest.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	private transient ResultSetDescriptor descriptor;
+
+	@Before
+	public void setUp() throws Exception {
+		descriptor = new ResultSetDescriptor();
+	}
+
+	@Test
+	public void testGetRangesContaining() {
+		log.debug("--- 1, 1");
+		for(Range i : descriptor.getRangesContaining(1, 1))
+			log.debug("i " + i);
+
+		log.debug("--- 2, 1000");
+		for(Range i : descriptor.getRangesContaining(2, 1000))
+			log.debug("i " + i);
+
+		log.debug("--- 5, 2000");
+		for(Range i : descriptor.getRangesContaining(5, 2000))
+			log.debug("i " + i);
+
+		log.debug("--- 5, 2001");
+		for(Range i : descriptor.getRangesContaining(5, 2001))
+			log.debug("i " + i);
+	}
+
+	@Test
+	public void testNext() {
+	}
+
+}
Index: modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/MappedResultSetTest.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/MappedResultSetTest.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/MappedResultSetTest.java	(revision 45117)
@@ -0,0 +1,137 @@
+package eu.dnetlib.enabling.resultset; // NOPMD
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.runners.MockitoJUnit44Runner;
+import org.mockito.stubbing.Answer;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
+import eu.dnetlib.enabling.tools.ServiceResolver;
+import eu.dnetlib.miscutils.factory.Factory;
+import eu.dnetlib.miscutils.functional.ThreadSafeUnaryFunction;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+/**
+ * test xslt resultset.
+ *
+ * @author marko
+ *
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class MappedResultSetTest {
+
+	/**
+	 * instance under test.
+	 */
+	private transient MappedResultSet mappedResultSet;
+
+	/**
+	 * service resolver.
+	 */
+	@Mock
+	private transient ServiceResolver serviceResolver;
+
+	/**
+	 * resultset service mock.
+	 */
+	@Mock
+	private transient ResultSetService resultSetService;
+	
+	/**
+	 * resultset mock.
+	 */
+	@Mock
+	private transient ResultSet resultSet;	
+
+	private Answer<Object> resultSetAnswer = new Answer<Object>() {
+
+		private List<String> list = Lists.newArrayList("1","2","3","4","5","6","7","8","9","10");
+		
+		@Override
+		public Object answer(InvocationOnMock invocation) throws Throwable {
+			String method = invocation.getMethod().getName();
+			if (method.equals("getResult") || method.equals("getResults")) {
+				int from = (Integer) invocation.getArguments()[1];
+				int to = (Integer) invocation.getArguments()[2];
+				
+				return list.subList(from-1, to);
+			}
+			if (method.equals("getNumberOfElements") || method.equals("getNumberOfResults")) {
+				return list.size();
+			}
+			if (method.equals("getRSStatus")) {
+				return "closed";
+			}
+			if (method.equals("isOpen")) {
+				return false;
+			}			
+			System.out.println(invocation.toString());
+			return null;
+		}		
+	};
+
+	/**
+	 * Common setup.
+	 * @throws ResultSetException 
+	 *
+	 */
+	@Before
+	public void setUp() throws ResultSetException {
+		
+		when(serviceResolver.getService(eq(ResultSetService.class), (W3CEndpointReference) anyObject())).thenReturn(resultSetService);
+		when(serviceResolver.getResourceIdentifier((W3CEndpointReference) anyObject())).thenReturn("123");
+
+		when(resultSetService.getNumberOfElements(anyString())).thenAnswer(resultSetAnswer);
+		when(resultSetService.getResult(anyString(), anyInt(), anyInt(), anyString())).thenAnswer(resultSetAnswer );
+		when(resultSetService.getRSStatus(anyString())).thenAnswer(resultSetAnswer);
+		
+		when(resultSet.getNumberOfResults()).thenAnswer(resultSetAnswer);
+		when(resultSet.getResults(anyInt(), anyInt())).thenAnswer(resultSetAnswer );
+		when(resultSet.isOpen()).thenAnswer(resultSetAnswer);		
+	}
+	
+	@Test
+	public void testThreadSafeMappedResultSet_1() {
+		
+		final Factory<UnaryFunction<String, String>> functionFactory = new Factory<UnaryFunction<String,String>>() {
+			@Override
+			public UnaryFunction<String, String> newInstance() {
+				return new UnaryFunction<String, String>() {
+					@Override
+					public String evaluate(String arg) {
+						return "mapped-" + arg;
+					}
+				};
+			}
+		}; 
+		mappedResultSet = new MappedResultSet(null, new ThreadSafeUnaryFunction<String, String>(functionFactory), serviceResolver);
+		mappedResultSet.setResultSet(resultSet);
+
+		for (String s : mappedResultSet.getResult(1, 10)) {
+			assertNotNull("null result", s);
+			assertFalse("empty result", s.isEmpty());
+			assertNotNull("null element", s);
+			assertTrue("transformed correctly", s.startsWith("mapped-"));	
+		}
+	}
+}
+

Property changes on: modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/MappedResultSetTest.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistry.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistry.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistry.java	(revision 45117)
@@ -0,0 +1,75 @@
+package eu.dnetlib.enabling.resultset;
+
+import eu.dnetlib.enabling.resultset.observer.ResultSetObserver;
+
+/**
+ * Instances of ResultSetRegistry manage a set of resultset objects and manage their garbage collection.
+ *
+ * @author marko
+ *
+ */
+public interface ResultSetRegistry extends ResultSetObserver {
+	/**
+	 * add a resultset object to the registry.
+	 *
+	 * The given resultset object from now on is managed by the resultset registry.
+	 *
+	 * @param resultSet
+	 *            a resultset object
+	 */
+	void addResultSet(ResultSet resultSet);
+	
+	/**
+	 * add a resultset object to the registry.
+	 *
+	 * The given resultset object from now on is managed by the resultset registry.
+	 *
+	 * @param resultSet
+	 *            a resultset object
+	 * @param identifier the identifier you want for the resultset
+	 */
+	void addResultSet(ResultSet resultSet, String identifier);
+
+	/**
+	 * add a resultset object to the registry.
+	 *
+	 * The given resultset object from now on is managed by the resultset registry.
+	 *
+	 * @param resultSet
+	 *            a resultset object
+	 * @param maxIdleTime
+	 *            max idle time
+	 */
+	void addResultSet(ResultSet resultSet, int maxIdleTime);
+	
+	/**
+	 * add a resultset object to the registry.
+	 *
+	 * The given resultset object from now on is managed by the resultset registry.
+	 *
+	 * @param resultSet
+	 *            a resultset object
+	 * @param identifier the identifier you want for the resultset
+	 * @param maxIdleTime max idle time
+	 */
+	void addResultSet(ResultSet resultSet, String identifier, int maxIdleTime);
+
+	/**
+	 * obtain the resultset with the given id.
+	 *
+	 * @param rsId
+	 *            resultset id
+	 * @return the resultset object matching the rsId or null
+	 */
+	ResultSet getResultSetById(String rsId);
+
+	/**
+	 * obtain the resultset's maxIdleTime parameter for a resultset with the given id.
+	 *
+	 * @param rsId
+	 *            resultset id
+	 * @return max idle time in seconds, as specified when the resultset has been registered
+	 */
+	int getMaxIdleTimeById(String rsId);
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetListener.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetListener.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetListener.java	(revision 45117)
@@ -0,0 +1,132 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Exposes an iterable through our resultset protocol.
+ * 
+ * <p>
+ * The resultset protocol is constructed as if it were random access. Some kind of sources, like an iterable, is not
+ * random access. The consumer of such a resultset knows that, and won't try to access the resultset randomly. However,
+ * it could ask for some data which is already sent, because of retries caused by network issues.
+ * </p>
+ * 
+ * @author marko
+ * 
+ */
+public class StreamingResultSetListener implements ResultSetListener, ResultSetAware {
+	private static final Log log = LogFactory.getLog(StreamingResultSetListener.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	private ResultSet resultSet;
+
+	private Iterable<String> iterable;
+	private Iterator<String> items;
+	private int size;
+
+	private int lastFrom = 0;
+	private int lastTo = 0;
+	private List<String> lastChunk;
+
+	public StreamingResultSetListener(Iterable<String> items, int size) {
+		this(items.iterator(), size);
+		this.iterable = items;
+	}
+
+	public StreamingResultSetListener(Iterator<String> items, int size) {
+		super();
+		this.items = items;
+		this.size = size;
+	}
+
+	protected void reset() {
+		lastFrom = 0;
+		items = iterable.iterator();
+	}
+
+	@Override
+	public List<String> getResult(int from, int to) {
+
+		log.debug("STREAM: getResult(" + from + ", " + to + ")");
+
+		// handle retry because of network error.
+		if (from == lastFrom && to == lastTo)
+			return lastChunk;
+
+		if (from != lastTo + 1) {
+			if (from == 1 && iterable != null)
+				reset();
+			else
+				throw new IllegalArgumentException("this resultset is not random access, you can only retry last chunk only, asked from " + from + " to "
+						+ to + " but lastTo = " + lastTo + ". Size = " + size);
+		}
+
+		List<String> chunk = new ArrayList<String>();
+		for (int i = from; i <= to; i++)
+			chunk.add(items.next());
+
+		if (resultSet != null && !items.hasNext())
+			resultSet.close();
+
+		lastFrom = from;
+		lastTo = to;
+		lastChunk = chunk;
+
+		return chunk;
+	}
+
+	@Override
+	public int getSize() {
+		return size;
+	}
+
+	public void setSize(int size) {
+		this.size = size;
+	}
+
+	public Iterator<String> getItems() {
+		return items;
+	}
+
+	public void setItems(Iterator<String> items) {
+		this.items = items;
+	}
+
+	public int getLastFrom() {
+		return lastFrom;
+	}
+
+	public void setLastFrom(int lastFrom) {
+		this.lastFrom = lastFrom;
+	}
+
+	public int getLastTo() {
+		return lastTo;
+	}
+
+	public void setLastTo(int lastTo) {
+		this.lastTo = lastTo;
+	}
+
+	public List<String> getLastChunk() {
+		return lastChunk;
+	}
+
+	public void setLastChunk(List<String> lastChunk) {
+		this.lastChunk = lastChunk;
+	}
+
+	public ResultSet getResultSet() {
+		return resultSet;
+	}
+
+	@Override
+	public void setResultSet(ResultSet resultSet) {
+		this.resultSet = resultSet;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImpl.java	(revision 45117)
@@ -0,0 +1,123 @@
+package eu.dnetlib.enabling.resultset;
+
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.enabling.tools.UniqueIdentifierGenerator;
+import eu.dnetlib.enabling.tools.UniqueIdentifierGeneratorImpl;
+import eu.dnetlib.miscutils.cache.Cache;
+
+/**
+ * Implement a in memory resultset registry.
+ *
+ * @author marko
+ *
+ */
+public class ResultSetRegistryImpl implements ResultSetRegistry {
+
+	/**
+	 * rsId -> ResultSet mappings are stored here.
+	 */
+	private Cache<String, ResultSet> cache;
+
+	/**
+	 * rsID -> initial maxIdleTime time are store here.
+	 */
+	private Cache<String, Integer> maxIdleTimeCache;
+
+	/**
+	 * identifier generator.
+	 */
+	private UniqueIdentifierGenerator idGenerator = new UniqueIdentifierGeneratorImpl("rs-");
+
+	/**
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.ResultSetRegistry#addResultSet(eu.dnetlib.enabling.resultset.ResultSet)
+	 */
+	@Override
+	public void addResultSet(final ResultSet resultSet) {
+		addResultSet(resultSet, 0);
+	}
+
+	/** 
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.ResultSetRegistry#addResultSet(eu.dnetlib.enabling.resultset.ResultSet, java.lang.String)
+	 */
+	@Override
+	public void addResultSet(final ResultSet resultSet, final String identifier) {
+		addResultSet(resultSet, identifier, 0);
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.ResultSetRegistry#addResultSet(eu.dnetlib.enabling.resultset.ResultSet, int)
+	 */
+	@Override
+	public void addResultSet(final ResultSet resultSet, final int maxIdleTime) {
+		addResultSet(resultSet, idGenerator.generateIdentifier(), maxIdleTime);
+	}
+	
+	/** 
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.ResultSetRegistry#addResultSet(eu.dnetlib.enabling.resultset.ResultSet, java.lang.String, int)
+	 */
+	@Override
+	public void addResultSet(final ResultSet resultSet, final String identifier, final int maxIdleTime) {
+		resultSet.setIdentifier(identifier);
+		resultSet.addObserver(this);
+		cache.put(resultSet.getIdentifier(), resultSet);
+		maxIdleTimeCache.put(resultSet.getIdentifier(), maxIdleTime);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see eu.dnetlib.enabling.resultset.ResultSetRegistry#getResultSetById(java.lang.String)
+	 */
+	@Override
+	public ResultSet getResultSetById(final String rsId) {
+		return cache.get(rsId);
+	}
+
+	@Override
+	public int getMaxIdleTimeById(final String rsId) {
+		return maxIdleTimeCache.get(rsId);
+	}
+
+
+	public Cache<String, ResultSet> getCache() {
+		return cache;
+	}
+
+	@Required
+	public void setCache(final Cache<String, ResultSet> cache) {
+		this.cache = cache;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.miscutils.observer.Observer#update(eu.dnetlib.enabling.resultset.observer.Observable, java.lang.Object)
+	 */
+	@Override
+	public void update(final ResultSet observed, final Object arg) {
+		if (!observed.isOpen())
+			cache.remove(observed.getIdentifier());
+	}
+
+	public UniqueIdentifierGenerator getIdGenerator() {
+		return idGenerator;
+	}
+
+	public void setIdGenerator(final UniqueIdentifierGenerator idGenerator) {
+		this.idGenerator = idGenerator;
+	}
+
+	public Cache<String, Integer> getMaxIdleTimeCache() {
+		return maxIdleTimeCache;
+	}
+
+	@Required
+	public void setMaxIdleTimeCache(Cache<String, Integer> maxIdleTimeCache) {
+		this.maxIdleTimeCache = maxIdleTimeCache;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSet.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSet.java	(revision 45117)
@@ -0,0 +1,116 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * an open ResultSet that can be iterated to get it's data results.
+ * 
+ * @author claudio
+ * 
+ */
+public class IterableResultSet implements ResultSetListener, ResultSetAware {
+
+	/**
+	 * logger.
+	 */
+	private static final Log log = LogFactory.getLog(IterableResultSet.class);
+
+	/**
+	 * the container for the data results.
+	 */
+	private ResultSet resultSet;
+
+	/**
+	 * the list that provides data for this resultSet.
+	 */
+	private FetchList<String> fetchList;
+
+	private int optionalNumberOfElements;
+
+	/**
+	 * 
+	 * @param iter
+	 * @param fetchSize
+	 */
+	protected IterableResultSet(Iterable<String> iter, int fetchSize) {
+		fetchList = new FetchList<String>(iter.iterator(), fetchSize);
+		if (iter instanceof SizedIterable<?>) {
+			optionalNumberOfElements = ((SizedIterable<?>) iter).getNumberOfElements();
+		} else {
+			optionalNumberOfElements = -1;
+		}
+	}
+
+	/**
+	 * @param fromPosition
+	 * @param toPosition
+	 * @return <T> List
+	 */
+	@Override
+	public List<String> getResult(int fromPosition, int toPosition) {
+
+		log.debug(" - getting result from " + fromPosition + " to " + toPosition + ", consumedElements: " + fetchList.getConsumedElements());
+
+		if (fromPosition != fetchList.getConsumedElements() + 1)
+			throw new RuntimeException("Unexpected value for 'fromPosition' parameter");
+		if (toPosition < fromPosition)
+			throw new RuntimeException("'fromPosition' must be lower or equal than 'toPosition'");
+
+		List<String> result = new ArrayList<String>();
+
+		for (int i = fromPosition; i <= toPosition; i++) {
+			if (fetchList.size() > 0)
+				result.add(fetchList.poll());
+			else
+				break;
+		}
+
+		ensureClosed();
+
+		return result;
+	}
+
+	private void ensureClosed() {
+		if (fetchList.size() == 0 && resultSet.isOpen()) {
+			log.info(">>>>>>>>>>> closing resultset <<<<<<<<<<<<<");
+			close();
+		}
+	}
+
+	public String getRSStatus() {
+		if (resultSet.isOpen())
+			return "open";
+		return "closed";
+	}
+
+	@Override
+	public int getSize() {
+		ensureClosed();
+
+		if (optionalNumberOfElements == -1)
+			return fetchList.getTotalElements();
+		else
+			return optionalNumberOfElements;
+	}
+
+	/**
+	 * closes the resultset.
+	 */
+	protected void close() {
+		resultSet.close();
+	}
+
+	@Override
+	public void setResultSet(ResultSet resultSet) {
+		this.resultSet = resultSet;
+	}
+
+	public ResultSet getResultSet() {
+		return resultSet;
+	}
+
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/AbstractObservableResultset.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/AbstractObservableResultset.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/AbstractObservableResultset.java	(revision 45117)
@@ -0,0 +1,155 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import eu.dnetlib.enabling.resultset.observer.DelegationObserver;
+import eu.dnetlib.enabling.resultset.observer.Observable;
+
+
+/**
+ * Common stuff for resultset implementations bound to a ResultSetRegistry.
+ * 
+ * @author marko
+ * 
+ */
+public abstract class AbstractObservableResultset implements ResultSet, Observable {
+	/**
+	 * true if the resultset is destroyed.
+	 */
+	private boolean destroyed = false;
+
+	/**
+	 * true if the resultset is open.
+	 */
+	private boolean open;
+
+	/**
+	 * delegate the real job to a java.util.Observable object.
+	 */
+	private transient final java.util.Observable observable = new DelegationObservable();
+
+	/**
+	 * weak map for removing single observers later on.
+	 */
+	private transient Map<ResultSetRegistry, DelegationObserver> observers = new WeakHashMap<ResultSetRegistry, DelegationObserver>();
+
+	/**
+	 * java.util.Observable requires a "change" in the object to be made for the notifyObservers methods to trigger
+	 * actually the notification. We don't think this should be part of the base Observable/Observer pattern and thus
+	 * hide this fact. If an user of AbstractObservable wants this behavior it should implement her own change tracking
+	 * and avoid calling notifyObservers altogether. The rationale behind this choice is that not all dirty states can
+	 * be expressed using a stateful boolean instance variable like that implemented by java.util.Observable; some users
+	 * may prefer/need a lazy dirty flag instead.
+	 * 
+	 * @author marko
+	 * 
+	 */
+	static class DelegationObservable extends java.util.Observable {
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see java.util.Observable#notifyObservers()
+		 */
+		@Override
+		public void notifyObservers() {
+			setChanged();
+			super.notifyObservers();
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see java.util.Observable#notifyObservers(java.lang.Object)
+		 */
+		@Override
+		public void notifyObservers(final Object arg) {
+			setChanged();
+			super.notifyObservers(arg);
+		}
+
+	}	
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#destroy()
+	 */
+	@Override
+	public void destroy() {
+		if (!isDestroyed()) {
+			setDestroyed(true);
+			notifyObservers();
+			deleteObservers();
+		}
+	}
+
+	public void setDestroyed(final boolean destroyed) {
+		this.destroyed = destroyed;
+	}
+
+	@Override
+	public boolean isDestroyed() {
+		return destroyed;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#isOpen()
+	 */
+	@Override
+	public boolean isOpen() {
+		return open;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#close()
+	 */
+	@Override
+	public void close() {
+		open = false;
+	}
+
+	public void setOpen(final boolean open) {
+		this.open = open;
+	}
+
+	@Override
+	public void addObserver(final ResultSetRegistry observer) {
+		final DelegationObserver delegate = new DelegationObserver(this, observer);
+		observers.put(observer, delegate);
+		observable.addObserver(delegate);
+	}
+
+	protected void notifyObservers() {
+		observable.notifyObservers();
+	}
+
+	protected void notifyObservers(final Object arg) {
+		observable.notifyObservers(arg);
+	}
+
+	public int countObservers() {
+		return observable.countObservers();
+	}
+
+	public void deleteObserver(final java.util.Observer observer) {
+		observable.deleteObserver(observer);
+	}
+
+	public void deleteObserver(ResultSetRegistry observer) {
+		DelegationObserver delegate = observers.get(observer);
+		if(delegate != null) {
+			observable.deleteObserver(delegate);
+		}
+	}	
+
+	public void deleteObservers() {
+		observable.deleteObservers();
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/AbstractPushResultSetFactoryImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/AbstractPushResultSetFactoryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/AbstractPushResultSetFactoryImpl.java	(revision 45117)
@@ -0,0 +1,44 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.enabling.resultset.ResultSetServiceImpl;
+
+/**
+ * push resultset factory.
+ *
+ * @author marko
+ *
+ */
+public abstract class AbstractPushResultSetFactoryImpl implements PushResultSetFactory {
+	/**
+	 * resultset service.
+	 */
+	private ResultSetServiceImpl resultSetService;
+
+	/**
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.push.PushResultSetFactory#createPushResultSet(int)
+	 */
+	@Override
+	public W3CEndpointReference createPushResultSet(final int maxIdleTime) {
+		final PushResultSet resultSet = newInstance();
+		resultSetService.getResultsetRegistry().addResultSet(resultSet, maxIdleTime);
+		return resultSetService.getEprBuilder().getEndpointReference(resultSetService.getEndpoint(), resultSet.getIdentifier());
+	}
+
+	/**
+	 * subclasses should override it and create a new push resultset instance.
+	 * @return push resultset instance
+	 */
+	protected abstract PushResultSet newInstance();
+
+	public ResultSetServiceImpl getResultSetService() {
+		return resultSetService;
+	}
+
+	public void setResultSetService(final ResultSetServiceImpl resultSetService) {
+		this.resultSetService = resultSetService;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptor.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptor.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptor.java	(revision 45117)
@@ -0,0 +1,156 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import java.io.Serializable;
+import java.util.Iterator;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Describes a push resultset.
+ *
+ * <p>
+ * A push resultset stores it's data in several ranges
+ * </p>
+ *
+ * @author marko
+ *
+ */
+public class ResultSetDescriptor implements Serializable {
+
+	/**
+	 * logger.
+	 */
+	private static final Log log = LogFactory.getLog(Range.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	/**
+	 * This class describes a range.
+	 *
+	 * @author marko
+	 *
+	 */
+	public class Range {
+		private int range;
+		private int begin;
+		private int end;
+
+		public Range(final int range, final int begin, final int end) {
+			super();
+			this.range = range;
+			this.begin = begin;
+			this.end = end;
+		}
+
+		@Override
+		public String toString() {
+			return "Range(" + range + ", " + begin + ", " + end + ")";
+		}
+
+		public int getRange() {
+			return range;
+		}
+
+		public void setRange(final int range) {
+			this.range = range;
+		}
+
+		public int getBegin() {
+			return begin;
+		}
+
+		public void setBegin(final int begin) {
+			this.begin = begin;
+		}
+
+		public int getEnd() {
+			return end;
+		}
+
+		public void setEnd(final int end) {
+			this.end = end;
+		}
+	}
+
+	/**
+	 *
+	 */
+	private static final long serialVersionUID = 7699992350256317181L;
+
+	private int rangeLength = 100;
+
+	private int ranges = 0;
+
+	public int getLastRange() {
+		return ranges - 1;
+	}
+
+	/**
+	 * @param fromPosition
+	 *            1 based count
+	 * @param toPosition
+	 *            1 based count
+	 * @return
+	 */
+	public Iterable<Range> getRangesContaining(final int fromPosition, final int toPosition) {
+
+		final int fromRange = (fromPosition - 1) / rangeLength;
+		int ttoRange = (int) Math.ceil((toPosition * 1.0) / rangeLength);
+
+		if (ttoRange > ranges)
+			ttoRange = ranges;
+
+		final int toRange = ttoRange;
+
+		log.debug("FROM range: " + fromRange);
+		log.debug("TTO range: " + ttoRange);
+		log.debug("TO range: " + toRange);
+
+		return new Iterable<Range>() {
+
+			@Override
+			public Iterator<Range> iterator() {
+				return new Iterator<Range>() {
+
+					int current = fromRange;
+
+					@Override
+					public boolean hasNext() {
+						return current < toRange;
+					}
+
+					@Override
+					public Range next() {
+						int begin = 0;
+						int end = rangeLength;
+						if (current == fromRange)
+							begin = (fromPosition - 1) % rangeLength;
+						if ((current + 1) == toRange)
+							end = (toPosition - 1) % rangeLength + 1;
+						return new Range(current++, begin, end);
+					}
+
+					@Override
+					public void remove() {
+						throw new IllegalStateException("text");
+					}
+				};
+			}
+		};
+	}
+
+	public int getRangeLength() {
+		return rangeLength;
+	}
+
+	public void setRangeLength(final int rangeLength) {
+		this.rangeLength = rangeLength;
+	}
+
+	public int getRanges() {
+		return ranges;
+	}
+
+	public void setRanges(final int ranges) {
+		this.ranges = ranges;
+	}
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImpl.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImpl.java	(revision 45117)
@@ -0,0 +1,123 @@
+package eu.dnetlib.enabling.resultset;
+
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.enabling.tools.UniqueIdentifierGenerator;
+import eu.dnetlib.enabling.tools.UniqueIdentifierGeneratorImpl;
+import eu.dnetlib.miscutils.cache.Cache;
+
+/**
+ * Implement a in memory resultset registry.
+ *
+ * @author marko
+ *
+ */
+public class ResultSetRegistryImpl implements ResultSetRegistry {
+
+	/**
+	 * rsId -> ResultSet mappings are stored here.
+	 */
+	private Cache<String, ResultSet> cache;
+
+	/**
+	 * rsID -> initial maxIdleTime time are store here.
+	 */
+	private Cache<String, Integer> maxIdleTimeCache;
+
+	/**
+	 * identifier generator.
+	 */
+	private UniqueIdentifierGenerator idGenerator = new UniqueIdentifierGeneratorImpl("rs-");
+
+	/**
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.ResultSetRegistry#addResultSet(eu.dnetlib.enabling.resultset.ResultSet)
+	 */
+	@Override
+	public void addResultSet(final ResultSet resultSet) {
+		addResultSet(resultSet, 0);
+	}
+
+	/** 
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.ResultSetRegistry#addResultSet(eu.dnetlib.enabling.resultset.ResultSet, java.lang.String)
+	 */
+	@Override
+	public void addResultSet(final ResultSet resultSet, final String identifier) {
+		addResultSet(resultSet, identifier, 0);
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.ResultSetRegistry#addResultSet(eu.dnetlib.enabling.resultset.ResultSet, int)
+	 */
+	@Override
+	public void addResultSet(final ResultSet resultSet, final int maxIdleTime) {
+		addResultSet(resultSet, idGenerator.generateIdentifier(), maxIdleTime);
+	}
+	
+	/** 
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.ResultSetRegistry#addResultSet(eu.dnetlib.enabling.resultset.ResultSet, java.lang.String, int)
+	 */
+	@Override
+	public void addResultSet(final ResultSet resultSet, final String identifier, final int maxIdleTime) {
+		resultSet.setIdentifier(identifier);
+		resultSet.addObserver(this);
+		cache.put(resultSet.getIdentifier(), resultSet);
+		maxIdleTimeCache.put(resultSet.getIdentifier(), maxIdleTime);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see eu.dnetlib.enabling.resultset.ResultSetRegistry#getResultSetById(java.lang.String)
+	 */
+	@Override
+	public ResultSet getResultSetById(final String rsId) {
+		return cache.get(rsId);
+	}
+
+	@Override
+	public int getMaxIdleTimeById(final String rsId) {
+		return maxIdleTimeCache.get(rsId);
+	}
+
+
+	public Cache<String, ResultSet> getCache() {
+		return cache;
+	}
+
+	@Required
+	public void setCache(final Cache<String, ResultSet> cache) {
+		this.cache = cache;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.miscutils.observer.Observer#update(eu.dnetlib.enabling.resultset.observer.Observable, java.lang.Object)
+	 */
+	@Override
+	public void update(final ResultSet observed, final Object arg) {
+		if (!observed.isOpen())
+			cache.remove(observed.getIdentifier());
+	}
+
+	public UniqueIdentifierGenerator getIdGenerator() {
+		return idGenerator;
+	}
+
+	public void setIdGenerator(final UniqueIdentifierGenerator idGenerator) {
+		this.idGenerator = idGenerator;
+	}
+
+	public Cache<String, Integer> getMaxIdleTimeCache() {
+		return maxIdleTimeCache;
+	}
+
+	@Required
+	public void setMaxIdleTimeCache(Cache<String, Integer> maxIdleTimeCache) {
+		this.maxIdleTimeCache = maxIdleTimeCache;
+	}
+
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistry.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistry.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistry.java	(revision 45117)
@@ -0,0 +1,75 @@
+package eu.dnetlib.enabling.resultset;
+
+import eu.dnetlib.enabling.resultset.observer.ResultSetObserver;
+
+/**
+ * Instances of ResultSetRegistry manage a set of resultset objects and manage their garbage collection.
+ *
+ * @author marko
+ *
+ */
+public interface ResultSetRegistry extends ResultSetObserver {
+	/**
+	 * add a resultset object to the registry.
+	 *
+	 * The given resultset object from now on is managed by the resultset registry.
+	 *
+	 * @param resultSet
+	 *            a resultset object
+	 */
+	void addResultSet(ResultSet resultSet);
+	
+	/**
+	 * add a resultset object to the registry.
+	 *
+	 * The given resultset object from now on is managed by the resultset registry.
+	 *
+	 * @param resultSet
+	 *            a resultset object
+	 * @param identifier the identifier you want for the resultset
+	 */
+	void addResultSet(ResultSet resultSet, String identifier);
+
+	/**
+	 * add a resultset object to the registry.
+	 *
+	 * The given resultset object from now on is managed by the resultset registry.
+	 *
+	 * @param resultSet
+	 *            a resultset object
+	 * @param maxIdleTime
+	 *            max idle time
+	 */
+	void addResultSet(ResultSet resultSet, int maxIdleTime);
+	
+	/**
+	 * add a resultset object to the registry.
+	 *
+	 * The given resultset object from now on is managed by the resultset registry.
+	 *
+	 * @param resultSet
+	 *            a resultset object
+	 * @param identifier the identifier you want for the resultset
+	 * @param maxIdleTime max idle time
+	 */
+	void addResultSet(ResultSet resultSet, String identifier, int maxIdleTime);
+
+	/**
+	 * obtain the resultset with the given id.
+	 *
+	 * @param rsId
+	 *            resultset id
+	 * @return the resultset object matching the rsId or null
+	 */
+	ResultSet getResultSetById(String rsId);
+
+	/**
+	 * obtain the resultset's maxIdleTime parameter for a resultset with the given id.
+	 *
+	 * @param rsId
+	 *            resultset id
+	 * @return max idle time in seconds, as specified when the resultset has been registered
+	 */
+	int getMaxIdleTimeById(String rsId);
+
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSet.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSet.java	(revision 45117)
@@ -0,0 +1,71 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import eu.dnetlib.enabling.resultset.observer.Observable;
+
+/**
+ * A ResultSet represents a set of data results.
+ * 
+ * @author marko
+ * 
+ */
+public interface ResultSet extends Observable {
+	/**
+	 * get the resource identifier.
+	 * 
+	 * @return rsId
+	 */
+	String getIdentifier();
+
+	/**
+	 * sets the resource identifier. The ResultSetRegistry will assign a new rsId.
+	 * 
+	 * @param rsId allocated resultset identifier
+	 */
+	void setIdentifier(String rsId);
+
+	/**
+	 * get a 'page' of results.
+	 * 
+	 * @param fromPosition
+	 *            from 1
+	 * @param toPosition
+	 *            last included
+	 * @return a page of data
+	 */
+	List<String> getResults(int fromPosition, int toPosition);
+
+	/**
+	 * get the number of result elements present in the resultset.
+	 * 
+	 * @return number of results
+	 */
+	int getNumberOfResults();
+
+	/**
+	 * Tells if the resultset is open or closed.
+	 * 
+	 * @return true if open
+	 */
+	boolean isOpen();
+
+	/**
+	 * close a resultset.
+	 */
+	void close();
+	
+	/**
+	 * Tells if the resultset is destroyed.
+	 * 
+	 * @return true if the resultset is destroyed. 
+	 */
+	boolean isDestroyed();
+	
+	/**
+	 * Destroy the resultset and free associated resources, remove it from the ResultSetRegistry.
+	 * After calling this method, the resultset is no more accessible from other services.
+	 */
+	void destroy();
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetDao.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetDao.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetDao.java	(revision 45117)
@@ -0,0 +1,45 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import java.util.List;
+
+/**
+ * offer access to the underlying in-memory or pseudo-memory (serialization backed caches) storage for the transient
+ * push-resultsets.
+ *
+ * This type of push resultsets doesn't even try to make efficient access to records, they just keep them as big lists
+ * on the underlying storage. Actual implementations may decide to keep them on the heap or to use some caching
+ * technology like ehcache.
+ *
+ * @author marko
+ *
+ */
+public interface TransientPushResultSetDao {
+	/**
+	 * add elements to a given key.
+	 *
+	 * @param key
+	 *            usually a rsid.
+	 * @param elements
+	 *            list of elements
+	 */
+	void addElements(String key, List<String> elements);
+
+	/**
+	 * obtain content for a given key (resultset) in a given range (1 based).
+	 *
+	 * @param key
+	 *            usually a rsid
+	 * @param fromPosition from position (1 based, inclusive)
+	 * @param toPosition to position (1 based, inclusive)
+	 * @return all the elements for a given key
+	 */
+	List<String> getElements(String key, int fromPosition, int toPosition);
+
+	/**
+	 * get the resultset size (number of elements).
+	 *
+	 * @param key usually a rsid
+	 * @return resultset size
+	 */
+	int getSize(String key);
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSetFactory.java	(revision 45117)
@@ -0,0 +1,21 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * creates a new push resultset.
+ *
+ * @author marko
+ *
+ */
+public interface PushResultSetFactory {
+
+	/**
+	 * create a new push resultset.
+	 *
+	 * @param maxIdleTime max time the resultset can be idle
+	 * @return push resultset epr
+	 */
+	W3CEndpointReference createPushResultSet(int maxIdleTime);
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDaoImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDaoImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDaoImpl.java	(revision 45117)
@@ -0,0 +1,23 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * fake resultset property dao.
+ * 
+ * @author marko
+ *
+ */
+public class ResultSetPropertyDaoImpl implements ResultSetPropertyDao {
+
+	/** 
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.ResultSetPropertyDao#getProperties(eu.dnetlib.enabling.resultset.ResultSet)
+	 */
+	@Override
+	public Map<String, String> getProperties(final ResultSet resultSet) {
+		return new HashMap<String, String>();
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/JaxbResultsetListenerWrapper.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/JaxbResultsetListenerWrapper.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/JaxbResultsetListenerWrapper.java	(revision 45117)
@@ -0,0 +1,68 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import javax.xml.bind.JAXBException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.miscutils.collections.MappedCollection;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+import eu.dnetlib.miscutils.jaxb.JaxbFactory;
+
+/**
+ * Given a jaxb factory for a given type, wraps TypedResultsetListeners to ResultSetListeners, serializing objects
+ * according to the jaxb factory.
+ * 
+ * @author marko
+ * 
+ * @param <T>
+ */
+public class JaxbResultsetListenerWrapper<T> {
+	private static final Log log = LogFactory.getLog(JaxbResultsetListenerWrapper.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	private JaxbFactory<T> factory;
+
+	/**
+	 * Returns a listener which serializes each item according to the jaxb factory.
+	 * 
+	 * @param listener
+	 *            listener which returns T
+	 * @return listener which returns strings
+	 */
+	public ResultSetListener wrap(final TypedResultSetListener<T> listener) {
+		return new ResultSetListener() {
+
+			@Override
+			public List<String> getResult(final int fromPosition, final int toPosition) {
+				return Lists.newArrayList(new MappedCollection<String, T>(listener.getResult(fromPosition, toPosition), new UnaryFunction<String, T>() {
+					@Override
+					public String evaluate(final T value) {
+						try {
+							return factory.serialize(value);
+						} catch (final JAXBException e) {
+							log.warn("cannot serialize", e);
+							throw new RuntimeException(e);
+						}
+					}
+				}));
+			}
+
+			@Override
+			public int getSize() {
+				return listener.getSize();
+			}
+		};
+	}
+
+	public JaxbFactory<T> getFactory() {
+		return factory;
+	}
+
+	public void setFactory(final JaxbFactory<T> factory) {
+		this.factory = factory;
+	}
+}
Index: modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/ResultSetServiceImplTest.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/ResultSetServiceImplTest.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/ResultSetServiceImplTest.java	(revision 45117)
@@ -0,0 +1,101 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.*; // NOPMD
+import static org.mockito.Mockito.*; // NOPMD
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+
+/**
+ * resultset service rmi implementation test.
+ *  
+ * @author marko
+ *
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class ResultSetServiceImplTest {
+
+	/**
+	 * mock resultset id.
+	 */
+	private static final String RS_ID = "123";
+
+	/**
+	 * instance under test.
+	 */
+	private transient ResultSetServiceImpl service;
+	
+	/**
+	 * custom property dao mock.
+	 */
+	@Mock
+	private transient ResultSetPropertyDao customPropertyDao;
+	
+	/**
+	 * resultset registry mock. 
+	 */
+	@Mock
+	private transient ResultSetRegistry resultsetRegistry;
+	
+	/**
+	 * resultset instance mock. 
+	 */
+	@Mock
+	private transient ResultSet resultSet;
+	
+	/**
+	 * setup. 
+	 */
+	@Before
+	public void setUp() {
+		service = new ResultSetServiceImpl();
+		service.setCustomPropertyDao(customPropertyDao);
+		service.setResultsetRegistry(resultsetRegistry);
+		
+		when(resultsetRegistry.getResultSetById(RS_ID)).thenReturn(resultSet);
+		when(resultSet.getIdentifier()).thenReturn(RS_ID);
+	}
+
+	/**
+	 * test get property.
+	 * @throws ResultSetException shouldn't happen
+	 */
+	@Test
+	public void testGetProperty() throws ResultSetException {
+		final Map<String, String> properties = new HashMap<String, String>();
+		properties.put("prefetch", "true");
+		
+		when(customPropertyDao.getProperties(resultSet)).thenReturn(properties);
+		when(resultSet.getNumberOfResults()).thenReturn(1);
+		
+		assertEquals("test builtin", "1", service.getProperty(RS_ID, "total"));
+		assertEquals("test builtin", RS_ID, service.getProperty(RS_ID, "rsId"));
+		
+		assertEquals("test custom", "true", service.getProperty(RS_ID, "prefetch"));
+		assertNull("test custom", service.getProperty(RS_ID, "unexistent"));
+	}
+
+	/**
+	 * get resultset status.
+	 * 
+	 * @throws ResultSetException shouldn't happen
+	 */
+	@Test
+	public void testGetRSStatus() throws ResultSetException {
+		when(resultSet.isOpen()).thenReturn(true);
+		
+		assertEquals("check open", service.getRSStatus(RS_ID), "open");
+		
+		when(resultSet.isOpen()).thenReturn(false);
+		assertEquals("check closed", service.getRSStatus(RS_ID), "closed");
+	}
+
+}
Index: modules/cnr-resultset-service/trunk/pom.xml
===================================================================
--- modules/cnr-resultset-service/trunk/pom.xml	(nonexistent)
+++ modules/cnr-resultset-service/trunk/pom.xml	(revision 45117)
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<parent>
+		<groupId>eu.dnetlib</groupId>
+		<artifactId>dnet-parent</artifactId>
+		<version>1.0.0</version>
+		<relativePath />
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>eu.dnetlib</groupId>
+	<artifactId>cnr-resultset-service</artifactId>
+	<packaging>jar</packaging>
+	<version>2.0.3-SNAPSHOT</version>
+	<scm>
+	  <developerConnection>scm:svn:https://svn.driver.research-infrastructures.eu/driver/dnet40/modules/cnr-resultset-service/trunk</developerConnection>
+	</scm>
+	<dependencies>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>${junit.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>com.google.guava</groupId>
+			<artifactId>guava</artifactId>
+			<version>${google.guava.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>cglib</groupId>
+			<artifactId>cglib-nodep</artifactId>
+			<version>2.2</version>
+		</dependency>
+		<dependency>
+			<groupId>org.mockito</groupId>
+			<artifactId>mockito-core</artifactId>
+			<version>1.6</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-test</artifactId>
+			<version>${spring.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-context-support</artifactId>
+			<version>${spring.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>eu.dnetlib</groupId>
+			<artifactId>cnr-rmi-api</artifactId>
+			<version>[2.0.0,3.0.0)</version>
+		</dependency>
+		<dependency>
+			<groupId>eu.dnetlib</groupId>
+			<artifactId>cnr-spring-utils</artifactId>
+			<version>[1.0.0,2.0.0)</version>
+		</dependency>
+		<dependency>
+			<groupId>eu.dnetlib</groupId>
+			<artifactId>cnr-service-common</artifactId>
+			<version>[2.0.0,3.0.0)</version>
+		</dependency>
+	</dependencies>
+</project>
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.properties
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.properties	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.properties	(revision 45117)
@@ -0,0 +1,10 @@
+services.is.resultset.resultSetRegistryCache.timeToIdle = 240
+services.is.resultset.resultSetRegistryMaxIdleTimeCache.timeToIdle = 240
+
+# jaxwsEndpointReferenceBuilder | staticResultSetServiceEprBuilder
+services.resultset.eprbuilder.bean = jaxwsEndpointReferenceBuilder
+services.resultset.endpoint.static.address = ${transport.soap.baseAddress}/resultSet
+
+services.is.resultset.push.timeToIdle=36000
+services.is.resultset.push.maxElementsInMemory=500
+services.is.resultset.push.maxElementsOnDisk=5000000
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSet.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSet.java	(revision 45117)
@@ -0,0 +1,151 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
+import eu.dnetlib.enabling.tools.ServiceResolver;
+import eu.dnetlib.miscutils.collections.MappedCollection;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+/**
+ * A resultset filter. Applies a transformation for every resultset record.
+ * 
+ * @author marko
+ * 
+ */
+public class MappedResultSet implements ResultSetListener, ResultSetAware {
+
+	/**
+	 * input resultset.
+	 */
+	private ResultSetService resultSetService;
+
+	/**
+	 * input resultset id.
+	 */
+	private String rsId;
+
+	/**
+	 * mapper function.
+	 */
+	private UnaryFunction<String, String> mapper;
+
+	/**
+	 * service resolver.
+	 */
+	private ServiceResolver serviceResolver;
+
+	private ResultSet resultSet;
+
+	/**
+	 * Create a new mapped resultset.
+	 * 
+	 * @param epr
+	 *            input resultset epr
+	 * @param mapper
+	 *            mapper function
+	 * @param serviceResolver
+	 *            service resolver
+	 */
+	public MappedResultSet(final W3CEndpointReference epr, final UnaryFunction<String, String> mapper, final ServiceResolver serviceResolver) {
+		super();
+
+		this.resultSetService = serviceResolver.getService(ResultSetService.class, epr);
+		this.rsId = serviceResolver.getResourceIdentifier(epr);
+
+		this.mapper = mapper;
+
+		this.serviceResolver = serviceResolver;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSetListener#getResult(int, int)
+	 */
+	@Override
+	public List<String> getResult(final int fromPosition, final int toPosition) {
+		return MappedCollection.listMap(getResultFromSource(fromPosition, toPosition), mapper);
+
+	}
+
+	protected List<String> getResultFromSource(final int fromPosition, final int toPosition) {
+		try {
+			List<String> res = resultSetService.getResult(rsId, fromPosition, toPosition, "waiting");
+			checkStatus();
+			return res;
+		} catch (final ResultSetException e) {
+			throw new IllegalStateException(e);
+		}
+	}
+
+	private void checkStatus() throws ResultSetException {
+		if (getResultSet().isOpen() && resultSetService.getRSStatus(rsId).equals("closed")) {
+			getResultSet().close();
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSetListener#getSize()
+	 */
+	@Override
+	public int getSize() {
+		try {
+			int numberOfElements = resultSetService.getNumberOfElements(rsId);
+			checkStatus();		
+			return numberOfElements;
+		} catch (final ResultSetException e) {
+			throw new IllegalStateException(e);
+		}
+	}
+
+	public ResultSetService getResultSetService() {
+		return resultSetService;
+	}
+
+	public void setResultSetService(final ResultSetService resultSetService) {
+		this.resultSetService = resultSetService;
+	}
+
+	public UnaryFunction<String, String> getMapper() {
+		return mapper;
+	}
+
+	public void setMapper(final UnaryFunction<String, String> mapper) {
+		this.mapper = mapper;
+	}
+
+	public ServiceResolver getServiceResolver() {
+		return serviceResolver;
+	}
+
+	@Required
+	public void setServiceResolver(final ServiceResolver serviceResolver) {
+		this.serviceResolver = serviceResolver;
+	}
+
+	@Override
+	public void setResultSet(ResultSet resultSet) {
+		this.resultSet = resultSet;
+	}
+
+	public ResultSet getResultSet() {
+		return resultSet;
+	}
+
+	public String getRsId() {
+		return rsId;
+	}
+
+	public void setRsId(String rsId) {
+		this.rsId = rsId;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalOpenResultSetFactoryImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalOpenResultSetFactoryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalOpenResultSetFactoryImpl.java	(revision 45117)
@@ -0,0 +1,23 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+public class EPRPoolingLocalOpenResultSetFactoryImpl extends LocalOpenResultSetFactoryImpl {
+	private ResultSetEPRPool pool;
+	
+	@Override
+	public W3CEndpointReference registerResultSet(ResultSet resultSet) {
+		return pool.registerResultSet(resultSet);
+	}
+
+	public ResultSetEPRPool getPool() {
+		return pool;
+	}
+
+	@Required
+	public void setPool(ResultSetEPRPool pool) {
+		this.pool = pool;
+	}
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/AbstractObservableResultset.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/AbstractObservableResultset.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/AbstractObservableResultset.java	(revision 45117)
@@ -0,0 +1,155 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import eu.dnetlib.enabling.resultset.observer.DelegationObserver;
+import eu.dnetlib.enabling.resultset.observer.Observable;
+
+
+/**
+ * Common stuff for resultset implementations bound to a ResultSetRegistry.
+ * 
+ * @author marko
+ * 
+ */
+public abstract class AbstractObservableResultset implements ResultSet, Observable {
+	/**
+	 * true if the resultset is destroyed.
+	 */
+	private boolean destroyed = false;
+
+	/**
+	 * true if the resultset is open.
+	 */
+	private boolean open;
+
+	/**
+	 * delegate the real job to a java.util.Observable object.
+	 */
+	private transient final java.util.Observable observable = new DelegationObservable();
+
+	/**
+	 * weak map for removing single observers later on.
+	 */
+	private transient Map<ResultSetRegistry, DelegationObserver> observers = new WeakHashMap<ResultSetRegistry, DelegationObserver>();
+
+	/**
+	 * java.util.Observable requires a "change" in the object to be made for the notifyObservers methods to trigger
+	 * actually the notification. We don't think this should be part of the base Observable/Observer pattern and thus
+	 * hide this fact. If an user of AbstractObservable wants this behavior it should implement her own change tracking
+	 * and avoid calling notifyObservers altogether. The rationale behind this choice is that not all dirty states can
+	 * be expressed using a stateful boolean instance variable like that implemented by java.util.Observable; some users
+	 * may prefer/need a lazy dirty flag instead.
+	 * 
+	 * @author marko
+	 * 
+	 */
+	static class DelegationObservable extends java.util.Observable {
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see java.util.Observable#notifyObservers()
+		 */
+		@Override
+		public void notifyObservers() {
+			setChanged();
+			super.notifyObservers();
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see java.util.Observable#notifyObservers(java.lang.Object)
+		 */
+		@Override
+		public void notifyObservers(final Object arg) {
+			setChanged();
+			super.notifyObservers(arg);
+		}
+
+	}	
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#destroy()
+	 */
+	@Override
+	public void destroy() {
+		if (!isDestroyed()) {
+			setDestroyed(true);
+			notifyObservers();
+			deleteObservers();
+		}
+	}
+
+	public void setDestroyed(final boolean destroyed) {
+		this.destroyed = destroyed;
+	}
+
+	@Override
+	public boolean isDestroyed() {
+		return destroyed;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#isOpen()
+	 */
+	@Override
+	public boolean isOpen() {
+		return open;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#close()
+	 */
+	@Override
+	public void close() {
+		open = false;
+	}
+
+	public void setOpen(final boolean open) {
+		this.open = open;
+	}
+
+	@Override
+	public void addObserver(final ResultSetRegistry observer) {
+		final DelegationObserver delegate = new DelegationObserver(this, observer);
+		observers.put(observer, delegate);
+		observable.addObserver(delegate);
+	}
+
+	protected void notifyObservers() {
+		observable.notifyObservers();
+	}
+
+	protected void notifyObservers(final Object arg) {
+		observable.notifyObservers(arg);
+	}
+
+	public int countObservers() {
+		return observable.countObservers();
+	}
+
+	public void deleteObserver(final java.util.Observer observer) {
+		observable.deleteObserver(observer);
+	}
+
+	public void deleteObserver(ResultSetRegistry observer) {
+		DelegationObserver delegate = observers.get(observer);
+		if(delegate != null) {
+			observable.deleteObserver(delegate);
+		}
+	}	
+
+	public void deleteObservers() {
+		observable.deleteObservers();
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSetFactory.java	(revision 45117)
@@ -0,0 +1,49 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+public class ParallelMappedResultSetFactory extends MappedResultSetFactory {
+
+	private ExecutorService executor;
+
+	private static final int QUEUE_SIZE = 40;
+
+	private int queueSize = QUEUE_SIZE;
+
+	private int cpus = 0;
+
+	public ParallelMappedResultSetFactory() {
+		super();
+
+		if (cpus == 0)
+			cpus = getNumberOfCPUs();
+		executor = new ThreadPoolExecutor(cpus, cpus, 5, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(queueSize),
+				new ThreadPoolExecutor.CallerRunsPolicy());
+	}
+
+	@Override
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final UnaryFunction<String, String> mapper) {
+		return getResultSetFactory().createResultSet(new ParallelMappedResultSet(source, mapper, getServiceResolver(), executor));
+	}
+
+	private int getNumberOfCPUs() {
+		return Runtime.getRuntime().availableProcessors();
+	}
+
+	public int getCpus() {
+		return cpus;
+	}
+
+	public void setCpus(int cpus) {
+		if(cpus > 0)
+			this.cpus = cpus;
+	}
+
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetImpl.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetImpl.java	(revision 45117)
@@ -0,0 +1,98 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Resultset backing implementation.
+ * 
+ * @author marko
+ * 
+ */
+public class LocalResultSetImpl extends AbstractObservableResultset implements ResultSet {
+
+	/**
+	 * rsId.
+	 */
+	private String identifier;
+
+	/**
+	 * this listener will provide the data to this local resultset by listening to events.
+	 */
+	private ResultSetListener listener;
+
+	/**
+	 * Construct a new local ResultSet which pulls data from the listener. If the listener implements ResultSetAware, it
+	 * will be injected with this instance.
+	 * 
+	 * @param listener
+	 *            a resultset listener
+	 */
+	public LocalResultSetImpl(final ResultSetListener listener) {
+		super();
+		this.listener = listener;
+
+		if (listener instanceof ResultSetAware)
+			((ResultSetAware) listener).setResultSet(this);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#getNumberOfResults()
+	 */
+	@Override
+	public int getNumberOfResults() {
+		return listener.getSize();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#getResults(int, int)
+	 */
+	@Override
+	public List<String> getResults(final int fromPosition, final int toPosition) {
+		int toPos = toPosition;
+		int fromPos = fromPosition;
+		if (!isOpen()) {
+			final int size = getNumberOfResults();
+			
+			if (size == 0)
+				return Lists.newArrayList();
+			
+			if (fromPos > size)
+				return Lists.newArrayList();
+
+			if (toPos > size)
+				toPos = size;
+		}
+		
+		if (fromPos < 1)
+			fromPos = 1;
+		if (toPos < fromPos)
+			toPos = fromPos;
+
+		return listener.getResult(fromPos, toPos);
+	}
+
+	@Override
+	public String getIdentifier() {
+		return identifier;
+	}
+
+	@Override
+	public void setIdentifier(final String identifier) {
+		this.identifier = identifier;
+	}
+
+	public ResultSetListener getListener() {
+		return listener;
+	}
+
+	public void setListener(final ResultSetListener listener) {
+		this.listener = listener;
+	}
+
+}

Property changes on: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetImpl.java
___________________________________________________________________
Added: svn:mergeinfo
## -0,0 +0,0 ##
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetImpl.java	(revision 45117)
@@ -0,0 +1,98 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Resultset backing implementation.
+ * 
+ * @author marko
+ * 
+ */
+public class LocalResultSetImpl extends AbstractObservableResultset implements ResultSet {
+
+	/**
+	 * rsId.
+	 */
+	private String identifier;
+
+	/**
+	 * this listener will provide the data to this local resultset by listening to events.
+	 */
+	private ResultSetListener listener;
+
+	/**
+	 * Construct a new local ResultSet which pulls data from the listener. If the listener implements ResultSetAware, it
+	 * will be injected with this instance.
+	 * 
+	 * @param listener
+	 *            a resultset listener
+	 */
+	public LocalResultSetImpl(final ResultSetListener listener) {
+		super();
+		this.listener = listener;
+
+		if (listener instanceof ResultSetAware)
+			((ResultSetAware) listener).setResultSet(this);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#getNumberOfResults()
+	 */
+	@Override
+	public int getNumberOfResults() {
+		return listener.getSize();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#getResults(int, int)
+	 */
+	@Override
+	public List<String> getResults(final int fromPosition, final int toPosition) {
+		int toPos = toPosition;
+		int fromPos = fromPosition;
+		if (!isOpen()) {
+			final int size = getNumberOfResults();
+			
+			if (size == 0)
+				return Lists.newArrayList();
+			
+			if (fromPos > size)
+				return Lists.newArrayList();
+
+			if (toPos > size)
+				toPos = size;
+		}
+		
+		if (fromPos < 1)
+			fromPos = 1;
+		if (toPos < fromPos)
+			toPos = fromPos;
+
+		return listener.getResult(fromPos, toPos);
+	}
+
+	@Override
+	public String getIdentifier() {
+		return identifier;
+	}
+
+	@Override
+	public void setIdentifier(final String identifier) {
+		this.identifier = identifier;
+	}
+
+	public ResultSetListener getListener() {
+		return listener;
+	}
+
+	public void setListener(final ResultSetListener listener) {
+		this.listener = listener;
+	}
+
+}

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetImpl.java
___________________________________________________________________
Added: svn:mergeinfo
## -0,0 +0,0 ##
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSet.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSet.java	(revision 45117)
@@ -0,0 +1,116 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * an open ResultSet that can be iterated to get it's data results.
+ * 
+ * @author claudio
+ * 
+ */
+public class IterableResultSet implements ResultSetListener, ResultSetAware {
+
+	/**
+	 * logger.
+	 */
+	private static final Log log = LogFactory.getLog(IterableResultSet.class);
+
+	/**
+	 * the container for the data results.
+	 */
+	private ResultSet resultSet;
+
+	/**
+	 * the list that provides data for this resultSet.
+	 */
+	private FetchList<String> fetchList;
+
+	private int optionalNumberOfElements;
+
+	/**
+	 * 
+	 * @param iter
+	 * @param fetchSize
+	 */
+	protected IterableResultSet(Iterable<String> iter, int fetchSize) {
+		fetchList = new FetchList<String>(iter.iterator(), fetchSize);
+		if (iter instanceof SizedIterable<?>) {
+			optionalNumberOfElements = ((SizedIterable<?>) iter).getNumberOfElements();
+		} else {
+			optionalNumberOfElements = -1;
+		}
+	}
+
+	/**
+	 * @param fromPosition
+	 * @param toPosition
+	 * @return <T> List
+	 */
+	@Override
+	public List<String> getResult(int fromPosition, int toPosition) {
+
+		log.debug(" - getting result from " + fromPosition + " to " + toPosition + ", consumedElements: " + fetchList.getConsumedElements());
+
+		if (fromPosition != fetchList.getConsumedElements() + 1)
+			throw new RuntimeException("Unexpected value for 'fromPosition' parameter");
+		if (toPosition < fromPosition)
+			throw new RuntimeException("'fromPosition' must be lower or equal than 'toPosition'");
+
+		List<String> result = new ArrayList<String>();
+
+		for (int i = fromPosition; i <= toPosition; i++) {
+			if (fetchList.size() > 0)
+				result.add(fetchList.poll());
+			else
+				break;
+		}
+
+		ensureClosed();
+
+		return result;
+	}
+
+	private void ensureClosed() {
+		if (fetchList.size() == 0 && resultSet.isOpen()) {
+			log.info(">>>>>>>>>>> closing resultset <<<<<<<<<<<<<");
+			close();
+		}
+	}
+
+	public String getRSStatus() {
+		if (resultSet.isOpen())
+			return "open";
+		return "closed";
+	}
+
+	@Override
+	public int getSize() {
+		ensureClosed();
+
+		if (optionalNumberOfElements == -1)
+			return fetchList.getTotalElements();
+		else
+			return optionalNumberOfElements;
+	}
+
+	/**
+	 * closes the resultset.
+	 */
+	protected void close() {
+		resultSet.close();
+	}
+
+	@Override
+	public void setResultSet(ResultSet resultSet) {
+		this.resultSet = resultSet;
+	}
+
+	public ResultSet getResultSet() {
+		return resultSet;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSetFactory.java	(revision 45117)
@@ -0,0 +1,26 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * Create a new resultset which takes each record of the input resultset and counts them.
+ * 
+ * @author claudio
+ * 
+ */
+public class CountingResultSetFactory extends MappedResultSetFactory {
+
+	/**
+	 * Create a new resultset which takes each record of the input resultset and counts them.
+	 * 
+	 * @param source
+	 *            source resultset epr
+	 * @param mapper
+	 *            mapper function
+	 * @return mapped resultset epr
+	 */
+	public W3CEndpointReference createCountingResultSet(final W3CEndpointReference source) {
+		return getResultSetFactory().createResultSet(new CountingResultSet(source, getServiceResolver()));
+	}
+
+}

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSetFactory.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetFactory.java	(revision 45117)
@@ -0,0 +1,46 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.annotation.Resource;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.enabling.tools.ServiceResolver;
+
+public class CachingResultSetFactory {
+	/**
+	 * underlying resultset factory, which exposes local resultsets to the world.
+	 */
+	private ResultSetFactory resultSetFactory;
+
+	@Resource
+	private ServiceResolver serviceResolver;
+	
+	/**
+	 * @param items
+	 * @param size
+	 *            the size of the iterable
+	 * @return
+	 */
+	public W3CEndpointReference createCachingResultSet(W3CEndpointReference epr) {
+		return resultSetFactory.createResultSet(new CachingResultSetListener(epr, serviceResolver));
+	}
+
+	public ResultSetFactory getResultSetFactory() {
+		return resultSetFactory;
+	}
+
+	@Required
+	public void setResultSetFactory(ResultSetFactory resultSetFactory) {
+		this.resultSetFactory = resultSetFactory;
+	}
+
+	public ServiceResolver getServiceResolver() {
+		return serviceResolver;
+	}
+
+	public void setServiceResolver(ServiceResolver serviceResolver) {
+		this.serviceResolver = serviceResolver;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/TypedResultSetListener.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/TypedResultSetListener.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/TypedResultSetListener.java	(revision 45117)
@@ -0,0 +1,34 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+/**
+ * A TypedResultSetListener is a pull interface to a ResultSet.
+ * 
+ * The Resultset will call method of ResultSetListener implementors whenever it needs to pull some data and provide it
+ * to clients. The ResultSet service acts as a decouple point between the producer and the consumer.
+ * 
+ * @author marko
+ * 
+ */
+public interface TypedResultSetListener<T> {
+
+	/**
+	 * get a single page of results.
+	 * 
+	 * @param fromPosition
+	 *            from 1
+	 * @param toPosition
+	 *            last included
+	 * @return page of results
+	 */
+	List<T> getResult(int fromPosition, int toPosition);
+
+	/**
+	 * get number of elements.
+	 * 
+	 * @return number of elements
+	 */
+	int getSize();
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetFactory.java	(revision 45117)
@@ -0,0 +1,32 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+public class StreamingResultSetFactory {
+	/**
+	 * underlying resultset factory, which exposes local resultsets to the world.
+	 */
+	private ResultSetFactory resultSetFactory;
+
+	/**
+	 * @param items
+	 * @param size the size of the iterable
+	 * @return
+	 */
+	public W3CEndpointReference createStreamingResultSet(final Iterable<String> items, int size) {
+		return resultSetFactory.createResultSet(new StreamingResultSetListener(items.iterator(), size));
+	}
+
+	
+	public ResultSetFactory getResultSetFactory() {
+		return resultSetFactory;
+	}
+
+	@Required
+	public void setResultSetFactory(ResultSetFactory resultSetFactory) {
+		this.resultSetFactory = resultSetFactory;
+	}
+
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetListener.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetListener.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetListener.java	(revision 45117)
@@ -0,0 +1,132 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Exposes an iterable through our resultset protocol.
+ * 
+ * <p>
+ * The resultset protocol is constructed as if it were random access. Some kind of sources, like an iterable, is not
+ * random access. The consumer of such a resultset knows that, and won't try to access the resultset randomly. However,
+ * it could ask for some data which is already sent, because of retries caused by network issues.
+ * </p>
+ * 
+ * @author marko
+ * 
+ */
+public class StreamingResultSetListener implements ResultSetListener, ResultSetAware {
+	private static final Log log = LogFactory.getLog(StreamingResultSetListener.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	private ResultSet resultSet;
+
+	private Iterable<String> iterable;
+	private Iterator<String> items;
+	private int size;
+
+	private int lastFrom = 0;
+	private int lastTo = 0;
+	private List<String> lastChunk;
+
+	public StreamingResultSetListener(Iterable<String> items, int size) {
+		this(items.iterator(), size);
+		this.iterable = items;
+	}
+
+	public StreamingResultSetListener(Iterator<String> items, int size) {
+		super();
+		this.items = items;
+		this.size = size;
+	}
+
+	protected void reset() {
+		lastFrom = 0;
+		items = iterable.iterator();
+	}
+
+	@Override
+	public List<String> getResult(int from, int to) {
+
+		log.debug("STREAM: getResult(" + from + ", " + to + ")");
+
+		// handle retry because of network error.
+		if (from == lastFrom && to == lastTo)
+			return lastChunk;
+
+		if (from != lastTo + 1) {
+			if (from == 1 && iterable != null)
+				reset();
+			else
+				throw new IllegalArgumentException("this resultset is not random access, you can only retry last chunk only, asked from " + from + " to "
+						+ to + " but lastTo = " + lastTo + ". Size = " + size);
+		}
+
+		List<String> chunk = new ArrayList<String>();
+		for (int i = from; i <= to; i++)
+			chunk.add(items.next());
+
+		if (resultSet != null && !items.hasNext())
+			resultSet.close();
+
+		lastFrom = from;
+		lastTo = to;
+		lastChunk = chunk;
+
+		return chunk;
+	}
+
+	@Override
+	public int getSize() {
+		return size;
+	}
+
+	public void setSize(int size) {
+		this.size = size;
+	}
+
+	public Iterator<String> getItems() {
+		return items;
+	}
+
+	public void setItems(Iterator<String> items) {
+		this.items = items;
+	}
+
+	public int getLastFrom() {
+		return lastFrom;
+	}
+
+	public void setLastFrom(int lastFrom) {
+		this.lastFrom = lastFrom;
+	}
+
+	public int getLastTo() {
+		return lastTo;
+	}
+
+	public void setLastTo(int lastTo) {
+		this.lastTo = lastTo;
+	}
+
+	public List<String> getLastChunk() {
+		return lastChunk;
+	}
+
+	public void setLastChunk(List<String> lastChunk) {
+		this.lastChunk = lastChunk;
+	}
+
+	public ResultSet getResultSet() {
+		return resultSet;
+	}
+
+	@Override
+	public void setResultSet(ResultSet resultSet) {
+		this.resultSet = resultSet;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/LocalOpenResultSetFactoryImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/LocalOpenResultSetFactoryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/LocalOpenResultSetFactoryImpl.java	(revision 45117)
@@ -0,0 +1,23 @@
+package eu.dnetlib.enabling.resultset;
+
+/**
+ * Creates an "open" (unbounded, unfreezed) local resultset.
+ * 
+ * @author marko
+ *
+ */
+public class LocalOpenResultSetFactoryImpl extends LocalResultSetFactoryImpl {
+
+	/** 
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.LocalResultSetFactoryImpl#createInstance(eu.dnetlib.enabling.resultset.ResultSetListener)
+	 */
+	@Override
+	protected LocalResultSetImpl createInstance(final ResultSetListener provider) {
+		final LocalResultSetImpl instance = super.createInstance(provider);
+		instance.setOpen(true);
+		return instance;
+	}
+
+
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetFactoryImpl.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetFactoryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetFactoryImpl.java	(revision 45117)
@@ -0,0 +1,38 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * This factory creates resultset bound to a given resultset registry shared with a resultset service which exposed them
+ * to the outside world.
+ *
+ * It's tightly coupled with a local instance of the ResultSetService.
+ *
+ * @see eu.dnetlib.enabling.resultset.ResultSetServiceImpl
+ *
+ * @author marko
+ *
+ */
+public class LocalResultSetFactoryImpl extends AbstractResultSetFactory {
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see eu.dnetlib.enabling.resultset.ResultSetFactory#createResultSet(eu.dnetlib.enabling.resultset.ResultSetListener)
+	 */
+	@Override
+	public W3CEndpointReference createResultSet(final ResultSetListener provider) {
+		return registerResultSet(createInstance(provider));
+	}
+
+	/**
+	 * create a new local resultset instance. Subclasses may override this to supply additional configuration.
+	 *
+	 * @param provider provider
+	 * @return a new resultset instance.
+	 */
+	protected LocalResultSetImpl createInstance(final ResultSetListener provider) {
+		return new LocalResultSetImpl(provider);
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/AbstractResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/AbstractResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/AbstractResultSetFactory.java	(revision 45117)
@@ -0,0 +1,38 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * Resultset factories bound to a resultset service, from which it takes the resultset registry and the epr builder.
+ *
+ * @author marko
+ *
+ */
+public abstract class AbstractResultSetFactory implements ResultSetFactory {
+
+	/**
+	 * resultset service.
+	 */
+	private ResultSetServiceImpl resultSetService;
+
+	/**
+	 * Register a resultset instance to the underlying resultset registry and returns
+	 * and EPR to accessible through the resultset service.
+	 *
+	 * @param resultSet resultset instance
+	 * @return epr to the newly created resultset
+	 */
+	public W3CEndpointReference registerResultSet(final ResultSet resultSet) {
+		resultSetService.getResultsetRegistry().addResultSet(resultSet);
+		return resultSetService.getEprBuilder().getEndpointReference(resultSetService.getEndpoint(), resultSet.getIdentifier());
+	}
+
+	public ResultSetServiceImpl getResultSetService() {
+		return resultSetService;
+	}
+
+	public void setResultSetService(final ResultSetServiceImpl resultSetService) {
+		this.resultSetService = resultSetService;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImpl.java	(revision 45117)
@@ -0,0 +1,99 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import eu.dnetlib.enabling.resultset.AbstractObservableResultset;
+
+/**
+ * a push resultset which holds it's data in a transient cache.
+ *
+ * @author marko
+ *
+ */
+public class TransientPushResultSetImpl extends AbstractObservableResultset implements PushResultSet {
+
+	/**
+	 * logger.
+	 */
+	private static final Log log = LogFactory.getLog(TransientPushResultSetImpl.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	/**
+	 * dao.
+	 */
+	private final transient TransientPushResultSetDao dao;
+
+	/**
+	 * rsId.
+	 */
+	private String identifier;
+
+	/**
+	 * constructed by the transient push resultset factory.
+	 *
+	 * @param dao dao
+	 */
+	public TransientPushResultSetImpl(final TransientPushResultSetDao dao) {
+		super();
+		this.dao = dao;
+		setOpen(true);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see eu.dnetlib.enabling.resultset.push.PushResultSet#addElements(java.util.List)
+	 */
+	@Override
+	public void addElements(final List<String> elements) {
+		log.debug("adding to push RS: " + elements);
+
+		if (isOpen())
+			dao.addElements(getIdentifier(), elements);
+		else
+			throw new IllegalStateException("cannot write to a closed push resultset");
+	}
+
+	@Override
+	public int getNumberOfResults() {
+		return dao.getSize(getIdentifier());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#getResults(int, int)
+	 */
+	@Override
+	public List<String> getResults(final int fromPosition, final int toPosition) {
+
+		final int size = getNumberOfResults();
+		int toPos = toPosition;
+		int fromPos = fromPosition;
+		if (fromPos > size)
+			fromPos = size;
+		if (toPos > size)
+			toPos = size;
+
+		log.debug("calling get elements: " + getIdentifier() + " from " + fromPos + " to " + toPos);
+		return dao.getElements(getIdentifier(), fromPos, toPos);
+	}
+
+	public TransientPushResultSetDao getDao() {
+		return dao;
+	}
+
+	@Override
+	public String getIdentifier() {
+		return identifier;
+	}
+
+	@Override
+	public void setIdentifier(final String identifier) {
+		this.identifier = identifier;
+	}
+
+
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImpl.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImpl.java	(revision 45117)
@@ -0,0 +1,99 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import eu.dnetlib.enabling.resultset.AbstractObservableResultset;
+
+/**
+ * a push resultset which holds it's data in a transient cache.
+ *
+ * @author marko
+ *
+ */
+public class TransientPushResultSetImpl extends AbstractObservableResultset implements PushResultSet {
+
+	/**
+	 * logger.
+	 */
+	private static final Log log = LogFactory.getLog(TransientPushResultSetImpl.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	/**
+	 * dao.
+	 */
+	private final transient TransientPushResultSetDao dao;
+
+	/**
+	 * rsId.
+	 */
+	private String identifier;
+
+	/**
+	 * constructed by the transient push resultset factory.
+	 *
+	 * @param dao dao
+	 */
+	public TransientPushResultSetImpl(final TransientPushResultSetDao dao) {
+		super();
+		this.dao = dao;
+		setOpen(true);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see eu.dnetlib.enabling.resultset.push.PushResultSet#addElements(java.util.List)
+	 */
+	@Override
+	public void addElements(final List<String> elements) {
+		log.debug("adding to push RS: " + elements);
+
+		if (isOpen())
+			dao.addElements(getIdentifier(), elements);
+		else
+			throw new IllegalStateException("cannot write to a closed push resultset");
+	}
+
+	@Override
+	public int getNumberOfResults() {
+		return dao.getSize(getIdentifier());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#getResults(int, int)
+	 */
+	@Override
+	public List<String> getResults(final int fromPosition, final int toPosition) {
+
+		final int size = getNumberOfResults();
+		int toPos = toPosition;
+		int fromPos = fromPosition;
+		if (fromPos > size)
+			fromPos = size;
+		if (toPos > size)
+			toPos = size;
+
+		log.debug("calling get elements: " + getIdentifier() + " from " + fromPos + " to " + toPos);
+		return dao.getElements(getIdentifier(), fromPos, toPos);
+	}
+
+	public TransientPushResultSetDao getDao() {
+		return dao;
+	}
+
+	@Override
+	public String getIdentifier() {
+		return identifier;
+	}
+
+	@Override
+	public void setIdentifier(final String identifier) {
+		this.identifier = identifier;
+	}
+
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactory.java	(revision 45117)
@@ -0,0 +1,7 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import eu.dnetlib.miscutils.factory.Factory;
+
+public interface ResultSetDescriptorFactory extends Factory<ResultSetDescriptor> {
+
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/AbstractPushResultSetFactoryImpl.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/AbstractPushResultSetFactoryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/AbstractPushResultSetFactoryImpl.java	(revision 45117)
@@ -0,0 +1,44 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.enabling.resultset.ResultSetServiceImpl;
+
+/**
+ * push resultset factory.
+ *
+ * @author marko
+ *
+ */
+public abstract class AbstractPushResultSetFactoryImpl implements PushResultSetFactory {
+	/**
+	 * resultset service.
+	 */
+	private ResultSetServiceImpl resultSetService;
+
+	/**
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.push.PushResultSetFactory#createPushResultSet(int)
+	 */
+	@Override
+	public W3CEndpointReference createPushResultSet(final int maxIdleTime) {
+		final PushResultSet resultSet = newInstance();
+		resultSetService.getResultsetRegistry().addResultSet(resultSet, maxIdleTime);
+		return resultSetService.getEprBuilder().getEndpointReference(resultSetService.getEndpoint(), resultSet.getIdentifier());
+	}
+
+	/**
+	 * subclasses should override it and create a new push resultset instance.
+	 * @return push resultset instance
+	 */
+	protected abstract PushResultSet newInstance();
+
+	public ResultSetServiceImpl getResultSetService() {
+		return resultSetService;
+	}
+
+	public void setResultSetService(final ResultSetServiceImpl resultSetService) {
+		this.resultSetService = resultSetService;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDao.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDao.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDao.java	(revision 45117)
@@ -0,0 +1,19 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.Map;
+
+/**
+ * access resultset properties.
+ * 
+ * @author marko
+ *
+ */
+public interface ResultSetPropertyDao {
+	/**
+	 * return a map of custom resultset properties.
+	 * 
+	 * @param resultSet resultset
+	 * @return property map
+	 */
+	Map<String, String> getProperties(ResultSet resultSet);
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetFactory.java	(revision 45117)
@@ -0,0 +1,19 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * Creates a resultset service from a producer.
+ * 
+ * @author marko
+ *
+ */
+public interface ResultSetFactory {
+	/**
+	 * TODO other parameters like expiration time etc.
+	 * 
+	 * @param provider a resultset listener which provides the data
+	 * @return an EPR to the resultset.
+	 */
+	W3CEndpointReference createResultSet(ResultSetListener provider);
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptor.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptor.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptor.java	(revision 45117)
@@ -0,0 +1,156 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import java.io.Serializable;
+import java.util.Iterator;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Describes a push resultset.
+ *
+ * <p>
+ * A push resultset stores it's data in several ranges
+ * </p>
+ *
+ * @author marko
+ *
+ */
+public class ResultSetDescriptor implements Serializable {
+
+	/**
+	 * logger.
+	 */
+	private static final Log log = LogFactory.getLog(Range.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	/**
+	 * This class describes a range.
+	 *
+	 * @author marko
+	 *
+	 */
+	public class Range {
+		private int range;
+		private int begin;
+		private int end;
+
+		public Range(final int range, final int begin, final int end) {
+			super();
+			this.range = range;
+			this.begin = begin;
+			this.end = end;
+		}
+
+		@Override
+		public String toString() {
+			return "Range(" + range + ", " + begin + ", " + end + ")";
+		}
+
+		public int getRange() {
+			return range;
+		}
+
+		public void setRange(final int range) {
+			this.range = range;
+		}
+
+		public int getBegin() {
+			return begin;
+		}
+
+		public void setBegin(final int begin) {
+			this.begin = begin;
+		}
+
+		public int getEnd() {
+			return end;
+		}
+
+		public void setEnd(final int end) {
+			this.end = end;
+		}
+	}
+
+	/**
+	 *
+	 */
+	private static final long serialVersionUID = 7699992350256317181L;
+
+	private int rangeLength = 100;
+
+	private int ranges = 0;
+
+	public int getLastRange() {
+		return ranges - 1;
+	}
+
+	/**
+	 * @param fromPosition
+	 *            1 based count
+	 * @param toPosition
+	 *            1 based count
+	 * @return
+	 */
+	public Iterable<Range> getRangesContaining(final int fromPosition, final int toPosition) {
+
+		final int fromRange = (fromPosition - 1) / rangeLength;
+		int ttoRange = (int) Math.ceil((toPosition * 1.0) / rangeLength);
+
+		if (ttoRange > ranges)
+			ttoRange = ranges;
+
+		final int toRange = ttoRange;
+
+		log.debug("FROM range: " + fromRange);
+		log.debug("TTO range: " + ttoRange);
+		log.debug("TO range: " + toRange);
+
+		return new Iterable<Range>() {
+
+			@Override
+			public Iterator<Range> iterator() {
+				return new Iterator<Range>() {
+
+					int current = fromRange;
+
+					@Override
+					public boolean hasNext() {
+						return current < toRange;
+					}
+
+					@Override
+					public Range next() {
+						int begin = 0;
+						int end = rangeLength;
+						if (current == fromRange)
+							begin = (fromPosition - 1) % rangeLength;
+						if ((current + 1) == toRange)
+							end = (toPosition - 1) % rangeLength + 1;
+						return new Range(current++, begin, end);
+					}
+
+					@Override
+					public void remove() {
+						throw new IllegalStateException("text");
+					}
+				};
+			}
+		};
+	}
+
+	public int getRangeLength() {
+		return rangeLength;
+	}
+
+	public void setRangeLength(final int rangeLength) {
+		this.rangeLength = rangeLength;
+	}
+
+	public int getRanges() {
+		return ranges;
+	}
+
+	public void setRanges(final int ranges) {
+		this.ranges = ranges;
+	}
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/push/AbstractTransientPushResultSetDaoTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/push/AbstractTransientPushResultSetDaoTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/push/AbstractTransientPushResultSetDaoTest.java	(revision 45117)
@@ -0,0 +1,223 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import static org.junit.Assert.*; // NOPMD
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.miscutils.cache.Cache;
+
+/**
+ * subclass this unit test class and provide a concrete transient push resultset dao implementation.
+ *
+ * @author marko
+ *
+ */
+@Ignore
+public abstract class AbstractTransientPushResultSetDaoTest {
+	/**
+	 * logger.
+	 */
+	private static final Log log = LogFactory.getLog(AbstractTransientPushResultSetDaoTest.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	/**
+	 * test first element.
+	 */
+	private static final String TWO = "two";
+
+	/**
+	 * test second element.
+	 */
+	private static final String ONE = "one";
+
+	/**
+	 * some key.
+	 */
+	private static final String RS_ID = "123";
+
+	/**
+	 * instance under test.
+	 */
+	private TransientPushResultSetDao dao;
+
+	/**
+	 * prepare the instance under test.
+	 *
+	 */
+	@Before
+	public void setUp() {
+		setDao(newInstance());
+	}
+
+	/**
+	 * specific unit tests will override this method and provide a concrete instance to test.
+	 *
+	 * @return new transient push resultset dao instance
+	 */
+	protected abstract TransientPushResultSetDao newInstance();
+
+	/**
+	 * test add elements.
+	 */
+	@Test
+	public void testAddElements() {
+		final List<String> freshGet = getDao().getElements(RS_ID, 1, 0);
+		assertNotNull("fresh get", freshGet);
+		assertEquals("fresh get", 0, freshGet.size());
+
+		final List<String> list = new ArrayList<String>();
+		list.add(ONE);
+
+		getDao().addElements(RS_ID, list);
+
+		final List<String> firstGet = getDao().getElements(RS_ID, 1, 1);
+		assertEquals("first get", 1, firstGet.size());
+		assertEquals("first get", ONE, firstGet.get(0));
+
+		final List<String> listAppend = new ArrayList<String>();
+		listAppend.add(TWO);
+
+		getDao().addElements(RS_ID, listAppend);
+
+		final List<String> secondGet = getDao().getElements(RS_ID, 1, 2);
+		assertEquals("second get", 2, secondGet.size());
+		assertEquals("second get", ONE, secondGet.get(0));
+		assertEquals("second get", TWO, secondGet.get(1));
+
+		final List<String> listBig = new ArrayList<String>();
+		for (int i = 0; i < 90; i++)
+			listBig.add(Integer.toString(i));
+
+		getDao().addElements(RS_ID, listBig);
+
+		final List<String> thirdGet = getDao().getElements(RS_ID, 3, 90);
+		assertEquals("third get", 88, thirdGet.size());
+		assertEquals("third get", "0", thirdGet.get(0));
+		assertEquals("third get", "1", thirdGet.get(1));
+	}
+
+	/**
+	 * check get elements.
+	 */
+	@Test
+	public void testGetElements() {
+		final List<String> list = new ArrayList<String>();
+		list.add(ONE);
+
+		getDao().addElements(RS_ID, list);
+
+		final List<String> res = getDao().getElements(RS_ID, 1, 1);
+		assertEquals("check size", 1, res.size());
+		assertEquals("check element", ONE, res.get(0));
+	}
+
+	/**
+	 * introduced for reproducing of #904. Thanks to Jochen for this one.
+	 */
+	@Test(expected = IllegalArgumentException.class)
+	public void testAddElementsDifferentSize() {
+		List<Integer> sizes = Lists.newArrayList(100, 200, 300, 99);
+		int run = 0;
+		int total = 0;
+
+		List<String> records = new LinkedList<String>();
+		for (int size : sizes) {
+			for (int i = 0; i < size; i++)
+				records.add("bla-" + run + "-" + i);
+
+			dao.addElements(RS_ID, records);
+			records.clear();
+
+			total += size;
+			run++;
+		}
+
+		assertEquals("check size", total, dao.getSize(RS_ID));
+	}
+
+	/**
+	 * introduced for reproducing of #904. with correct size (limited by 100)
+	 */
+	@Test
+	public void testAddElementsDifferentSizeCorrectSize() {
+		List<Integer> sizes = Lists.newArrayList(51, 51, 51, 51);
+
+		int total = 0;
+		int run = 0;
+		String lastName = null;
+
+		List<String> records = new LinkedList<String>();
+		for (int size : sizes) {
+			for (int i = 0; i < size; i++) {
+				lastName = "bla-" + run + "-" + i;
+				records.add(lastName);
+			}
+
+			dao.addElements(RS_ID, records);
+			records.clear();
+
+			total += size;
+			run++;
+		}
+
+		inspect();
+
+		assertEquals("check size", total, dao.getSize(RS_ID));
+		assertEquals("check last", lastName, dao.getElements(RS_ID, total, total).get(0));
+
+		assertEquals("check first page", "bla-0-11", dao.getElements(RS_ID, 12, 12).get(0));
+		assertEquals("check last page", "bla-1-11", dao.getElements(RS_ID, 51 + 12, 51 + 12).get(0));
+
+		assertEquals("check range", 10, dao.getElements(RS_ID, 1, 10).size());
+		assertEquals("check range", 10, dao.getElements(RS_ID, 51 + 1, 51 + 10).size());
+		assertEquals("check range", 51, dao.getElements(RS_ID, 1, 51).size());
+		assertEquals("check range", 52, dao.getElements(RS_ID, 1, 52).size());
+		assertEquals("check range", 51, dao.getElements(RS_ID, 2, 52).size());
+
+		assertEquals("check range", 100, dao.getElements(RS_ID, 1, 100).size());
+		assertEquals("check range", 99, dao.getElements(RS_ID, 2, 100).size());
+		assertEquals("check range", 100, dao.getElements(RS_ID, 2, 101).size());
+
+		assertEquals("check range", 200, dao.getElements(RS_ID, 2, 201).size());
+	}
+
+	private void inspect() {
+		CacheTransientResultSetDaoImpl dao = (CacheTransientResultSetDaoImpl) this.dao;
+		ResultSetDescriptor desc = dao.getResultSetCache().get(RS_ID);
+		Cache<String, List<String>> cache = dao.getCache();
+
+		log.debug("----------------");
+		log.debug("ranges: " + desc.getRanges());
+		log.debug("last range index: " + desc.getLastRange());
+		for (int i = 0; i < desc.getRanges(); i++) {
+			final List<String> range = cache.get(RS_ID + "-" + i);
+			log.debug("range: " + i + " has " + range.size() + " elements");
+			log.debug(" " + range);
+		}
+
+		log.debug("----------------");
+	}
+
+	@Test
+	public void testSizeOfEmpty() {
+		assertEquals("empty size", 0, dao.getSize(RS_ID));
+	}
+
+	public TransientPushResultSetDao getDao() {
+		return dao;
+	}
+
+	public void setDao(final TransientPushResultSetDao dao) {
+		this.dao = dao;
+	}
+
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/CacheTransientResultSetDaoImpl.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/CacheTransientResultSetDaoImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/CacheTransientResultSetDaoImpl.java	(revision 45117)
@@ -0,0 +1,179 @@
+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<String, List<String>> cache;
+
+	/**
+	 * resultsets
+	 */
+	private Cache<String, ResultSetDescriptor> resultSetCache;
+
+	/**
+	 * resultset descriptor factory.
+	 */
+	@Resource
+	private Factory<ResultSetDescriptor> 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<String> 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<String> lastRange = cache.get(key + "-" + lastRangeIndex);
+			log.debug("stored last range: " + lastRange);
+
+			if (lastRange == null) {
+				lastRange = new ArrayList<String>();
+				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<String> nextRange = new ArrayList<String>(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<String> 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<String> res = new ArrayList<String>();
+
+		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<String, List<String>> getCache() {
+		return cache;
+	}
+
+	@Required
+	public void setCache(final Cache<String, List<String>> cache) {
+		this.cache = cache;
+	}
+
+	public Cache<String, ResultSetDescriptor> getResultSetCache() {
+		return resultSetCache;
+	}
+
+	@Required
+	public void setResultSetCache(final Cache<String, ResultSetDescriptor> resultSetCache) {
+		this.resultSetCache = resultSetCache;
+	}
+
+	public Factory<ResultSetDescriptor> getResultSetDescriptorFactory() {
+		return resultSetDescriptorFactory;
+	}
+
+	public void setResultSetDescriptorFactory(final Factory<ResultSetDescriptor> resultSetDescriptorFactory) {
+		this.resultSetDescriptorFactory = resultSetDescriptorFactory;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImplTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImplTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImplTest.java	(revision 45117)
@@ -0,0 +1,166 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import static org.junit.Assert.*; // NOPMD
+import static org.mockito.Mockito.*; // NOPMD
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.enabling.resultset.ResultSetRegistry;
+
+/**
+ * test the transient push resultset.
+ *
+ * @author marko
+ *
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class TransientPushResultSetImplTest {
+
+	/**
+	 * first test value.
+	 */
+	private static final String ONE = "one";
+
+	/**
+	 * second test value.
+	 */
+	private static final String TWO = "two";
+
+	/**
+	 * test rs id.
+	 */
+	private static final String RS_ID = "123";
+
+	/**
+	 * instance to be tested.
+	 */
+	private transient TransientPushResultSetImpl resultSet;
+
+	/**
+	 * dao mock.
+	 */
+	@Mock
+	private transient TransientPushResultSetDao dao;
+
+	/**
+	 * resultset registry mock.
+	 */
+	@Mock
+	private transient ResultSetRegistry registry;
+
+	/**
+	 * setup class to be tested.
+	 *
+	 * @throws Exception
+	 */
+	@Before
+	public void setUp() {
+		resultSet = new TransientPushResultSetImpl(dao);
+		resultSet.setIdentifier(RS_ID);
+		resultSet.getDao(); // getter code coverage hack
+	}
+
+	/**
+	 * test adding elements.
+	 */
+	@Test
+	public void testAddElements() {
+		final List<String> list = new ArrayList<String>();
+		list.add(ONE);
+
+		resultSet.addElements(list);
+
+		verify(dao).addElements(RS_ID, list);
+		assertNotNull("dummy", resultSet);
+	}
+
+	/**
+	 * test get number of results.
+	 */
+	@Test
+	public void testGetNumberOfResults() {
+		when(dao.getSize(RS_ID)).thenReturn(1);
+
+		assertEquals("check size", 1, resultSet.getNumberOfResults());
+	}
+
+	/**
+	 * get result.
+	 */
+	@Test
+	public void testGetResults() {
+		final List<String> list = new ArrayList<String>();
+		list.add(TWO);
+
+		when(dao.getSize(RS_ID)).thenReturn(2);
+		when(dao.getElements(RS_ID, 2, 2)).thenReturn(list);
+
+		assertEquals("check list", TWO, resultSet.getResults(2, 2).get(0));
+		assertEquals("check size", 1, resultSet.getResults(2, 2).size());
+	}
+
+	/**
+	 * test when indices are out of range, trailing stuff should be skipped.
+	 */
+	@Test
+	public void testGetResultOutOfRange() {
+		final List<String> list = new ArrayList<String>();
+		list.add(TWO);
+
+		when(dao.getSize(RS_ID)).thenReturn(2);
+		when(dao.getElements(RS_ID, 2, 2)).thenReturn(list);
+
+		assertEquals("check list", TWO, resultSet.getResults(2, 2 + 1).get(0));
+		assertEquals("check size", 1, resultSet.getResults(2, 2 + 1).size());
+	}
+
+	/**
+	 * open.
+	 */
+	@Test
+	public void testIsOpen() {
+		assertTrue("check is open by default", resultSet.isOpen());
+	}
+
+	/**
+	 * test close.
+	 */
+	@Test
+	public void testClose() {
+		resultSet.addObserver(registry);
+		assertEquals("observer should be added", 1, resultSet.countObservers());
+
+		resultSet.destroy();
+		assertTrue("should be destroyed", resultSet.isDestroyed());
+
+		assertEquals("observers should be cleared", 0, resultSet.countObservers());
+		verify(registry, times(1)).update(resultSet, null);
+	}
+
+	@Test
+	public void testFromAfterSize() {
+		final List<String> list = new ArrayList<String>();
+		list.add(TWO);
+
+		when(dao.getSize(RS_ID)).thenReturn(2);
+		when(dao.getElements(RS_ID, 2, 2)).thenReturn(list);
+
+		resultSet.getResults(3, 2);
+	}
+
+	@Test(expected = IllegalStateException.class)
+	public void testWriteClosed() {
+		resultSet.close();
+		resultSet.addElements(Lists.newArrayList("test"));
+	}
+
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactory.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactory.java	(revision 45117)
@@ -0,0 +1,7 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import eu.dnetlib.miscutils.factory.Factory;
+
+public interface ResultSetDescriptorFactory extends Factory<ResultSetDescriptor> {
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactoryTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactoryTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactoryTest.java	(revision 45117)
@@ -0,0 +1,139 @@
+package eu.dnetlib.enabling.resultset; // NOPMD
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.List;
+
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
+import eu.dnetlib.enabling.tools.ServiceResolver;
+
+/**
+ * test xslt resultset.
+ *
+ * @author marko
+ *
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class XSLTMappedResultSetFactoryTest {
+
+	/**
+	 * instance under test.
+	 */
+	private transient XSLTMappedResultSetFactory factory;
+
+	/**
+	 * resultset factory mock.
+	 */
+	@Mock
+	private transient ResultSetFactory resultSetFactory;
+
+	/**
+	 * service resolver.
+	 */
+	@Mock
+	private transient ServiceResolver serviceResolver;
+
+	/**
+	 * resultset service mock.
+	 */
+	@Mock
+	private transient ResultSetService resultSetService;
+	
+	/**
+	 * underlying resultSet mock
+	 */
+	@Mock
+	private transient ResultSet resultSet;
+
+	/**
+	 * Common setup.
+	 *
+	 */
+	@Before
+	public void setUp() {
+		factory = new XSLTMappedResultSetFactory();
+		factory.setResultSetFactory(resultSetFactory);
+		factory.setServiceResolver(serviceResolver);
+	}
+
+	/**
+	 * test invalid xslt.
+	 *
+	 * @throws TransformerConfigurationException
+	 *             could happen
+	 */
+	@Test(expected = IllegalStateException.class)
+	public void testInvalidXslt() throws TransformerConfigurationException {
+		factory.createMappedResultSet(null, "<bla/>");
+	}
+
+	/**
+	 * test xslt.
+	 *
+	 * @throws TransformerConfigurationException
+	 *             could happen
+	 * @throws IOException
+	 *             could happen
+	 * @throws ResultSetException mock
+	 */
+	@Test
+	public void testXslt() throws TransformerConfigurationException, IOException, ResultSetException {
+		when(serviceResolver.getService(eq(ResultSetService.class), (W3CEndpointReference) anyObject())).thenReturn(resultSetService);
+		when(serviceResolver.getResourceIdentifier((W3CEndpointReference) anyObject())).thenReturn("123");
+
+		when(resultSetService.getNumberOfElements(anyString())).thenReturn(1);
+		when(resultSetService.getResult("123", 1, 1, "waiting")).thenReturn(Lists.newArrayList("<first>something</first>"));
+		when(resultSetService.getRSStatus("123")).thenReturn("closed");
+		
+		when(resultSet.isOpen()).thenReturn(true);
+		
+		final StringWriter xsltSource = new StringWriter();
+		IOUtils.copy(getClass().getResourceAsStream("test.xsl"), xsltSource);
+		factory.createMappedResultSet(null, xsltSource.toString());
+
+		verify(resultSetFactory, times(1)).createResultSet(argThat(new ArgumentMatcher<ResultSetListener>() {
+
+			@Override
+			public boolean matches(final Object argument) {
+				final MappedResultSet listener = (MappedResultSet) argument;
+				listener.setResultSet(resultSet);
+				final List<String> res = listener.getResult(1, 1);
+
+				assertNotNull("null result", res);
+				assertFalse("empty result", res.isEmpty());
+
+				assertNotNull("null element", res.get(0));
+
+				assertTrue("transformed correctly", res.get(0).contains("<second>something</second>"));
+
+				return true;
+			}
+		}));
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSet.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSet.java	(revision 45117)
@@ -0,0 +1,22 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import java.util.List;
+
+import eu.dnetlib.enabling.resultset.ResultSet;
+
+/**
+ * resultset which receive data through the "push" interface, i.e. data is directly appended to it.
+ * 
+ * @author marko
+ *
+ */
+public interface PushResultSet extends ResultSet {
+
+	/**
+	 * add a list of elements at the end of the resultset.
+	 * 
+	 * @param elements list of elements
+	 */
+	void addElements(List<String> elements);
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/LocalResultSetImplTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/LocalResultSetImplTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/LocalResultSetImplTest.java	(revision 45117)
@@ -0,0 +1,174 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.*; // NOPMD
+import static org.mockito.Mockito.*; // NOPMD by marko on 11/26/08 9:13 PM
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+/**
+ * test the resultset concrete implementation.
+ * 
+ * @author marko
+ * 
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class LocalResultSetImplTest {
+
+	/**
+	 * This class could be an anonymous class, but is here to be shared among tests.
+	 * 
+	 * @author marko
+	 * 
+	 */
+	private static final class TestResultSetListener implements ResultSetListener {
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see eu.dnetlib.enabling.resultset.ResultSetListener#getResult(int, int)
+		 */
+		@Override
+		public List<String> getResult(final int fromPosition, final int toPosition) {
+			final List<String> res = new ArrayList<String>();
+			for (int i = fromPosition; i <= toPosition; i++)
+				res.add(((Integer) (i - 1)).toString());
+			return res;
+		}
+
+		@Override
+		public int getSize() {
+			return RESULT_SIZE;
+		}
+	}
+
+	/**
+	 * Mockito lacks of multiple interfaces mocking.
+	 * 
+	 * @author marko
+	 * 
+	 */
+	private abstract static class AbstractResultSetAware implements ResultSetListener, ResultSetAware {
+	}
+
+	/**
+	 * resultset registry mock.
+	 */
+	@Mock
+	private transient ResultSetRegistry registry;
+
+	/**
+	 * object under test.
+	 */
+	private transient LocalResultSetImpl resultSet;
+
+	/**
+	 * number of returned test results.
+	 */
+	private static final int RESULT_SIZE = 3;
+
+	/**
+	 * provides data to the resultset under test.
+	 */
+	private transient TestResultSetListener resultSetListener;
+
+	/**
+	 * prepare.
+	 * 
+	 */
+	@Before
+	public void setUp() {
+		resultSetListener = new TestResultSetListener();
+		resultSet = new LocalResultSetImpl(resultSetListener);
+	}
+
+	/**
+	 * test the get number of results method.
+	 */
+	@Test
+	public void testGetNumberOfResults() {
+		assertEquals("check number of results", RESULT_SIZE, resultSet.getNumberOfResults());
+	}
+
+	/**
+	 * test the get result method.
+	 */
+	@Test
+	public void testGetResults() {
+		final List<String> res = resultSet.getResults(1, RESULT_SIZE); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("whole length", RESULT_SIZE, res.size());
+		for (int i = 0; i < RESULT_SIZE; i++)
+			assertEquals("check element", ((Integer) i).toString(), res.get(i));
+
+		final List<String> res2 = resultSet.getResults(1, RESULT_SIZE - 1); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("shorter", RESULT_SIZE - 1, res2.size());
+
+		final List<String> res3 = resultSet.getResults(1, RESULT_SIZE + 1); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("to out of bounds", RESULT_SIZE, res3.size());
+
+		final List<String> res4 = resultSet.getResults(RESULT_SIZE + 1, RESULT_SIZE); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("from out of bounds", 0, res4.size());
+		
+		final List<String> res5 = resultSet.getResults(0, RESULT_SIZE); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("from lesser than 1", RESULT_SIZE, res5.size());		
+
+		final List<String> res6 = resultSet.getResults(RESULT_SIZE, 1); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("inverted from and to", 1, res6.size());		
+		
+		resultSet.setOpen(true);
+		final List<String> res7 = resultSet.getResults(1, RESULT_SIZE + 1); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("to out of bounds - pass through", RESULT_SIZE + 1, res7.size());
+	}
+
+	/**
+	 * test observer/observable pattern.
+	 */
+	@Test
+	public void testDestroy() {
+		resultSet.addObserver(registry);
+		assertEquals("observer should be added", 1, resultSet.countObservers());
+
+		resultSet.destroy();
+		assertTrue("should be destroyed", resultSet.isDestroyed());
+
+		assertEquals("observers should be cleared", 0, resultSet.countObservers());
+		verify(registry, times(1)).update(resultSet, null);
+	}
+
+	/**
+	 * test getter ... let's make code coverage happy.
+	 */
+	@Test
+	public void testGetListener() {
+		assertEquals("test getter?", resultSetListener, resultSet.getListener());
+	}
+
+	/**
+	 * test setter ... let's make code coverage happy.
+	 */
+	@Test
+	public void testSetListener() {
+		assertEquals("test getter?", resultSetListener, resultSet.getListener());
+		resultSet.setListener(null);
+		assertNull("test setter?", resultSet.getListener());
+	}
+
+	/**
+	 * test.
+	 */
+	@Test
+	public void testResultSetAware() {
+		final AbstractResultSetAware abr = mock(AbstractResultSetAware.class);
+		resultSet = new LocalResultSetImpl(abr);
+		assertNotNull("dummy", resultSet);
+		
+		verify(abr).setResultSet((ResultSet) anyObject());
+		
+	}
+
+}

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/LocalResultSetImplTest.java
___________________________________________________________________
Added: svn:mergeinfo
## -0,0 +0,0 ##
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetDao.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetDao.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetDao.java	(revision 45117)
@@ -0,0 +1,45 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import java.util.List;
+
+/**
+ * offer access to the underlying in-memory or pseudo-memory (serialization backed caches) storage for the transient
+ * push-resultsets.
+ *
+ * This type of push resultsets doesn't even try to make efficient access to records, they just keep them as big lists
+ * on the underlying storage. Actual implementations may decide to keep them on the heap or to use some caching
+ * technology like ehcache.
+ *
+ * @author marko
+ *
+ */
+public interface TransientPushResultSetDao {
+	/**
+	 * add elements to a given key.
+	 *
+	 * @param key
+	 *            usually a rsid.
+	 * @param elements
+	 *            list of elements
+	 */
+	void addElements(String key, List<String> elements);
+
+	/**
+	 * obtain content for a given key (resultset) in a given range (1 based).
+	 *
+	 * @param key
+	 *            usually a rsid
+	 * @param fromPosition from position (1 based, inclusive)
+	 * @param toPosition to position (1 based, inclusive)
+	 * @return all the elements for a given key
+	 */
+	List<String> getElements(String key, int fromPosition, int toPosition);
+
+	/**
+	 * get the resultset size (number of elements).
+	 *
+	 * @param key usually a rsid
+	 * @return resultset size
+	 */
+	int getSize(String key);
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetEPRPool.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetEPRPool.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetEPRPool.java	(revision 45117)
@@ -0,0 +1,137 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import javax.annotation.PostConstruct;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.enabling.tools.UniqueIdentifierGenerator;
+import eu.dnetlib.enabling.tools.UniqueIdentifierGeneratorImpl;
+
+public class ResultSetEPRPool {
+	private static final Log log = LogFactory.getLog(ResultSetEPRPool.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	static class PreparedResultSet {
+		private String rsId;
+		private W3CEndpointReference epr;
+
+		public PreparedResultSet(final String rsId, final W3CEndpointReference epr) {
+			super();
+			this.rsId = rsId;
+			this.epr = epr;
+		}
+
+		public String getRsId() {
+			return rsId;
+		}
+
+		public void setRsId(final String rsId) {
+			this.rsId = rsId;
+		}
+
+		public W3CEndpointReference getEpr() {
+			return epr;
+		}
+
+		public void setEpr(final W3CEndpointReference epr) {
+			this.epr = epr;
+		}
+	}
+
+	class PoolFiller implements Runnable {
+
+		@Override
+		public void run() {
+			while (true)
+				try {
+					final PreparedResultSet resultSet = prepareResultSet();
+					pool.put(resultSet);
+				} catch (final InterruptedException e) {
+					// eat this exception
+					log.debug("cannot add resultset to pool", e);
+				}
+		}
+
+		private PreparedResultSet prepareResultSet() {
+			final String rsId = idGenerator.generateIdentifier();
+			return new PreparedResultSet(rsId, createEPR(rsId));
+		}
+
+		private W3CEndpointReference createEPR(final String rsId) {
+			return getResultSetService().getEprBuilder().getEndpointReference(getResultSetService().getEndpoint(), rsId);
+		}
+	}
+
+	/**
+	 * resultset service.
+	 */
+	private ResultSetServiceImpl resultSetService;
+
+	private int capacity = 1000;
+	private int fillerThreads = 10;
+	private final BlockingQueue<PreparedResultSet> pool = new LinkedBlockingQueue<PreparedResultSet>(capacity);
+
+	/**
+	 * identifier generator.
+	 */
+	private UniqueIdentifierGenerator idGenerator = new UniqueIdentifierGeneratorImpl("rs-");
+
+	@PostConstruct
+	public void init() {
+		log.info("-------<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>> Starting fill threads");
+		for (int i = 0; i < fillerThreads; i++)
+			startFillter();
+	}
+
+	protected void startFillter() {
+		final Thread filler = new Thread(new PoolFiller());
+		filler.setDaemon(true);
+		filler.start();
+	}
+
+	public W3CEndpointReference registerResultSet(final ResultSet resultSet) {
+		final PreparedResultSet prepared = nextPreparedResultSet();
+		if (prepared == null) {
+			log.info("EPR cache is empty, creating EPR in caller thread");
+			return getResultSetService().getEprBuilder().getEndpointReference(getResultSetService().getEndpoint(), idGenerator.generateIdentifier());
+		}
+
+		getResultSetService().getResultsetRegistry().addResultSet(resultSet, prepared.getRsId());
+		return prepared.getEpr();
+	}
+
+	private PreparedResultSet nextPreparedResultSet() {
+		log.info(">>>> fetching a prepared resultset from the pool");
+		return pool.poll();
+	}
+
+	public int getCapacity() {
+		return capacity;
+	}
+
+	public void setCapacity(int capacity) {
+		this.capacity = capacity;
+	}
+
+	public UniqueIdentifierGenerator getIdGenerator() {
+		return idGenerator;
+	}
+
+	public void setIdGenerator(UniqueIdentifierGenerator idGenerator) {
+		this.idGenerator = idGenerator;
+	}
+
+	public ResultSetServiceImpl getResultSetService() {
+		return resultSetService;
+	}
+
+	@Required
+	public void setResultSetService(ResultSetServiceImpl resultSetService) {
+		this.resultSetService = resultSetService;
+	}
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSetFactory.java	(revision 45117)
@@ -0,0 +1,21 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * creates a new push resultset.
+ *
+ * @author marko
+ *
+ */
+public interface PushResultSetFactory {
+
+	/**
+	 * create a new push resultset.
+	 *
+	 * @param maxIdleTime max time the resultset can be idle
+	 * @return push resultset epr
+	 */
+	W3CEndpointReference createPushResultSet(int maxIdleTime);
+
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetFactory.java	(revision 45117)
@@ -0,0 +1,34 @@
+package eu.dnetlib.enabling.resultset.push;
+
+
+/**
+ * creates a transient push resultset.
+ * 
+ * @author marko
+ *
+ */
+public class TransientPushResultSetFactory extends AbstractPushResultSetFactoryImpl {
+
+	/**
+	 * dao.
+	 */
+	private TransientPushResultSetDao dao;
+	
+	/** 
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.push.AbstractPushResultSetFactoryImpl#newInstance()
+	 */
+	@Override
+	protected PushResultSet newInstance() {
+		return new TransientPushResultSetImpl(dao);
+	}
+
+	public TransientPushResultSetDao getDao() {
+		return dao;
+	}
+
+	public void setDao(final TransientPushResultSetDao dao) {
+		this.dao = dao;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/StreamingResultSetListenerTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/StreamingResultSetListenerTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/StreamingResultSetListenerTest.java	(revision 45117)
@@ -0,0 +1,62 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.*;
+
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+public class StreamingResultSetListenerTest {
+
+	private StreamingResultSetListener listener;
+	private List<String> data;
+
+	@Before
+	public void setUp() throws Exception {
+		data = Lists.newArrayList("uno", "due", "tre", "quattro");
+		listener = new StreamingResultSetListener(data.iterator(), data.size());
+	}
+
+	@Test
+	public void testGetResult() {
+		assertEquals(data.size(), listener.getSize());
+
+		final List<String> res = listener.getResult(1, 2);
+		assertEquals(2, res.size());
+		assertEquals("uno", res.get(0));
+		assertEquals("due", res.get(1));
+	}
+
+	@Test
+	public void testGetResult2() {
+		listener.getResult(1, 2);
+		final List<String> res = listener.getResult(3, 4);
+		assertEquals(2, res.size());
+		assertEquals("tre", res.get(0));
+		assertEquals("quattro", res.get(1));
+	}
+
+	@Test
+	public void testGetResult_retry() {
+		listener.getResult(1, 2);
+		final List<String> res = listener.getResult(1, 2);
+		assertEquals(2, res.size());
+		assertEquals("uno", res.get(0));
+		assertEquals("due", res.get(1));
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testGetResult_random() {
+		listener.getResult(1, 2);
+		listener.getResult(2, 3);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testGetResult_skip() {
+		listener.getResult(1, 2);
+		listener.getResult(4, 4);
+	}
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDaoImpl.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDaoImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDaoImpl.java	(revision 45117)
@@ -0,0 +1,23 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * fake resultset property dao.
+ * 
+ * @author marko
+ *
+ */
+public class ResultSetPropertyDaoImpl implements ResultSetPropertyDao {
+
+	/** 
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.ResultSetPropertyDao#getProperties(eu.dnetlib.enabling.resultset.ResultSet)
+	 */
+	@Override
+	public Map<String, String> getProperties(final ResultSet resultSet) {
+		return new HashMap<String, String>();
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSet.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSet.java	(revision 45117)
@@ -0,0 +1,60 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.enabling.tools.ServiceResolver;
+import eu.dnetlib.miscutils.functional.IdentityFunction;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+/**
+ * A resultset record counter.
+ * 
+ * @author claudio
+ * 
+ */
+public class CountingResultSet extends MappedResultSet {
+
+	/**
+	 * counter.
+	 */
+	private int count;
+
+
+	/**
+	 * @param epr
+	 * @param serviceResolver
+	 */
+	public CountingResultSet(final W3CEndpointReference epr, final ServiceResolver serviceResolver) {
+		this(epr, new IdentityFunction<String>(), serviceResolver);
+	}
+
+	/**
+	 * @param epr
+	 * @param mapper
+	 * @param serviceResolver
+	 */
+	public CountingResultSet(final W3CEndpointReference epr, final UnaryFunction<String, String> mapper, final ServiceResolver serviceResolver) {
+		super(epr, mapper, serviceResolver);
+		count = 0;
+	}
+
+	/**
+	 * method sets the counter to the higher allowed value of toPosition.
+	 */
+	@Override
+	public List<String> getResult(int fromPosition, int toPosition) {
+
+		if (toPosition > count)
+			count = toPosition;
+		if (toPosition > super.getSize())
+			count = super.getSize();
+
+		return super.getResult(fromPosition, toPosition);
+	}
+
+	public int getCount() {
+		return count;
+	}
+}

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSet.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/resources/eu/dnetlib/enabling/resultset/test.xsl
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/resources/eu/dnetlib/enabling/resultset/test.xsl	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/resources/eu/dnetlib/enabling/resultset/test.xsl	(revision 45117)
@@ -0,0 +1,6 @@
+<xsl:stylesheet version="1.0"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+	<xsl:template match="first">
+		<second><xsl:value-of select="."/></second>
+	</xsl:template>
+</xsl:stylesheet>
\ No newline at end of file
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetListener.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetListener.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetListener.java	(revision 45117)
@@ -0,0 +1,15 @@
+package eu.dnetlib.enabling.resultset;
+
+
+/**
+ * A ResultSetListener is a pull interface to a ResultSet.
+ * 
+ * The Resultset will call method of ResultSetListener implementors whenever it needs to pull some data and provide it
+ * to clients. The ResultSet service acts as a decouple point between the producer and the consumer.
+ * 
+ * @author marko
+ * 
+ */
+public interface ResultSetListener extends TypedResultSetListener<String> {
+
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalResultSetFactoryImpl.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalResultSetFactoryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalResultSetFactoryImpl.java	(revision 45117)
@@ -0,0 +1,27 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+public class EPRPoolingLocalResultSetFactoryImpl extends LocalResultSetFactoryImpl {
+
+	private ResultSetEPRPool pool;
+	
+	@Override
+	public W3CEndpointReference registerResultSet(ResultSet resultSet) {
+		return pool.registerResultSet(resultSet);
+	}
+
+	public ResultSetEPRPool getPool() {
+		return pool;
+	}
+
+	@Required
+	public void setPool(ResultSetEPRPool pool) {
+		this.pool = pool;
+	}
+
+	
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/FetchList.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/FetchList.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/FetchList.java	(revision 45117)
@@ -0,0 +1,105 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+
+/**
+ * a LinkedList populated by a given iterable, which provides a fetch window of elements
+ *
+ * @author claudio
+ *
+ * @param <T>
+ *            The FetchList type
+ */
+public class FetchList<T> extends LinkedList<T> {
+
+	/**
+	 *
+	 */
+	private static final long serialVersionUID = 7135272008563693321L;
+
+	/**
+	 * represents the number of elements ready to be pulled out of the list
+	 */
+	private int fetchSize;
+
+	/**
+	 * represents the number of elements already consumed by a poll call
+	 */
+	private int consumedElements;
+
+	/**
+	 * the given itarable used to populate the list
+	 */
+	private Iterator<T> iter;
+
+	/**
+	 * @param iter
+	 * @param fetchSize
+	 */
+	public FetchList(final Iterator<T> iter, final int fetchSize) {
+		super();
+		this.consumedElements = 0;
+		this.fetchSize = fetchSize;
+		this.iter = iter;
+	}
+
+	/**
+	 * used to fill the list
+	 */
+	public synchronized void fill() {
+		for (int i = 0; i < fetchSize; i++) {
+			if (!iter.hasNext()) {
+				break;
+			}
+			this.add(iter.next());
+		}
+	}
+
+	/**
+	 * return the first element and makes the list to be filled in case its size is zero
+	 */
+	@Override
+	public T poll() {
+		if (this.isEmpty()) {
+			fill();
+		}
+
+		if (this.size() > 0) {
+			consumedElements++;
+			return super.poll();
+		}
+		return null;
+	}
+
+	/**
+	 * @return the number of elements already consumed by a "poll"
+	 */
+	public int getConsumedElements() {
+		return consumedElements;
+	}
+
+	/**
+	 * @return the actual number of elements of the list
+	 */
+	public int getTotalElements() {
+		return consumedElements + this.size();
+	}
+
+	/**
+	 * to provide an actual size, fills the list if there are elements to fill it
+	 */
+	@Override
+	public int size() {
+		if (this.isEmpty() && iter.hasNext()) {
+			fill();
+		}
+		return super.size();
+	}
+
+	@Override
+	public boolean isEmpty() {
+		return super.size() == 0;
+	}
+
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalOpenResultSetFactoryImpl.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalOpenResultSetFactoryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalOpenResultSetFactoryImpl.java	(revision 45117)
@@ -0,0 +1,23 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+public class EPRPoolingLocalOpenResultSetFactoryImpl extends LocalOpenResultSetFactoryImpl {
+	private ResultSetEPRPool pool;
+	
+	@Override
+	public W3CEndpointReference registerResultSet(ResultSet resultSet) {
+		return pool.registerResultSet(resultSet);
+	}
+
+	public ResultSetEPRPool getPool() {
+		return pool;
+	}
+
+	@Required
+	public void setPool(ResultSetEPRPool pool) {
+		this.pool = pool;
+	}
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSet.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSet.java	(revision 45117)
@@ -0,0 +1,57 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.enabling.tools.ServiceResolver;
+import eu.dnetlib.miscutils.collections.MappedCollection;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+public class ParallelMappedResultSet extends MappedResultSet {
+
+	private ExecutorService executor;
+
+	public ParallelMappedResultSet(final W3CEndpointReference source, final UnaryFunction<String, String> mapper, final ServiceResolver serviceResolver,
+			final ExecutorService executor) {
+		super(source, mapper, serviceResolver);
+		this.executor = executor;
+	}
+
+	@Override
+	public List<String> getResult(int fromPosition, int toPosition) {
+
+//		log.info("Parallel page " + (toPosition - fromPosition + 1));
+
+		List<Future<String>> results = Lists.newArrayList();
+
+		for (final String input : getResultFromSource(fromPosition, toPosition)) {
+			results.add(executor.submit(new Callable<String>() {
+				@Override
+				public String call() throws Exception {
+					return getMapper().evaluate(input);
+				}
+			}));
+		}
+
+		return MappedCollection.listMap(results, new UnaryFunction<String, Future<String>>() {
+			@Override
+			public String evaluate(Future<String> arg) {
+				try {
+					return arg.get();
+				} catch (InterruptedException e) {
+					throw new IllegalStateException(e);
+				} catch (ExecutionException e) {
+					throw new IllegalStateException(e);
+				}
+			}
+		});
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/observer/ResultSetObserver.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/observer/ResultSetObserver.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/observer/ResultSetObserver.java	(revision 45117)
@@ -0,0 +1,23 @@
+package eu.dnetlib.enabling.resultset.observer;
+
+import eu.dnetlib.enabling.resultset.ResultSet;
+
+
+/**
+ * Implement the same interface as JDK java.util.Observer as java interface (not as a class) and introduce static type
+ * safeness through generics.
+ * 
+ * @author marko, claudio, alessia, michele
+ * 
+ */
+public interface ResultSetObserver {
+	/**
+	 * gets notified when an observed object is updated.
+	 * 
+	 * @param observed
+	 *            observed object which modification triggered this call.
+	 * @param arg
+	 *            arg
+	 */
+	void update(ResultSet observed, Object arg);
+}

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/observer/ResultSetObserver.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetFactory.java	(revision 45117)
@@ -0,0 +1,46 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.annotation.Resource;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.enabling.tools.ServiceResolver;
+
+public class CachingResultSetFactory {
+	/**
+	 * underlying resultset factory, which exposes local resultsets to the world.
+	 */
+	private ResultSetFactory resultSetFactory;
+
+	@Resource
+	private ServiceResolver serviceResolver;
+	
+	/**
+	 * @param items
+	 * @param size
+	 *            the size of the iterable
+	 * @return
+	 */
+	public W3CEndpointReference createCachingResultSet(W3CEndpointReference epr) {
+		return resultSetFactory.createResultSet(new CachingResultSetListener(epr, serviceResolver));
+	}
+
+	public ResultSetFactory getResultSetFactory() {
+		return resultSetFactory;
+	}
+
+	@Required
+	public void setResultSetFactory(ResultSetFactory resultSetFactory) {
+		this.resultSetFactory = resultSetFactory;
+	}
+
+	public ServiceResolver getServiceResolver() {
+		return serviceResolver;
+	}
+
+	public void setServiceResolver(ServiceResolver serviceResolver) {
+		this.serviceResolver = serviceResolver;
+	}
+
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/TypedResultSetListener.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/TypedResultSetListener.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/TypedResultSetListener.java	(revision 45117)
@@ -0,0 +1,34 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+/**
+ * A TypedResultSetListener is a pull interface to a ResultSet.
+ * 
+ * The Resultset will call method of ResultSetListener implementors whenever it needs to pull some data and provide it
+ * to clients. The ResultSet service acts as a decouple point between the producer and the consumer.
+ * 
+ * @author marko
+ * 
+ */
+public interface TypedResultSetListener<T> {
+
+	/**
+	 * get a single page of results.
+	 * 
+	 * @param fromPosition
+	 *            from 1
+	 * @param toPosition
+	 *            last included
+	 * @return page of results
+	 */
+	List<T> getResult(int fromPosition, int toPosition);
+
+	/**
+	 * get number of elements.
+	 * 
+	 * @return number of elements
+	 */
+	int getSize();
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImpl.java	(revision 45117)
@@ -0,0 +1,123 @@
+package eu.dnetlib.enabling.resultset;
+
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.enabling.tools.UniqueIdentifierGenerator;
+import eu.dnetlib.enabling.tools.UniqueIdentifierGeneratorImpl;
+import eu.dnetlib.miscutils.cache.Cache;
+
+/**
+ * Implement a in memory resultset registry.
+ *
+ * @author marko
+ *
+ */
+public class ResultSetRegistryImpl implements ResultSetRegistry {
+
+	/**
+	 * rsId -> ResultSet mappings are stored here.
+	 */
+	private Cache<String, ResultSet> cache;
+
+	/**
+	 * rsID -> initial maxIdleTime time are store here.
+	 */
+	private Cache<String, Integer> maxIdleTimeCache;
+
+	/**
+	 * identifier generator.
+	 */
+	private UniqueIdentifierGenerator idGenerator = new UniqueIdentifierGeneratorImpl("rs-");
+
+	/**
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.ResultSetRegistry#addResultSet(eu.dnetlib.enabling.resultset.ResultSet)
+	 */
+	@Override
+	public void addResultSet(final ResultSet resultSet) {
+		addResultSet(resultSet, 0);
+	}
+
+	/** 
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.ResultSetRegistry#addResultSet(eu.dnetlib.enabling.resultset.ResultSet, java.lang.String)
+	 */
+	@Override
+	public void addResultSet(final ResultSet resultSet, final String identifier) {
+		addResultSet(resultSet, identifier, 0);
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.ResultSetRegistry#addResultSet(eu.dnetlib.enabling.resultset.ResultSet, int)
+	 */
+	@Override
+	public void addResultSet(final ResultSet resultSet, final int maxIdleTime) {
+		addResultSet(resultSet, idGenerator.generateIdentifier(), maxIdleTime);
+	}
+	
+	/** 
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.ResultSetRegistry#addResultSet(eu.dnetlib.enabling.resultset.ResultSet, java.lang.String, int)
+	 */
+	@Override
+	public void addResultSet(final ResultSet resultSet, final String identifier, final int maxIdleTime) {
+		resultSet.setIdentifier(identifier);
+		resultSet.addObserver(this);
+		cache.put(resultSet.getIdentifier(), resultSet);
+		maxIdleTimeCache.put(resultSet.getIdentifier(), maxIdleTime);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see eu.dnetlib.enabling.resultset.ResultSetRegistry#getResultSetById(java.lang.String)
+	 */
+	@Override
+	public ResultSet getResultSetById(final String rsId) {
+		return cache.get(rsId);
+	}
+
+	@Override
+	public int getMaxIdleTimeById(final String rsId) {
+		return maxIdleTimeCache.get(rsId);
+	}
+
+
+	public Cache<String, ResultSet> getCache() {
+		return cache;
+	}
+
+	@Required
+	public void setCache(final Cache<String, ResultSet> cache) {
+		this.cache = cache;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.miscutils.observer.Observer#update(eu.dnetlib.enabling.resultset.observer.Observable, java.lang.Object)
+	 */
+	@Override
+	public void update(final ResultSet observed, final Object arg) {
+		if (!observed.isOpen())
+			cache.remove(observed.getIdentifier());
+	}
+
+	public UniqueIdentifierGenerator getIdGenerator() {
+		return idGenerator;
+	}
+
+	public void setIdGenerator(final UniqueIdentifierGenerator idGenerator) {
+		this.idGenerator = idGenerator;
+	}
+
+	public Cache<String, Integer> getMaxIdleTimeCache() {
+		return maxIdleTimeCache;
+	}
+
+	@Required
+	public void setMaxIdleTimeCache(Cache<String, Integer> maxIdleTimeCache) {
+		this.maxIdleTimeCache = maxIdleTimeCache;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSet.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSet.java	(revision 45117)
@@ -0,0 +1,116 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * an open ResultSet that can be iterated to get it's data results.
+ * 
+ * @author claudio
+ * 
+ */
+public class IterableResultSet implements ResultSetListener, ResultSetAware {
+
+	/**
+	 * logger.
+	 */
+	private static final Log log = LogFactory.getLog(IterableResultSet.class);
+
+	/**
+	 * the container for the data results.
+	 */
+	private ResultSet resultSet;
+
+	/**
+	 * the list that provides data for this resultSet.
+	 */
+	private FetchList<String> fetchList;
+
+	private int optionalNumberOfElements;
+
+	/**
+	 * 
+	 * @param iter
+	 * @param fetchSize
+	 */
+	protected IterableResultSet(Iterable<String> iter, int fetchSize) {
+		fetchList = new FetchList<String>(iter.iterator(), fetchSize);
+		if (iter instanceof SizedIterable<?>) {
+			optionalNumberOfElements = ((SizedIterable<?>) iter).getNumberOfElements();
+		} else {
+			optionalNumberOfElements = -1;
+		}
+	}
+
+	/**
+	 * @param fromPosition
+	 * @param toPosition
+	 * @return <T> List
+	 */
+	@Override
+	public List<String> getResult(int fromPosition, int toPosition) {
+
+		log.debug(" - getting result from " + fromPosition + " to " + toPosition + ", consumedElements: " + fetchList.getConsumedElements());
+
+		if (fromPosition != fetchList.getConsumedElements() + 1)
+			throw new RuntimeException("Unexpected value for 'fromPosition' parameter");
+		if (toPosition < fromPosition)
+			throw new RuntimeException("'fromPosition' must be lower or equal than 'toPosition'");
+
+		List<String> result = new ArrayList<String>();
+
+		for (int i = fromPosition; i <= toPosition; i++) {
+			if (fetchList.size() > 0)
+				result.add(fetchList.poll());
+			else
+				break;
+		}
+
+		ensureClosed();
+
+		return result;
+	}
+
+	private void ensureClosed() {
+		if (fetchList.size() == 0 && resultSet.isOpen()) {
+			log.info(">>>>>>>>>>> closing resultset <<<<<<<<<<<<<");
+			close();
+		}
+	}
+
+	public String getRSStatus() {
+		if (resultSet.isOpen())
+			return "open";
+		return "closed";
+	}
+
+	@Override
+	public int getSize() {
+		ensureClosed();
+
+		if (optionalNumberOfElements == -1)
+			return fetchList.getTotalElements();
+		else
+			return optionalNumberOfElements;
+	}
+
+	/**
+	 * closes the resultset.
+	 */
+	protected void close() {
+		resultSet.close();
+	}
+
+	@Override
+	public void setResultSet(ResultSet resultSet) {
+		this.resultSet = resultSet;
+	}
+
+	public ResultSet getResultSet() {
+		return resultSet;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/FetchListTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/FetchListTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/FetchListTest.java	(revision 45117)
@@ -0,0 +1,75 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+@RunWith(MockitoJUnit44Runner.class)
+public class FetchListTest {
+	
+	/**
+	 * object to test
+	 */
+	private FetchList<String> fetchList;
+	
+	private List<String> list;
+	private Iterator<String> iter;
+	
+	private int FETCH_SIZE = 10;
+	
+	private int TOTAL_ELEMENTS = 100;
+
+	@Before
+	public void setUp() throws Exception {
+		list = new ArrayList<String>();
+		for (int i = 0; i < TOTAL_ELEMENTS; i++) {
+			list.add("XXX" + i);
+		}
+		this.iter = list.iterator();
+		fetchList = new FetchList<String>(iter, FETCH_SIZE);
+		
+	}
+
+	@Test
+	public void testFetchList() {
+		assertNotNull(fetchList);
+	}
+
+	@Test
+	public void testPoll_consumedElements() {
+		assertEquals(0, fetchList.getConsumedElements());
+		fetchList.poll();
+		assertEquals(1, fetchList.getConsumedElements());
+	}
+	
+	@Test
+	public void testFill_totalElements() {
+		assertEquals(FETCH_SIZE, fetchList.getTotalElements());
+	}
+	
+	@Test
+	public void testPoll() {
+		for (int i = 0; i < TOTAL_ELEMENTS; i++) {
+			assertEquals(i, fetchList.getConsumedElements());
+			assertEquals(list.get(i), fetchList.poll());
+		}
+		assertEquals(TOTAL_ELEMENTS, fetchList.getConsumedElements());
+		assertEquals(TOTAL_ELEMENTS, fetchList.getTotalElements());
+	}
+	
+	@Test
+	public void testPoll_null() {
+		for (int i = 0; i < TOTAL_ELEMENTS; i++) {
+			fetchList.poll();
+		}
+		assertNull(fetchList.poll());
+		assertNull(fetchList.poll());
+		assertNull(fetchList.poll());
+	}
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSetFactory.java	(revision 45117)
@@ -0,0 +1,67 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+/**
+ * 
+ * @author claudio
+ *
+ */
+public class IterableResultSetFactory {
+
+	/**
+	 * {@link ResultSetFactory}
+	 */
+	private LocalOpenResultSetFactoryImpl resultSetFactory;
+	
+	/**
+	 * 
+	 */
+	private int fetchSize;
+	
+	/**
+	 * 
+	 * @param source
+	 * @return
+	 */
+	public W3CEndpointReference createIterableResultSet(final Iterable<String> source) {
+		return resultSetFactory.createResultSet(new IterableResultSet(source, fetchSize));
+	}
+	
+	/**
+	 * 
+	 * @return
+	 */
+	public LocalOpenResultSetFactoryImpl getResultSetFactory() {
+		return resultSetFactory;
+	}
+
+	/**
+	 * 
+	 * @param resultSetFactory
+	 */
+	@Required
+	public void setResultSetFactory(final LocalOpenResultSetFactoryImpl resultSetFactory) {
+		this.resultSetFactory = resultSetFactory;
+	}
+	
+	/**
+	 * 
+	 * @param fetchSize
+	 */
+	@Required
+	public void setFetchSize(int fetchSize) {
+		this.fetchSize = fetchSize;
+	}
+
+	/**
+	 * 
+	 * @return
+	 */
+	public int getFetchSize() {
+		return fetchSize;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetAware.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetAware.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetAware.java	(revision 45117)
@@ -0,0 +1,16 @@
+package eu.dnetlib.enabling.resultset;
+
+/**
+ * ResultSet listeners can add this interface in order to receive the ResultSet they are bound to.
+ * 
+ * @author marko
+ *
+ */
+public interface ResultSetAware {
+	/**
+	 * sets the resultset instance.
+	 * 
+	 * @param resultSet the resultset instance
+	 */
+	void setResultSet(ResultSet resultSet);
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/resources/log4j.properties
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/resources/log4j.properties	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/resources/log4j.properties	(revision 45117)
@@ -0,0 +1,29 @@
+org.apache.cxf.Logger=org.apache.cxf.common.logging.Log4jLogger
+
+log4j.rootLogger=WARN, CONSOLE
+log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
+log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
+log4j.appender.CONSOLE.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
+
+log4j.logger.eu.dnetlib=INFO
+log4j.logger.eu.dnetlib.enabling.is.sn=INFO
+#log4j.logger.org.apache.cxf.interceptor=FATAL
+log4j.logger.org.apache.cxf.ws.addressing.ContextUtils=FATAL
+log4j.logger.eu.dnetlib.enabling.tools.AbstractBaseService=INFO
+log4j.logger.eu.dnetlib.enabling.inspector=DEBUG
+log4j.logger.eu.dnetlib.xml.database.LoggingTrigger=FATAL
+#log4j.logger.eu.dnetlib.enabling.tools.registration=DEBUG
+log4j.logger.eu.dnetlib.enabling.tools.registration.ServiceRegistrator=INFO
+log4j.logger.eu.dnetlib.enabling.inspector=FATAL
+log4j.logger.eu.dnetlib.enabling.resultset=DEBUG
+log4j.logger.eu.dnetlib.enabling.inspector.SubscriptionController=DEBUG
+log4j.logger.eu.dnetlib.springutils.stringtemplate.StringTemplateViewResolver=FATAL
+log4j.logger.eu.dnetlib.enabling.is.sn.SynchronousNotificationSenderImpl=WARN
+
+log4j.logger.eu.dnetlib.enabling.manager.msro.wf.RefreshIndexJob=DEBUG
+log4j.logger.eu.dnetlib.enabling.ui=DEBUG
+log4j.logger.eu.dnetlib.enabling.manager.msro.wf.RefreshIndexJob=DEBUG
+
+log4j.logger.org.apache.zookeeper.ClientCnxn=FATAL
+
+log4j.logger.eu.dnetlib.enabling.resultset.push=DEBUG
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest.java	(revision 45117)
@@ -0,0 +1,36 @@
+package eu.dnetlib.enabling.resultset.push;
+
+
+import static org.junit.Assert.*;
+
+import javax.annotation.Resource;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import eu.dnetlib.miscutils.factory.Factory;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration
+public class ResultSetDescriptorFactoryTest {
+
+	@Resource
+	Factory<ResultSetDescriptor> factory;
+
+	@Before
+	public void setUp() throws Exception {
+	}
+
+	@Test
+	public void testFactory() {
+		ResultSetDescriptor desc1 = factory.newInstance();
+		ResultSetDescriptor desc2 = factory.newInstance();
+
+		assertTrue("check different instances", desc1 != desc2);
+		assertEquals("check that it's a spring prototype", 200, desc1.getRangeLength());
+		assertEquals("check that it's a spring prototype", 200, desc2.getRangeLength());
+	}
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactory.java	(revision 45117)
@@ -0,0 +1,75 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.Map;
+import java.util.UUID;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.core.io.Resource;
+
+import eu.dnetlib.miscutils.functional.xml.ApplyXslt;
+
+/**
+ * Create a mapped resultset using a given XSLT.
+ * 
+ * @author marko
+ * 
+ */
+public class XSLTMappedResultSetFactory extends MappedResultSetFactory {
+
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final String xslt) {
+		return createMappedResultSet(source, new ApplyXslt(xslt));
+	}
+
+	/**
+	 * Create a mapped resultset using a given XSLT.
+	 * 
+	 * @param source
+	 *            source
+	 * @param xslt
+	 *            XSLT source
+	 * @return epr of mapped resultset
+	 * @throws TransformerConfigurationException
+	 *             could happen
+	 */
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final String xslt, final String name)
+			throws TransformerConfigurationException {
+		return createMappedResultSet(source, new ApplyXslt(xslt, name));
+	}
+
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final Resource xslt) {
+		return createMappedResultSet(source, new ApplyXslt(xslt));
+	}
+
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final Source xslt) {
+		return createMappedResultSet(source, new ApplyXslt(xslt));
+	}
+	
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final Resource xslt, final Map<String, String> parameters) {
+		return createMappedResultSet(source, new ApplyXslt(xslt, parameters));
+	}
+	
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final String xslt, final Map<String, String> parameters) {
+		return createMappedResultSet(source, new ApplyXslt(xslt, "rs-" + UUID.randomUUID(), parameters));
+	}
+
+	/**
+	 * Create a mapped resultset using a given XSLT.
+	 * 
+	 * @param source
+	 *            source
+	 * @param xslt
+	 *            XSLT
+	 * @return epr of mapped resultset
+	 * @throws TransformerFactoryConfigurationError
+	 * @throws TransformerConfigurationException
+	 *             could happen
+	 */
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final Source xslt, final String name) {
+		return createMappedResultSet(source, new ApplyXslt(xslt, name));
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImplTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImplTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImplTest.java	(revision 45117)
@@ -0,0 +1,184 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.matches;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import net.sf.ehcache.Cache;
+import net.sf.ehcache.CacheManager;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+import eu.dnetlib.miscutils.cache.EhCache;
+
+/**
+ * Test ResultSetRegistryImpl.
+ * 
+ * @author marko
+ * 
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class ResultSetRegistryImplTest {
+
+	/**
+	 * max in memory elements.
+	 */
+	private static final int MAX_IN_MEM = 100;
+
+	/**
+	 * default time.
+	 */
+	private static final int DEFAULT_TTI = 1000;
+
+	/**
+	 * default time to live.
+	 */
+	private static final int DEFAULT_TTL = 1000;
+
+	/**
+	 * class under test.
+	 */
+	private transient ResultSetRegistryImpl registry;
+
+	/**
+	 * mock of a resultset object.
+	 */
+	@Mock
+	private transient ResultSet resultSet;
+
+	/**
+	 * ehcache manager.
+	 */
+	private final transient CacheManager cacheManager = CacheManager.create();
+
+	/**
+	 * Set up basic mocks.
+	 */
+	@Before
+	public void setUp() {
+		final Cache ehCache = new net.sf.ehcache.Cache("testCache", MAX_IN_MEM, false, false, DEFAULT_TTL, DEFAULT_TTI);
+		cacheManager.addCache(ehCache);
+
+		final Cache mtEhCache = new net.sf.ehcache.Cache("testMTCache", MAX_IN_MEM, false, false, DEFAULT_TTL, DEFAULT_TTI);
+		cacheManager.addCache(mtEhCache);
+
+		final EhCache<String, ResultSet> cache = new EhCache<String, ResultSet>(ehCache);
+		cache.setCache(ehCache);
+
+		final EhCache<String, Integer> mtCache = new EhCache<String, Integer>(mtEhCache);
+		mtCache.setCache(mtEhCache);
+
+		registry = new ResultSetRegistryImpl();
+		registry.setCache(cache);
+		registry.setMaxIdleTimeCache(mtCache);
+
+		when(resultSet.getIdentifier()).thenReturn("123456");
+		when(resultSet.isOpen()).thenReturn(true);
+	}
+
+	/**
+	 * remove ehcache from ehcachemanager.
+	 */
+	@After
+	public void tearDown() {
+		cacheManager.removeAllCaches();
+	}
+
+	/**
+	 * Test that registered resultsets are really registered.
+	 */
+	@Test
+	public void testAddResultSet() {
+
+		final String rsId = resultSet.getIdentifier();
+		assertNotNull("the resultset should not be null", rsId);
+
+		registry.addResultSet(resultSet);
+		verify(resultSet).setIdentifier(matches("rs-" + registry.getIdGenerator().getRegEx()));
+
+		final ResultSet res = registry.getResultSetById(rsId); // NOPMD
+		assertNotNull("the resultset is not found", res);
+		assertEquals("the resultsets don't have the same id", rsId, res.getIdentifier());
+		assertEquals("the resultsets are not the same instance", resultSet, res);
+	}
+
+	/**
+	 * Test that registered resultsets are really registered.
+	 */
+	@Test
+	public void testAddResultSetWithId() {
+		resultSet = mock(ResultSet.class);
+		when(resultSet.getIdentifier()).thenReturn("123");
+
+		final String rsId = resultSet.getIdentifier();
+
+		registry.addResultSet(resultSet, rsId);
+		verify(resultSet).setIdentifier(rsId);
+
+		final ResultSet res = registry.getResultSetById(rsId); // NOPMD
+		assertNotNull("the resultset is not found", res);
+		assertEquals("the resultsets don't have the same id", rsId, res.getIdentifier());
+		assertEquals("the resultsets are not the same instance", resultSet, res);
+	}
+
+	/**
+	 * try to obtain a inexistent resultset.
+	 */
+	@Test
+	public void testInexistentResultSet() {
+		final String rsId = resultSet.getIdentifier();
+		assertNull("inexisten resultset returns null", registry.getResultSetById(rsId));
+	}
+
+	/**
+	 * test closing of resultset and its pruning from the registry.
+	 */
+	@Test
+	public void testResultSetClose() {
+		final String rsId = resultSet.getIdentifier();
+
+		assertTrue("check if resultset is open", resultSet.isOpen());
+
+		registry.addResultSet(resultSet);
+		verify(resultSet).addObserver(registry);
+
+		// simulate a resultset close on the mock
+		when(resultSet.isOpen()).thenReturn(false);
+		registry.update(resultSet, null);
+
+		assertFalse("check if resultset is closed", resultSet.isOpen());
+		assertNull("check if the object is pruned from the registry", registry.getResultSetById(rsId));
+	}
+
+	/**
+	 * same as testResultSetClose() but with a real observer/observable mechanism, i.e. without resultset mock class.
+	 * 
+	 */
+	@Test
+	public void testWithRealObservable() {
+		final LocalResultSetImpl rset = new LocalResultSetImpl(null);
+		rset.setIdentifier("123456");
+		resultSet = rset;
+
+		final String rsId = resultSet.getIdentifier();
+
+		assertFalse("check if resultset is not destroyed", resultSet.isDestroyed());
+
+		registry.addResultSet(resultSet);
+		resultSet.destroy();
+
+		assertTrue("check if resultset is destroyed", resultSet.isDestroyed());
+		assertNull("check if the object is pruned from the registry", registry.getResultSetById(rsId));
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/observer/DelegationObserver.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/observer/DelegationObserver.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/observer/DelegationObserver.java	(revision 45117)
@@ -0,0 +1,29 @@
+package eu.dnetlib.enabling.resultset.observer;
+
+import eu.dnetlib.enabling.resultset.ResultSet;
+import eu.dnetlib.enabling.resultset.ResultSetRegistry;
+
+/**
+ * This class delegates an observation event from the java.util.Observable producer to the real consumer which is not a
+ * java.util.Observer (as expected by java.util.Observable) but instead a miscutils Observer.
+ * 
+ * @author marko, claudio, alessia, michele
+ * 
+ */
+public class DelegationObserver implements java.util.Observer {
+	/**
+	 * 
+	 */
+	private transient final ResultSet observable;
+	private transient final ResultSetRegistry observer;
+
+	public DelegationObserver(final ResultSet observable, final ResultSetRegistry observer) {
+		this.observable = observable;
+		this.observer = observer;
+	}
+
+	@Override
+	public void update(final java.util.Observable ignored, final Object arg) {
+		observer.update(observable, arg);
+	}
+}
\ No newline at end of file

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/observer/DelegationObserver.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/IterableResultSetTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/IterableResultSetTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/IterableResultSetTest.java	(revision 45117)
@@ -0,0 +1,150 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+/**
+ * tests the IterableResult class
+ * 
+ * @author claudio
+ *
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class IterableResultSetTest {
+
+	/**
+	 * number of total elements 
+	 */
+	private static int NUM_ELEM = 100;
+	
+	/**
+	 * number of elements available to fetch
+	 */
+	private static int FETCH_SIZE = 10;
+	
+	@Mock
+	private ResultSet mockResultSet;
+	
+	/**
+	 * a list used to compare elements.
+	 */
+	private List<String> list;
+	
+	/**
+	 * Iterator associated with the test list.
+	 */
+	private Iterator<String> iter;
+	
+	/**
+	 * Object to test.
+	 */
+	private IterableResultSet iterResultSet;
+
+	@Before
+	public void setUp() {
+		list = new ArrayList<String>();
+		for (int i=0; i< NUM_ELEM; i++)
+			list.add("XXXXX " + i);
+				
+		iter = list.iterator();
+		when(mockResultSet.isOpen()).thenReturn(iter.hasNext());
+		
+		iterResultSet = new IterableResultSet(list, FETCH_SIZE);
+		iterResultSet.setResultSet(mockResultSet);
+	}
+	
+	@Test
+	public void testIterableResultSet() {
+		assertNotNull(iterResultSet);
+		assertTrue(iterResultSet.getSize() > 0);
+	}
+
+	@Test(expected=RuntimeException.class)
+	public void testGetResult_fail_1() {
+		iterResultSet.getResult(0, 5);
+	}
+
+	@Test(expected=RuntimeException.class)
+	public void testGetResult_fail_2() {
+		iterResultSet.getResult(1, 5);
+		iterResultSet.getResult(1, 5);
+	}
+	
+	@Test(expected=RuntimeException.class)
+	public void testGetResult_fail_3() {
+		iterResultSet.getResult(1, 5);
+		iterResultSet.getResult(6, 5);
+	}
+	
+	@Test(expected=RuntimeException.class)
+	public void testGetResult_fail_4() {
+		iterResultSet.getResult(1, 5);
+		iterResultSet.getResult(7, 10);
+	}
+	
+	@Test
+	public void testGetResult_success_1() {
+		List<String> result = iterResultSet.getResult(1, NUM_ELEM);
+		for (int i=0; i<NUM_ELEM; i++) {
+			assertEquals(list.get(i), result.get(i));
+		}
+	}
+	
+	@Test
+	public void testGetResult_success_2() {
+		List<String> result = iterResultSet.getResult(1, NUM_ELEM);
+		
+		for (int i=0; i<NUM_ELEM; i++) {
+			assertEquals(list.get(i), result.get(i));
+			iter.next();
+		}
+		verify(mockResultSet).close();
+	}
+
+	@Test
+	public void testGetResult_success_3() {
+		for (int i = 1; i < NUM_ELEM; i+= FETCH_SIZE)
+			iterResultSet.getResult(i, i + FETCH_SIZE-1);
+		verify(mockResultSet, times(1)).close();
+	}
+	
+	@Test
+	public void testGetResult_success_4() {
+		iterResultSet.getResult(1, NUM_ELEM + 1);
+		verify(mockResultSet, times(1)).close();
+	}
+	
+	@Test
+	public void testGetResultSet_success_1() {
+		assertNotNull(iterResultSet.getResultSet());
+	}
+
+	@Test
+	public void testGetSize_fail_1() {
+		iterResultSet.getResult(1, 8);
+		assertNotSame(7, iterResultSet.getSize());
+		assertNotSame(9, iterResultSet.getSize());
+	}
+	
+	@Test
+	public void testGetSize_success_1() {
+		iterResultSet.getResult(1, 8);
+		assertEquals(FETCH_SIZE, iterResultSet.getSize());
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistry.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistry.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistry.java	(revision 45117)
@@ -0,0 +1,75 @@
+package eu.dnetlib.enabling.resultset;
+
+import eu.dnetlib.enabling.resultset.observer.ResultSetObserver;
+
+/**
+ * Instances of ResultSetRegistry manage a set of resultset objects and manage their garbage collection.
+ *
+ * @author marko
+ *
+ */
+public interface ResultSetRegistry extends ResultSetObserver {
+	/**
+	 * add a resultset object to the registry.
+	 *
+	 * The given resultset object from now on is managed by the resultset registry.
+	 *
+	 * @param resultSet
+	 *            a resultset object
+	 */
+	void addResultSet(ResultSet resultSet);
+	
+	/**
+	 * add a resultset object to the registry.
+	 *
+	 * The given resultset object from now on is managed by the resultset registry.
+	 *
+	 * @param resultSet
+	 *            a resultset object
+	 * @param identifier the identifier you want for the resultset
+	 */
+	void addResultSet(ResultSet resultSet, String identifier);
+
+	/**
+	 * add a resultset object to the registry.
+	 *
+	 * The given resultset object from now on is managed by the resultset registry.
+	 *
+	 * @param resultSet
+	 *            a resultset object
+	 * @param maxIdleTime
+	 *            max idle time
+	 */
+	void addResultSet(ResultSet resultSet, int maxIdleTime);
+	
+	/**
+	 * add a resultset object to the registry.
+	 *
+	 * The given resultset object from now on is managed by the resultset registry.
+	 *
+	 * @param resultSet
+	 *            a resultset object
+	 * @param identifier the identifier you want for the resultset
+	 * @param maxIdleTime max idle time
+	 */
+	void addResultSet(ResultSet resultSet, String identifier, int maxIdleTime);
+
+	/**
+	 * obtain the resultset with the given id.
+	 *
+	 * @param rsId
+	 *            resultset id
+	 * @return the resultset object matching the rsId or null
+	 */
+	ResultSet getResultSetById(String rsId);
+
+	/**
+	 * obtain the resultset's maxIdleTime parameter for a resultset with the given id.
+	 *
+	 * @param rsId
+	 *            resultset id
+	 * @return max idle time in seconds, as specified when the resultset has been registered
+	 */
+	int getMaxIdleTimeById(String rsId);
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/resources/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest-context.xml
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/resources/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest-context.xml	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/resources/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest-context.xml	(revision 45117)
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
+	xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
+
+	<bean id="resultSetDescriptorPrototype" class="eu.dnetlib.enabling.resultset.push.ResultSetDescriptor"
+		p:rangeLength="200" scope="prototype" />
+
+	<bean id="resultSetDescriptorFactory" class="eu.dnetlib.springutils.beans.factory.PrototypeFactory">
+		<lookup-method name="newInstance" bean="resultSetDescriptorPrototype" />
+	</bean>
+</beans>
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetListener.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetListener.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetListener.java	(revision 45117)
@@ -0,0 +1,132 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Exposes an iterable through our resultset protocol.
+ * 
+ * <p>
+ * The resultset protocol is constructed as if it were random access. Some kind of sources, like an iterable, is not
+ * random access. The consumer of such a resultset knows that, and won't try to access the resultset randomly. However,
+ * it could ask for some data which is already sent, because of retries caused by network issues.
+ * </p>
+ * 
+ * @author marko
+ * 
+ */
+public class StreamingResultSetListener implements ResultSetListener, ResultSetAware {
+	private static final Log log = LogFactory.getLog(StreamingResultSetListener.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	private ResultSet resultSet;
+
+	private Iterable<String> iterable;
+	private Iterator<String> items;
+	private int size;
+
+	private int lastFrom = 0;
+	private int lastTo = 0;
+	private List<String> lastChunk;
+
+	public StreamingResultSetListener(Iterable<String> items, int size) {
+		this(items.iterator(), size);
+		this.iterable = items;
+	}
+
+	public StreamingResultSetListener(Iterator<String> items, int size) {
+		super();
+		this.items = items;
+		this.size = size;
+	}
+
+	protected void reset() {
+		lastFrom = 0;
+		items = iterable.iterator();
+	}
+
+	@Override
+	public List<String> getResult(int from, int to) {
+
+		log.debug("STREAM: getResult(" + from + ", " + to + ")");
+
+		// handle retry because of network error.
+		if (from == lastFrom && to == lastTo)
+			return lastChunk;
+
+		if (from != lastTo + 1) {
+			if (from == 1 && iterable != null)
+				reset();
+			else
+				throw new IllegalArgumentException("this resultset is not random access, you can only retry last chunk only, asked from " + from + " to "
+						+ to + " but lastTo = " + lastTo + ". Size = " + size);
+		}
+
+		List<String> chunk = new ArrayList<String>();
+		for (int i = from; i <= to; i++)
+			chunk.add(items.next());
+
+		if (resultSet != null && !items.hasNext())
+			resultSet.close();
+
+		lastFrom = from;
+		lastTo = to;
+		lastChunk = chunk;
+
+		return chunk;
+	}
+
+	@Override
+	public int getSize() {
+		return size;
+	}
+
+	public void setSize(int size) {
+		this.size = size;
+	}
+
+	public Iterator<String> getItems() {
+		return items;
+	}
+
+	public void setItems(Iterator<String> items) {
+		this.items = items;
+	}
+
+	public int getLastFrom() {
+		return lastFrom;
+	}
+
+	public void setLastFrom(int lastFrom) {
+		this.lastFrom = lastFrom;
+	}
+
+	public int getLastTo() {
+		return lastTo;
+	}
+
+	public void setLastTo(int lastTo) {
+		this.lastTo = lastTo;
+	}
+
+	public List<String> getLastChunk() {
+		return lastChunk;
+	}
+
+	public void setLastChunk(List<String> lastChunk) {
+		this.lastChunk = lastChunk;
+	}
+
+	public ResultSet getResultSet() {
+		return resultSet;
+	}
+
+	@Override
+	public void setResultSet(ResultSet resultSet) {
+		this.resultSet = resultSet;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/pom.xml
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/pom.xml	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/pom.xml	(revision 45117)
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<parent>
+		<groupId>eu.dnetlib</groupId>
+		<artifactId>dnet-parent</artifactId>
+		<version>1.0.0</version>
+		<relativePath />
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>eu.dnetlib</groupId>
+	<artifactId>cnr-resultset-service</artifactId>
+	<packaging>jar</packaging>
+	<version>2.0.1</version>
+	<scm>
+	  <developerConnection>scm:svn:https://svn.driver.research-infrastructures.eu/driver/dnet40/modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1</developerConnection>
+	</scm>
+	<dependencies>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>${junit.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>com.google.guava</groupId>
+			<artifactId>guava</artifactId>
+			<version>${google.guava.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>cglib</groupId>
+			<artifactId>cglib-nodep</artifactId>
+			<version>2.2</version>
+		</dependency>
+		<dependency>
+			<groupId>org.mockito</groupId>
+			<artifactId>mockito-core</artifactId>
+			<version>1.6</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-test</artifactId>
+			<version>${spring.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-context-support</artifactId>
+			<version>${spring.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>eu.dnetlib</groupId>
+			<artifactId>cnr-rmi-api</artifactId>
+			<version>[2.0.0,3.0.0)</version>
+		</dependency>
+		<dependency>
+			<groupId>eu.dnetlib</groupId>
+			<artifactId>cnr-spring-utils</artifactId>
+			<version>[1.0.0,2.0.0)</version>
+		</dependency>
+		<dependency>
+			<groupId>eu.dnetlib</groupId>
+			<artifactId>cnr-service-common</artifactId>
+			<version>[2.0.0,3.0.0)</version>
+		</dependency>
+	</dependencies>
+</project>
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptor.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptor.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptor.java	(revision 45117)
@@ -0,0 +1,156 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import java.io.Serializable;
+import java.util.Iterator;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Describes a push resultset.
+ *
+ * <p>
+ * A push resultset stores it's data in several ranges
+ * </p>
+ *
+ * @author marko
+ *
+ */
+public class ResultSetDescriptor implements Serializable {
+
+	/**
+	 * logger.
+	 */
+	private static final Log log = LogFactory.getLog(Range.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	/**
+	 * This class describes a range.
+	 *
+	 * @author marko
+	 *
+	 */
+	public class Range {
+		private int range;
+		private int begin;
+		private int end;
+
+		public Range(final int range, final int begin, final int end) {
+			super();
+			this.range = range;
+			this.begin = begin;
+			this.end = end;
+		}
+
+		@Override
+		public String toString() {
+			return "Range(" + range + ", " + begin + ", " + end + ")";
+		}
+
+		public int getRange() {
+			return range;
+		}
+
+		public void setRange(final int range) {
+			this.range = range;
+		}
+
+		public int getBegin() {
+			return begin;
+		}
+
+		public void setBegin(final int begin) {
+			this.begin = begin;
+		}
+
+		public int getEnd() {
+			return end;
+		}
+
+		public void setEnd(final int end) {
+			this.end = end;
+		}
+	}
+
+	/**
+	 *
+	 */
+	private static final long serialVersionUID = 7699992350256317181L;
+
+	private int rangeLength = 100;
+
+	private int ranges = 0;
+
+	public int getLastRange() {
+		return ranges - 1;
+	}
+
+	/**
+	 * @param fromPosition
+	 *            1 based count
+	 * @param toPosition
+	 *            1 based count
+	 * @return
+	 */
+	public Iterable<Range> getRangesContaining(final int fromPosition, final int toPosition) {
+
+		final int fromRange = (fromPosition - 1) / rangeLength;
+		int ttoRange = (int) Math.ceil((toPosition * 1.0) / rangeLength);
+
+		if (ttoRange > ranges)
+			ttoRange = ranges;
+
+		final int toRange = ttoRange;
+
+		log.debug("FROM range: " + fromRange);
+		log.debug("TTO range: " + ttoRange);
+		log.debug("TO range: " + toRange);
+
+		return new Iterable<Range>() {
+
+			@Override
+			public Iterator<Range> iterator() {
+				return new Iterator<Range>() {
+
+					int current = fromRange;
+
+					@Override
+					public boolean hasNext() {
+						return current < toRange;
+					}
+
+					@Override
+					public Range next() {
+						int begin = 0;
+						int end = rangeLength;
+						if (current == fromRange)
+							begin = (fromPosition - 1) % rangeLength;
+						if ((current + 1) == toRange)
+							end = (toPosition - 1) % rangeLength + 1;
+						return new Range(current++, begin, end);
+					}
+
+					@Override
+					public void remove() {
+						throw new IllegalStateException("text");
+					}
+				};
+			}
+		};
+	}
+
+	public int getRangeLength() {
+		return rangeLength;
+	}
+
+	public void setRangeLength(final int rangeLength) {
+		this.rangeLength = rangeLength;
+	}
+
+	public int getRanges() {
+		return ranges;
+	}
+
+	public void setRanges(final int ranges) {
+		this.ranges = ranges;
+	}
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSet.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSet.java	(revision 45117)
@@ -0,0 +1,151 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
+import eu.dnetlib.enabling.tools.ServiceResolver;
+import eu.dnetlib.miscutils.collections.MappedCollection;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+/**
+ * A resultset filter. Applies a transformation for every resultset record.
+ * 
+ * @author marko
+ * 
+ */
+public class MappedResultSet implements ResultSetListener, ResultSetAware {
+
+	/**
+	 * input resultset.
+	 */
+	private ResultSetService resultSetService;
+
+	/**
+	 * input resultset id.
+	 */
+	private String rsId;
+
+	/**
+	 * mapper function.
+	 */
+	private UnaryFunction<String, String> mapper;
+
+	/**
+	 * service resolver.
+	 */
+	private ServiceResolver serviceResolver;
+
+	private ResultSet resultSet;
+
+	/**
+	 * Create a new mapped resultset.
+	 * 
+	 * @param epr
+	 *            input resultset epr
+	 * @param mapper
+	 *            mapper function
+	 * @param serviceResolver
+	 *            service resolver
+	 */
+	public MappedResultSet(final W3CEndpointReference epr, final UnaryFunction<String, String> mapper, final ServiceResolver serviceResolver) {
+		super();
+
+		this.resultSetService = serviceResolver.getService(ResultSetService.class, epr);
+		this.rsId = serviceResolver.getResourceIdentifier(epr);
+
+		this.mapper = mapper;
+
+		this.serviceResolver = serviceResolver;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSetListener#getResult(int, int)
+	 */
+	@Override
+	public List<String> getResult(final int fromPosition, final int toPosition) {
+		return MappedCollection.listMap(getResultFromSource(fromPosition, toPosition), mapper);
+
+	}
+
+	protected List<String> getResultFromSource(final int fromPosition, final int toPosition) {
+		try {
+			List<String> res = resultSetService.getResult(rsId, fromPosition, toPosition, "waiting");
+			checkStatus();
+			return res;
+		} catch (final ResultSetException e) {
+			throw new IllegalStateException(e);
+		}
+	}
+
+	private void checkStatus() throws ResultSetException {
+		if (getResultSet().isOpen() && resultSetService.getRSStatus(rsId).equals("closed")) {
+			getResultSet().close();
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSetListener#getSize()
+	 */
+	@Override
+	public int getSize() {
+		try {
+			int numberOfElements = resultSetService.getNumberOfElements(rsId);
+			checkStatus();		
+			return numberOfElements;
+		} catch (final ResultSetException e) {
+			throw new IllegalStateException(e);
+		}
+	}
+
+	public ResultSetService getResultSetService() {
+		return resultSetService;
+	}
+
+	public void setResultSetService(final ResultSetService resultSetService) {
+		this.resultSetService = resultSetService;
+	}
+
+	public UnaryFunction<String, String> getMapper() {
+		return mapper;
+	}
+
+	public void setMapper(final UnaryFunction<String, String> mapper) {
+		this.mapper = mapper;
+	}
+
+	public ServiceResolver getServiceResolver() {
+		return serviceResolver;
+	}
+
+	@Required
+	public void setServiceResolver(final ServiceResolver serviceResolver) {
+		this.serviceResolver = serviceResolver;
+	}
+
+	@Override
+	public void setResultSet(ResultSet resultSet) {
+		this.resultSet = resultSet;
+	}
+
+	public ResultSet getResultSet() {
+		return resultSet;
+	}
+
+	public String getRsId() {
+		return rsId;
+	}
+
+	public void setRsId(String rsId) {
+		this.rsId = rsId;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSetFactory.java	(revision 45117)
@@ -0,0 +1,21 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * creates a new push resultset.
+ *
+ * @author marko
+ *
+ */
+public interface PushResultSetFactory {
+
+	/**
+	 * create a new push resultset.
+	 *
+	 * @param maxIdleTime max time the resultset can be idle
+	 * @return push resultset epr
+	 */
+	W3CEndpointReference createPushResultSet(int maxIdleTime);
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/AbstractObservableResultset.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/AbstractObservableResultset.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/AbstractObservableResultset.java	(revision 45117)
@@ -0,0 +1,155 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import eu.dnetlib.enabling.resultset.observer.DelegationObserver;
+import eu.dnetlib.enabling.resultset.observer.Observable;
+
+
+/**
+ * Common stuff for resultset implementations bound to a ResultSetRegistry.
+ * 
+ * @author marko
+ * 
+ */
+public abstract class AbstractObservableResultset implements ResultSet, Observable {
+	/**
+	 * true if the resultset is destroyed.
+	 */
+	private boolean destroyed = false;
+
+	/**
+	 * true if the resultset is open.
+	 */
+	private boolean open;
+
+	/**
+	 * delegate the real job to a java.util.Observable object.
+	 */
+	private transient final java.util.Observable observable = new DelegationObservable();
+
+	/**
+	 * weak map for removing single observers later on.
+	 */
+	private transient Map<ResultSetRegistry, DelegationObserver> observers = new WeakHashMap<ResultSetRegistry, DelegationObserver>();
+
+	/**
+	 * java.util.Observable requires a "change" in the object to be made for the notifyObservers methods to trigger
+	 * actually the notification. We don't think this should be part of the base Observable/Observer pattern and thus
+	 * hide this fact. If an user of AbstractObservable wants this behavior it should implement her own change tracking
+	 * and avoid calling notifyObservers altogether. The rationale behind this choice is that not all dirty states can
+	 * be expressed using a stateful boolean instance variable like that implemented by java.util.Observable; some users
+	 * may prefer/need a lazy dirty flag instead.
+	 * 
+	 * @author marko
+	 * 
+	 */
+	static class DelegationObservable extends java.util.Observable {
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see java.util.Observable#notifyObservers()
+		 */
+		@Override
+		public void notifyObservers() {
+			setChanged();
+			super.notifyObservers();
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see java.util.Observable#notifyObservers(java.lang.Object)
+		 */
+		@Override
+		public void notifyObservers(final Object arg) {
+			setChanged();
+			super.notifyObservers(arg);
+		}
+
+	}	
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#destroy()
+	 */
+	@Override
+	public void destroy() {
+		if (!isDestroyed()) {
+			setDestroyed(true);
+			notifyObservers();
+			deleteObservers();
+		}
+	}
+
+	public void setDestroyed(final boolean destroyed) {
+		this.destroyed = destroyed;
+	}
+
+	@Override
+	public boolean isDestroyed() {
+		return destroyed;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#isOpen()
+	 */
+	@Override
+	public boolean isOpen() {
+		return open;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#close()
+	 */
+	@Override
+	public void close() {
+		open = false;
+	}
+
+	public void setOpen(final boolean open) {
+		this.open = open;
+	}
+
+	@Override
+	public void addObserver(final ResultSetRegistry observer) {
+		final DelegationObserver delegate = new DelegationObserver(this, observer);
+		observers.put(observer, delegate);
+		observable.addObserver(delegate);
+	}
+
+	protected void notifyObservers() {
+		observable.notifyObservers();
+	}
+
+	protected void notifyObservers(final Object arg) {
+		observable.notifyObservers(arg);
+	}
+
+	public int countObservers() {
+		return observable.countObservers();
+	}
+
+	public void deleteObserver(final java.util.Observer observer) {
+		observable.deleteObserver(observer);
+	}
+
+	public void deleteObserver(ResultSetRegistry observer) {
+		DelegationObserver delegate = observers.get(observer);
+		if(delegate != null) {
+			observable.deleteObserver(delegate);
+		}
+	}	
+
+	public void deleteObservers() {
+		observable.deleteObservers();
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/JaxbResultsetListenerWrapper.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/JaxbResultsetListenerWrapper.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/JaxbResultsetListenerWrapper.java	(revision 45117)
@@ -0,0 +1,68 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import javax.xml.bind.JAXBException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.miscutils.collections.MappedCollection;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+import eu.dnetlib.miscutils.jaxb.JaxbFactory;
+
+/**
+ * Given a jaxb factory for a given type, wraps TypedResultsetListeners to ResultSetListeners, serializing objects
+ * according to the jaxb factory.
+ * 
+ * @author marko
+ * 
+ * @param <T>
+ */
+public class JaxbResultsetListenerWrapper<T> {
+	private static final Log log = LogFactory.getLog(JaxbResultsetListenerWrapper.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	private JaxbFactory<T> factory;
+
+	/**
+	 * Returns a listener which serializes each item according to the jaxb factory.
+	 * 
+	 * @param listener
+	 *            listener which returns T
+	 * @return listener which returns strings
+	 */
+	public ResultSetListener wrap(final TypedResultSetListener<T> listener) {
+		return new ResultSetListener() {
+
+			@Override
+			public List<String> getResult(final int fromPosition, final int toPosition) {
+				return Lists.newArrayList(new MappedCollection<String, T>(listener.getResult(fromPosition, toPosition), new UnaryFunction<String, T>() {
+					@Override
+					public String evaluate(final T value) {
+						try {
+							return factory.serialize(value);
+						} catch (final JAXBException e) {
+							log.warn("cannot serialize", e);
+							throw new RuntimeException(e);
+						}
+					}
+				}));
+			}
+
+			@Override
+			public int getSize() {
+				return listener.getSize();
+			}
+		};
+	}
+
+	public JaxbFactory<T> getFactory() {
+		return factory;
+	}
+
+	public void setFactory(final JaxbFactory<T> factory) {
+		this.factory = factory;
+	}
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetImpl.java	(revision 45117)
@@ -0,0 +1,98 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Resultset backing implementation.
+ * 
+ * @author marko
+ * 
+ */
+public class LocalResultSetImpl extends AbstractObservableResultset implements ResultSet {
+
+	/**
+	 * rsId.
+	 */
+	private String identifier;
+
+	/**
+	 * this listener will provide the data to this local resultset by listening to events.
+	 */
+	private ResultSetListener listener;
+
+	/**
+	 * Construct a new local ResultSet which pulls data from the listener. If the listener implements ResultSetAware, it
+	 * will be injected with this instance.
+	 * 
+	 * @param listener
+	 *            a resultset listener
+	 */
+	public LocalResultSetImpl(final ResultSetListener listener) {
+		super();
+		this.listener = listener;
+
+		if (listener instanceof ResultSetAware)
+			((ResultSetAware) listener).setResultSet(this);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#getNumberOfResults()
+	 */
+	@Override
+	public int getNumberOfResults() {
+		return listener.getSize();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#getResults(int, int)
+	 */
+	@Override
+	public List<String> getResults(final int fromPosition, final int toPosition) {
+		int toPos = toPosition;
+		int fromPos = fromPosition;
+		if (!isOpen()) {
+			final int size = getNumberOfResults();
+			
+			if (size == 0)
+				return Lists.newArrayList();
+			
+			if (fromPos > size)
+				return Lists.newArrayList();
+
+			if (toPos > size)
+				toPos = size;
+		}
+		
+		if (fromPos < 1)
+			fromPos = 1;
+		if (toPos < fromPos)
+			toPos = fromPos;
+
+		return listener.getResult(fromPos, toPos);
+	}
+
+	@Override
+	public String getIdentifier() {
+		return identifier;
+	}
+
+	@Override
+	public void setIdentifier(final String identifier) {
+		this.identifier = identifier;
+	}
+
+	public ResultSetListener getListener() {
+		return listener;
+	}
+
+	public void setListener(final ResultSetListener listener) {
+		this.listener = listener;
+	}
+
+}

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetImpl.java
___________________________________________________________________
Added: svn:mergeinfo
## -0,0 +0,0 ##
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImpl.java	(revision 45117)
@@ -0,0 +1,99 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import eu.dnetlib.enabling.resultset.AbstractObservableResultset;
+
+/**
+ * a push resultset which holds it's data in a transient cache.
+ *
+ * @author marko
+ *
+ */
+public class TransientPushResultSetImpl extends AbstractObservableResultset implements PushResultSet {
+
+	/**
+	 * logger.
+	 */
+	private static final Log log = LogFactory.getLog(TransientPushResultSetImpl.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	/**
+	 * dao.
+	 */
+	private final transient TransientPushResultSetDao dao;
+
+	/**
+	 * rsId.
+	 */
+	private String identifier;
+
+	/**
+	 * constructed by the transient push resultset factory.
+	 *
+	 * @param dao dao
+	 */
+	public TransientPushResultSetImpl(final TransientPushResultSetDao dao) {
+		super();
+		this.dao = dao;
+		setOpen(true);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see eu.dnetlib.enabling.resultset.push.PushResultSet#addElements(java.util.List)
+	 */
+	@Override
+	public void addElements(final List<String> elements) {
+		log.debug("adding to push RS: " + elements);
+
+		if (isOpen())
+			dao.addElements(getIdentifier(), elements);
+		else
+			throw new IllegalStateException("cannot write to a closed push resultset");
+	}
+
+	@Override
+	public int getNumberOfResults() {
+		return dao.getSize(getIdentifier());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#getResults(int, int)
+	 */
+	@Override
+	public List<String> getResults(final int fromPosition, final int toPosition) {
+
+		final int size = getNumberOfResults();
+		int toPos = toPosition;
+		int fromPos = fromPosition;
+		if (fromPos > size)
+			fromPos = size;
+		if (toPos > size)
+			toPos = size;
+
+		log.debug("calling get elements: " + getIdentifier() + " from " + fromPos + " to " + toPos);
+		return dao.getElements(getIdentifier(), fromPos, toPos);
+	}
+
+	public TransientPushResultSetDao getDao() {
+		return dao;
+	}
+
+	@Override
+	public String getIdentifier() {
+		return identifier;
+	}
+
+	@Override
+	public void setIdentifier(final String identifier) {
+		this.identifier = identifier;
+	}
+
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/AbstractPushResultSetFactoryImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/AbstractPushResultSetFactoryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/AbstractPushResultSetFactoryImpl.java	(revision 45117)
@@ -0,0 +1,44 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.enabling.resultset.ResultSetServiceImpl;
+
+/**
+ * push resultset factory.
+ *
+ * @author marko
+ *
+ */
+public abstract class AbstractPushResultSetFactoryImpl implements PushResultSetFactory {
+	/**
+	 * resultset service.
+	 */
+	private ResultSetServiceImpl resultSetService;
+
+	/**
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.push.PushResultSetFactory#createPushResultSet(int)
+	 */
+	@Override
+	public W3CEndpointReference createPushResultSet(final int maxIdleTime) {
+		final PushResultSet resultSet = newInstance();
+		resultSetService.getResultsetRegistry().addResultSet(resultSet, maxIdleTime);
+		return resultSetService.getEprBuilder().getEndpointReference(resultSetService.getEndpoint(), resultSet.getIdentifier());
+	}
+
+	/**
+	 * subclasses should override it and create a new push resultset instance.
+	 * @return push resultset instance
+	 */
+	protected abstract PushResultSet newInstance();
+
+	public ResultSetServiceImpl getResultSetService() {
+		return resultSetService;
+	}
+
+	public void setResultSetService(final ResultSetServiceImpl resultSetService) {
+		this.resultSetService = resultSetService;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactory.java	(revision 45117)
@@ -0,0 +1,7 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import eu.dnetlib.miscutils.factory.Factory;
+
+public interface ResultSetDescriptorFactory extends Factory<ResultSetDescriptor> {
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetDao.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetDao.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetDao.java	(revision 45117)
@@ -0,0 +1,45 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import java.util.List;
+
+/**
+ * offer access to the underlying in-memory or pseudo-memory (serialization backed caches) storage for the transient
+ * push-resultsets.
+ *
+ * This type of push resultsets doesn't even try to make efficient access to records, they just keep them as big lists
+ * on the underlying storage. Actual implementations may decide to keep them on the heap or to use some caching
+ * technology like ehcache.
+ *
+ * @author marko
+ *
+ */
+public interface TransientPushResultSetDao {
+	/**
+	 * add elements to a given key.
+	 *
+	 * @param key
+	 *            usually a rsid.
+	 * @param elements
+	 *            list of elements
+	 */
+	void addElements(String key, List<String> elements);
+
+	/**
+	 * obtain content for a given key (resultset) in a given range (1 based).
+	 *
+	 * @param key
+	 *            usually a rsid
+	 * @param fromPosition from position (1 based, inclusive)
+	 * @param toPosition to position (1 based, inclusive)
+	 * @return all the elements for a given key
+	 */
+	List<String> getElements(String key, int fromPosition, int toPosition);
+
+	/**
+	 * get the resultset size (number of elements).
+	 *
+	 * @param key usually a rsid
+	 * @return resultset size
+	 */
+	int getSize(String key);
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSet.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSet.java	(revision 45117)
@@ -0,0 +1,22 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import java.util.List;
+
+import eu.dnetlib.enabling.resultset.ResultSet;
+
+/**
+ * resultset which receive data through the "push" interface, i.e. data is directly appended to it.
+ * 
+ * @author marko
+ *
+ */
+public interface PushResultSet extends ResultSet {
+
+	/**
+	 * add a list of elements at the end of the resultset.
+	 * 
+	 * @param elements list of elements
+	 */
+	void addElements(List<String> elements);
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDaoImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDaoImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDaoImpl.java	(revision 45117)
@@ -0,0 +1,23 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * fake resultset property dao.
+ * 
+ * @author marko
+ *
+ */
+public class ResultSetPropertyDaoImpl implements ResultSetPropertyDao {
+
+	/** 
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.ResultSetPropertyDao#getProperties(eu.dnetlib.enabling.resultset.ResultSet)
+	 */
+	@Override
+	public Map<String, String> getProperties(final ResultSet resultSet) {
+		return new HashMap<String, String>();
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetEPRPool.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetEPRPool.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetEPRPool.java	(revision 45117)
@@ -0,0 +1,137 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import javax.annotation.PostConstruct;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.enabling.tools.UniqueIdentifierGenerator;
+import eu.dnetlib.enabling.tools.UniqueIdentifierGeneratorImpl;
+
+public class ResultSetEPRPool {
+	private static final Log log = LogFactory.getLog(ResultSetEPRPool.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	static class PreparedResultSet {
+		private String rsId;
+		private W3CEndpointReference epr;
+
+		public PreparedResultSet(final String rsId, final W3CEndpointReference epr) {
+			super();
+			this.rsId = rsId;
+			this.epr = epr;
+		}
+
+		public String getRsId() {
+			return rsId;
+		}
+
+		public void setRsId(final String rsId) {
+			this.rsId = rsId;
+		}
+
+		public W3CEndpointReference getEpr() {
+			return epr;
+		}
+
+		public void setEpr(final W3CEndpointReference epr) {
+			this.epr = epr;
+		}
+	}
+
+	class PoolFiller implements Runnable {
+
+		@Override
+		public void run() {
+			while (true)
+				try {
+					final PreparedResultSet resultSet = prepareResultSet();
+					pool.put(resultSet);
+				} catch (final InterruptedException e) {
+					// eat this exception
+					log.debug("cannot add resultset to pool", e);
+				}
+		}
+
+		private PreparedResultSet prepareResultSet() {
+			final String rsId = idGenerator.generateIdentifier();
+			return new PreparedResultSet(rsId, createEPR(rsId));
+		}
+
+		private W3CEndpointReference createEPR(final String rsId) {
+			return getResultSetService().getEprBuilder().getEndpointReference(getResultSetService().getEndpoint(), rsId);
+		}
+	}
+
+	/**
+	 * resultset service.
+	 */
+	private ResultSetServiceImpl resultSetService;
+
+	private int capacity = 1000;
+	private int fillerThreads = 10;
+	private final BlockingQueue<PreparedResultSet> pool = new LinkedBlockingQueue<PreparedResultSet>(capacity);
+
+	/**
+	 * identifier generator.
+	 */
+	private UniqueIdentifierGenerator idGenerator = new UniqueIdentifierGeneratorImpl("rs-");
+
+	@PostConstruct
+	public void init() {
+		log.info("-------<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>> Starting fill threads");
+		for (int i = 0; i < fillerThreads; i++)
+			startFillter();
+	}
+
+	protected void startFillter() {
+		final Thread filler = new Thread(new PoolFiller());
+		filler.setDaemon(true);
+		filler.start();
+	}
+
+	public W3CEndpointReference registerResultSet(final ResultSet resultSet) {
+		final PreparedResultSet prepared = nextPreparedResultSet();
+		if (prepared == null) {
+			log.info("EPR cache is empty, creating EPR in caller thread");
+			return getResultSetService().getEprBuilder().getEndpointReference(getResultSetService().getEndpoint(), idGenerator.generateIdentifier());
+		}
+
+		getResultSetService().getResultsetRegistry().addResultSet(resultSet, prepared.getRsId());
+		return prepared.getEpr();
+	}
+
+	private PreparedResultSet nextPreparedResultSet() {
+		log.info(">>>> fetching a prepared resultset from the pool");
+		return pool.poll();
+	}
+
+	public int getCapacity() {
+		return capacity;
+	}
+
+	public void setCapacity(int capacity) {
+		this.capacity = capacity;
+	}
+
+	public UniqueIdentifierGenerator getIdGenerator() {
+		return idGenerator;
+	}
+
+	public void setIdGenerator(UniqueIdentifierGenerator idGenerator) {
+		this.idGenerator = idGenerator;
+	}
+
+	public ResultSetServiceImpl getResultSetService() {
+		return resultSetService;
+	}
+
+	@Required
+	public void setResultSetService(ResultSetServiceImpl resultSetService) {
+		this.resultSetService = resultSetService;
+	}
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSetFactory.java	(revision 45117)
@@ -0,0 +1,67 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+/**
+ * 
+ * @author claudio
+ *
+ */
+public class IterableResultSetFactory {
+
+	/**
+	 * {@link ResultSetFactory}
+	 */
+	private LocalOpenResultSetFactoryImpl resultSetFactory;
+	
+	/**
+	 * 
+	 */
+	private int fetchSize;
+	
+	/**
+	 * 
+	 * @param source
+	 * @return
+	 */
+	public W3CEndpointReference createIterableResultSet(final Iterable<String> source) {
+		return resultSetFactory.createResultSet(new IterableResultSet(source, fetchSize));
+	}
+	
+	/**
+	 * 
+	 * @return
+	 */
+	public LocalOpenResultSetFactoryImpl getResultSetFactory() {
+		return resultSetFactory;
+	}
+
+	/**
+	 * 
+	 * @param resultSetFactory
+	 */
+	@Required
+	public void setResultSetFactory(final LocalOpenResultSetFactoryImpl resultSetFactory) {
+		this.resultSetFactory = resultSetFactory;
+	}
+	
+	/**
+	 * 
+	 * @param fetchSize
+	 */
+	@Required
+	public void setFetchSize(int fetchSize) {
+		this.fetchSize = fetchSize;
+	}
+
+	/**
+	 * 
+	 * @return
+	 */
+	public int getFetchSize() {
+		return fetchSize;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSetFactory.java	(revision 45117)
@@ -0,0 +1,49 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+public class ParallelMappedResultSetFactory extends MappedResultSetFactory {
+
+	private ExecutorService executor;
+
+	private static final int QUEUE_SIZE = 40;
+
+	private int queueSize = QUEUE_SIZE;
+
+	private int cpus = 0;
+
+	public ParallelMappedResultSetFactory() {
+		super();
+
+		if (cpus == 0)
+			cpus = getNumberOfCPUs();
+		executor = new ThreadPoolExecutor(cpus, cpus, 5, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(queueSize),
+				new ThreadPoolExecutor.CallerRunsPolicy());
+	}
+
+	@Override
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final UnaryFunction<String, String> mapper) {
+		return getResultSetFactory().createResultSet(new ParallelMappedResultSet(source, mapper, getServiceResolver(), executor));
+	}
+
+	private int getNumberOfCPUs() {
+		return Runtime.getRuntime().availableProcessors();
+	}
+
+	public int getCpus() {
+		return cpus;
+	}
+
+	public void setCpus(int cpus) {
+		if(cpus > 0)
+			this.cpus = cpus;
+	}
+
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSetFactory.java	(revision 45117)
@@ -0,0 +1,53 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.enabling.tools.ServiceResolver;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+/**
+ * Create a new resultset which takes each record of the input resultset and applies the mapping function to it.
+ *
+ * @author marko
+ *
+ */
+public class MappedResultSetFactory {
+
+	/**
+	 * underlying resultset factory, which exposes local resultsets to the world.
+	 */
+	private ResultSetFactory resultSetFactory;
+
+	/**
+	 * service resolver, transforms eprs to services.
+	 */
+	private ServiceResolver serviceResolver;
+
+	/**
+	 * Create a new resultset which takes each record of the input resultset and applies the mapping function to it.
+	 *
+	 * @param source source resultset epr
+	 * @param mapper mapper function
+	 * @return mapped resultset epr
+	 */
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final UnaryFunction<String, String> mapper) {
+		return resultSetFactory.createResultSet(new MappedResultSet(source, mapper, serviceResolver));
+	}
+
+	public ResultSetFactory getResultSetFactory() {
+		return resultSetFactory;
+	}
+
+	public void setResultSetFactory(final ResultSetFactory resultSetFactory) {
+		this.resultSetFactory = resultSetFactory;
+	}
+
+	public ServiceResolver getServiceResolver() {
+		return serviceResolver;
+	}
+
+	public void setServiceResolver(final ServiceResolver serviceResolver) {
+		this.serviceResolver = serviceResolver;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetFactory.java	(revision 45117)
@@ -0,0 +1,46 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.annotation.Resource;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.enabling.tools.ServiceResolver;
+
+public class CachingResultSetFactory {
+	/**
+	 * underlying resultset factory, which exposes local resultsets to the world.
+	 */
+	private ResultSetFactory resultSetFactory;
+
+	@Resource
+	private ServiceResolver serviceResolver;
+	
+	/**
+	 * @param items
+	 * @param size
+	 *            the size of the iterable
+	 * @return
+	 */
+	public W3CEndpointReference createCachingResultSet(W3CEndpointReference epr) {
+		return resultSetFactory.createResultSet(new CachingResultSetListener(epr, serviceResolver));
+	}
+
+	public ResultSetFactory getResultSetFactory() {
+		return resultSetFactory;
+	}
+
+	@Required
+	public void setResultSetFactory(ResultSetFactory resultSetFactory) {
+		this.resultSetFactory = resultSetFactory;
+	}
+
+	public ServiceResolver getServiceResolver() {
+		return serviceResolver;
+	}
+
+	public void setServiceResolver(ServiceResolver serviceResolver) {
+		this.serviceResolver = serviceResolver;
+	}
+
+}
Index: modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDao.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDao.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDao.java	(revision 45117)
@@ -0,0 +1,19 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.Map;
+
+/**
+ * access resultset properties.
+ * 
+ * @author marko
+ *
+ */
+public interface ResultSetPropertyDao {
+	/**
+	 * return a map of custom resultset properties.
+	 * 
+	 * @param resultSet resultset
+	 * @return property map
+	 */
+	Map<String, String> getProperties(ResultSet resultSet);
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetFactory.java	(revision 45117)
@@ -0,0 +1,32 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+public class StreamingResultSetFactory {
+	/**
+	 * underlying resultset factory, which exposes local resultsets to the world.
+	 */
+	private ResultSetFactory resultSetFactory;
+
+	/**
+	 * @param items
+	 * @param size the size of the iterable
+	 * @return
+	 */
+	public W3CEndpointReference createStreamingResultSet(final Iterable<String> items, int size) {
+		return resultSetFactory.createResultSet(new StreamingResultSetListener(items.iterator(), size));
+	}
+
+	
+	public ResultSetFactory getResultSetFactory() {
+		return resultSetFactory;
+	}
+
+	@Required
+	public void setResultSetFactory(ResultSetFactory resultSetFactory) {
+		this.resultSetFactory = resultSetFactory;
+	}
+
+}
Index: modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImplTest.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImplTest.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImplTest.java	(revision 45117)
@@ -0,0 +1,166 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import static org.junit.Assert.*; // NOPMD
+import static org.mockito.Mockito.*; // NOPMD
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.enabling.resultset.ResultSetRegistry;
+
+/**
+ * test the transient push resultset.
+ *
+ * @author marko
+ *
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class TransientPushResultSetImplTest {
+
+	/**
+	 * first test value.
+	 */
+	private static final String ONE = "one";
+
+	/**
+	 * second test value.
+	 */
+	private static final String TWO = "two";
+
+	/**
+	 * test rs id.
+	 */
+	private static final String RS_ID = "123";
+
+	/**
+	 * instance to be tested.
+	 */
+	private transient TransientPushResultSetImpl resultSet;
+
+	/**
+	 * dao mock.
+	 */
+	@Mock
+	private transient TransientPushResultSetDao dao;
+
+	/**
+	 * resultset registry mock.
+	 */
+	@Mock
+	private transient ResultSetRegistry registry;
+
+	/**
+	 * setup class to be tested.
+	 *
+	 * @throws Exception
+	 */
+	@Before
+	public void setUp() {
+		resultSet = new TransientPushResultSetImpl(dao);
+		resultSet.setIdentifier(RS_ID);
+		resultSet.getDao(); // getter code coverage hack
+	}
+
+	/**
+	 * test adding elements.
+	 */
+	@Test
+	public void testAddElements() {
+		final List<String> list = new ArrayList<String>();
+		list.add(ONE);
+
+		resultSet.addElements(list);
+
+		verify(dao).addElements(RS_ID, list);
+		assertNotNull("dummy", resultSet);
+	}
+
+	/**
+	 * test get number of results.
+	 */
+	@Test
+	public void testGetNumberOfResults() {
+		when(dao.getSize(RS_ID)).thenReturn(1);
+
+		assertEquals("check size", 1, resultSet.getNumberOfResults());
+	}
+
+	/**
+	 * get result.
+	 */
+	@Test
+	public void testGetResults() {
+		final List<String> list = new ArrayList<String>();
+		list.add(TWO);
+
+		when(dao.getSize(RS_ID)).thenReturn(2);
+		when(dao.getElements(RS_ID, 2, 2)).thenReturn(list);
+
+		assertEquals("check list", TWO, resultSet.getResults(2, 2).get(0));
+		assertEquals("check size", 1, resultSet.getResults(2, 2).size());
+	}
+
+	/**
+	 * test when indices are out of range, trailing stuff should be skipped.
+	 */
+	@Test
+	public void testGetResultOutOfRange() {
+		final List<String> list = new ArrayList<String>();
+		list.add(TWO);
+
+		when(dao.getSize(RS_ID)).thenReturn(2);
+		when(dao.getElements(RS_ID, 2, 2)).thenReturn(list);
+
+		assertEquals("check list", TWO, resultSet.getResults(2, 2 + 1).get(0));
+		assertEquals("check size", 1, resultSet.getResults(2, 2 + 1).size());
+	}
+
+	/**
+	 * open.
+	 */
+	@Test
+	public void testIsOpen() {
+		assertTrue("check is open by default", resultSet.isOpen());
+	}
+
+	/**
+	 * test close.
+	 */
+	@Test
+	public void testClose() {
+		resultSet.addObserver(registry);
+		assertEquals("observer should be added", 1, resultSet.countObservers());
+
+		resultSet.destroy();
+		assertTrue("should be destroyed", resultSet.isDestroyed());
+
+		assertEquals("observers should be cleared", 0, resultSet.countObservers());
+		verify(registry, times(1)).update(resultSet, null);
+	}
+
+	@Test
+	public void testFromAfterSize() {
+		final List<String> list = new ArrayList<String>();
+		list.add(TWO);
+
+		when(dao.getSize(RS_ID)).thenReturn(2);
+		when(dao.getElements(RS_ID, 2, 2)).thenReturn(list);
+
+		resultSet.getResults(3, 2);
+	}
+
+	@Test(expected = IllegalStateException.class)
+	public void testWriteClosed() {
+		resultSet.close();
+		resultSet.addElements(Lists.newArrayList("test"));
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/AbstractResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/AbstractResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/AbstractResultSetFactory.java	(revision 45117)
@@ -0,0 +1,38 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * Resultset factories bound to a resultset service, from which it takes the resultset registry and the epr builder.
+ *
+ * @author marko
+ *
+ */
+public abstract class AbstractResultSetFactory implements ResultSetFactory {
+
+	/**
+	 * resultset service.
+	 */
+	private ResultSetServiceImpl resultSetService;
+
+	/**
+	 * Register a resultset instance to the underlying resultset registry and returns
+	 * and EPR to accessible through the resultset service.
+	 *
+	 * @param resultSet resultset instance
+	 * @return epr to the newly created resultset
+	 */
+	public W3CEndpointReference registerResultSet(final ResultSet resultSet) {
+		resultSetService.getResultsetRegistry().addResultSet(resultSet);
+		return resultSetService.getEprBuilder().getEndpointReference(resultSetService.getEndpoint(), resultSet.getIdentifier());
+	}
+
+	public ResultSetServiceImpl getResultSetService() {
+		return resultSetService;
+	}
+
+	public void setResultSetService(final ResultSetServiceImpl resultSetService) {
+		this.resultSetService = resultSetService;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalOpenResultSetFactoryImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalOpenResultSetFactoryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalOpenResultSetFactoryImpl.java	(revision 45117)
@@ -0,0 +1,23 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+public class EPRPoolingLocalOpenResultSetFactoryImpl extends LocalOpenResultSetFactoryImpl {
+	private ResultSetEPRPool pool;
+	
+	@Override
+	public W3CEndpointReference registerResultSet(ResultSet resultSet) {
+		return pool.registerResultSet(resultSet);
+	}
+
+	public ResultSetEPRPool getPool() {
+		return pool;
+	}
+
+	@Required
+	public void setPool(ResultSetEPRPool pool) {
+		this.pool = pool;
+	}
+}
Index: modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/LocalResultSetImplTest.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/LocalResultSetImplTest.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/LocalResultSetImplTest.java	(revision 45117)
@@ -0,0 +1,174 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.*; // NOPMD
+import static org.mockito.Mockito.*; // NOPMD by marko on 11/26/08 9:13 PM
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+/**
+ * test the resultset concrete implementation.
+ * 
+ * @author marko
+ * 
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class LocalResultSetImplTest {
+
+	/**
+	 * This class could be an anonymous class, but is here to be shared among tests.
+	 * 
+	 * @author marko
+	 * 
+	 */
+	private static final class TestResultSetListener implements ResultSetListener {
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see eu.dnetlib.enabling.resultset.ResultSetListener#getResult(int, int)
+		 */
+		@Override
+		public List<String> getResult(final int fromPosition, final int toPosition) {
+			final List<String> res = new ArrayList<String>();
+			for (int i = fromPosition; i <= toPosition; i++)
+				res.add(((Integer) (i - 1)).toString());
+			return res;
+		}
+
+		@Override
+		public int getSize() {
+			return RESULT_SIZE;
+		}
+	}
+
+	/**
+	 * Mockito lacks of multiple interfaces mocking.
+	 * 
+	 * @author marko
+	 * 
+	 */
+	private abstract static class AbstractResultSetAware implements ResultSetListener, ResultSetAware {
+	}
+
+	/**
+	 * resultset registry mock.
+	 */
+	@Mock
+	private transient ResultSetRegistry registry;
+
+	/**
+	 * object under test.
+	 */
+	private transient LocalResultSetImpl resultSet;
+
+	/**
+	 * number of returned test results.
+	 */
+	private static final int RESULT_SIZE = 3;
+
+	/**
+	 * provides data to the resultset under test.
+	 */
+	private transient TestResultSetListener resultSetListener;
+
+	/**
+	 * prepare.
+	 * 
+	 */
+	@Before
+	public void setUp() {
+		resultSetListener = new TestResultSetListener();
+		resultSet = new LocalResultSetImpl(resultSetListener);
+	}
+
+	/**
+	 * test the get number of results method.
+	 */
+	@Test
+	public void testGetNumberOfResults() {
+		assertEquals("check number of results", RESULT_SIZE, resultSet.getNumberOfResults());
+	}
+
+	/**
+	 * test the get result method.
+	 */
+	@Test
+	public void testGetResults() {
+		final List<String> res = resultSet.getResults(1, RESULT_SIZE); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("whole length", RESULT_SIZE, res.size());
+		for (int i = 0; i < RESULT_SIZE; i++)
+			assertEquals("check element", ((Integer) i).toString(), res.get(i));
+
+		final List<String> res2 = resultSet.getResults(1, RESULT_SIZE - 1); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("shorter", RESULT_SIZE - 1, res2.size());
+
+		final List<String> res3 = resultSet.getResults(1, RESULT_SIZE + 1); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("to out of bounds", RESULT_SIZE, res3.size());
+
+		final List<String> res4 = resultSet.getResults(RESULT_SIZE + 1, RESULT_SIZE); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("from out of bounds", 0, res4.size());
+		
+		final List<String> res5 = resultSet.getResults(0, RESULT_SIZE); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("from lesser than 1", RESULT_SIZE, res5.size());		
+
+		final List<String> res6 = resultSet.getResults(RESULT_SIZE, 1); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("inverted from and to", 1, res6.size());		
+		
+		resultSet.setOpen(true);
+		final List<String> res7 = resultSet.getResults(1, RESULT_SIZE + 1); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("to out of bounds - pass through", RESULT_SIZE + 1, res7.size());
+	}
+
+	/**
+	 * test observer/observable pattern.
+	 */
+	@Test
+	public void testDestroy() {
+		resultSet.addObserver(registry);
+		assertEquals("observer should be added", 1, resultSet.countObservers());
+
+		resultSet.destroy();
+		assertTrue("should be destroyed", resultSet.isDestroyed());
+
+		assertEquals("observers should be cleared", 0, resultSet.countObservers());
+		verify(registry, times(1)).update(resultSet, null);
+	}
+
+	/**
+	 * test getter ... let's make code coverage happy.
+	 */
+	@Test
+	public void testGetListener() {
+		assertEquals("test getter?", resultSetListener, resultSet.getListener());
+	}
+
+	/**
+	 * test setter ... let's make code coverage happy.
+	 */
+	@Test
+	public void testSetListener() {
+		assertEquals("test getter?", resultSetListener, resultSet.getListener());
+		resultSet.setListener(null);
+		assertNull("test setter?", resultSet.getListener());
+	}
+
+	/**
+	 * test.
+	 */
+	@Test
+	public void testResultSetAware() {
+		final AbstractResultSetAware abr = mock(AbstractResultSetAware.class);
+		resultSet = new LocalResultSetImpl(abr);
+		assertNotNull("dummy", resultSet);
+		
+		verify(abr).setResultSet((ResultSet) anyObject());
+		
+	}
+
+}

Property changes on: modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/LocalResultSetImplTest.java
___________________________________________________________________
Added: svn:mergeinfo
## -0,0 +0,0 ##
Index: modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/FetchListTest.java
===================================================================
--- modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/FetchListTest.java	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/test/java/eu/dnetlib/enabling/resultset/FetchListTest.java	(revision 45117)
@@ -0,0 +1,75 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+@RunWith(MockitoJUnit44Runner.class)
+public class FetchListTest {
+	
+	/**
+	 * object to test
+	 */
+	private FetchList<String> fetchList;
+	
+	private List<String> list;
+	private Iterator<String> iter;
+	
+	private int FETCH_SIZE = 10;
+	
+	private int TOTAL_ELEMENTS = 100;
+
+	@Before
+	public void setUp() throws Exception {
+		list = new ArrayList<String>();
+		for (int i = 0; i < TOTAL_ELEMENTS; i++) {
+			list.add("XXX" + i);
+		}
+		this.iter = list.iterator();
+		fetchList = new FetchList<String>(iter, FETCH_SIZE);
+		
+	}
+
+	@Test
+	public void testFetchList() {
+		assertNotNull(fetchList);
+	}
+
+	@Test
+	public void testPoll_consumedElements() {
+		assertEquals(0, fetchList.getConsumedElements());
+		fetchList.poll();
+		assertEquals(1, fetchList.getConsumedElements());
+	}
+	
+	@Test
+	public void testFill_totalElements() {
+		assertEquals(FETCH_SIZE, fetchList.getTotalElements());
+	}
+	
+	@Test
+	public void testPoll() {
+		for (int i = 0; i < TOTAL_ELEMENTS; i++) {
+			assertEquals(i, fetchList.getConsumedElements());
+			assertEquals(list.get(i), fetchList.poll());
+		}
+		assertEquals(TOTAL_ELEMENTS, fetchList.getConsumedElements());
+		assertEquals(TOTAL_ELEMENTS, fetchList.getTotalElements());
+	}
+	
+	@Test
+	public void testPoll_null() {
+		for (int i = 0; i < TOTAL_ELEMENTS; i++) {
+			fetchList.poll();
+		}
+		assertNull(fetchList.poll());
+		assertNull(fetchList.poll());
+		assertNull(fetchList.poll());
+	}
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSetFactory.java	(revision 45117)
@@ -0,0 +1,26 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * Create a new resultset which takes each record of the input resultset and counts them.
+ * 
+ * @author claudio
+ * 
+ */
+public class CountingResultSetFactory extends MappedResultSetFactory {
+
+	/**
+	 * Create a new resultset which takes each record of the input resultset and counts them.
+	 * 
+	 * @param source
+	 *            source resultset epr
+	 * @param mapper
+	 *            mapper function
+	 * @return mapped resultset epr
+	 */
+	public W3CEndpointReference createCountingResultSet(final W3CEndpointReference source) {
+		return getResultSetFactory().createResultSet(new CountingResultSet(source, getServiceResolver()));
+	}
+
+}

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSetFactory.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/trunk/src/test/resources/log4j.properties
===================================================================
--- modules/cnr-resultset-service/trunk/src/test/resources/log4j.properties	(nonexistent)
+++ modules/cnr-resultset-service/trunk/src/test/resources/log4j.properties	(revision 45117)
@@ -0,0 +1,29 @@
+org.apache.cxf.Logger=org.apache.cxf.common.logging.Log4jLogger
+
+log4j.rootLogger=WARN, CONSOLE
+log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
+log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
+log4j.appender.CONSOLE.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
+
+log4j.logger.eu.dnetlib=INFO
+log4j.logger.eu.dnetlib.enabling.is.sn=INFO
+#log4j.logger.org.apache.cxf.interceptor=FATAL
+log4j.logger.org.apache.cxf.ws.addressing.ContextUtils=FATAL
+log4j.logger.eu.dnetlib.enabling.tools.AbstractBaseService=INFO
+log4j.logger.eu.dnetlib.enabling.inspector=DEBUG
+log4j.logger.eu.dnetlib.xml.database.LoggingTrigger=FATAL
+#log4j.logger.eu.dnetlib.enabling.tools.registration=DEBUG
+log4j.logger.eu.dnetlib.enabling.tools.registration.ServiceRegistrator=INFO
+log4j.logger.eu.dnetlib.enabling.inspector=FATAL
+log4j.logger.eu.dnetlib.enabling.resultset=DEBUG
+log4j.logger.eu.dnetlib.enabling.inspector.SubscriptionController=DEBUG
+log4j.logger.eu.dnetlib.springutils.stringtemplate.StringTemplateViewResolver=FATAL
+log4j.logger.eu.dnetlib.enabling.is.sn.SynchronousNotificationSenderImpl=WARN
+
+log4j.logger.eu.dnetlib.enabling.manager.msro.wf.RefreshIndexJob=DEBUG
+log4j.logger.eu.dnetlib.enabling.ui=DEBUG
+log4j.logger.eu.dnetlib.enabling.manager.msro.wf.RefreshIndexJob=DEBUG
+
+log4j.logger.org.apache.zookeeper.ClientCnxn=FATAL
+
+log4j.logger.eu.dnetlib.enabling.resultset.push=DEBUG
Index: modules/cnr-resultset-service/trunk
===================================================================
--- modules/cnr-resultset-service/trunk	(nonexistent)
+++ modules/cnr-resultset-service/trunk	(revision 45117)

Property changes on: modules/cnr-resultset-service/trunk
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,5 ##
+.project
+.classpath
+.settings
+target
+*.iml
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDao.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDao.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDao.java	(revision 45117)
@@ -0,0 +1,19 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.Map;
+
+/**
+ * access resultset properties.
+ * 
+ * @author marko
+ *
+ */
+public interface ResultSetPropertyDao {
+	/**
+	 * return a map of custom resultset properties.
+	 * 
+	 * @param resultSet resultset
+	 * @return property map
+	 */
+	Map<String, String> getProperties(ResultSet resultSet);
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/TypedResultSetListener.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/TypedResultSetListener.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/TypedResultSetListener.java	(revision 45117)
@@ -0,0 +1,34 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+/**
+ * A TypedResultSetListener is a pull interface to a ResultSet.
+ * 
+ * The Resultset will call method of ResultSetListener implementors whenever it needs to pull some data and provide it
+ * to clients. The ResultSet service acts as a decouple point between the producer and the consumer.
+ * 
+ * @author marko
+ * 
+ */
+public interface TypedResultSetListener<T> {
+
+	/**
+	 * get a single page of results.
+	 * 
+	 * @param fromPosition
+	 *            from 1
+	 * @param toPosition
+	 *            last included
+	 * @return page of results
+	 */
+	List<T> getResult(int fromPosition, int toPosition);
+
+	/**
+	 * get number of elements.
+	 * 
+	 * @return number of elements
+	 */
+	int getSize();
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSet.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSet.java	(revision 45117)
@@ -0,0 +1,60 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.enabling.tools.ServiceResolver;
+import eu.dnetlib.miscutils.functional.IdentityFunction;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+/**
+ * A resultset record counter.
+ * 
+ * @author claudio
+ * 
+ */
+public class CountingResultSet extends MappedResultSet {
+
+	/**
+	 * counter.
+	 */
+	private int count;
+
+
+	/**
+	 * @param epr
+	 * @param serviceResolver
+	 */
+	public CountingResultSet(final W3CEndpointReference epr, final ServiceResolver serviceResolver) {
+		this(epr, new IdentityFunction<String>(), serviceResolver);
+	}
+
+	/**
+	 * @param epr
+	 * @param mapper
+	 * @param serviceResolver
+	 */
+	public CountingResultSet(final W3CEndpointReference epr, final UnaryFunction<String, String> mapper, final ServiceResolver serviceResolver) {
+		super(epr, mapper, serviceResolver);
+		count = 0;
+	}
+
+	/**
+	 * method sets the counter to the higher allowed value of toPosition.
+	 */
+	@Override
+	public List<String> getResult(int fromPosition, int toPosition) {
+
+		if (toPosition > count)
+			count = toPosition;
+		if (toPosition > super.getSize())
+			count = super.getSize();
+
+		return super.getResult(fromPosition, toPosition);
+	}
+
+	public int getCount() {
+		return count;
+	}
+}

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSet.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/LocalOpenResultSetFactoryImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/LocalOpenResultSetFactoryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/LocalOpenResultSetFactoryImpl.java	(revision 45117)
@@ -0,0 +1,23 @@
+package eu.dnetlib.enabling.resultset;
+
+/**
+ * Creates an "open" (unbounded, unfreezed) local resultset.
+ * 
+ * @author marko
+ *
+ */
+public class LocalOpenResultSetFactoryImpl extends LocalResultSetFactoryImpl {
+
+	/** 
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.LocalResultSetFactoryImpl#createInstance(eu.dnetlib.enabling.resultset.ResultSetListener)
+	 */
+	@Override
+	protected LocalResultSetImpl createInstance(final ResultSetListener provider) {
+		final LocalResultSetImpl instance = super.createInstance(provider);
+		instance.setOpen(true);
+		return instance;
+	}
+
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetFactory.java	(revision 45117)
@@ -0,0 +1,19 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * Creates a resultset service from a producer.
+ * 
+ * @author marko
+ *
+ */
+public interface ResultSetFactory {
+	/**
+	 * TODO other parameters like expiration time etc.
+	 * 
+	 * @param provider a resultset listener which provides the data
+	 * @return an EPR to the resultset.
+	 */
+	W3CEndpointReference createResultSet(ResultSetListener provider);
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest.java	(revision 45117)
@@ -0,0 +1,36 @@
+package eu.dnetlib.enabling.resultset.push;
+
+
+import static org.junit.Assert.*;
+
+import javax.annotation.Resource;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import eu.dnetlib.miscutils.factory.Factory;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration
+public class ResultSetDescriptorFactoryTest {
+
+	@Resource
+	Factory<ResultSetDescriptor> factory;
+
+	@Before
+	public void setUp() throws Exception {
+	}
+
+	@Test
+	public void testFactory() {
+		ResultSetDescriptor desc1 = factory.newInstance();
+		ResultSetDescriptor desc2 = factory.newInstance();
+
+		assertTrue("check different instances", desc1 != desc2);
+		assertEquals("check that it's a spring prototype", 200, desc1.getRangeLength());
+		assertEquals("check that it's a spring prototype", 200, desc2.getRangeLength());
+	}
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/push/CacheTransientPushResultSetDaoTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/push/CacheTransientPushResultSetDaoTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/push/CacheTransientPushResultSetDaoTest.java	(revision 45117)
@@ -0,0 +1,78 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import java.util.List;
+
+import net.sf.ehcache.CacheManager;
+
+import org.junit.After;
+
+import eu.dnetlib.miscutils.cache.Cache;
+import eu.dnetlib.miscutils.cache.EhCache;
+import eu.dnetlib.miscutils.factory.Factory;
+
+/**
+ * concrete push resultset dao test.
+ * 
+ * @author marko
+ * 
+ */
+public class CacheTransientPushResultSetDaoTest extends AbstractTransientPushResultSetDaoTest { // NOPMD
+
+	/**
+	 * max in memory elements.
+	 */
+	private static final int MAX_IN_MEM = 100;
+
+	/**
+	 * default time.
+	 */
+	private static final int DEFAULT_TTI = 1000;
+
+	/**
+	 * default time to live.
+	 */
+	private static final int DEFAULT_TTL = 1000;
+
+	/**
+	 * cache manager.
+	 */
+	private final transient CacheManager cacheManager = CacheManager.create();
+
+	/**
+	 * clean cache after test.
+	 */
+	@After
+	public void cleanCache() {
+		cacheManager.removeAllCaches();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.push.AbstractTransientPushResultSetDaoTest#newInstance()
+	 */
+	@Override
+	protected TransientPushResultSetDao newInstance() {
+		final net.sf.ehcache.Cache ehcache = new net.sf.ehcache.Cache("testCache", MAX_IN_MEM, false, false, DEFAULT_TTL, DEFAULT_TTI);
+		cacheManager.addCache(ehcache);
+
+		final net.sf.ehcache.Cache rsehcache = new net.sf.ehcache.Cache("rsetCache", MAX_IN_MEM, false, false, DEFAULT_TTL, DEFAULT_TTI);
+		cacheManager.addCache(rsehcache);
+
+		final CacheTransientResultSetDaoImpl resultSet = new CacheTransientResultSetDaoImpl();
+		final Cache<String, List<String>> cache = new EhCache<String, List<String>>(ehcache);
+		final Cache<String, ResultSetDescriptor> rscache = new EhCache<String, ResultSetDescriptor>(rsehcache);
+		resultSet.setCache(cache);
+		resultSet.setResultSetCache(rscache);
+
+		resultSet.setResultSetDescriptorFactory(new Factory<ResultSetDescriptor>() {
+
+			@Override
+			public ResultSetDescriptor newInstance() {
+				return new ResultSetDescriptor();
+			}
+		});
+		return resultSet;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImplTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImplTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImplTest.java	(revision 45117)
@@ -0,0 +1,184 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.matches;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import net.sf.ehcache.Cache;
+import net.sf.ehcache.CacheManager;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+import eu.dnetlib.miscutils.cache.EhCache;
+
+/**
+ * Test ResultSetRegistryImpl.
+ * 
+ * @author marko
+ * 
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class ResultSetRegistryImplTest {
+
+	/**
+	 * max in memory elements.
+	 */
+	private static final int MAX_IN_MEM = 100;
+
+	/**
+	 * default time.
+	 */
+	private static final int DEFAULT_TTI = 1000;
+
+	/**
+	 * default time to live.
+	 */
+	private static final int DEFAULT_TTL = 1000;
+
+	/**
+	 * class under test.
+	 */
+	private transient ResultSetRegistryImpl registry;
+
+	/**
+	 * mock of a resultset object.
+	 */
+	@Mock
+	private transient ResultSet resultSet;
+
+	/**
+	 * ehcache manager.
+	 */
+	private final transient CacheManager cacheManager = CacheManager.create();
+
+	/**
+	 * Set up basic mocks.
+	 */
+	@Before
+	public void setUp() {
+		final Cache ehCache = new net.sf.ehcache.Cache("testCache", MAX_IN_MEM, false, false, DEFAULT_TTL, DEFAULT_TTI);
+		cacheManager.addCache(ehCache);
+
+		final Cache mtEhCache = new net.sf.ehcache.Cache("testMTCache", MAX_IN_MEM, false, false, DEFAULT_TTL, DEFAULT_TTI);
+		cacheManager.addCache(mtEhCache);
+
+		final EhCache<String, ResultSet> cache = new EhCache<String, ResultSet>(ehCache);
+		cache.setCache(ehCache);
+
+		final EhCache<String, Integer> mtCache = new EhCache<String, Integer>(mtEhCache);
+		mtCache.setCache(mtEhCache);
+
+		registry = new ResultSetRegistryImpl();
+		registry.setCache(cache);
+		registry.setMaxIdleTimeCache(mtCache);
+
+		when(resultSet.getIdentifier()).thenReturn("123456");
+		when(resultSet.isOpen()).thenReturn(true);
+	}
+
+	/**
+	 * remove ehcache from ehcachemanager.
+	 */
+	@After
+	public void tearDown() {
+		cacheManager.removeAllCaches();
+	}
+
+	/**
+	 * Test that registered resultsets are really registered.
+	 */
+	@Test
+	public void testAddResultSet() {
+
+		final String rsId = resultSet.getIdentifier();
+		assertNotNull("the resultset should not be null", rsId);
+
+		registry.addResultSet(resultSet);
+		verify(resultSet).setIdentifier(matches("rs-" + registry.getIdGenerator().getRegEx()));
+
+		final ResultSet res = registry.getResultSetById(rsId); // NOPMD
+		assertNotNull("the resultset is not found", res);
+		assertEquals("the resultsets don't have the same id", rsId, res.getIdentifier());
+		assertEquals("the resultsets are not the same instance", resultSet, res);
+	}
+
+	/**
+	 * Test that registered resultsets are really registered.
+	 */
+	@Test
+	public void testAddResultSetWithId() {
+		resultSet = mock(ResultSet.class);
+		when(resultSet.getIdentifier()).thenReturn("123");
+
+		final String rsId = resultSet.getIdentifier();
+
+		registry.addResultSet(resultSet, rsId);
+		verify(resultSet).setIdentifier(rsId);
+
+		final ResultSet res = registry.getResultSetById(rsId); // NOPMD
+		assertNotNull("the resultset is not found", res);
+		assertEquals("the resultsets don't have the same id", rsId, res.getIdentifier());
+		assertEquals("the resultsets are not the same instance", resultSet, res);
+	}
+
+	/**
+	 * try to obtain a inexistent resultset.
+	 */
+	@Test
+	public void testInexistentResultSet() {
+		final String rsId = resultSet.getIdentifier();
+		assertNull("inexisten resultset returns null", registry.getResultSetById(rsId));
+	}
+
+	/**
+	 * test closing of resultset and its pruning from the registry.
+	 */
+	@Test
+	public void testResultSetClose() {
+		final String rsId = resultSet.getIdentifier();
+
+		assertTrue("check if resultset is open", resultSet.isOpen());
+
+		registry.addResultSet(resultSet);
+		verify(resultSet).addObserver(registry);
+
+		// simulate a resultset close on the mock
+		when(resultSet.isOpen()).thenReturn(false);
+		registry.update(resultSet, null);
+
+		assertFalse("check if resultset is closed", resultSet.isOpen());
+		assertNull("check if the object is pruned from the registry", registry.getResultSetById(rsId));
+	}
+
+	/**
+	 * same as testResultSetClose() but with a real observer/observable mechanism, i.e. without resultset mock class.
+	 * 
+	 */
+	@Test
+	public void testWithRealObservable() {
+		final LocalResultSetImpl rset = new LocalResultSetImpl(null);
+		rset.setIdentifier("123456");
+		resultSet = rset;
+
+		final String rsId = resultSet.getIdentifier();
+
+		assertFalse("check if resultset is not destroyed", resultSet.isDestroyed());
+
+		registry.addResultSet(resultSet);
+		resultSet.destroy();
+
+		assertTrue("check if resultset is destroyed", resultSet.isDestroyed());
+		assertNull("check if the object is pruned from the registry", registry.getResultSetById(rsId));
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetListener.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetListener.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetListener.java	(revision 45117)
@@ -0,0 +1,15 @@
+package eu.dnetlib.enabling.resultset;
+
+
+/**
+ * A ResultSetListener is a pull interface to a ResultSet.
+ * 
+ * The Resultset will call method of ResultSetListener implementors whenever it needs to pull some data and provide it
+ * to clients. The ResultSet service acts as a decouple point between the producer and the consumer.
+ * 
+ * @author marko
+ * 
+ */
+public interface ResultSetListener extends TypedResultSetListener<String> {
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/IterableResultSetTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/IterableResultSetTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/IterableResultSetTest.java	(revision 45117)
@@ -0,0 +1,150 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+/**
+ * tests the IterableResult class
+ * 
+ * @author claudio
+ *
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class IterableResultSetTest {
+
+	/**
+	 * number of total elements 
+	 */
+	private static int NUM_ELEM = 100;
+	
+	/**
+	 * number of elements available to fetch
+	 */
+	private static int FETCH_SIZE = 10;
+	
+	@Mock
+	private ResultSet mockResultSet;
+	
+	/**
+	 * a list used to compare elements.
+	 */
+	private List<String> list;
+	
+	/**
+	 * Iterator associated with the test list.
+	 */
+	private Iterator<String> iter;
+	
+	/**
+	 * Object to test.
+	 */
+	private IterableResultSet iterResultSet;
+
+	@Before
+	public void setUp() {
+		list = new ArrayList<String>();
+		for (int i=0; i< NUM_ELEM; i++)
+			list.add("XXXXX " + i);
+				
+		iter = list.iterator();
+		when(mockResultSet.isOpen()).thenReturn(iter.hasNext());
+		
+		iterResultSet = new IterableResultSet(list, FETCH_SIZE);
+		iterResultSet.setResultSet(mockResultSet);
+	}
+	
+	@Test
+	public void testIterableResultSet() {
+		assertNotNull(iterResultSet);
+		assertTrue(iterResultSet.getSize() > 0);
+	}
+
+	@Test(expected=RuntimeException.class)
+	public void testGetResult_fail_1() {
+		iterResultSet.getResult(0, 5);
+	}
+
+	@Test(expected=RuntimeException.class)
+	public void testGetResult_fail_2() {
+		iterResultSet.getResult(1, 5);
+		iterResultSet.getResult(1, 5);
+	}
+	
+	@Test(expected=RuntimeException.class)
+	public void testGetResult_fail_3() {
+		iterResultSet.getResult(1, 5);
+		iterResultSet.getResult(6, 5);
+	}
+	
+	@Test(expected=RuntimeException.class)
+	public void testGetResult_fail_4() {
+		iterResultSet.getResult(1, 5);
+		iterResultSet.getResult(7, 10);
+	}
+	
+	@Test
+	public void testGetResult_success_1() {
+		List<String> result = iterResultSet.getResult(1, NUM_ELEM);
+		for (int i=0; i<NUM_ELEM; i++) {
+			assertEquals(list.get(i), result.get(i));
+		}
+	}
+	
+	@Test
+	public void testGetResult_success_2() {
+		List<String> result = iterResultSet.getResult(1, NUM_ELEM);
+		
+		for (int i=0; i<NUM_ELEM; i++) {
+			assertEquals(list.get(i), result.get(i));
+			iter.next();
+		}
+		verify(mockResultSet).close();
+	}
+
+	@Test
+	public void testGetResult_success_3() {
+		for (int i = 1; i < NUM_ELEM; i+= FETCH_SIZE)
+			iterResultSet.getResult(i, i + FETCH_SIZE-1);
+		verify(mockResultSet, times(1)).close();
+	}
+	
+	@Test
+	public void testGetResult_success_4() {
+		iterResultSet.getResult(1, NUM_ELEM + 1);
+		verify(mockResultSet, times(1)).close();
+	}
+	
+	@Test
+	public void testGetResultSet_success_1() {
+		assertNotNull(iterResultSet.getResultSet());
+	}
+
+	@Test
+	public void testGetSize_fail_1() {
+		iterResultSet.getResult(1, 8);
+		assertNotSame(7, iterResultSet.getSize());
+		assertNotSame(9, iterResultSet.getSize());
+	}
+	
+	@Test
+	public void testGetSize_success_1() {
+		iterResultSet.getResult(1, 8);
+		assertEquals(FETCH_SIZE, iterResultSet.getSize());
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSetFactory.java	(revision 45117)
@@ -0,0 +1,67 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+/**
+ * 
+ * @author claudio
+ *
+ */
+public class IterableResultSetFactory {
+
+	/**
+	 * {@link ResultSetFactory}
+	 */
+	private LocalOpenResultSetFactoryImpl resultSetFactory;
+	
+	/**
+	 * 
+	 */
+	private int fetchSize;
+	
+	/**
+	 * 
+	 * @param source
+	 * @return
+	 */
+	public W3CEndpointReference createIterableResultSet(final Iterable<String> source) {
+		return resultSetFactory.createResultSet(new IterableResultSet(source, fetchSize));
+	}
+	
+	/**
+	 * 
+	 * @return
+	 */
+	public LocalOpenResultSetFactoryImpl getResultSetFactory() {
+		return resultSetFactory;
+	}
+
+	/**
+	 * 
+	 * @param resultSetFactory
+	 */
+	@Required
+	public void setResultSetFactory(final LocalOpenResultSetFactoryImpl resultSetFactory) {
+		this.resultSetFactory = resultSetFactory;
+	}
+	
+	/**
+	 * 
+	 * @param fetchSize
+	 */
+	@Required
+	public void setFetchSize(int fetchSize) {
+		this.fetchSize = fetchSize;
+	}
+
+	/**
+	 * 
+	 * @return
+	 */
+	public int getFetchSize() {
+		return fetchSize;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorTest.java	(revision 45117)
@@ -0,0 +1,44 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.junit.Before;
+import org.junit.Test;
+
+import eu.dnetlib.enabling.resultset.push.ResultSetDescriptor.Range;
+
+public class ResultSetDescriptorTest {
+
+	private static final Log log = LogFactory.getLog(ResultSetDescriptorTest.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	private transient ResultSetDescriptor descriptor;
+
+	@Before
+	public void setUp() throws Exception {
+		descriptor = new ResultSetDescriptor();
+	}
+
+	@Test
+	public void testGetRangesContaining() {
+		log.debug("--- 1, 1");
+		for(Range i : descriptor.getRangesContaining(1, 1))
+			log.debug("i " + i);
+
+		log.debug("--- 2, 1000");
+		for(Range i : descriptor.getRangesContaining(2, 1000))
+			log.debug("i " + i);
+
+		log.debug("--- 5, 2000");
+		for(Range i : descriptor.getRangesContaining(5, 2000))
+			log.debug("i " + i);
+
+		log.debug("--- 5, 2001");
+		for(Range i : descriptor.getRangesContaining(5, 2001))
+			log.debug("i " + i);
+	}
+
+	@Test
+	public void testNext() {
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/MappedResultSetTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/MappedResultSetTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/MappedResultSetTest.java	(revision 45117)
@@ -0,0 +1,137 @@
+package eu.dnetlib.enabling.resultset; // NOPMD
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.runners.MockitoJUnit44Runner;
+import org.mockito.stubbing.Answer;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
+import eu.dnetlib.enabling.tools.ServiceResolver;
+import eu.dnetlib.miscutils.factory.Factory;
+import eu.dnetlib.miscutils.functional.ThreadSafeUnaryFunction;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+/**
+ * test xslt resultset.
+ *
+ * @author marko
+ *
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class MappedResultSetTest {
+
+	/**
+	 * instance under test.
+	 */
+	private transient MappedResultSet mappedResultSet;
+
+	/**
+	 * service resolver.
+	 */
+	@Mock
+	private transient ServiceResolver serviceResolver;
+
+	/**
+	 * resultset service mock.
+	 */
+	@Mock
+	private transient ResultSetService resultSetService;
+	
+	/**
+	 * resultset mock.
+	 */
+	@Mock
+	private transient ResultSet resultSet;	
+
+	private Answer<Object> resultSetAnswer = new Answer<Object>() {
+
+		private List<String> list = Lists.newArrayList("1","2","3","4","5","6","7","8","9","10");
+		
+		@Override
+		public Object answer(InvocationOnMock invocation) throws Throwable {
+			String method = invocation.getMethod().getName();
+			if (method.equals("getResult") || method.equals("getResults")) {
+				int from = (Integer) invocation.getArguments()[1];
+				int to = (Integer) invocation.getArguments()[2];
+				
+				return list.subList(from-1, to);
+			}
+			if (method.equals("getNumberOfElements") || method.equals("getNumberOfResults")) {
+				return list.size();
+			}
+			if (method.equals("getRSStatus")) {
+				return "closed";
+			}
+			if (method.equals("isOpen")) {
+				return false;
+			}			
+			System.out.println(invocation.toString());
+			return null;
+		}		
+	};
+
+	/**
+	 * Common setup.
+	 * @throws ResultSetException 
+	 *
+	 */
+	@Before
+	public void setUp() throws ResultSetException {
+		
+		when(serviceResolver.getService(eq(ResultSetService.class), (W3CEndpointReference) anyObject())).thenReturn(resultSetService);
+		when(serviceResolver.getResourceIdentifier((W3CEndpointReference) anyObject())).thenReturn("123");
+
+		when(resultSetService.getNumberOfElements(anyString())).thenAnswer(resultSetAnswer);
+		when(resultSetService.getResult(anyString(), anyInt(), anyInt(), anyString())).thenAnswer(resultSetAnswer );
+		when(resultSetService.getRSStatus(anyString())).thenAnswer(resultSetAnswer);
+		
+		when(resultSet.getNumberOfResults()).thenAnswer(resultSetAnswer);
+		when(resultSet.getResults(anyInt(), anyInt())).thenAnswer(resultSetAnswer );
+		when(resultSet.isOpen()).thenAnswer(resultSetAnswer);		
+	}
+	
+	@Test
+	public void testThreadSafeMappedResultSet_1() {
+		
+		final Factory<UnaryFunction<String, String>> functionFactory = new Factory<UnaryFunction<String,String>>() {
+			@Override
+			public UnaryFunction<String, String> newInstance() {
+				return new UnaryFunction<String, String>() {
+					@Override
+					public String evaluate(String arg) {
+						return "mapped-" + arg;
+					}
+				};
+			}
+		}; 
+		mappedResultSet = new MappedResultSet(null, new ThreadSafeUnaryFunction<String, String>(functionFactory), serviceResolver);
+		mappedResultSet.setResultSet(resultSet);
+
+		for (String s : mappedResultSet.getResult(1, 10)) {
+			assertNotNull("null result", s);
+			assertFalse("empty result", s.isEmpty());
+			assertNotNull("null element", s);
+			assertTrue("transformed correctly", s.startsWith("mapped-"));	
+		}
+	}
+}
+

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/MappedResultSetTest.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetAware.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetAware.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetAware.java	(revision 45117)
@@ -0,0 +1,16 @@
+package eu.dnetlib.enabling.resultset;
+
+/**
+ * ResultSet listeners can add this interface in order to receive the ResultSet they are bound to.
+ * 
+ * @author marko
+ *
+ */
+public interface ResultSetAware {
+	/**
+	 * sets the resultset instance.
+	 * 
+	 * @param resultSet the resultset instance
+	 */
+	void setResultSet(ResultSet resultSet);
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.xml
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.xml	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.xml	(revision 45117)
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
+	xmlns:sec="http://cxf.apache.org/configuration/security" xmlns:wsa="http://cxf.apache.org/ws/addressing"
+	xmlns:p="http://www.springframework.org/schema/p" xmlns:http="http://cxf.apache.org/transports/http/configuration"
+	xmlns:t="http://dnetlib.eu/springbeans/t" xmlns:template="http://dnetlib.eu/springbeans/template"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+                                    http://cxf.apache.org/ws/addressing http://cxf.apache.org/schemas/ws-addr-conf.xsd
+                                    http://cxf.apache.org/configuration/security http://cxf.apache.org/schemas/configuration/security.xsd
+                                    http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd
+                            http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
+                            http://dnetlib.eu/springbeans/template http://dnetlib.eu/springbeans/template.xsd">
+
+	<!-- beans -->
+	<bean id="resultSetCacheManager"
+		class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" />
+	<!-- p:configLocation="classpath:eu/dnetlib/enabling/resultset/ehcache.xml" -->
+
+	<bean id="resultSetRegistryCache" class="eu.dnetlib.miscutils.cache.EhCache">
+		<property name="cache">
+			<bean id="resultSetRegistryCacheCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"
+				p:cacheManager-ref="resultSetCacheManager" p:cacheName="resultSetFactoryCache"
+				p:eternal="false" p:timeToLive="0"
+				p:timeToIdle="${services.is.resultset.resultSetRegistryCache.timeToIdle}" />
+		</property>
+	</bean>
+
+	<bean id="resultSetRegistryMaxIdleTimeCache" class="eu.dnetlib.miscutils.cache.EhCache">
+		<property name="cache">
+			<bean id="resultSetRegistryMaxIdleTimeCacheCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"
+				p:cacheManager-ref="resultSetCacheManager" p:cacheName="resultSetFactoryMaxIdleTimeCache"
+				p:eternal="false" p:timeToLive="0"
+				p:timeToIdle="${services.is.resultset.resultSetRegistryMaxIdleTimeCache.timeToIdle}" />
+		</property>
+	</bean>
+
+	<!-- backing store for the pushResultSetDao -->
+	<bean id="pushResultSetStoreCache" class="eu.dnetlib.miscutils.cache.EhCache">
+		<property name="cache">
+			<bean id="pushResultSetStoreCacheCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"
+				p:eternal="false" p:timeToLive="0" p:timeToIdle="${services.is.resultset.push.timeToIdle}"
+				p:maxElementsInMemory="${services.is.resultset.push.maxElementsInMemory}" 
+				p:maxElementsOnDisk="${services.is.resultset.push.maxElementsOnDisk}"
+				p:cacheManager-ref="resultSetCacheManager" p:cacheName="pushResultSetStoreCache" />
+		</property>
+	</bean>
+
+	<!-- resultset descriptor store for the pushResultSetDao -->
+	<bean id="pushResultSetDescriptorCache" class="eu.dnetlib.miscutils.cache.EhCache">
+		<property name="cache">
+			<bean id="pushResultSetDescriptorCacheCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"
+				p:eternal="false" p:timeToLive="0" p:timeToIdle="1800"
+				p:cacheManager-ref="resultSetCacheManager" p:cacheName="pushResultSetDescriptorCache" />
+		</property>
+	</bean>
+
+	<bean id="resultSetDescriptorFactory" class="eu.dnetlib.springutils.beans.factory.PrototypeFactory">
+		<lookup-method name="newInstance" bean="resultSetDescriptorPrototype" />
+	</bean>
+
+	<bean id="resultSetDescriptorPrototype" class="eu.dnetlib.enabling.resultset.push.ResultSetDescriptor"
+		p:rangeLength="100" scope="prototype" />
+
+	<bean id="resultSetRegistry" class="eu.dnetlib.enabling.resultset.ResultSetRegistryImpl"
+		p:cache-ref="resultSetRegistryCache" p:maxIdleTimeCache-ref="resultSetRegistryMaxIdleTimeCache" />
+
+<!--
+  <bean id="resultSetEPRPool" class="eu.dnetlib.enabling.resultset.ResultSetEPRPool"
+   p:resultSetService-ref="resultSetService" />
+-->
+
+	<!-- <bean id="resultSetFactory" class="eu.dnetlib.enabling.resultset.LocalResultSetFactoryImpl" -->
+	<!-- <bean id="resultSetFactory" class="eu.dnetlib.enabling.resultset.EPRPoolingLocalResultSetFactoryImpl" p:pool-ref="resultSetEPRPool" 
+		p:resultSetService-ref="resultSetService" /> -->
+
+  <bean id="resultSetFactory" class="eu.dnetlib.enabling.resultset.LocalResultSetFactoryImpl" 
+		p:resultSetService-ref="resultSetService" /> 
+
+	<bean id="openResultSetFactory"
+		class="eu.dnetlib.enabling.resultset.LocalOpenResultSetFactoryImpl"
+		p:resultSetService-ref="resultSetService" />
+		
+<!--
+	<bean id="openResultSetFactory"
+		class="eu.dnetlib.enabling.resultset.EPRPoolingLocalOpenResultSetFactoryImpl" p:pool-ref="resultSetEPRPool"
+		p:resultSetService-ref="resultSetService" />
+-->
+	<bean id="mappedResultSetFactory" class="eu.dnetlib.enabling.resultset.MappedResultSetFactory"
+		p:serviceResolver-ref="serviceResolver" p:resultSetFactory-ref="resultSetFactory" />
+		
+	<bean id="parallelMappedResultSetFactory" class="eu.dnetlib.enabling.resultset.ParallelMappedResultSetFactory"
+		p:serviceResolver-ref="serviceResolver" p:resultSetFactory-ref="resultSetFactory" />		
+
+	<bean id="xsltResultSetFactory"
+		class="eu.dnetlib.enabling.resultset.XSLTMappedResultSetFactory"
+		p:serviceResolver-ref="serviceResolver" p:resultSetFactory-ref="resultSetFactory" />
+
+	<bean id="countingResultSetFactory" class="eu.dnetlib.enabling.resultset.CountingResultSetFactory"
+		p:serviceResolver-ref="serviceResolver" p:resultSetFactory-ref="resultSetFactory" />
+
+	<bean id="streamingResultSetFactory" class="eu.dnetlib.enabling.resultset.StreamingResultSetFactory"
+		p:resultSetFactory-ref="resultSetFactory" />
+
+	<bean id="cachingResultSetFactory" class="eu.dnetlib.enabling.resultset.CachingResultSetFactory"
+		p:resultSetFactory-ref="resultSetFactory" />
+
+	<bean id="pushResultSetFactory"
+		class="eu.dnetlib.enabling.resultset.push.TransientPushResultSetFactory"
+		p:dao-ref="pushResultSetDao" p:resultSetService-ref="resultSetService" />
+
+	<bean id="iterableResultSetFactory" class="eu.dnetlib.enabling.resultset.IterableResultSetFactory"
+		p:fetchSize="10" p:resultSetFactory-ref="openResultSetFactory"
+		lazy-init="true" />
+
+
+	<bean id="pushResultSetDao"
+		class="eu.dnetlib.enabling.resultset.push.CacheTransientResultSetDaoImpl"
+		p:cache-ref="pushResultSetStoreCache" p:resultSetCache-ref="pushResultSetDescriptorCache" />
+
+	<bean id="customResultSetPropertyDao" class="eu.dnetlib.enabling.resultset.ResultSetPropertyDaoImpl" />
+
+	<bean id="resultSetService" class="eu.dnetlib.enabling.resultset.ResultSetServiceImpl"
+		init-method="start" p:resultsetRegistry-ref="resultSetRegistry"
+		p:pushFactory-ref="pushResultSetFactory" p:endpoint-ref="resultSetServiceEndpoint"
+		p:eprBuilder-ref="jaxwsEndpointReferenceBuilder" p:customPropertyDao-ref="customResultSetPropertyDao" />
+		
+	<!-- endpoints -->
+	<jaxws:endpoint id="resultSetServiceEndpoint"
+		implementor="#resultSetService" implementorClass="eu.dnetlib.enabling.resultset.rmi.ResultSetService"
+		address="/resultSet" />
+
+	<template:instance name="serviceRegistrationManager"
+		t:serviceRegistrationManagerClass="eu.dnetlib.enabling.tools.registration.ValidatingServiceRegistrationManagerImpl"
+		t:name="resultSetServiceRegistrationManager" t:service="resultSetService"
+		t:endpoint="resultSetServiceEndpoint" t:jobScheduler="jobScheduler" />
+
+</beans>
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/ResultSetServiceImplTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/ResultSetServiceImplTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/ResultSetServiceImplTest.java	(revision 45117)
@@ -0,0 +1,101 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.*; // NOPMD
+import static org.mockito.Mockito.*; // NOPMD
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+
+/**
+ * resultset service rmi implementation test.
+ *  
+ * @author marko
+ *
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class ResultSetServiceImplTest {
+
+	/**
+	 * mock resultset id.
+	 */
+	private static final String RS_ID = "123";
+
+	/**
+	 * instance under test.
+	 */
+	private transient ResultSetServiceImpl service;
+	
+	/**
+	 * custom property dao mock.
+	 */
+	@Mock
+	private transient ResultSetPropertyDao customPropertyDao;
+	
+	/**
+	 * resultset registry mock. 
+	 */
+	@Mock
+	private transient ResultSetRegistry resultsetRegistry;
+	
+	/**
+	 * resultset instance mock. 
+	 */
+	@Mock
+	private transient ResultSet resultSet;
+	
+	/**
+	 * setup. 
+	 */
+	@Before
+	public void setUp() {
+		service = new ResultSetServiceImpl();
+		service.setCustomPropertyDao(customPropertyDao);
+		service.setResultsetRegistry(resultsetRegistry);
+		
+		when(resultsetRegistry.getResultSetById(RS_ID)).thenReturn(resultSet);
+		when(resultSet.getIdentifier()).thenReturn(RS_ID);
+	}
+
+	/**
+	 * test get property.
+	 * @throws ResultSetException shouldn't happen
+	 */
+	@Test
+	public void testGetProperty() throws ResultSetException {
+		final Map<String, String> properties = new HashMap<String, String>();
+		properties.put("prefetch", "true");
+		
+		when(customPropertyDao.getProperties(resultSet)).thenReturn(properties);
+		when(resultSet.getNumberOfResults()).thenReturn(1);
+		
+		assertEquals("test builtin", "1", service.getProperty(RS_ID, "total"));
+		assertEquals("test builtin", RS_ID, service.getProperty(RS_ID, "rsId"));
+		
+		assertEquals("test custom", "true", service.getProperty(RS_ID, "prefetch"));
+		assertNull("test custom", service.getProperty(RS_ID, "unexistent"));
+	}
+
+	/**
+	 * get resultset status.
+	 * 
+	 * @throws ResultSetException shouldn't happen
+	 */
+	@Test
+	public void testGetRSStatus() throws ResultSetException {
+		when(resultSet.isOpen()).thenReturn(true);
+		
+		assertEquals("check open", service.getRSStatus(RS_ID), "open");
+		
+		when(resultSet.isOpen()).thenReturn(false);
+		assertEquals("check closed", service.getRSStatus(RS_ID), "closed");
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/resources/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest-context.xml
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/resources/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest-context.xml	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/resources/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest-context.xml	(revision 45117)
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
+	xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
+
+	<bean id="resultSetDescriptorPrototype" class="eu.dnetlib.enabling.resultset.push.ResultSetDescriptor"
+		p:rangeLength="200" scope="prototype" />
+
+	<bean id="resultSetDescriptorFactory" class="eu.dnetlib.springutils.beans.factory.PrototypeFactory">
+		<lookup-method name="newInstance" bean="resultSetDescriptorPrototype" />
+	</bean>
+</beans>
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/deploy.info
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/deploy.info	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/deploy.info	(revision 45117)
@@ -0,0 +1 @@
+{"type_source": "SVN", "goal": "package -U -T 4C source:jar", "url": "http://svn-public.driver.research-infrastructures.eu/driver/dnet40/modules/cnr-resultset-service/trunk/", "deploy_repository": "dnet4-snapshots", "version": "4", "mail": "sandro.labruzzo@isti.cnr.it,michele.artini@isti.cnr.it, claudio.atzori@isti.cnr.it, alessia.bardi@isti.cnr.it", "deploy_repository_url": "http://maven.research-infrastructures.eu/nexus/content/repositories/dnet4-snapshots", "name": "cnr-resultset-service"}
\ No newline at end of file
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/pom.xml
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/pom.xml	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/pom.xml	(revision 45117)
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<parent>
+		<groupId>eu.dnetlib</groupId>
+		<artifactId>dnet-parent</artifactId>
+		<version>1.0.0</version>
+		<relativePath />
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>eu.dnetlib</groupId>
+	<artifactId>cnr-resultset-service</artifactId>
+	<packaging>jar</packaging>
+	<version>2.0.0</version>
+	<scm>
+	  <developerConnection>scm:svn:https://svn.driver.research-infrastructures.eu/driver/dnet40/modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0</developerConnection>
+	</scm>
+	<dependencies>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>${junit.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>com.google.guava</groupId>
+			<artifactId>guava</artifactId>
+			<version>${google.guava.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>cglib</groupId>
+			<artifactId>cglib-nodep</artifactId>
+			<version>2.2</version>
+		</dependency>
+		<dependency>
+			<groupId>org.mockito</groupId>
+			<artifactId>mockito-core</artifactId>
+			<version>1.6</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-test</artifactId>
+			<version>${spring.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-context-support</artifactId>
+			<version>${spring.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>eu.dnetlib</groupId>
+			<artifactId>cnr-rmi-api</artifactId>
+			<version>[2.0.0,3.0.0)</version>
+		</dependency>
+		<dependency>
+			<groupId>eu.dnetlib</groupId>
+			<artifactId>cnr-spring-utils</artifactId>
+			<version>[1.0.0,2.0.0)</version>
+		</dependency>
+		<dependency>
+			<groupId>eu.dnetlib</groupId>
+			<artifactId>cnr-service-common</artifactId>
+			<version>[2.0.0,3.0.0)</version>
+		</dependency>
+	</dependencies>
+</project>
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetServiceImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetServiceImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetServiceImpl.java	(revision 45117)
@@ -0,0 +1,258 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import javax.jws.WebService;
+import javax.xml.ws.Endpoint;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.common.rmi.UnimplementedException;
+import eu.dnetlib.enabling.resultset.push.PushResultSet;
+import eu.dnetlib.enabling.resultset.push.PushResultSetFactory;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
+import eu.dnetlib.enabling.tools.AbstractBaseService;
+import eu.dnetlib.soap.EndpointReferenceBuilder;
+
+/**
+ * This component dispatches the service method calls to stateful datastructure instances and to the singleton core.
+ * 
+ * @author marko
+ * 
+ */
+@WebService(targetNamespace = "http://services.dnetlib.eu/")
+public class ResultSetServiceImpl extends AbstractBaseService implements ResultSetService {
+
+	/**
+	 * logger.
+	 */
+	private static final Log log = LogFactory.getLog(ResultSetServiceImpl.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	/**
+	 * Maps resultset identifiers to resultsets and manages expiration etc.
+	 */
+	private ResultSetRegistry resultsetRegistry;
+
+	/**
+	 * push resultset factory.
+	 */
+	private PushResultSetFactory pushFactory;
+
+	/**
+	 * Service endpoint.
+	 */
+	private Endpoint endpoint;
+
+	/**
+	 * injected epr builder.
+	 */
+	private EndpointReferenceBuilder<Endpoint> eprBuilder;
+
+	/**
+	 * custom resultset properties.
+	 */
+	private ResultSetPropertyDao customPropertyDao;
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#closeRS(java.lang.String)
+	 */
+	@Override
+	public void closeRS(final String rsId) {
+		try {
+			final ResultSet resultSet = getResultSetById(rsId);
+			resultSet.close();
+		} catch (ResultSetException e) {
+			log.warn("should throw checked exception but wasn't declared in cnr-rmi-api", e);
+			throw new IllegalStateException(e);
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#createPullRS(java.lang.String, java.lang.String, int, int, java.lang.String,
+	 *      java.lang.Integer, java.lang.Integer)
+	 */
+	@Override
+	public W3CEndpointReference createPullRS(final String providerAddress,
+			final String bdId,
+			final int initialPageSize,
+			final int expiryTime,
+			final String styleSheet,
+			final Integer keepAliveTime,
+			final Integer total) {
+		throw new UnimplementedException();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#createPullRSEPR(javax.xml.ws.wsaddressing.W3CEndpointReference,
+	 *      java.lang.String, int, int, java.lang.String, java.lang.Integer, java.lang.Integer)
+	 */
+	@Override
+	public W3CEndpointReference createPullRSEPR(final W3CEndpointReference dataProviderEPR,
+			final String bdId,
+			final int initialPageSize,
+			final int expiryTime,
+			final String styleSheet,
+			final Integer keepAliveTime,
+			final Integer total) {
+		throw new UnimplementedException();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#getNumberOfElements(java.lang.String)
+	 */
+	@Override
+	public int getNumberOfElements(final String rsId) throws ResultSetException {
+		final ResultSet resultSet = getResultSetById(rsId); // NOPMD
+		return resultSet.getNumberOfResults();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#getResult(java.lang.String, int, int, java.lang.String)
+	 */
+	@Override
+	public List<String> getResult(final String rsId, final int fromPosition, final int toPosition, final String requestMode) throws ResultSetException {
+		final ResultSet resultSet = getResultSetById(rsId); // NOPMD
+		return resultSet.getResults(fromPosition, toPosition);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#createPushRS(int, int)
+	 */
+	@Override
+	public W3CEndpointReference createPushRS(final int expiryTime, final int keepAliveTime) throws ResultSetException {
+		return pushFactory.createPushResultSet(expiryTime);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#getProperty(java.lang.String, java.lang.String)
+	 */
+	@Override
+	public String getProperty(final String rsId, final String name) throws ResultSetException {
+		final ResultSet resultSet = getResultSetById(rsId); // NOPMD
+
+		if ("rsId".equals(name)) return resultSet.getIdentifier();
+		else if ("total".equals(name)) return Integer.toString(resultSet.getNumberOfResults());
+		else if ("maxExpiryTime".equals(name)) return Integer.toString(resultsetRegistry.getMaxIdleTimeById(rsId));
+		else if ("expiryTime".equals(name)) return Integer.toString(resultsetRegistry.getMaxIdleTimeById(rsId));
+		else if ("keepAliveTime".equals(name)) return Integer.toString(resultsetRegistry.getMaxIdleTimeById(rsId));
+		// ...
+
+		return customPropertyDao.getProperties(resultSet).get(name);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#getRSStatus(java.lang.String)
+	 */
+	@Override
+	public String getRSStatus(final String rsId) throws ResultSetException {
+		final ResultSet resultSet = getResultSetById(rsId); // NOPMD
+		if (resultSet.isOpen()) return "open";
+		return "closed";
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#populateRS(java.lang.String, java.util.List)
+	 */
+	@Override
+	public String populateRS(final String rsId, final List<String> elements) throws ResultSetException {
+		final ResultSet resultSet = getResultSetById(rsId); // NOPMD
+		if (resultSet instanceof PushResultSet) {
+			((PushResultSet) resultSet).addElements(elements);
+		} else throw new ResultSetException("ResultSet '" + rsId + "' is not a push resultset");
+
+		return "1";
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.common.rmi.BaseService#start()
+	 */
+	@Override
+	public void start() {
+		// TODO Auto-generated method stub
+
+	}
+
+	/**
+	 * obtain the resultset object for a given id.
+	 * 
+	 * @param rsId
+	 *            resultset id
+	 * @return resultset object, never null
+	 * @throws ResultSetException
+	 *             thrown when the id doesn't exist;
+	 */
+	private ResultSet getResultSetById(final String rsId) throws ResultSetException {
+		final ResultSet resultSet = resultsetRegistry.getResultSetById(rsId); // NOPMD
+		if (resultSet == null) throw new ResultSetException("resultset with id '" + rsId + "' doesn't exist");
+		return resultSet;
+	}
+
+	public ResultSetRegistry getResultsetRegistry() {
+		return resultsetRegistry;
+	}
+
+	@Required
+	public void setResultsetRegistry(final ResultSetRegistry resultsetRegistry) {
+		this.resultsetRegistry = resultsetRegistry;
+	}
+
+	public EndpointReferenceBuilder<Endpoint> getEprBuilder() {
+		return eprBuilder;
+	}
+
+	@Required
+	public void setEprBuilder(final EndpointReferenceBuilder<Endpoint> eprBuilder) {
+		this.eprBuilder = eprBuilder;
+	}
+
+	public Endpoint getEndpoint() {
+		return endpoint;
+	}
+
+	@Required
+	public void setEndpoint(final Endpoint endpoint) {
+		this.endpoint = endpoint;
+	}
+
+	public PushResultSetFactory getPushFactory() {
+		return pushFactory;
+	}
+
+	@Required
+	public void setPushFactory(final PushResultSetFactory pushFactory) {
+		this.pushFactory = pushFactory;
+	}
+
+	public ResultSetPropertyDao getCustomPropertyDao() {
+		return customPropertyDao;
+	}
+
+	public void setCustomPropertyDao(final ResultSetPropertyDao customPropertyDao) {
+		this.customPropertyDao = customPropertyDao;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSet.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSet.java	(revision 45117)
@@ -0,0 +1,151 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
+import eu.dnetlib.enabling.tools.ServiceResolver;
+import eu.dnetlib.miscutils.collections.MappedCollection;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+/**
+ * A resultset filter. Applies a transformation for every resultset record.
+ * 
+ * @author marko
+ * 
+ */
+public class MappedResultSet implements ResultSetListener, ResultSetAware {
+
+	/**
+	 * input resultset.
+	 */
+	private ResultSetService resultSetService;
+
+	/**
+	 * input resultset id.
+	 */
+	private String rsId;
+
+	/**
+	 * mapper function.
+	 */
+	private UnaryFunction<String, String> mapper;
+
+	/**
+	 * service resolver.
+	 */
+	private ServiceResolver serviceResolver;
+
+	private ResultSet resultSet;
+
+	/**
+	 * Create a new mapped resultset.
+	 * 
+	 * @param epr
+	 *            input resultset epr
+	 * @param mapper
+	 *            mapper function
+	 * @param serviceResolver
+	 *            service resolver
+	 */
+	public MappedResultSet(final W3CEndpointReference epr, final UnaryFunction<String, String> mapper, final ServiceResolver serviceResolver) {
+		super();
+
+		this.resultSetService = serviceResolver.getService(ResultSetService.class, epr);
+		this.rsId = serviceResolver.getResourceIdentifier(epr);
+
+		this.mapper = mapper;
+
+		this.serviceResolver = serviceResolver;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSetListener#getResult(int, int)
+	 */
+	@Override
+	public List<String> getResult(final int fromPosition, final int toPosition) {
+		return MappedCollection.listMap(getResultFromSource(fromPosition, toPosition), mapper);
+
+	}
+
+	protected List<String> getResultFromSource(final int fromPosition, final int toPosition) {
+		try {
+			List<String> res = resultSetService.getResult(rsId, fromPosition, toPosition, "waiting");
+			checkStatus();
+			return res;
+		} catch (final ResultSetException e) {
+			throw new IllegalStateException(e);
+		}
+	}
+
+	private void checkStatus() throws ResultSetException {
+		if (getResultSet().isOpen() && resultSetService.getRSStatus(rsId).equals("closed")) {
+			getResultSet().close();
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSetListener#getSize()
+	 */
+	@Override
+	public int getSize() {
+		try {
+			int numberOfElements = resultSetService.getNumberOfElements(rsId);
+			checkStatus();		
+			return numberOfElements;
+		} catch (final ResultSetException e) {
+			throw new IllegalStateException(e);
+		}
+	}
+
+	public ResultSetService getResultSetService() {
+		return resultSetService;
+	}
+
+	public void setResultSetService(final ResultSetService resultSetService) {
+		this.resultSetService = resultSetService;
+	}
+
+	public UnaryFunction<String, String> getMapper() {
+		return mapper;
+	}
+
+	public void setMapper(final UnaryFunction<String, String> mapper) {
+		this.mapper = mapper;
+	}
+
+	public ServiceResolver getServiceResolver() {
+		return serviceResolver;
+	}
+
+	@Required
+	public void setServiceResolver(final ServiceResolver serviceResolver) {
+		this.serviceResolver = serviceResolver;
+	}
+
+	@Override
+	public void setResultSet(ResultSet resultSet) {
+		this.resultSet = resultSet;
+	}
+
+	public ResultSet getResultSet() {
+		return resultSet;
+	}
+
+	public String getRsId() {
+		return rsId;
+	}
+
+	public void setRsId(String rsId) {
+		this.rsId = rsId;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetServiceImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetServiceImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSetServiceImpl.java	(revision 45117)
@@ -0,0 +1,258 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import javax.jws.WebService;
+import javax.xml.ws.Endpoint;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.common.rmi.UnimplementedException;
+import eu.dnetlib.enabling.resultset.push.PushResultSet;
+import eu.dnetlib.enabling.resultset.push.PushResultSetFactory;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
+import eu.dnetlib.enabling.tools.AbstractBaseService;
+import eu.dnetlib.soap.EndpointReferenceBuilder;
+
+/**
+ * This component dispatches the service method calls to stateful datastructure instances and to the singleton core.
+ * 
+ * @author marko
+ * 
+ */
+@WebService(targetNamespace = "http://services.dnetlib.eu/")
+public class ResultSetServiceImpl extends AbstractBaseService implements ResultSetService {
+
+	/**
+	 * logger.
+	 */
+	private static final Log log = LogFactory.getLog(ResultSetServiceImpl.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	/**
+	 * Maps resultset identifiers to resultsets and manages expiration etc.
+	 */
+	private ResultSetRegistry resultsetRegistry;
+
+	/**
+	 * push resultset factory.
+	 */
+	private PushResultSetFactory pushFactory;
+
+	/**
+	 * Service endpoint.
+	 */
+	private Endpoint endpoint;
+
+	/**
+	 * injected epr builder.
+	 */
+	private EndpointReferenceBuilder<Endpoint> eprBuilder;
+
+	/**
+	 * custom resultset properties.
+	 */
+	private ResultSetPropertyDao customPropertyDao;
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#closeRS(java.lang.String)
+	 */
+	@Override
+	public void closeRS(final String rsId) {
+		try {
+			final ResultSet resultSet = getResultSetById(rsId);
+			resultSet.close();
+		} catch (ResultSetException e) {
+			log.warn("should throw checked exception but wasn't declared in cnr-rmi-api", e);
+			throw new IllegalStateException(e);
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#createPullRS(java.lang.String, java.lang.String, int, int, java.lang.String,
+	 *      java.lang.Integer, java.lang.Integer)
+	 */
+	@Override
+	public W3CEndpointReference createPullRS(final String providerAddress,
+			final String bdId,
+			final int initialPageSize,
+			final int expiryTime,
+			final String styleSheet,
+			final Integer keepAliveTime,
+			final Integer total) {
+		throw new UnimplementedException();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#createPullRSEPR(javax.xml.ws.wsaddressing.W3CEndpointReference,
+	 *      java.lang.String, int, int, java.lang.String, java.lang.Integer, java.lang.Integer)
+	 */
+	@Override
+	public W3CEndpointReference createPullRSEPR(final W3CEndpointReference dataProviderEPR,
+			final String bdId,
+			final int initialPageSize,
+			final int expiryTime,
+			final String styleSheet,
+			final Integer keepAliveTime,
+			final Integer total) {
+		throw new UnimplementedException();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#getNumberOfElements(java.lang.String)
+	 */
+	@Override
+	public int getNumberOfElements(final String rsId) throws ResultSetException {
+		final ResultSet resultSet = getResultSetById(rsId); // NOPMD
+		return resultSet.getNumberOfResults();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#getResult(java.lang.String, int, int, java.lang.String)
+	 */
+	@Override
+	public List<String> getResult(final String rsId, final int fromPosition, final int toPosition, final String requestMode) throws ResultSetException {
+		final ResultSet resultSet = getResultSetById(rsId); // NOPMD
+		return resultSet.getResults(fromPosition, toPosition);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#createPushRS(int, int)
+	 */
+	@Override
+	public W3CEndpointReference createPushRS(final int expiryTime, final int keepAliveTime) throws ResultSetException {
+		return pushFactory.createPushResultSet(expiryTime);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#getProperty(java.lang.String, java.lang.String)
+	 */
+	@Override
+	public String getProperty(final String rsId, final String name) throws ResultSetException {
+		final ResultSet resultSet = getResultSetById(rsId); // NOPMD
+
+		if ("rsId".equals(name)) return resultSet.getIdentifier();
+		else if ("total".equals(name)) return Integer.toString(resultSet.getNumberOfResults());
+		else if ("maxExpiryTime".equals(name)) return Integer.toString(resultsetRegistry.getMaxIdleTimeById(rsId));
+		else if ("expiryTime".equals(name)) return Integer.toString(resultsetRegistry.getMaxIdleTimeById(rsId));
+		else if ("keepAliveTime".equals(name)) return Integer.toString(resultsetRegistry.getMaxIdleTimeById(rsId));
+		// ...
+
+		return customPropertyDao.getProperties(resultSet).get(name);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#getRSStatus(java.lang.String)
+	 */
+	@Override
+	public String getRSStatus(final String rsId) throws ResultSetException {
+		final ResultSet resultSet = getResultSetById(rsId); // NOPMD
+		if (resultSet.isOpen()) return "open";
+		return "closed";
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#populateRS(java.lang.String, java.util.List)
+	 */
+	@Override
+	public String populateRS(final String rsId, final List<String> elements) throws ResultSetException {
+		final ResultSet resultSet = getResultSetById(rsId); // NOPMD
+		if (resultSet instanceof PushResultSet) {
+			((PushResultSet) resultSet).addElements(elements);
+		} else throw new ResultSetException("ResultSet '" + rsId + "' is not a push resultset");
+
+		return "1";
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.common.rmi.BaseService#start()
+	 */
+	@Override
+	public void start() {
+		// TODO Auto-generated method stub
+
+	}
+
+	/**
+	 * obtain the resultset object for a given id.
+	 * 
+	 * @param rsId
+	 *            resultset id
+	 * @return resultset object, never null
+	 * @throws ResultSetException
+	 *             thrown when the id doesn't exist;
+	 */
+	private ResultSet getResultSetById(final String rsId) throws ResultSetException {
+		final ResultSet resultSet = resultsetRegistry.getResultSetById(rsId); // NOPMD
+		if (resultSet == null) throw new ResultSetException("resultset with id '" + rsId + "' doesn't exist");
+		return resultSet;
+	}
+
+	public ResultSetRegistry getResultsetRegistry() {
+		return resultsetRegistry;
+	}
+
+	@Required
+	public void setResultsetRegistry(final ResultSetRegistry resultsetRegistry) {
+		this.resultsetRegistry = resultsetRegistry;
+	}
+
+	public EndpointReferenceBuilder<Endpoint> getEprBuilder() {
+		return eprBuilder;
+	}
+
+	@Required
+	public void setEprBuilder(final EndpointReferenceBuilder<Endpoint> eprBuilder) {
+		this.eprBuilder = eprBuilder;
+	}
+
+	public Endpoint getEndpoint() {
+		return endpoint;
+	}
+
+	@Required
+	public void setEndpoint(final Endpoint endpoint) {
+		this.endpoint = endpoint;
+	}
+
+	public PushResultSetFactory getPushFactory() {
+		return pushFactory;
+	}
+
+	@Required
+	public void setPushFactory(final PushResultSetFactory pushFactory) {
+		this.pushFactory = pushFactory;
+	}
+
+	public ResultSetPropertyDao getCustomPropertyDao() {
+		return customPropertyDao;
+	}
+
+	public void setCustomPropertyDao(final ResultSetPropertyDao customPropertyDao) {
+		this.customPropertyDao = customPropertyDao;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/observer/Observable.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/observer/Observable.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/observer/Observable.java	(revision 45117)
@@ -0,0 +1,18 @@
+package eu.dnetlib.enabling.resultset.observer;
+
+import eu.dnetlib.enabling.resultset.ResultSetRegistry;
+
+/**
+ * Declares the JDK-like standard observable pattern as a java interface.
+ * 
+ * @author marko, claudio, alessia, michele
+ */
+public interface Observable {
+	/**
+	 * add a given observer to this object.
+	 * 
+	 * @param observer
+	 *            observer
+	 */
+	void addObserver(ResultSetRegistry observer);
+}

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/observer/Observable.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/observer/Observable.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/observer/Observable.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/observer/Observable.java	(revision 45117)
@@ -0,0 +1,18 @@
+package eu.dnetlib.enabling.resultset.observer;
+
+import eu.dnetlib.enabling.resultset.ResultSetRegistry;
+
+/**
+ * Declares the JDK-like standard observable pattern as a java interface.
+ * 
+ * @author marko, claudio, alessia, michele
+ */
+public interface Observable {
+	/**
+	 * add a given observer to this object.
+	 * 
+	 * @param observer
+	 *            observer
+	 */
+	void addObserver(ResultSetRegistry observer);
+}

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/observer/Observable.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/AbstractObservableResultset.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/AbstractObservableResultset.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/AbstractObservableResultset.java	(revision 45117)
@@ -0,0 +1,155 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import eu.dnetlib.enabling.resultset.observer.DelegationObserver;
+import eu.dnetlib.enabling.resultset.observer.Observable;
+
+
+/**
+ * Common stuff for resultset implementations bound to a ResultSetRegistry.
+ * 
+ * @author marko
+ * 
+ */
+public abstract class AbstractObservableResultset implements ResultSet, Observable {
+	/**
+	 * true if the resultset is destroyed.
+	 */
+	private boolean destroyed = false;
+
+	/**
+	 * true if the resultset is open.
+	 */
+	private boolean open;
+
+	/**
+	 * delegate the real job to a java.util.Observable object.
+	 */
+	private transient final java.util.Observable observable = new DelegationObservable();
+
+	/**
+	 * weak map for removing single observers later on.
+	 */
+	private transient Map<ResultSetRegistry, DelegationObserver> observers = new WeakHashMap<ResultSetRegistry, DelegationObserver>();
+
+	/**
+	 * java.util.Observable requires a "change" in the object to be made for the notifyObservers methods to trigger
+	 * actually the notification. We don't think this should be part of the base Observable/Observer pattern and thus
+	 * hide this fact. If an user of AbstractObservable wants this behavior it should implement her own change tracking
+	 * and avoid calling notifyObservers altogether. The rationale behind this choice is that not all dirty states can
+	 * be expressed using a stateful boolean instance variable like that implemented by java.util.Observable; some users
+	 * may prefer/need a lazy dirty flag instead.
+	 * 
+	 * @author marko
+	 * 
+	 */
+	static class DelegationObservable extends java.util.Observable {
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see java.util.Observable#notifyObservers()
+		 */
+		@Override
+		public void notifyObservers() {
+			setChanged();
+			super.notifyObservers();
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see java.util.Observable#notifyObservers(java.lang.Object)
+		 */
+		@Override
+		public void notifyObservers(final Object arg) {
+			setChanged();
+			super.notifyObservers(arg);
+		}
+
+	}	
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#destroy()
+	 */
+	@Override
+	public void destroy() {
+		if (!isDestroyed()) {
+			setDestroyed(true);
+			notifyObservers();
+			deleteObservers();
+		}
+	}
+
+	public void setDestroyed(final boolean destroyed) {
+		this.destroyed = destroyed;
+	}
+
+	@Override
+	public boolean isDestroyed() {
+		return destroyed;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#isOpen()
+	 */
+	@Override
+	public boolean isOpen() {
+		return open;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#close()
+	 */
+	@Override
+	public void close() {
+		open = false;
+	}
+
+	public void setOpen(final boolean open) {
+		this.open = open;
+	}
+
+	@Override
+	public void addObserver(final ResultSetRegistry observer) {
+		final DelegationObserver delegate = new DelegationObserver(this, observer);
+		observers.put(observer, delegate);
+		observable.addObserver(delegate);
+	}
+
+	protected void notifyObservers() {
+		observable.notifyObservers();
+	}
+
+	protected void notifyObservers(final Object arg) {
+		observable.notifyObservers(arg);
+	}
+
+	public int countObservers() {
+		return observable.countObservers();
+	}
+
+	public void deleteObserver(final java.util.Observer observer) {
+		observable.deleteObserver(observer);
+	}
+
+	public void deleteObserver(ResultSetRegistry observer) {
+		DelegationObserver delegate = observers.get(observer);
+		if(delegate != null) {
+			observable.deleteObserver(delegate);
+		}
+	}	
+
+	public void deleteObservers() {
+		observable.deleteObservers();
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSet.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSet.java	(revision 45117)
@@ -0,0 +1,71 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import eu.dnetlib.enabling.resultset.observer.Observable;
+
+/**
+ * A ResultSet represents a set of data results.
+ * 
+ * @author marko
+ * 
+ */
+public interface ResultSet extends Observable {
+	/**
+	 * get the resource identifier.
+	 * 
+	 * @return rsId
+	 */
+	String getIdentifier();
+
+	/**
+	 * sets the resource identifier. The ResultSetRegistry will assign a new rsId.
+	 * 
+	 * @param rsId allocated resultset identifier
+	 */
+	void setIdentifier(String rsId);
+
+	/**
+	 * get a 'page' of results.
+	 * 
+	 * @param fromPosition
+	 *            from 1
+	 * @param toPosition
+	 *            last included
+	 * @return a page of data
+	 */
+	List<String> getResults(int fromPosition, int toPosition);
+
+	/**
+	 * get the number of result elements present in the resultset.
+	 * 
+	 * @return number of results
+	 */
+	int getNumberOfResults();
+
+	/**
+	 * Tells if the resultset is open or closed.
+	 * 
+	 * @return true if open
+	 */
+	boolean isOpen();
+
+	/**
+	 * close a resultset.
+	 */
+	void close();
+	
+	/**
+	 * Tells if the resultset is destroyed.
+	 * 
+	 * @return true if the resultset is destroyed. 
+	 */
+	boolean isDestroyed();
+	
+	/**
+	 * Destroy the resultset and free associated resources, remove it from the ResultSetRegistry.
+	 * After calling this method, the resultset is no more accessible from other services.
+	 */
+	void destroy();
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSet.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ResultSet.java	(revision 45117)
@@ -0,0 +1,71 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import eu.dnetlib.enabling.resultset.observer.Observable;
+
+/**
+ * A ResultSet represents a set of data results.
+ * 
+ * @author marko
+ * 
+ */
+public interface ResultSet extends Observable {
+	/**
+	 * get the resource identifier.
+	 * 
+	 * @return rsId
+	 */
+	String getIdentifier();
+
+	/**
+	 * sets the resource identifier. The ResultSetRegistry will assign a new rsId.
+	 * 
+	 * @param rsId allocated resultset identifier
+	 */
+	void setIdentifier(String rsId);
+
+	/**
+	 * get a 'page' of results.
+	 * 
+	 * @param fromPosition
+	 *            from 1
+	 * @param toPosition
+	 *            last included
+	 * @return a page of data
+	 */
+	List<String> getResults(int fromPosition, int toPosition);
+
+	/**
+	 * get the number of result elements present in the resultset.
+	 * 
+	 * @return number of results
+	 */
+	int getNumberOfResults();
+
+	/**
+	 * Tells if the resultset is open or closed.
+	 * 
+	 * @return true if open
+	 */
+	boolean isOpen();
+
+	/**
+	 * close a resultset.
+	 */
+	void close();
+	
+	/**
+	 * Tells if the resultset is destroyed.
+	 * 
+	 * @return true if the resultset is destroyed. 
+	 */
+	boolean isDestroyed();
+	
+	/**
+	 * Destroy the resultset and free associated resources, remove it from the ResultSetRegistry.
+	 * After calling this method, the resultset is no more accessible from other services.
+	 */
+	void destroy();
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetFactoryImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetFactoryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetFactoryImpl.java	(revision 45117)
@@ -0,0 +1,38 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * This factory creates resultset bound to a given resultset registry shared with a resultset service which exposed them
+ * to the outside world.
+ *
+ * It's tightly coupled with a local instance of the ResultSetService.
+ *
+ * @see eu.dnetlib.enabling.resultset.ResultSetServiceImpl
+ *
+ * @author marko
+ *
+ */
+public class LocalResultSetFactoryImpl extends AbstractResultSetFactory {
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see eu.dnetlib.enabling.resultset.ResultSetFactory#createResultSet(eu.dnetlib.enabling.resultset.ResultSetListener)
+	 */
+	@Override
+	public W3CEndpointReference createResultSet(final ResultSetListener provider) {
+		return registerResultSet(createInstance(provider));
+	}
+
+	/**
+	 * create a new local resultset instance. Subclasses may override this to supply additional configuration.
+	 *
+	 * @param provider provider
+	 * @return a new resultset instance.
+	 */
+	protected LocalResultSetImpl createInstance(final ResultSetListener provider) {
+		return new LocalResultSetImpl(provider);
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.properties
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.properties	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.properties	(revision 45117)
@@ -0,0 +1,6 @@
+services.is.resultset.resultSetRegistryCache.timeToIdle = 240
+services.is.resultset.resultSetRegistryMaxIdleTimeCache.timeToIdle = 240
+
+# jaxwsEndpointReferenceBuilder | staticResultSetServiceEprBuilder
+services.resultset.eprbuilder.bean = jaxwsEndpointReferenceBuilder
+services.resultset.endpoint.static.address = ${transport.soap.baseAddress}/resultSet
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetFactoryImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetFactoryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetFactoryImpl.java	(revision 45117)
@@ -0,0 +1,38 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * This factory creates resultset bound to a given resultset registry shared with a resultset service which exposed them
+ * to the outside world.
+ *
+ * It's tightly coupled with a local instance of the ResultSetService.
+ *
+ * @see eu.dnetlib.enabling.resultset.ResultSetServiceImpl
+ *
+ * @author marko
+ *
+ */
+public class LocalResultSetFactoryImpl extends AbstractResultSetFactory {
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see eu.dnetlib.enabling.resultset.ResultSetFactory#createResultSet(eu.dnetlib.enabling.resultset.ResultSetListener)
+	 */
+	@Override
+	public W3CEndpointReference createResultSet(final ResultSetListener provider) {
+		return registerResultSet(createInstance(provider));
+	}
+
+	/**
+	 * create a new local resultset instance. Subclasses may override this to supply additional configuration.
+	 *
+	 * @param provider provider
+	 * @return a new resultset instance.
+	 */
+	protected LocalResultSetImpl createInstance(final ResultSetListener provider) {
+		return new LocalResultSetImpl(provider);
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/CacheTransientResultSetDaoImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/CacheTransientResultSetDaoImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/CacheTransientResultSetDaoImpl.java	(revision 45117)
@@ -0,0 +1,179 @@
+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<String, List<String>> cache;
+
+	/**
+	 * resultsets
+	 */
+	private Cache<String, ResultSetDescriptor> resultSetCache;
+
+	/**
+	 * resultset descriptor factory.
+	 */
+	@Resource
+	private Factory<ResultSetDescriptor> 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<String> 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<String> lastRange = cache.get(key + "-" + lastRangeIndex);
+			log.debug("stored last range: " + lastRange);
+
+			if (lastRange == null) {
+				lastRange = new ArrayList<String>();
+				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<String> nextRange = new ArrayList<String>(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<String> 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<String> res = new ArrayList<String>();
+
+		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<String, List<String>> getCache() {
+		return cache;
+	}
+
+	@Required
+	public void setCache(final Cache<String, List<String>> cache) {
+		this.cache = cache;
+	}
+
+	public Cache<String, ResultSetDescriptor> getResultSetCache() {
+		return resultSetCache;
+	}
+
+	@Required
+	public void setResultSetCache(final Cache<String, ResultSetDescriptor> resultSetCache) {
+		this.resultSetCache = resultSetCache;
+	}
+
+	public Factory<ResultSetDescriptor> getResultSetDescriptorFactory() {
+		return resultSetDescriptorFactory;
+	}
+
+	public void setResultSetDescriptorFactory(final Factory<ResultSetDescriptor> resultSetDescriptorFactory) {
+		this.resultSetDescriptorFactory = resultSetDescriptorFactory;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetImpl.java	(revision 45117)
@@ -0,0 +1,98 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Resultset backing implementation.
+ * 
+ * @author marko
+ * 
+ */
+public class LocalResultSetImpl extends AbstractObservableResultset implements ResultSet {
+
+	/**
+	 * rsId.
+	 */
+	private String identifier;
+
+	/**
+	 * this listener will provide the data to this local resultset by listening to events.
+	 */
+	private ResultSetListener listener;
+
+	/**
+	 * Construct a new local ResultSet which pulls data from the listener. If the listener implements ResultSetAware, it
+	 * will be injected with this instance.
+	 * 
+	 * @param listener
+	 *            a resultset listener
+	 */
+	public LocalResultSetImpl(final ResultSetListener listener) {
+		super();
+		this.listener = listener;
+
+		if (listener instanceof ResultSetAware)
+			((ResultSetAware) listener).setResultSet(this);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#getNumberOfResults()
+	 */
+	@Override
+	public int getNumberOfResults() {
+		return listener.getSize();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#getResults(int, int)
+	 */
+	@Override
+	public List<String> getResults(final int fromPosition, final int toPosition) {
+		int toPos = toPosition;
+		int fromPos = fromPosition;
+		if (!isOpen()) {
+			final int size = getNumberOfResults();
+			
+			if (size == 0)
+				return Lists.newArrayList();
+			
+			if (fromPos > size)
+				return Lists.newArrayList();
+
+			if (toPos > size)
+				toPos = size;
+		}
+		
+		if (fromPos < 1)
+			fromPos = 1;
+		if (toPos < fromPos)
+			toPos = fromPos;
+
+		return listener.getResult(fromPos, toPos);
+	}
+
+	@Override
+	public String getIdentifier() {
+		return identifier;
+	}
+
+	@Override
+	public void setIdentifier(final String identifier) {
+		this.identifier = identifier;
+	}
+
+	public ResultSetListener getListener() {
+		return listener;
+	}
+
+	public void setListener(final ResultSetListener listener) {
+		this.listener = listener;
+	}
+
+}

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetImpl.java
___________________________________________________________________
Added: svn:mergeinfo
## -0,0 +0,0 ##
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetFactory.java	(revision 45117)
@@ -0,0 +1,34 @@
+package eu.dnetlib.enabling.resultset.push;
+
+
+/**
+ * creates a transient push resultset.
+ * 
+ * @author marko
+ *
+ */
+public class TransientPushResultSetFactory extends AbstractPushResultSetFactoryImpl {
+
+	/**
+	 * dao.
+	 */
+	private TransientPushResultSetDao dao;
+	
+	/** 
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.push.AbstractPushResultSetFactoryImpl#newInstance()
+	 */
+	@Override
+	protected PushResultSet newInstance() {
+		return new TransientPushResultSetImpl(dao);
+	}
+
+	public TransientPushResultSetDao getDao() {
+		return dao;
+	}
+
+	public void setDao(final TransientPushResultSetDao dao) {
+		this.dao = dao;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImpl.java	(revision 45117)
@@ -0,0 +1,99 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import eu.dnetlib.enabling.resultset.AbstractObservableResultset;
+
+/**
+ * a push resultset which holds it's data in a transient cache.
+ *
+ * @author marko
+ *
+ */
+public class TransientPushResultSetImpl extends AbstractObservableResultset implements PushResultSet {
+
+	/**
+	 * logger.
+	 */
+	private static final Log log = LogFactory.getLog(TransientPushResultSetImpl.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	/**
+	 * dao.
+	 */
+	private final transient TransientPushResultSetDao dao;
+
+	/**
+	 * rsId.
+	 */
+	private String identifier;
+
+	/**
+	 * constructed by the transient push resultset factory.
+	 *
+	 * @param dao dao
+	 */
+	public TransientPushResultSetImpl(final TransientPushResultSetDao dao) {
+		super();
+		this.dao = dao;
+		setOpen(true);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see eu.dnetlib.enabling.resultset.push.PushResultSet#addElements(java.util.List)
+	 */
+	@Override
+	public void addElements(final List<String> elements) {
+		log.debug("adding to push RS: " + elements);
+
+		if (isOpen())
+			dao.addElements(getIdentifier(), elements);
+		else
+			throw new IllegalStateException("cannot write to a closed push resultset");
+	}
+
+	@Override
+	public int getNumberOfResults() {
+		return dao.getSize(getIdentifier());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#getResults(int, int)
+	 */
+	@Override
+	public List<String> getResults(final int fromPosition, final int toPosition) {
+
+		final int size = getNumberOfResults();
+		int toPos = toPosition;
+		int fromPos = fromPosition;
+		if (fromPos > size)
+			fromPos = size;
+		if (toPos > size)
+			toPos = size;
+
+		log.debug("calling get elements: " + getIdentifier() + " from " + fromPos + " to " + toPos);
+		return dao.getElements(getIdentifier(), fromPos, toPos);
+	}
+
+	public TransientPushResultSetDao getDao() {
+		return dao;
+	}
+
+	@Override
+	public String getIdentifier() {
+		return identifier;
+	}
+
+	@Override
+	public void setIdentifier(final String identifier) {
+		this.identifier = identifier;
+	}
+
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalResultSetFactoryImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalResultSetFactoryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalResultSetFactoryImpl.java	(revision 45117)
@@ -0,0 +1,27 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+public class EPRPoolingLocalResultSetFactoryImpl extends LocalResultSetFactoryImpl {
+
+	private ResultSetEPRPool pool;
+	
+	@Override
+	public W3CEndpointReference registerResultSet(ResultSet resultSet) {
+		return pool.registerResultSet(resultSet);
+	}
+
+	public ResultSetEPRPool getPool() {
+		return pool;
+	}
+
+	@Required
+	public void setPool(ResultSetEPRPool pool) {
+		this.pool = pool;
+	}
+
+	
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSet.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSet.java	(revision 45117)
@@ -0,0 +1,57 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.enabling.tools.ServiceResolver;
+import eu.dnetlib.miscutils.collections.MappedCollection;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+public class ParallelMappedResultSet extends MappedResultSet {
+
+	private ExecutorService executor;
+
+	public ParallelMappedResultSet(final W3CEndpointReference source, final UnaryFunction<String, String> mapper, final ServiceResolver serviceResolver,
+			final ExecutorService executor) {
+		super(source, mapper, serviceResolver);
+		this.executor = executor;
+	}
+
+	@Override
+	public List<String> getResult(int fromPosition, int toPosition) {
+
+//		log.info("Parallel page " + (toPosition - fromPosition + 1));
+
+		List<Future<String>> results = Lists.newArrayList();
+
+		for (final String input : getResultFromSource(fromPosition, toPosition)) {
+			results.add(executor.submit(new Callable<String>() {
+				@Override
+				public String call() throws Exception {
+					return getMapper().evaluate(input);
+				}
+			}));
+		}
+
+		return MappedCollection.listMap(results, new UnaryFunction<String, Future<String>>() {
+			@Override
+			public String evaluate(Future<String> arg) {
+				try {
+					return arg.get();
+				} catch (InterruptedException e) {
+					throw new IllegalStateException(e);
+				} catch (ExecutionException e) {
+					throw new IllegalStateException(e);
+				}
+			}
+		});
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetListener.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetListener.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetListener.java	(revision 45117)
@@ -0,0 +1,61 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
+import eu.dnetlib.enabling.tools.ServiceResolver;
+
+public class CachingResultSetListener implements ResultSetListener {
+	private static final Log log = LogFactory.getLog(CachingResultSetListener.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	
+	private ResultSetService service;
+	private String rsId;
+
+	private ArrayList<String> storage = new ArrayList<String>();
+
+	public CachingResultSetListener(W3CEndpointReference epr, ServiceResolver serviceResolver) {
+		this.service = serviceResolver.getService(ResultSetService.class, epr);
+		this.rsId = serviceResolver.getResourceIdentifier(epr);
+	}
+
+	@Override
+	public List<String> getResult(int fromPosition, int toPosition) {
+		if (storage.get(fromPosition) != null)
+			return cached(fromPosition, toPosition);
+		try {
+			List<String> data = service.getResult(rsId, fromPosition, toPosition, "waiting");
+			cache(data, fromPosition, toPosition);
+			return data;
+		} catch (ResultSetException e) {
+			throw new IllegalStateException(e);
+		}
+	}
+
+	private void cache(List<String> data, int fromPosition, int toPosition) {
+		for(String value : data)
+			storage.set(fromPosition++, value);
+	}
+
+	private List<String> cached(int fromPosition, int toPosition) {
+		log.info("found cached page " + fromPosition + ", " + toPosition);
+		return storage.subList(fromPosition-1, toPosition);
+	}
+
+	@Override
+	public int getSize() {
+		try {
+			return service.getNumberOfElements(rsId);
+		} catch (ResultSetException e) {
+			throw new IllegalStateException(e);
+		}
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/SizedIterable.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/SizedIterable.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/SizedIterable.java	(revision 45117)
@@ -0,0 +1,7 @@
+package eu.dnetlib.enabling.resultset;
+
+public interface SizedIterable<T> extends Iterable<T> {
+
+	public int getNumberOfElements();
+	
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/CacheTransientResultSetDaoImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/CacheTransientResultSetDaoImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/CacheTransientResultSetDaoImpl.java	(revision 45117)
@@ -0,0 +1,179 @@
+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<String, List<String>> cache;
+
+	/**
+	 * resultsets
+	 */
+	private Cache<String, ResultSetDescriptor> resultSetCache;
+
+	/**
+	 * resultset descriptor factory.
+	 */
+	@Resource
+	private Factory<ResultSetDescriptor> 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<String> 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<String> lastRange = cache.get(key + "-" + lastRangeIndex);
+			log.debug("stored last range: " + lastRange);
+
+			if (lastRange == null) {
+				lastRange = new ArrayList<String>();
+				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<String> nextRange = new ArrayList<String>(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<String> 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<String> res = new ArrayList<String>();
+
+		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<String, List<String>> getCache() {
+		return cache;
+	}
+
+	@Required
+	public void setCache(final Cache<String, List<String>> cache) {
+		this.cache = cache;
+	}
+
+	public Cache<String, ResultSetDescriptor> getResultSetCache() {
+		return resultSetCache;
+	}
+
+	@Required
+	public void setResultSetCache(final Cache<String, ResultSetDescriptor> resultSetCache) {
+		this.resultSetCache = resultSetCache;
+	}
+
+	public Factory<ResultSetDescriptor> getResultSetDescriptorFactory() {
+		return resultSetDescriptorFactory;
+	}
+
+	public void setResultSetDescriptorFactory(final Factory<ResultSetDescriptor> resultSetDescriptorFactory) {
+		this.resultSetDescriptorFactory = resultSetDescriptorFactory;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSetFactory.java	(revision 45117)
@@ -0,0 +1,53 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.enabling.tools.ServiceResolver;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+/**
+ * Create a new resultset which takes each record of the input resultset and applies the mapping function to it.
+ *
+ * @author marko
+ *
+ */
+public class MappedResultSetFactory {
+
+	/**
+	 * underlying resultset factory, which exposes local resultsets to the world.
+	 */
+	private ResultSetFactory resultSetFactory;
+
+	/**
+	 * service resolver, transforms eprs to services.
+	 */
+	private ServiceResolver serviceResolver;
+
+	/**
+	 * Create a new resultset which takes each record of the input resultset and applies the mapping function to it.
+	 *
+	 * @param source source resultset epr
+	 * @param mapper mapper function
+	 * @return mapped resultset epr
+	 */
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final UnaryFunction<String, String> mapper) {
+		return resultSetFactory.createResultSet(new MappedResultSet(source, mapper, serviceResolver));
+	}
+
+	public ResultSetFactory getResultSetFactory() {
+		return resultSetFactory;
+	}
+
+	public void setResultSetFactory(final ResultSetFactory resultSetFactory) {
+		this.resultSetFactory = resultSetFactory;
+	}
+
+	public ServiceResolver getServiceResolver() {
+		return serviceResolver;
+	}
+
+	public void setServiceResolver(final ServiceResolver serviceResolver) {
+		this.serviceResolver = serviceResolver;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactory.java	(revision 45117)
@@ -0,0 +1,7 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import eu.dnetlib.miscutils.factory.Factory;
+
+public interface ResultSetDescriptorFactory extends Factory<ResultSetDescriptor> {
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/push/CacheTransientPushResultSetDaoTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/push/CacheTransientPushResultSetDaoTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/push/CacheTransientPushResultSetDaoTest.java	(revision 45117)
@@ -0,0 +1,78 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import java.util.List;
+
+import net.sf.ehcache.CacheManager;
+
+import org.junit.After;
+
+import eu.dnetlib.miscutils.cache.Cache;
+import eu.dnetlib.miscutils.cache.EhCache;
+import eu.dnetlib.miscutils.factory.Factory;
+
+/**
+ * concrete push resultset dao test.
+ * 
+ * @author marko
+ * 
+ */
+public class CacheTransientPushResultSetDaoTest extends AbstractTransientPushResultSetDaoTest { // NOPMD
+
+	/**
+	 * max in memory elements.
+	 */
+	private static final int MAX_IN_MEM = 100;
+
+	/**
+	 * default time.
+	 */
+	private static final int DEFAULT_TTI = 1000;
+
+	/**
+	 * default time to live.
+	 */
+	private static final int DEFAULT_TTL = 1000;
+
+	/**
+	 * cache manager.
+	 */
+	private final transient CacheManager cacheManager = CacheManager.create();
+
+	/**
+	 * clean cache after test.
+	 */
+	@After
+	public void cleanCache() {
+		cacheManager.removeAllCaches();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.push.AbstractTransientPushResultSetDaoTest#newInstance()
+	 */
+	@Override
+	protected TransientPushResultSetDao newInstance() {
+		final net.sf.ehcache.Cache ehcache = new net.sf.ehcache.Cache("testCache", MAX_IN_MEM, false, false, DEFAULT_TTL, DEFAULT_TTI);
+		cacheManager.addCache(ehcache);
+
+		final net.sf.ehcache.Cache rsehcache = new net.sf.ehcache.Cache("rsetCache", MAX_IN_MEM, false, false, DEFAULT_TTL, DEFAULT_TTI);
+		cacheManager.addCache(rsehcache);
+
+		final CacheTransientResultSetDaoImpl resultSet = new CacheTransientResultSetDaoImpl();
+		final Cache<String, List<String>> cache = new EhCache<String, List<String>>(ehcache);
+		final Cache<String, ResultSetDescriptor> rscache = new EhCache<String, ResultSetDescriptor>(rsehcache);
+		resultSet.setCache(cache);
+		resultSet.setResultSetCache(rscache);
+
+		resultSet.setResultSetDescriptorFactory(new Factory<ResultSetDescriptor>() {
+
+			@Override
+			public ResultSetDescriptor newInstance() {
+				return new ResultSetDescriptor();
+			}
+		});
+		return resultSet;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetFactory.java	(revision 45117)
@@ -0,0 +1,34 @@
+package eu.dnetlib.enabling.resultset.push;
+
+
+/**
+ * creates a transient push resultset.
+ * 
+ * @author marko
+ *
+ */
+public class TransientPushResultSetFactory extends AbstractPushResultSetFactoryImpl {
+
+	/**
+	 * dao.
+	 */
+	private TransientPushResultSetDao dao;
+	
+	/** 
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.push.AbstractPushResultSetFactoryImpl#newInstance()
+	 */
+	@Override
+	protected PushResultSet newInstance() {
+		return new TransientPushResultSetImpl(dao);
+	}
+
+	public TransientPushResultSetDao getDao() {
+		return dao;
+	}
+
+	public void setDao(final TransientPushResultSetDao dao) {
+		this.dao = dao;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorTest.java	(revision 45117)
@@ -0,0 +1,44 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.junit.Before;
+import org.junit.Test;
+
+import eu.dnetlib.enabling.resultset.push.ResultSetDescriptor.Range;
+
+public class ResultSetDescriptorTest {
+
+	private static final Log log = LogFactory.getLog(ResultSetDescriptorTest.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	private transient ResultSetDescriptor descriptor;
+
+	@Before
+	public void setUp() throws Exception {
+		descriptor = new ResultSetDescriptor();
+	}
+
+	@Test
+	public void testGetRangesContaining() {
+		log.debug("--- 1, 1");
+		for(Range i : descriptor.getRangesContaining(1, 1))
+			log.debug("i " + i);
+
+		log.debug("--- 2, 1000");
+		for(Range i : descriptor.getRangesContaining(2, 1000))
+			log.debug("i " + i);
+
+		log.debug("--- 5, 2000");
+		for(Range i : descriptor.getRangesContaining(5, 2000))
+			log.debug("i " + i);
+
+		log.debug("--- 5, 2001");
+		for(Range i : descriptor.getRangesContaining(5, 2001))
+			log.debug("i " + i);
+	}
+
+	@Test
+	public void testNext() {
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalResultSetFactoryImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalResultSetFactoryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalResultSetFactoryImpl.java	(revision 45117)
@@ -0,0 +1,27 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+public class EPRPoolingLocalResultSetFactoryImpl extends LocalResultSetFactoryImpl {
+
+	private ResultSetEPRPool pool;
+	
+	@Override
+	public W3CEndpointReference registerResultSet(ResultSet resultSet) {
+		return pool.registerResultSet(resultSet);
+	}
+
+	public ResultSetEPRPool getPool() {
+		return pool;
+	}
+
+	@Required
+	public void setPool(ResultSetEPRPool pool) {
+		this.pool = pool;
+	}
+
+	
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImplTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImplTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImplTest.java	(revision 45117)
@@ -0,0 +1,166 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import static org.junit.Assert.*; // NOPMD
+import static org.mockito.Mockito.*; // NOPMD
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.enabling.resultset.ResultSetRegistry;
+
+/**
+ * test the transient push resultset.
+ *
+ * @author marko
+ *
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class TransientPushResultSetImplTest {
+
+	/**
+	 * first test value.
+	 */
+	private static final String ONE = "one";
+
+	/**
+	 * second test value.
+	 */
+	private static final String TWO = "two";
+
+	/**
+	 * test rs id.
+	 */
+	private static final String RS_ID = "123";
+
+	/**
+	 * instance to be tested.
+	 */
+	private transient TransientPushResultSetImpl resultSet;
+
+	/**
+	 * dao mock.
+	 */
+	@Mock
+	private transient TransientPushResultSetDao dao;
+
+	/**
+	 * resultset registry mock.
+	 */
+	@Mock
+	private transient ResultSetRegistry registry;
+
+	/**
+	 * setup class to be tested.
+	 *
+	 * @throws Exception
+	 */
+	@Before
+	public void setUp() {
+		resultSet = new TransientPushResultSetImpl(dao);
+		resultSet.setIdentifier(RS_ID);
+		resultSet.getDao(); // getter code coverage hack
+	}
+
+	/**
+	 * test adding elements.
+	 */
+	@Test
+	public void testAddElements() {
+		final List<String> list = new ArrayList<String>();
+		list.add(ONE);
+
+		resultSet.addElements(list);
+
+		verify(dao).addElements(RS_ID, list);
+		assertNotNull("dummy", resultSet);
+	}
+
+	/**
+	 * test get number of results.
+	 */
+	@Test
+	public void testGetNumberOfResults() {
+		when(dao.getSize(RS_ID)).thenReturn(1);
+
+		assertEquals("check size", 1, resultSet.getNumberOfResults());
+	}
+
+	/**
+	 * get result.
+	 */
+	@Test
+	public void testGetResults() {
+		final List<String> list = new ArrayList<String>();
+		list.add(TWO);
+
+		when(dao.getSize(RS_ID)).thenReturn(2);
+		when(dao.getElements(RS_ID, 2, 2)).thenReturn(list);
+
+		assertEquals("check list", TWO, resultSet.getResults(2, 2).get(0));
+		assertEquals("check size", 1, resultSet.getResults(2, 2).size());
+	}
+
+	/**
+	 * test when indices are out of range, trailing stuff should be skipped.
+	 */
+	@Test
+	public void testGetResultOutOfRange() {
+		final List<String> list = new ArrayList<String>();
+		list.add(TWO);
+
+		when(dao.getSize(RS_ID)).thenReturn(2);
+		when(dao.getElements(RS_ID, 2, 2)).thenReturn(list);
+
+		assertEquals("check list", TWO, resultSet.getResults(2, 2 + 1).get(0));
+		assertEquals("check size", 1, resultSet.getResults(2, 2 + 1).size());
+	}
+
+	/**
+	 * open.
+	 */
+	@Test
+	public void testIsOpen() {
+		assertTrue("check is open by default", resultSet.isOpen());
+	}
+
+	/**
+	 * test close.
+	 */
+	@Test
+	public void testClose() {
+		resultSet.addObserver(registry);
+		assertEquals("observer should be added", 1, resultSet.countObservers());
+
+		resultSet.destroy();
+		assertTrue("should be destroyed", resultSet.isDestroyed());
+
+		assertEquals("observers should be cleared", 0, resultSet.countObservers());
+		verify(registry, times(1)).update(resultSet, null);
+	}
+
+	@Test
+	public void testFromAfterSize() {
+		final List<String> list = new ArrayList<String>();
+		list.add(TWO);
+
+		when(dao.getSize(RS_ID)).thenReturn(2);
+		when(dao.getElements(RS_ID, 2, 2)).thenReturn(list);
+
+		resultSet.getResults(3, 2);
+	}
+
+	@Test(expected = IllegalStateException.class)
+	public void testWriteClosed() {
+		resultSet.close();
+		resultSet.addElements(Lists.newArrayList("test"));
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSet.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSet.java	(revision 45117)
@@ -0,0 +1,22 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import java.util.List;
+
+import eu.dnetlib.enabling.resultset.ResultSet;
+
+/**
+ * resultset which receive data through the "push" interface, i.e. data is directly appended to it.
+ * 
+ * @author marko
+ *
+ */
+public interface PushResultSet extends ResultSet {
+
+	/**
+	 * add a list of elements at the end of the resultset.
+	 * 
+	 * @param elements list of elements
+	 */
+	void addElements(List<String> elements);
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetEPRPool.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetEPRPool.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetEPRPool.java	(revision 45117)
@@ -0,0 +1,137 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import javax.annotation.PostConstruct;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.enabling.tools.UniqueIdentifierGenerator;
+import eu.dnetlib.enabling.tools.UniqueIdentifierGeneratorImpl;
+
+public class ResultSetEPRPool {
+	private static final Log log = LogFactory.getLog(ResultSetEPRPool.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	static class PreparedResultSet {
+		private String rsId;
+		private W3CEndpointReference epr;
+
+		public PreparedResultSet(final String rsId, final W3CEndpointReference epr) {
+			super();
+			this.rsId = rsId;
+			this.epr = epr;
+		}
+
+		public String getRsId() {
+			return rsId;
+		}
+
+		public void setRsId(final String rsId) {
+			this.rsId = rsId;
+		}
+
+		public W3CEndpointReference getEpr() {
+			return epr;
+		}
+
+		public void setEpr(final W3CEndpointReference epr) {
+			this.epr = epr;
+		}
+	}
+
+	class PoolFiller implements Runnable {
+
+		@Override
+		public void run() {
+			while (true)
+				try {
+					final PreparedResultSet resultSet = prepareResultSet();
+					pool.put(resultSet);
+				} catch (final InterruptedException e) {
+					// eat this exception
+					log.debug("cannot add resultset to pool", e);
+				}
+		}
+
+		private PreparedResultSet prepareResultSet() {
+			final String rsId = idGenerator.generateIdentifier();
+			return new PreparedResultSet(rsId, createEPR(rsId));
+		}
+
+		private W3CEndpointReference createEPR(final String rsId) {
+			return getResultSetService().getEprBuilder().getEndpointReference(getResultSetService().getEndpoint(), rsId);
+		}
+	}
+
+	/**
+	 * resultset service.
+	 */
+	private ResultSetServiceImpl resultSetService;
+
+	private int capacity = 1000;
+	private int fillerThreads = 10;
+	private final BlockingQueue<PreparedResultSet> pool = new LinkedBlockingQueue<PreparedResultSet>(capacity);
+
+	/**
+	 * identifier generator.
+	 */
+	private UniqueIdentifierGenerator idGenerator = new UniqueIdentifierGeneratorImpl("rs-");
+
+	@PostConstruct
+	public void init() {
+		log.info("-------<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>> Starting fill threads");
+		for (int i = 0; i < fillerThreads; i++)
+			startFillter();
+	}
+
+	protected void startFillter() {
+		final Thread filler = new Thread(new PoolFiller());
+		filler.setDaemon(true);
+		filler.start();
+	}
+
+	public W3CEndpointReference registerResultSet(final ResultSet resultSet) {
+		final PreparedResultSet prepared = nextPreparedResultSet();
+		if (prepared == null) {
+			log.info("EPR cache is empty, creating EPR in caller thread");
+			return getResultSetService().getEprBuilder().getEndpointReference(getResultSetService().getEndpoint(), idGenerator.generateIdentifier());
+		}
+
+		getResultSetService().getResultsetRegistry().addResultSet(resultSet, prepared.getRsId());
+		return prepared.getEpr();
+	}
+
+	private PreparedResultSet nextPreparedResultSet() {
+		log.info(">>>> fetching a prepared resultset from the pool");
+		return pool.poll();
+	}
+
+	public int getCapacity() {
+		return capacity;
+	}
+
+	public void setCapacity(int capacity) {
+		this.capacity = capacity;
+	}
+
+	public UniqueIdentifierGenerator getIdGenerator() {
+		return idGenerator;
+	}
+
+	public void setIdGenerator(UniqueIdentifierGenerator idGenerator) {
+		this.idGenerator = idGenerator;
+	}
+
+	public ResultSetServiceImpl getResultSetService() {
+		return resultSetService;
+	}
+
+	@Required
+	public void setResultSetService(ResultSetServiceImpl resultSetService) {
+		this.resultSetService = resultSetService;
+	}
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSet.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSet.java	(revision 45117)
@@ -0,0 +1,57 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.enabling.tools.ServiceResolver;
+import eu.dnetlib.miscutils.collections.MappedCollection;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+public class ParallelMappedResultSet extends MappedResultSet {
+
+	private ExecutorService executor;
+
+	public ParallelMappedResultSet(final W3CEndpointReference source, final UnaryFunction<String, String> mapper, final ServiceResolver serviceResolver,
+			final ExecutorService executor) {
+		super(source, mapper, serviceResolver);
+		this.executor = executor;
+	}
+
+	@Override
+	public List<String> getResult(int fromPosition, int toPosition) {
+
+//		log.info("Parallel page " + (toPosition - fromPosition + 1));
+
+		List<Future<String>> results = Lists.newArrayList();
+
+		for (final String input : getResultFromSource(fromPosition, toPosition)) {
+			results.add(executor.submit(new Callable<String>() {
+				@Override
+				public String call() throws Exception {
+					return getMapper().evaluate(input);
+				}
+			}));
+		}
+
+		return MappedCollection.listMap(results, new UnaryFunction<String, Future<String>>() {
+			@Override
+			public String evaluate(Future<String> arg) {
+				try {
+					return arg.get();
+				} catch (InterruptedException e) {
+					throw new IllegalStateException(e);
+				} catch (ExecutionException e) {
+					throw new IllegalStateException(e);
+				}
+			}
+		});
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/LocalResultSetImplTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/LocalResultSetImplTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/LocalResultSetImplTest.java	(revision 45117)
@@ -0,0 +1,174 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.*; // NOPMD
+import static org.mockito.Mockito.*; // NOPMD by marko on 11/26/08 9:13 PM
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+/**
+ * test the resultset concrete implementation.
+ * 
+ * @author marko
+ * 
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class LocalResultSetImplTest {
+
+	/**
+	 * This class could be an anonymous class, but is here to be shared among tests.
+	 * 
+	 * @author marko
+	 * 
+	 */
+	private static final class TestResultSetListener implements ResultSetListener {
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see eu.dnetlib.enabling.resultset.ResultSetListener#getResult(int, int)
+		 */
+		@Override
+		public List<String> getResult(final int fromPosition, final int toPosition) {
+			final List<String> res = new ArrayList<String>();
+			for (int i = fromPosition; i <= toPosition; i++)
+				res.add(((Integer) (i - 1)).toString());
+			return res;
+		}
+
+		@Override
+		public int getSize() {
+			return RESULT_SIZE;
+		}
+	}
+
+	/**
+	 * Mockito lacks of multiple interfaces mocking.
+	 * 
+	 * @author marko
+	 * 
+	 */
+	private abstract static class AbstractResultSetAware implements ResultSetListener, ResultSetAware {
+	}
+
+	/**
+	 * resultset registry mock.
+	 */
+	@Mock
+	private transient ResultSetRegistry registry;
+
+	/**
+	 * object under test.
+	 */
+	private transient LocalResultSetImpl resultSet;
+
+	/**
+	 * number of returned test results.
+	 */
+	private static final int RESULT_SIZE = 3;
+
+	/**
+	 * provides data to the resultset under test.
+	 */
+	private transient TestResultSetListener resultSetListener;
+
+	/**
+	 * prepare.
+	 * 
+	 */
+	@Before
+	public void setUp() {
+		resultSetListener = new TestResultSetListener();
+		resultSet = new LocalResultSetImpl(resultSetListener);
+	}
+
+	/**
+	 * test the get number of results method.
+	 */
+	@Test
+	public void testGetNumberOfResults() {
+		assertEquals("check number of results", RESULT_SIZE, resultSet.getNumberOfResults());
+	}
+
+	/**
+	 * test the get result method.
+	 */
+	@Test
+	public void testGetResults() {
+		final List<String> res = resultSet.getResults(1, RESULT_SIZE); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("whole length", RESULT_SIZE, res.size());
+		for (int i = 0; i < RESULT_SIZE; i++)
+			assertEquals("check element", ((Integer) i).toString(), res.get(i));
+
+		final List<String> res2 = resultSet.getResults(1, RESULT_SIZE - 1); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("shorter", RESULT_SIZE - 1, res2.size());
+
+		final List<String> res3 = resultSet.getResults(1, RESULT_SIZE + 1); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("to out of bounds", RESULT_SIZE, res3.size());
+
+		final List<String> res4 = resultSet.getResults(RESULT_SIZE + 1, RESULT_SIZE); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("from out of bounds", 0, res4.size());
+		
+		final List<String> res5 = resultSet.getResults(0, RESULT_SIZE); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("from lesser than 1", RESULT_SIZE, res5.size());		
+
+		final List<String> res6 = resultSet.getResults(RESULT_SIZE, 1); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("inverted from and to", 1, res6.size());		
+		
+		resultSet.setOpen(true);
+		final List<String> res7 = resultSet.getResults(1, RESULT_SIZE + 1); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("to out of bounds - pass through", RESULT_SIZE + 1, res7.size());
+	}
+
+	/**
+	 * test observer/observable pattern.
+	 */
+	@Test
+	public void testDestroy() {
+		resultSet.addObserver(registry);
+		assertEquals("observer should be added", 1, resultSet.countObservers());
+
+		resultSet.destroy();
+		assertTrue("should be destroyed", resultSet.isDestroyed());
+
+		assertEquals("observers should be cleared", 0, resultSet.countObservers());
+		verify(registry, times(1)).update(resultSet, null);
+	}
+
+	/**
+	 * test getter ... let's make code coverage happy.
+	 */
+	@Test
+	public void testGetListener() {
+		assertEquals("test getter?", resultSetListener, resultSet.getListener());
+	}
+
+	/**
+	 * test setter ... let's make code coverage happy.
+	 */
+	@Test
+	public void testSetListener() {
+		assertEquals("test getter?", resultSetListener, resultSet.getListener());
+		resultSet.setListener(null);
+		assertNull("test setter?", resultSet.getListener());
+	}
+
+	/**
+	 * test.
+	 */
+	@Test
+	public void testResultSetAware() {
+		final AbstractResultSetAware abr = mock(AbstractResultSetAware.class);
+		resultSet = new LocalResultSetImpl(abr);
+		assertNotNull("dummy", resultSet);
+		
+		verify(abr).setResultSet((ResultSet) anyObject());
+		
+	}
+
+}

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/LocalResultSetImplTest.java
___________________________________________________________________
Added: svn:mergeinfo
## -0,0 +0,0 ##
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSet.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSet.java	(revision 45117)
@@ -0,0 +1,60 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.enabling.tools.ServiceResolver;
+import eu.dnetlib.miscutils.functional.IdentityFunction;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+/**
+ * A resultset record counter.
+ * 
+ * @author claudio
+ * 
+ */
+public class CountingResultSet extends MappedResultSet {
+
+	/**
+	 * counter.
+	 */
+	private int count;
+
+
+	/**
+	 * @param epr
+	 * @param serviceResolver
+	 */
+	public CountingResultSet(final W3CEndpointReference epr, final ServiceResolver serviceResolver) {
+		this(epr, new IdentityFunction<String>(), serviceResolver);
+	}
+
+	/**
+	 * @param epr
+	 * @param mapper
+	 * @param serviceResolver
+	 */
+	public CountingResultSet(final W3CEndpointReference epr, final UnaryFunction<String, String> mapper, final ServiceResolver serviceResolver) {
+		super(epr, mapper, serviceResolver);
+		count = 0;
+	}
+
+	/**
+	 * method sets the counter to the higher allowed value of toPosition.
+	 */
+	@Override
+	public List<String> getResult(int fromPosition, int toPosition) {
+
+		if (toPosition > count)
+			count = toPosition;
+		if (toPosition > super.getSize())
+			count = super.getSize();
+
+		return super.getResult(fromPosition, toPosition);
+	}
+
+	public int getCount() {
+		return count;
+	}
+}

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSet.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/MappedResultSetTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/MappedResultSetTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/MappedResultSetTest.java	(revision 45117)
@@ -0,0 +1,137 @@
+package eu.dnetlib.enabling.resultset; // NOPMD
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.runners.MockitoJUnit44Runner;
+import org.mockito.stubbing.Answer;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
+import eu.dnetlib.enabling.tools.ServiceResolver;
+import eu.dnetlib.miscutils.factory.Factory;
+import eu.dnetlib.miscutils.functional.ThreadSafeUnaryFunction;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+/**
+ * test xslt resultset.
+ *
+ * @author marko
+ *
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class MappedResultSetTest {
+
+	/**
+	 * instance under test.
+	 */
+	private transient MappedResultSet mappedResultSet;
+
+	/**
+	 * service resolver.
+	 */
+	@Mock
+	private transient ServiceResolver serviceResolver;
+
+	/**
+	 * resultset service mock.
+	 */
+	@Mock
+	private transient ResultSetService resultSetService;
+	
+	/**
+	 * resultset mock.
+	 */
+	@Mock
+	private transient ResultSet resultSet;	
+
+	private Answer<Object> resultSetAnswer = new Answer<Object>() {
+
+		private List<String> list = Lists.newArrayList("1","2","3","4","5","6","7","8","9","10");
+		
+		@Override
+		public Object answer(InvocationOnMock invocation) throws Throwable {
+			String method = invocation.getMethod().getName();
+			if (method.equals("getResult") || method.equals("getResults")) {
+				int from = (Integer) invocation.getArguments()[1];
+				int to = (Integer) invocation.getArguments()[2];
+				
+				return list.subList(from-1, to);
+			}
+			if (method.equals("getNumberOfElements") || method.equals("getNumberOfResults")) {
+				return list.size();
+			}
+			if (method.equals("getRSStatus")) {
+				return "closed";
+			}
+			if (method.equals("isOpen")) {
+				return false;
+			}			
+			System.out.println(invocation.toString());
+			return null;
+		}		
+	};
+
+	/**
+	 * Common setup.
+	 * @throws ResultSetException 
+	 *
+	 */
+	@Before
+	public void setUp() throws ResultSetException {
+		
+		when(serviceResolver.getService(eq(ResultSetService.class), (W3CEndpointReference) anyObject())).thenReturn(resultSetService);
+		when(serviceResolver.getResourceIdentifier((W3CEndpointReference) anyObject())).thenReturn("123");
+
+		when(resultSetService.getNumberOfElements(anyString())).thenAnswer(resultSetAnswer);
+		when(resultSetService.getResult(anyString(), anyInt(), anyInt(), anyString())).thenAnswer(resultSetAnswer );
+		when(resultSetService.getRSStatus(anyString())).thenAnswer(resultSetAnswer);
+		
+		when(resultSet.getNumberOfResults()).thenAnswer(resultSetAnswer);
+		when(resultSet.getResults(anyInt(), anyInt())).thenAnswer(resultSetAnswer );
+		when(resultSet.isOpen()).thenAnswer(resultSetAnswer);		
+	}
+	
+	@Test
+	public void testThreadSafeMappedResultSet_1() {
+		
+		final Factory<UnaryFunction<String, String>> functionFactory = new Factory<UnaryFunction<String,String>>() {
+			@Override
+			public UnaryFunction<String, String> newInstance() {
+				return new UnaryFunction<String, String>() {
+					@Override
+					public String evaluate(String arg) {
+						return "mapped-" + arg;
+					}
+				};
+			}
+		}; 
+		mappedResultSet = new MappedResultSet(null, new ThreadSafeUnaryFunction<String, String>(functionFactory), serviceResolver);
+		mappedResultSet.setResultSet(resultSet);
+
+		for (String s : mappedResultSet.getResult(1, 10)) {
+			assertNotNull("null result", s);
+			assertFalse("empty result", s.isEmpty());
+			assertNotNull("null element", s);
+			assertTrue("transformed correctly", s.startsWith("mapped-"));	
+		}
+	}
+}
+

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/MappedResultSetTest.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/ResultSetServiceImplTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/ResultSetServiceImplTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/src/test/java/eu/dnetlib/enabling/resultset/ResultSetServiceImplTest.java	(revision 45117)
@@ -0,0 +1,101 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.*; // NOPMD
+import static org.mockito.Mockito.*; // NOPMD
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+
+/**
+ * resultset service rmi implementation test.
+ *  
+ * @author marko
+ *
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class ResultSetServiceImplTest {
+
+	/**
+	 * mock resultset id.
+	 */
+	private static final String RS_ID = "123";
+
+	/**
+	 * instance under test.
+	 */
+	private transient ResultSetServiceImpl service;
+	
+	/**
+	 * custom property dao mock.
+	 */
+	@Mock
+	private transient ResultSetPropertyDao customPropertyDao;
+	
+	/**
+	 * resultset registry mock. 
+	 */
+	@Mock
+	private transient ResultSetRegistry resultsetRegistry;
+	
+	/**
+	 * resultset instance mock. 
+	 */
+	@Mock
+	private transient ResultSet resultSet;
+	
+	/**
+	 * setup. 
+	 */
+	@Before
+	public void setUp() {
+		service = new ResultSetServiceImpl();
+		service.setCustomPropertyDao(customPropertyDao);
+		service.setResultsetRegistry(resultsetRegistry);
+		
+		when(resultsetRegistry.getResultSetById(RS_ID)).thenReturn(resultSet);
+		when(resultSet.getIdentifier()).thenReturn(RS_ID);
+	}
+
+	/**
+	 * test get property.
+	 * @throws ResultSetException shouldn't happen
+	 */
+	@Test
+	public void testGetProperty() throws ResultSetException {
+		final Map<String, String> properties = new HashMap<String, String>();
+		properties.put("prefetch", "true");
+		
+		when(customPropertyDao.getProperties(resultSet)).thenReturn(properties);
+		when(resultSet.getNumberOfResults()).thenReturn(1);
+		
+		assertEquals("test builtin", "1", service.getProperty(RS_ID, "total"));
+		assertEquals("test builtin", RS_ID, service.getProperty(RS_ID, "rsId"));
+		
+		assertEquals("test custom", "true", service.getProperty(RS_ID, "prefetch"));
+		assertNull("test custom", service.getProperty(RS_ID, "unexistent"));
+	}
+
+	/**
+	 * get resultset status.
+	 * 
+	 * @throws ResultSetException shouldn't happen
+	 */
+	@Test
+	public void testGetRSStatus() throws ResultSetException {
+		when(resultSet.isOpen()).thenReturn(true);
+		
+		assertEquals("check open", service.getRSStatus(RS_ID), "open");
+		
+		when(resultSet.isOpen()).thenReturn(false);
+		assertEquals("check closed", service.getRSStatus(RS_ID), "closed");
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/deploy.info
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/deploy.info	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2/deploy.info	(revision 45117)
@@ -0,0 +1 @@
+{"type_source": "SVN", "goal": "package -U -T 4C source:jar", "url": "http://svn-public.driver.research-infrastructures.eu/driver/dnet40/modules/cnr-resultset-service/trunk/", "deploy_repository": "dnet4-snapshots", "version": "4", "mail": "sandro.labruzzo@isti.cnr.it,michele.artini@isti.cnr.it, claudio.atzori@isti.cnr.it, alessia.bardi@isti.cnr.it", "deploy_repository_url": "http://maven.research-infrastructures.eu/nexus/content/repositories/dnet4-snapshots", "name": "cnr-resultset-service"}
\ No newline at end of file
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2	(revision 45117)

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.2
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,5 ##
+.project
+.classpath
+.settings
+target
+
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/FetchListTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/FetchListTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/FetchListTest.java	(revision 45117)
@@ -0,0 +1,75 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+@RunWith(MockitoJUnit44Runner.class)
+public class FetchListTest {
+	
+	/**
+	 * object to test
+	 */
+	private FetchList<String> fetchList;
+	
+	private List<String> list;
+	private Iterator<String> iter;
+	
+	private int FETCH_SIZE = 10;
+	
+	private int TOTAL_ELEMENTS = 100;
+
+	@Before
+	public void setUp() throws Exception {
+		list = new ArrayList<String>();
+		for (int i = 0; i < TOTAL_ELEMENTS; i++) {
+			list.add("XXX" + i);
+		}
+		this.iter = list.iterator();
+		fetchList = new FetchList<String>(iter, FETCH_SIZE);
+		
+	}
+
+	@Test
+	public void testFetchList() {
+		assertNotNull(fetchList);
+	}
+
+	@Test
+	public void testPoll_consumedElements() {
+		assertEquals(0, fetchList.getConsumedElements());
+		fetchList.poll();
+		assertEquals(1, fetchList.getConsumedElements());
+	}
+	
+	@Test
+	public void testFill_totalElements() {
+		assertEquals(FETCH_SIZE, fetchList.getTotalElements());
+	}
+	
+	@Test
+	public void testPoll() {
+		for (int i = 0; i < TOTAL_ELEMENTS; i++) {
+			assertEquals(i, fetchList.getConsumedElements());
+			assertEquals(list.get(i), fetchList.poll());
+		}
+		assertEquals(TOTAL_ELEMENTS, fetchList.getConsumedElements());
+		assertEquals(TOTAL_ELEMENTS, fetchList.getTotalElements());
+	}
+	
+	@Test
+	public void testPoll_null() {
+		for (int i = 0; i < TOTAL_ELEMENTS; i++) {
+			fetchList.poll();
+		}
+		assertNull(fetchList.poll());
+		assertNull(fetchList.poll());
+		assertNull(fetchList.poll());
+	}
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetFactory.java	(revision 45117)
@@ -0,0 +1,46 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.annotation.Resource;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.enabling.tools.ServiceResolver;
+
+public class CachingResultSetFactory {
+	/**
+	 * underlying resultset factory, which exposes local resultsets to the world.
+	 */
+	private ResultSetFactory resultSetFactory;
+
+	@Resource
+	private ServiceResolver serviceResolver;
+	
+	/**
+	 * @param items
+	 * @param size
+	 *            the size of the iterable
+	 * @return
+	 */
+	public W3CEndpointReference createCachingResultSet(W3CEndpointReference epr) {
+		return resultSetFactory.createResultSet(new CachingResultSetListener(epr, serviceResolver));
+	}
+
+	public ResultSetFactory getResultSetFactory() {
+		return resultSetFactory;
+	}
+
+	@Required
+	public void setResultSetFactory(ResultSetFactory resultSetFactory) {
+		this.resultSetFactory = resultSetFactory;
+	}
+
+	public ServiceResolver getServiceResolver() {
+		return serviceResolver;
+	}
+
+	public void setServiceResolver(ServiceResolver serviceResolver) {
+		this.serviceResolver = serviceResolver;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/resources/log4j.properties
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/resources/log4j.properties	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/resources/log4j.properties	(revision 45117)
@@ -0,0 +1,29 @@
+org.apache.cxf.Logger=org.apache.cxf.common.logging.Log4jLogger
+
+log4j.rootLogger=WARN, CONSOLE
+log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
+log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
+log4j.appender.CONSOLE.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
+
+log4j.logger.eu.dnetlib=INFO
+log4j.logger.eu.dnetlib.enabling.is.sn=INFO
+#log4j.logger.org.apache.cxf.interceptor=FATAL
+log4j.logger.org.apache.cxf.ws.addressing.ContextUtils=FATAL
+log4j.logger.eu.dnetlib.enabling.tools.AbstractBaseService=INFO
+log4j.logger.eu.dnetlib.enabling.inspector=DEBUG
+log4j.logger.eu.dnetlib.xml.database.LoggingTrigger=FATAL
+#log4j.logger.eu.dnetlib.enabling.tools.registration=DEBUG
+log4j.logger.eu.dnetlib.enabling.tools.registration.ServiceRegistrator=INFO
+log4j.logger.eu.dnetlib.enabling.inspector=FATAL
+log4j.logger.eu.dnetlib.enabling.resultset=DEBUG
+log4j.logger.eu.dnetlib.enabling.inspector.SubscriptionController=DEBUG
+log4j.logger.eu.dnetlib.springutils.stringtemplate.StringTemplateViewResolver=FATAL
+log4j.logger.eu.dnetlib.enabling.is.sn.SynchronousNotificationSenderImpl=WARN
+
+log4j.logger.eu.dnetlib.enabling.manager.msro.wf.RefreshIndexJob=DEBUG
+log4j.logger.eu.dnetlib.enabling.ui=DEBUG
+log4j.logger.eu.dnetlib.enabling.manager.msro.wf.RefreshIndexJob=DEBUG
+
+log4j.logger.org.apache.zookeeper.ClientCnxn=FATAL
+
+log4j.logger.eu.dnetlib.enabling.resultset.push=DEBUG
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetFactory.java	(revision 45117)
@@ -0,0 +1,32 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+public class StreamingResultSetFactory {
+	/**
+	 * underlying resultset factory, which exposes local resultsets to the world.
+	 */
+	private ResultSetFactory resultSetFactory;
+
+	/**
+	 * @param items
+	 * @param size the size of the iterable
+	 * @return
+	 */
+	public W3CEndpointReference createStreamingResultSet(final Iterable<String> items, int size) {
+		return resultSetFactory.createResultSet(new StreamingResultSetListener(items.iterator(), size));
+	}
+
+	
+	public ResultSetFactory getResultSetFactory() {
+		return resultSetFactory;
+	}
+
+	@Required
+	public void setResultSetFactory(ResultSetFactory resultSetFactory) {
+		this.resultSetFactory = resultSetFactory;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactory.java	(revision 45117)
@@ -0,0 +1,75 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.Map;
+import java.util.UUID;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.core.io.Resource;
+
+import eu.dnetlib.miscutils.functional.xml.ApplyXslt;
+
+/**
+ * Create a mapped resultset using a given XSLT.
+ * 
+ * @author marko
+ * 
+ */
+public class XSLTMappedResultSetFactory extends MappedResultSetFactory {
+
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final String xslt) {
+		return createMappedResultSet(source, new ApplyXslt(xslt));
+	}
+
+	/**
+	 * Create a mapped resultset using a given XSLT.
+	 * 
+	 * @param source
+	 *            source
+	 * @param xslt
+	 *            XSLT source
+	 * @return epr of mapped resultset
+	 * @throws TransformerConfigurationException
+	 *             could happen
+	 */
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final String xslt, final String name)
+			throws TransformerConfigurationException {
+		return createMappedResultSet(source, new ApplyXslt(xslt, name));
+	}
+
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final Resource xslt) {
+		return createMappedResultSet(source, new ApplyXslt(xslt));
+	}
+
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final Source xslt) {
+		return createMappedResultSet(source, new ApplyXslt(xslt));
+	}
+	
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final Resource xslt, final Map<String, String> parameters) {
+		return createMappedResultSet(source, new ApplyXslt(xslt, parameters));
+	}
+	
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final String xslt, final Map<String, String> parameters) {
+		return createMappedResultSet(source, new ApplyXslt(xslt, "rs-" + UUID.randomUUID(), parameters));
+	}
+
+	/**
+	 * Create a mapped resultset using a given XSLT.
+	 * 
+	 * @param source
+	 *            source
+	 * @param xslt
+	 *            XSLT
+	 * @return epr of mapped resultset
+	 * @throws TransformerFactoryConfigurationError
+	 * @throws TransformerConfigurationException
+	 *             could happen
+	 */
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final Source xslt, final String name) {
+		return createMappedResultSet(source, new ApplyXslt(xslt, name));
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetListener.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetListener.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetListener.java	(revision 45117)
@@ -0,0 +1,61 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
+import eu.dnetlib.enabling.tools.ServiceResolver;
+
+public class CachingResultSetListener implements ResultSetListener {
+	private static final Log log = LogFactory.getLog(CachingResultSetListener.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	
+	private ResultSetService service;
+	private String rsId;
+
+	private ArrayList<String> storage = new ArrayList<String>();
+
+	public CachingResultSetListener(W3CEndpointReference epr, ServiceResolver serviceResolver) {
+		this.service = serviceResolver.getService(ResultSetService.class, epr);
+		this.rsId = serviceResolver.getResourceIdentifier(epr);
+	}
+
+	@Override
+	public List<String> getResult(int fromPosition, int toPosition) {
+		if (storage.get(fromPosition) != null)
+			return cached(fromPosition, toPosition);
+		try {
+			List<String> data = service.getResult(rsId, fromPosition, toPosition, "waiting");
+			cache(data, fromPosition, toPosition);
+			return data;
+		} catch (ResultSetException e) {
+			throw new IllegalStateException(e);
+		}
+	}
+
+	private void cache(List<String> data, int fromPosition, int toPosition) {
+		for(String value : data)
+			storage.set(fromPosition++, value);
+	}
+
+	private List<String> cached(int fromPosition, int toPosition) {
+		log.info("found cached page " + fromPosition + ", " + toPosition);
+		return storage.subList(fromPosition-1, toPosition);
+	}
+
+	@Override
+	public int getSize() {
+		try {
+			return service.getNumberOfElements(rsId);
+		} catch (ResultSetException e) {
+			throw new IllegalStateException(e);
+		}
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/SizedIterable.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/SizedIterable.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/SizedIterable.java	(revision 45117)
@@ -0,0 +1,7 @@
+package eu.dnetlib.enabling.resultset;
+
+public interface SizedIterable<T> extends Iterable<T> {
+
+	public int getNumberOfElements();
+	
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/AbstractResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/AbstractResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/AbstractResultSetFactory.java	(revision 45117)
@@ -0,0 +1,38 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * Resultset factories bound to a resultset service, from which it takes the resultset registry and the epr builder.
+ *
+ * @author marko
+ *
+ */
+public abstract class AbstractResultSetFactory implements ResultSetFactory {
+
+	/**
+	 * resultset service.
+	 */
+	private ResultSetServiceImpl resultSetService;
+
+	/**
+	 * Register a resultset instance to the underlying resultset registry and returns
+	 * and EPR to accessible through the resultset service.
+	 *
+	 * @param resultSet resultset instance
+	 * @return epr to the newly created resultset
+	 */
+	public W3CEndpointReference registerResultSet(final ResultSet resultSet) {
+		resultSetService.getResultsetRegistry().addResultSet(resultSet);
+		return resultSetService.getEprBuilder().getEndpointReference(resultSetService.getEndpoint(), resultSet.getIdentifier());
+	}
+
+	public ResultSetServiceImpl getResultSetService() {
+		return resultSetService;
+	}
+
+	public void setResultSetService(final ResultSetServiceImpl resultSetService) {
+		this.resultSetService = resultSetService;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSetFactory.java	(revision 45117)
@@ -0,0 +1,53 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.enabling.tools.ServiceResolver;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+/**
+ * Create a new resultset which takes each record of the input resultset and applies the mapping function to it.
+ *
+ * @author marko
+ *
+ */
+public class MappedResultSetFactory {
+
+	/**
+	 * underlying resultset factory, which exposes local resultsets to the world.
+	 */
+	private ResultSetFactory resultSetFactory;
+
+	/**
+	 * service resolver, transforms eprs to services.
+	 */
+	private ServiceResolver serviceResolver;
+
+	/**
+	 * Create a new resultset which takes each record of the input resultset and applies the mapping function to it.
+	 *
+	 * @param source source resultset epr
+	 * @param mapper mapper function
+	 * @return mapped resultset epr
+	 */
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final UnaryFunction<String, String> mapper) {
+		return resultSetFactory.createResultSet(new MappedResultSet(source, mapper, serviceResolver));
+	}
+
+	public ResultSetFactory getResultSetFactory() {
+		return resultSetFactory;
+	}
+
+	public void setResultSetFactory(final ResultSetFactory resultSetFactory) {
+		this.resultSetFactory = resultSetFactory;
+	}
+
+	public ServiceResolver getServiceResolver() {
+		return serviceResolver;
+	}
+
+	public void setServiceResolver(final ServiceResolver serviceResolver) {
+		this.serviceResolver = serviceResolver;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDao.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDao.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDao.java	(revision 45117)
@@ -0,0 +1,19 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.Map;
+
+/**
+ * access resultset properties.
+ * 
+ * @author marko
+ *
+ */
+public interface ResultSetPropertyDao {
+	/**
+	 * return a map of custom resultset properties.
+	 * 
+	 * @param resultSet resultset
+	 * @return property map
+	 */
+	Map<String, String> getProperties(ResultSet resultSet);
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetServiceImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetServiceImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSetServiceImpl.java	(revision 45117)
@@ -0,0 +1,258 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import javax.jws.WebService;
+import javax.xml.ws.Endpoint;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.common.rmi.UnimplementedException;
+import eu.dnetlib.enabling.resultset.push.PushResultSet;
+import eu.dnetlib.enabling.resultset.push.PushResultSetFactory;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
+import eu.dnetlib.enabling.tools.AbstractBaseService;
+import eu.dnetlib.soap.EndpointReferenceBuilder;
+
+/**
+ * This component dispatches the service method calls to stateful datastructure instances and to the singleton core.
+ * 
+ * @author marko
+ * 
+ */
+@WebService(targetNamespace = "http://services.dnetlib.eu/")
+public class ResultSetServiceImpl extends AbstractBaseService implements ResultSetService {
+
+	/**
+	 * logger.
+	 */
+	private static final Log log = LogFactory.getLog(ResultSetServiceImpl.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	/**
+	 * Maps resultset identifiers to resultsets and manages expiration etc.
+	 */
+	private ResultSetRegistry resultsetRegistry;
+
+	/**
+	 * push resultset factory.
+	 */
+	private PushResultSetFactory pushFactory;
+
+	/**
+	 * Service endpoint.
+	 */
+	private Endpoint endpoint;
+
+	/**
+	 * injected epr builder.
+	 */
+	private EndpointReferenceBuilder<Endpoint> eprBuilder;
+
+	/**
+	 * custom resultset properties.
+	 */
+	private ResultSetPropertyDao customPropertyDao;
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#closeRS(java.lang.String)
+	 */
+	@Override
+	public void closeRS(final String rsId) {
+		try {
+			final ResultSet resultSet = getResultSetById(rsId);
+			resultSet.close();
+		} catch (ResultSetException e) {
+			log.warn("should throw checked exception but wasn't declared in cnr-rmi-api", e);
+			throw new IllegalStateException(e);
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#createPullRS(java.lang.String, java.lang.String, int, int, java.lang.String,
+	 *      java.lang.Integer, java.lang.Integer)
+	 */
+	@Override
+	public W3CEndpointReference createPullRS(final String providerAddress,
+			final String bdId,
+			final int initialPageSize,
+			final int expiryTime,
+			final String styleSheet,
+			final Integer keepAliveTime,
+			final Integer total) {
+		throw new UnimplementedException();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#createPullRSEPR(javax.xml.ws.wsaddressing.W3CEndpointReference,
+	 *      java.lang.String, int, int, java.lang.String, java.lang.Integer, java.lang.Integer)
+	 */
+	@Override
+	public W3CEndpointReference createPullRSEPR(final W3CEndpointReference dataProviderEPR,
+			final String bdId,
+			final int initialPageSize,
+			final int expiryTime,
+			final String styleSheet,
+			final Integer keepAliveTime,
+			final Integer total) {
+		throw new UnimplementedException();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#getNumberOfElements(java.lang.String)
+	 */
+	@Override
+	public int getNumberOfElements(final String rsId) throws ResultSetException {
+		final ResultSet resultSet = getResultSetById(rsId); // NOPMD
+		return resultSet.getNumberOfResults();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#getResult(java.lang.String, int, int, java.lang.String)
+	 */
+	@Override
+	public List<String> getResult(final String rsId, final int fromPosition, final int toPosition, final String requestMode) throws ResultSetException {
+		final ResultSet resultSet = getResultSetById(rsId); // NOPMD
+		return resultSet.getResults(fromPosition, toPosition);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#createPushRS(int, int)
+	 */
+	@Override
+	public W3CEndpointReference createPushRS(final int expiryTime, final int keepAliveTime) throws ResultSetException {
+		return pushFactory.createPushResultSet(expiryTime);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#getProperty(java.lang.String, java.lang.String)
+	 */
+	@Override
+	public String getProperty(final String rsId, final String name) throws ResultSetException {
+		final ResultSet resultSet = getResultSetById(rsId); // NOPMD
+
+		if ("rsId".equals(name)) return resultSet.getIdentifier();
+		else if ("total".equals(name)) return Integer.toString(resultSet.getNumberOfResults());
+		else if ("maxExpiryTime".equals(name)) return Integer.toString(resultsetRegistry.getMaxIdleTimeById(rsId));
+		else if ("expiryTime".equals(name)) return Integer.toString(resultsetRegistry.getMaxIdleTimeById(rsId));
+		else if ("keepAliveTime".equals(name)) return Integer.toString(resultsetRegistry.getMaxIdleTimeById(rsId));
+		// ...
+
+		return customPropertyDao.getProperties(resultSet).get(name);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#getRSStatus(java.lang.String)
+	 */
+	@Override
+	public String getRSStatus(final String rsId) throws ResultSetException {
+		final ResultSet resultSet = getResultSetById(rsId); // NOPMD
+		if (resultSet.isOpen()) return "open";
+		return "closed";
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#populateRS(java.lang.String, java.util.List)
+	 */
+	@Override
+	public String populateRS(final String rsId, final List<String> elements) throws ResultSetException {
+		final ResultSet resultSet = getResultSetById(rsId); // NOPMD
+		if (resultSet instanceof PushResultSet) {
+			((PushResultSet) resultSet).addElements(elements);
+		} else throw new ResultSetException("ResultSet '" + rsId + "' is not a push resultset");
+
+		return "1";
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.common.rmi.BaseService#start()
+	 */
+	@Override
+	public void start() {
+		// TODO Auto-generated method stub
+
+	}
+
+	/**
+	 * obtain the resultset object for a given id.
+	 * 
+	 * @param rsId
+	 *            resultset id
+	 * @return resultset object, never null
+	 * @throws ResultSetException
+	 *             thrown when the id doesn't exist;
+	 */
+	private ResultSet getResultSetById(final String rsId) throws ResultSetException {
+		final ResultSet resultSet = resultsetRegistry.getResultSetById(rsId); // NOPMD
+		if (resultSet == null) throw new ResultSetException("resultset with id '" + rsId + "' doesn't exist");
+		return resultSet;
+	}
+
+	public ResultSetRegistry getResultsetRegistry() {
+		return resultsetRegistry;
+	}
+
+	@Required
+	public void setResultsetRegistry(final ResultSetRegistry resultsetRegistry) {
+		this.resultsetRegistry = resultsetRegistry;
+	}
+
+	public EndpointReferenceBuilder<Endpoint> getEprBuilder() {
+		return eprBuilder;
+	}
+
+	@Required
+	public void setEprBuilder(final EndpointReferenceBuilder<Endpoint> eprBuilder) {
+		this.eprBuilder = eprBuilder;
+	}
+
+	public Endpoint getEndpoint() {
+		return endpoint;
+	}
+
+	@Required
+	public void setEndpoint(final Endpoint endpoint) {
+		this.endpoint = endpoint;
+	}
+
+	public PushResultSetFactory getPushFactory() {
+		return pushFactory;
+	}
+
+	@Required
+	public void setPushFactory(final PushResultSetFactory pushFactory) {
+		this.pushFactory = pushFactory;
+	}
+
+	public ResultSetPropertyDao getCustomPropertyDao() {
+		return customPropertyDao;
+	}
+
+	public void setCustomPropertyDao(final ResultSetPropertyDao customPropertyDao) {
+		this.customPropertyDao = customPropertyDao;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/observer/DelegationObserver.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/observer/DelegationObserver.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/observer/DelegationObserver.java	(revision 45117)
@@ -0,0 +1,29 @@
+package eu.dnetlib.enabling.resultset.observer;
+
+import eu.dnetlib.enabling.resultset.ResultSet;
+import eu.dnetlib.enabling.resultset.ResultSetRegistry;
+
+/**
+ * This class delegates an observation event from the java.util.Observable producer to the real consumer which is not a
+ * java.util.Observer (as expected by java.util.Observable) but instead a miscutils Observer.
+ * 
+ * @author marko, claudio, alessia, michele
+ * 
+ */
+public class DelegationObserver implements java.util.Observer {
+	/**
+	 * 
+	 */
+	private transient final ResultSet observable;
+	private transient final ResultSetRegistry observer;
+
+	public DelegationObserver(final ResultSet observable, final ResultSetRegistry observer) {
+		this.observable = observable;
+		this.observer = observer;
+	}
+
+	@Override
+	public void update(final java.util.Observable ignored, final Object arg) {
+		observer.update(observable, arg);
+	}
+}
\ No newline at end of file

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/observer/DelegationObserver.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/observer/Observable.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/observer/Observable.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/observer/Observable.java	(revision 45117)
@@ -0,0 +1,18 @@
+package eu.dnetlib.enabling.resultset.observer;
+
+import eu.dnetlib.enabling.resultset.ResultSetRegistry;
+
+/**
+ * Declares the JDK-like standard observable pattern as a java interface.
+ * 
+ * @author marko, claudio, alessia, michele
+ */
+public interface Observable {
+	/**
+	 * add a given observer to this object.
+	 * 
+	 * @param observer
+	 *            observer
+	 */
+	void addObserver(ResultSetRegistry observer);
+}

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/observer/Observable.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.xml
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.xml	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.xml	(revision 45117)
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
+	xmlns:sec="http://cxf.apache.org/configuration/security" xmlns:wsa="http://cxf.apache.org/ws/addressing"
+	xmlns:p="http://www.springframework.org/schema/p" xmlns:http="http://cxf.apache.org/transports/http/configuration"
+	xmlns:t="http://dnetlib.eu/springbeans/t" xmlns:template="http://dnetlib.eu/springbeans/template"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+                                    http://cxf.apache.org/ws/addressing http://cxf.apache.org/schemas/ws-addr-conf.xsd
+                                    http://cxf.apache.org/configuration/security http://cxf.apache.org/schemas/configuration/security.xsd
+                                    http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd
+                            http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
+                            http://dnetlib.eu/springbeans/template http://dnetlib.eu/springbeans/template.xsd">
+
+	<!-- beans -->
+	<bean id="resultSetCacheManager"
+		class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" />
+	<!-- p:configLocation="classpath:eu/dnetlib/enabling/resultset/ehcache.xml" -->
+
+	<bean id="resultSetRegistryCache" class="eu.dnetlib.miscutils.cache.EhCache">
+		<property name="cache">
+			<bean id="resultSetRegistryCacheCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"
+				p:cacheManager-ref="resultSetCacheManager" p:cacheName="resultSetFactoryCache"
+				p:eternal="false" p:timeToLive="0"
+				p:timeToIdle="${services.is.resultset.resultSetRegistryCache.timeToIdle}" />
+		</property>
+	</bean>
+
+	<bean id="resultSetRegistryMaxIdleTimeCache" class="eu.dnetlib.miscutils.cache.EhCache">
+		<property name="cache">
+			<bean id="resultSetRegistryMaxIdleTimeCacheCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"
+				p:cacheManager-ref="resultSetCacheManager" p:cacheName="resultSetFactoryMaxIdleTimeCache"
+				p:eternal="false" p:timeToLive="0"
+				p:timeToIdle="${services.is.resultset.resultSetRegistryMaxIdleTimeCache.timeToIdle}" />
+		</property>
+	</bean>
+
+	<!-- backing store for the pushResultSetDao -->
+	<bean id="pushResultSetStoreCache" class="eu.dnetlib.miscutils.cache.EhCache">
+		<property name="cache">
+			<bean id="pushResultSetStoreCacheCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"
+				p:eternal="false" p:timeToLive="0" p:timeToIdle="36000"
+				p:maxElementsInMemory="100" p:maxElementsOnDisk="20000"
+				p:cacheManager-ref="resultSetCacheManager" p:cacheName="pushResultSetStoreCache" />
+		</property>
+	</bean>
+
+	<!-- resultset descriptor store for the pushResultSetDao -->
+	<bean id="pushResultSetDescriptorCache" class="eu.dnetlib.miscutils.cache.EhCache">
+		<property name="cache">
+			<bean id="pushResultSetDescriptorCacheCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"
+				p:eternal="false" p:timeToLive="0" p:timeToIdle="1800"
+				p:cacheManager-ref="resultSetCacheManager" p:cacheName="pushResultSetDescriptorCache" />
+		</property>
+	</bean>
+
+	<bean id="resultSetDescriptorFactory" class="eu.dnetlib.springutils.beans.factory.PrototypeFactory">
+		<lookup-method name="newInstance" bean="resultSetDescriptorPrototype" />
+	</bean>
+
+	<bean id="resultSetDescriptorPrototype" class="eu.dnetlib.enabling.resultset.push.ResultSetDescriptor"
+		p:rangeLength="100" scope="prototype" />
+
+	<bean id="resultSetRegistry" class="eu.dnetlib.enabling.resultset.ResultSetRegistryImpl"
+		p:cache-ref="resultSetRegistryCache" p:maxIdleTimeCache-ref="resultSetRegistryMaxIdleTimeCache" />
+
+<!--
+  <bean id="resultSetEPRPool" class="eu.dnetlib.enabling.resultset.ResultSetEPRPool"
+   p:resultSetService-ref="resultSetService" />
+-->
+
+	<!-- <bean id="resultSetFactory" class="eu.dnetlib.enabling.resultset.LocalResultSetFactoryImpl" -->
+	<!-- <bean id="resultSetFactory" class="eu.dnetlib.enabling.resultset.EPRPoolingLocalResultSetFactoryImpl" p:pool-ref="resultSetEPRPool" 
+		p:resultSetService-ref="resultSetService" /> -->
+
+  <bean id="resultSetFactory" class="eu.dnetlib.enabling.resultset.LocalResultSetFactoryImpl" 
+		p:resultSetService-ref="resultSetService" /> 
+
+	<bean id="openResultSetFactory"
+		class="eu.dnetlib.enabling.resultset.LocalOpenResultSetFactoryImpl"
+		p:resultSetService-ref="resultSetService" />
+		
+<!--
+	<bean id="openResultSetFactory"
+		class="eu.dnetlib.enabling.resultset.EPRPoolingLocalOpenResultSetFactoryImpl" p:pool-ref="resultSetEPRPool"
+		p:resultSetService-ref="resultSetService" />
+-->
+	<bean id="mappedResultSetFactory" class="eu.dnetlib.enabling.resultset.MappedResultSetFactory"
+		p:serviceResolver-ref="serviceResolver" p:resultSetFactory-ref="resultSetFactory" />
+		
+	<bean id="parallelMappedResultSetFactory" class="eu.dnetlib.enabling.resultset.ParallelMappedResultSetFactory"
+		p:serviceResolver-ref="serviceResolver" p:resultSetFactory-ref="resultSetFactory" />		
+
+	<bean id="xsltResultSetFactory"
+		class="eu.dnetlib.enabling.resultset.XSLTMappedResultSetFactory"
+		p:serviceResolver-ref="serviceResolver" p:resultSetFactory-ref="resultSetFactory" />
+
+	<bean id="countingResultSetFactory" class="eu.dnetlib.enabling.resultset.CountingResultSetFactory"
+		p:serviceResolver-ref="serviceResolver" p:resultSetFactory-ref="resultSetFactory" />
+
+	<bean id="streamingResultSetFactory" class="eu.dnetlib.enabling.resultset.StreamingResultSetFactory"
+		p:resultSetFactory-ref="resultSetFactory" />
+
+	<bean id="cachingResultSetFactory" class="eu.dnetlib.enabling.resultset.CachingResultSetFactory"
+		p:resultSetFactory-ref="resultSetFactory" />
+
+	<bean id="pushResultSetFactory"
+		class="eu.dnetlib.enabling.resultset.push.TransientPushResultSetFactory"
+		p:dao-ref="pushResultSetDao" p:resultSetService-ref="resultSetService" />
+
+	<bean id="iterableResultSetFactory" class="eu.dnetlib.enabling.resultset.IterableResultSetFactory"
+		p:fetchSize="10" p:resultSetFactory-ref="openResultSetFactory"
+		lazy-init="true" />
+
+
+	<bean id="pushResultSetDao"
+		class="eu.dnetlib.enabling.resultset.push.CacheTransientResultSetDaoImpl"
+		p:cache-ref="pushResultSetStoreCache" p:resultSetCache-ref="pushResultSetDescriptorCache" />
+
+	<bean id="customResultSetPropertyDao" class="eu.dnetlib.enabling.resultset.ResultSetPropertyDaoImpl" />
+
+	<bean id="resultSetService" class="eu.dnetlib.enabling.resultset.ResultSetServiceImpl"
+		init-method="start" p:resultsetRegistry-ref="resultSetRegistry"
+		p:pushFactory-ref="pushResultSetFactory" p:endpoint-ref="resultSetServiceEndpoint"
+		p:eprBuilder-ref="jaxwsEndpointReferenceBuilder" p:customPropertyDao-ref="customResultSetPropertyDao" />
+		
+	<!-- endpoints -->
+	<jaxws:endpoint id="resultSetServiceEndpoint"
+		implementor="#resultSetService" implementorClass="eu.dnetlib.enabling.resultset.rmi.ResultSetService"
+		address="/resultSet" />
+
+	<template:instance name="serviceRegistrationManager"
+		t:serviceRegistrationManagerClass="eu.dnetlib.enabling.tools.registration.ValidatingServiceRegistrationManagerImpl"
+		t:name="resultSetServiceRegistrationManager" t:service="resultSetService"
+		t:endpoint="resultSetServiceEndpoint" t:jobScheduler="jobScheduler" />
+
+</beans>
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSet.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ResultSet.java	(revision 45117)
@@ -0,0 +1,71 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import eu.dnetlib.enabling.resultset.observer.Observable;
+
+/**
+ * A ResultSet represents a set of data results.
+ * 
+ * @author marko
+ * 
+ */
+public interface ResultSet extends Observable {
+	/**
+	 * get the resource identifier.
+	 * 
+	 * @return rsId
+	 */
+	String getIdentifier();
+
+	/**
+	 * sets the resource identifier. The ResultSetRegistry will assign a new rsId.
+	 * 
+	 * @param rsId allocated resultset identifier
+	 */
+	void setIdentifier(String rsId);
+
+	/**
+	 * get a 'page' of results.
+	 * 
+	 * @param fromPosition
+	 *            from 1
+	 * @param toPosition
+	 *            last included
+	 * @return a page of data
+	 */
+	List<String> getResults(int fromPosition, int toPosition);
+
+	/**
+	 * get the number of result elements present in the resultset.
+	 * 
+	 * @return number of results
+	 */
+	int getNumberOfResults();
+
+	/**
+	 * Tells if the resultset is open or closed.
+	 * 
+	 * @return true if open
+	 */
+	boolean isOpen();
+
+	/**
+	 * close a resultset.
+	 */
+	void close();
+	
+	/**
+	 * Tells if the resultset is destroyed.
+	 * 
+	 * @return true if the resultset is destroyed. 
+	 */
+	boolean isDestroyed();
+	
+	/**
+	 * Destroy the resultset and free associated resources, remove it from the ResultSetRegistry.
+	 * After calling this method, the resultset is no more accessible from other services.
+	 */
+	void destroy();
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest.java	(revision 45117)
@@ -0,0 +1,36 @@
+package eu.dnetlib.enabling.resultset.push;
+
+
+import static org.junit.Assert.*;
+
+import javax.annotation.Resource;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import eu.dnetlib.miscutils.factory.Factory;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration
+public class ResultSetDescriptorFactoryTest {
+
+	@Resource
+	Factory<ResultSetDescriptor> factory;
+
+	@Before
+	public void setUp() throws Exception {
+	}
+
+	@Test
+	public void testFactory() {
+		ResultSetDescriptor desc1 = factory.newInstance();
+		ResultSetDescriptor desc2 = factory.newInstance();
+
+		assertTrue("check different instances", desc1 != desc2);
+		assertEquals("check that it's a spring prototype", 200, desc1.getRangeLength());
+		assertEquals("check that it's a spring prototype", 200, desc2.getRangeLength());
+	}
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetFactoryImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetFactoryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetFactoryImpl.java	(revision 45117)
@@ -0,0 +1,38 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * This factory creates resultset bound to a given resultset registry shared with a resultset service which exposed them
+ * to the outside world.
+ *
+ * It's tightly coupled with a local instance of the ResultSetService.
+ *
+ * @see eu.dnetlib.enabling.resultset.ResultSetServiceImpl
+ *
+ * @author marko
+ *
+ */
+public class LocalResultSetFactoryImpl extends AbstractResultSetFactory {
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see eu.dnetlib.enabling.resultset.ResultSetFactory#createResultSet(eu.dnetlib.enabling.resultset.ResultSetListener)
+	 */
+	@Override
+	public W3CEndpointReference createResultSet(final ResultSetListener provider) {
+		return registerResultSet(createInstance(provider));
+	}
+
+	/**
+	 * create a new local resultset instance. Subclasses may override this to supply additional configuration.
+	 *
+	 * @param provider provider
+	 * @return a new resultset instance.
+	 */
+	protected LocalResultSetImpl createInstance(final ResultSetListener provider) {
+		return new LocalResultSetImpl(provider);
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/AbstractTransientPushResultSetDaoTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/AbstractTransientPushResultSetDaoTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/AbstractTransientPushResultSetDaoTest.java	(revision 45117)
@@ -0,0 +1,223 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import static org.junit.Assert.*; // NOPMD
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.miscutils.cache.Cache;
+
+/**
+ * subclass this unit test class and provide a concrete transient push resultset dao implementation.
+ *
+ * @author marko
+ *
+ */
+@Ignore
+public abstract class AbstractTransientPushResultSetDaoTest {
+	/**
+	 * logger.
+	 */
+	private static final Log log = LogFactory.getLog(AbstractTransientPushResultSetDaoTest.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	/**
+	 * test first element.
+	 */
+	private static final String TWO = "two";
+
+	/**
+	 * test second element.
+	 */
+	private static final String ONE = "one";
+
+	/**
+	 * some key.
+	 */
+	private static final String RS_ID = "123";
+
+	/**
+	 * instance under test.
+	 */
+	private TransientPushResultSetDao dao;
+
+	/**
+	 * prepare the instance under test.
+	 *
+	 */
+	@Before
+	public void setUp() {
+		setDao(newInstance());
+	}
+
+	/**
+	 * specific unit tests will override this method and provide a concrete instance to test.
+	 *
+	 * @return new transient push resultset dao instance
+	 */
+	protected abstract TransientPushResultSetDao newInstance();
+
+	/**
+	 * test add elements.
+	 */
+	@Test
+	public void testAddElements() {
+		final List<String> freshGet = getDao().getElements(RS_ID, 1, 0);
+		assertNotNull("fresh get", freshGet);
+		assertEquals("fresh get", 0, freshGet.size());
+
+		final List<String> list = new ArrayList<String>();
+		list.add(ONE);
+
+		getDao().addElements(RS_ID, list);
+
+		final List<String> firstGet = getDao().getElements(RS_ID, 1, 1);
+		assertEquals("first get", 1, firstGet.size());
+		assertEquals("first get", ONE, firstGet.get(0));
+
+		final List<String> listAppend = new ArrayList<String>();
+		listAppend.add(TWO);
+
+		getDao().addElements(RS_ID, listAppend);
+
+		final List<String> secondGet = getDao().getElements(RS_ID, 1, 2);
+		assertEquals("second get", 2, secondGet.size());
+		assertEquals("second get", ONE, secondGet.get(0));
+		assertEquals("second get", TWO, secondGet.get(1));
+
+		final List<String> listBig = new ArrayList<String>();
+		for (int i = 0; i < 90; i++)
+			listBig.add(Integer.toString(i));
+
+		getDao().addElements(RS_ID, listBig);
+
+		final List<String> thirdGet = getDao().getElements(RS_ID, 3, 90);
+		assertEquals("third get", 88, thirdGet.size());
+		assertEquals("third get", "0", thirdGet.get(0));
+		assertEquals("third get", "1", thirdGet.get(1));
+	}
+
+	/**
+	 * check get elements.
+	 */
+	@Test
+	public void testGetElements() {
+		final List<String> list = new ArrayList<String>();
+		list.add(ONE);
+
+		getDao().addElements(RS_ID, list);
+
+		final List<String> res = getDao().getElements(RS_ID, 1, 1);
+		assertEquals("check size", 1, res.size());
+		assertEquals("check element", ONE, res.get(0));
+	}
+
+	/**
+	 * introduced for reproducing of #904. Thanks to Jochen for this one.
+	 */
+	@Test(expected = IllegalArgumentException.class)
+	public void testAddElementsDifferentSize() {
+		List<Integer> sizes = Lists.newArrayList(100, 200, 300, 99);
+		int run = 0;
+		int total = 0;
+
+		List<String> records = new LinkedList<String>();
+		for (int size : sizes) {
+			for (int i = 0; i < size; i++)
+				records.add("bla-" + run + "-" + i);
+
+			dao.addElements(RS_ID, records);
+			records.clear();
+
+			total += size;
+			run++;
+		}
+
+		assertEquals("check size", total, dao.getSize(RS_ID));
+	}
+
+	/**
+	 * introduced for reproducing of #904. with correct size (limited by 100)
+	 */
+	@Test
+	public void testAddElementsDifferentSizeCorrectSize() {
+		List<Integer> sizes = Lists.newArrayList(51, 51, 51, 51);
+
+		int total = 0;
+		int run = 0;
+		String lastName = null;
+
+		List<String> records = new LinkedList<String>();
+		for (int size : sizes) {
+			for (int i = 0; i < size; i++) {
+				lastName = "bla-" + run + "-" + i;
+				records.add(lastName);
+			}
+
+			dao.addElements(RS_ID, records);
+			records.clear();
+
+			total += size;
+			run++;
+		}
+
+		inspect();
+
+		assertEquals("check size", total, dao.getSize(RS_ID));
+		assertEquals("check last", lastName, dao.getElements(RS_ID, total, total).get(0));
+
+		assertEquals("check first page", "bla-0-11", dao.getElements(RS_ID, 12, 12).get(0));
+		assertEquals("check last page", "bla-1-11", dao.getElements(RS_ID, 51 + 12, 51 + 12).get(0));
+
+		assertEquals("check range", 10, dao.getElements(RS_ID, 1, 10).size());
+		assertEquals("check range", 10, dao.getElements(RS_ID, 51 + 1, 51 + 10).size());
+		assertEquals("check range", 51, dao.getElements(RS_ID, 1, 51).size());
+		assertEquals("check range", 52, dao.getElements(RS_ID, 1, 52).size());
+		assertEquals("check range", 51, dao.getElements(RS_ID, 2, 52).size());
+
+		assertEquals("check range", 100, dao.getElements(RS_ID, 1, 100).size());
+		assertEquals("check range", 99, dao.getElements(RS_ID, 2, 100).size());
+		assertEquals("check range", 100, dao.getElements(RS_ID, 2, 101).size());
+
+		assertEquals("check range", 200, dao.getElements(RS_ID, 2, 201).size());
+	}
+
+	private void inspect() {
+		CacheTransientResultSetDaoImpl dao = (CacheTransientResultSetDaoImpl) this.dao;
+		ResultSetDescriptor desc = dao.getResultSetCache().get(RS_ID);
+		Cache<String, List<String>> cache = dao.getCache();
+
+		log.debug("----------------");
+		log.debug("ranges: " + desc.getRanges());
+		log.debug("last range index: " + desc.getLastRange());
+		for (int i = 0; i < desc.getRanges(); i++) {
+			final List<String> range = cache.get(RS_ID + "-" + i);
+			log.debug("range: " + i + " has " + range.size() + " elements");
+			log.debug(" " + range);
+		}
+
+		log.debug("----------------");
+	}
+
+	@Test
+	public void testSizeOfEmpty() {
+		assertEquals("empty size", 0, dao.getSize(RS_ID));
+	}
+
+	public TransientPushResultSetDao getDao() {
+		return dao;
+	}
+
+	public void setDao(final TransientPushResultSetDao dao) {
+		this.dao = dao;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/CacheTransientResultSetDaoImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/CacheTransientResultSetDaoImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/CacheTransientResultSetDaoImpl.java	(revision 45117)
@@ -0,0 +1,179 @@
+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<String, List<String>> cache;
+
+	/**
+	 * resultsets
+	 */
+	private Cache<String, ResultSetDescriptor> resultSetCache;
+
+	/**
+	 * resultset descriptor factory.
+	 */
+	@Resource
+	private Factory<ResultSetDescriptor> 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<String> 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<String> lastRange = cache.get(key + "-" + lastRangeIndex);
+			log.debug("stored last range: " + lastRange);
+
+			if (lastRange == null) {
+				lastRange = new ArrayList<String>();
+				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<String> nextRange = new ArrayList<String>(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<String> 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<String> res = new ArrayList<String>();
+
+		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<String, List<String>> getCache() {
+		return cache;
+	}
+
+	@Required
+	public void setCache(final Cache<String, List<String>> cache) {
+		this.cache = cache;
+	}
+
+	public Cache<String, ResultSetDescriptor> getResultSetCache() {
+		return resultSetCache;
+	}
+
+	@Required
+	public void setResultSetCache(final Cache<String, ResultSetDescriptor> resultSetCache) {
+		this.resultSetCache = resultSetCache;
+	}
+
+	public Factory<ResultSetDescriptor> getResultSetDescriptorFactory() {
+		return resultSetDescriptorFactory;
+	}
+
+	public void setResultSetDescriptorFactory(final Factory<ResultSetDescriptor> resultSetDescriptorFactory) {
+		this.resultSetDescriptorFactory = resultSetDescriptorFactory;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetFactory.java	(revision 45117)
@@ -0,0 +1,34 @@
+package eu.dnetlib.enabling.resultset.push;
+
+
+/**
+ * creates a transient push resultset.
+ * 
+ * @author marko
+ *
+ */
+public class TransientPushResultSetFactory extends AbstractPushResultSetFactoryImpl {
+
+	/**
+	 * dao.
+	 */
+	private TransientPushResultSetDao dao;
+	
+	/** 
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.push.AbstractPushResultSetFactoryImpl#newInstance()
+	 */
+	@Override
+	protected PushResultSet newInstance() {
+		return new TransientPushResultSetImpl(dao);
+	}
+
+	public TransientPushResultSetDao getDao() {
+		return dao;
+	}
+
+	public void setDao(final TransientPushResultSetDao dao) {
+		this.dao = dao;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImplTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImplTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImplTest.java	(revision 45117)
@@ -0,0 +1,184 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.matches;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import net.sf.ehcache.Cache;
+import net.sf.ehcache.CacheManager;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+import eu.dnetlib.miscutils.cache.EhCache;
+
+/**
+ * Test ResultSetRegistryImpl.
+ * 
+ * @author marko
+ * 
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class ResultSetRegistryImplTest {
+
+	/**
+	 * max in memory elements.
+	 */
+	private static final int MAX_IN_MEM = 100;
+
+	/**
+	 * default time.
+	 */
+	private static final int DEFAULT_TTI = 1000;
+
+	/**
+	 * default time to live.
+	 */
+	private static final int DEFAULT_TTL = 1000;
+
+	/**
+	 * class under test.
+	 */
+	private transient ResultSetRegistryImpl registry;
+
+	/**
+	 * mock of a resultset object.
+	 */
+	@Mock
+	private transient ResultSet resultSet;
+
+	/**
+	 * ehcache manager.
+	 */
+	private final transient CacheManager cacheManager = CacheManager.create();
+
+	/**
+	 * Set up basic mocks.
+	 */
+	@Before
+	public void setUp() {
+		final Cache ehCache = new net.sf.ehcache.Cache("testCache", MAX_IN_MEM, false, false, DEFAULT_TTL, DEFAULT_TTI);
+		cacheManager.addCache(ehCache);
+
+		final Cache mtEhCache = new net.sf.ehcache.Cache("testMTCache", MAX_IN_MEM, false, false, DEFAULT_TTL, DEFAULT_TTI);
+		cacheManager.addCache(mtEhCache);
+
+		final EhCache<String, ResultSet> cache = new EhCache<String, ResultSet>(ehCache);
+		cache.setCache(ehCache);
+
+		final EhCache<String, Integer> mtCache = new EhCache<String, Integer>(mtEhCache);
+		mtCache.setCache(mtEhCache);
+
+		registry = new ResultSetRegistryImpl();
+		registry.setCache(cache);
+		registry.setMaxIdleTimeCache(mtCache);
+
+		when(resultSet.getIdentifier()).thenReturn("123456");
+		when(resultSet.isOpen()).thenReturn(true);
+	}
+
+	/**
+	 * remove ehcache from ehcachemanager.
+	 */
+	@After
+	public void tearDown() {
+		cacheManager.removeAllCaches();
+	}
+
+	/**
+	 * Test that registered resultsets are really registered.
+	 */
+	@Test
+	public void testAddResultSet() {
+
+		final String rsId = resultSet.getIdentifier();
+		assertNotNull("the resultset should not be null", rsId);
+
+		registry.addResultSet(resultSet);
+		verify(resultSet).setIdentifier(matches("rs-" + registry.getIdGenerator().getRegEx()));
+
+		final ResultSet res = registry.getResultSetById(rsId); // NOPMD
+		assertNotNull("the resultset is not found", res);
+		assertEquals("the resultsets don't have the same id", rsId, res.getIdentifier());
+		assertEquals("the resultsets are not the same instance", resultSet, res);
+	}
+
+	/**
+	 * Test that registered resultsets are really registered.
+	 */
+	@Test
+	public void testAddResultSetWithId() {
+		resultSet = mock(ResultSet.class);
+		when(resultSet.getIdentifier()).thenReturn("123");
+
+		final String rsId = resultSet.getIdentifier();
+
+		registry.addResultSet(resultSet, rsId);
+		verify(resultSet).setIdentifier(rsId);
+
+		final ResultSet res = registry.getResultSetById(rsId); // NOPMD
+		assertNotNull("the resultset is not found", res);
+		assertEquals("the resultsets don't have the same id", rsId, res.getIdentifier());
+		assertEquals("the resultsets are not the same instance", resultSet, res);
+	}
+
+	/**
+	 * try to obtain a inexistent resultset.
+	 */
+	@Test
+	public void testInexistentResultSet() {
+		final String rsId = resultSet.getIdentifier();
+		assertNull("inexisten resultset returns null", registry.getResultSetById(rsId));
+	}
+
+	/**
+	 * test closing of resultset and its pruning from the registry.
+	 */
+	@Test
+	public void testResultSetClose() {
+		final String rsId = resultSet.getIdentifier();
+
+		assertTrue("check if resultset is open", resultSet.isOpen());
+
+		registry.addResultSet(resultSet);
+		verify(resultSet).addObserver(registry);
+
+		// simulate a resultset close on the mock
+		when(resultSet.isOpen()).thenReturn(false);
+		registry.update(resultSet, null);
+
+		assertFalse("check if resultset is closed", resultSet.isOpen());
+		assertNull("check if the object is pruned from the registry", registry.getResultSetById(rsId));
+	}
+
+	/**
+	 * same as testResultSetClose() but with a real observer/observable mechanism, i.e. without resultset mock class.
+	 * 
+	 */
+	@Test
+	public void testWithRealObservable() {
+		final LocalResultSetImpl rset = new LocalResultSetImpl(null);
+		rset.setIdentifier("123456");
+		resultSet = rset;
+
+		final String rsId = resultSet.getIdentifier();
+
+		assertFalse("check if resultset is not destroyed", resultSet.isDestroyed());
+
+		registry.addResultSet(resultSet);
+		resultSet.destroy();
+
+		assertTrue("check if resultset is destroyed", resultSet.isDestroyed());
+		assertNull("check if the object is pruned from the registry", registry.getResultSetById(rsId));
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalResultSetFactoryImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalResultSetFactoryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalResultSetFactoryImpl.java	(revision 45117)
@@ -0,0 +1,27 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+public class EPRPoolingLocalResultSetFactoryImpl extends LocalResultSetFactoryImpl {
+
+	private ResultSetEPRPool pool;
+	
+	@Override
+	public W3CEndpointReference registerResultSet(ResultSet resultSet) {
+		return pool.registerResultSet(resultSet);
+	}
+
+	public ResultSetEPRPool getPool() {
+		return pool;
+	}
+
+	@Required
+	public void setPool(ResultSetEPRPool pool) {
+		this.pool = pool;
+	}
+
+	
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/IterableResultSetTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/IterableResultSetTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/IterableResultSetTest.java	(revision 45117)
@@ -0,0 +1,150 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+/**
+ * tests the IterableResult class
+ * 
+ * @author claudio
+ *
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class IterableResultSetTest {
+
+	/**
+	 * number of total elements 
+	 */
+	private static int NUM_ELEM = 100;
+	
+	/**
+	 * number of elements available to fetch
+	 */
+	private static int FETCH_SIZE = 10;
+	
+	@Mock
+	private ResultSet mockResultSet;
+	
+	/**
+	 * a list used to compare elements.
+	 */
+	private List<String> list;
+	
+	/**
+	 * Iterator associated with the test list.
+	 */
+	private Iterator<String> iter;
+	
+	/**
+	 * Object to test.
+	 */
+	private IterableResultSet iterResultSet;
+
+	@Before
+	public void setUp() {
+		list = new ArrayList<String>();
+		for (int i=0; i< NUM_ELEM; i++)
+			list.add("XXXXX " + i);
+				
+		iter = list.iterator();
+		when(mockResultSet.isOpen()).thenReturn(iter.hasNext());
+		
+		iterResultSet = new IterableResultSet(list, FETCH_SIZE);
+		iterResultSet.setResultSet(mockResultSet);
+	}
+	
+	@Test
+	public void testIterableResultSet() {
+		assertNotNull(iterResultSet);
+		assertTrue(iterResultSet.getSize() > 0);
+	}
+
+	@Test(expected=RuntimeException.class)
+	public void testGetResult_fail_1() {
+		iterResultSet.getResult(0, 5);
+	}
+
+	@Test(expected=RuntimeException.class)
+	public void testGetResult_fail_2() {
+		iterResultSet.getResult(1, 5);
+		iterResultSet.getResult(1, 5);
+	}
+	
+	@Test(expected=RuntimeException.class)
+	public void testGetResult_fail_3() {
+		iterResultSet.getResult(1, 5);
+		iterResultSet.getResult(6, 5);
+	}
+	
+	@Test(expected=RuntimeException.class)
+	public void testGetResult_fail_4() {
+		iterResultSet.getResult(1, 5);
+		iterResultSet.getResult(7, 10);
+	}
+	
+	@Test
+	public void testGetResult_success_1() {
+		List<String> result = iterResultSet.getResult(1, NUM_ELEM);
+		for (int i=0; i<NUM_ELEM; i++) {
+			assertEquals(list.get(i), result.get(i));
+		}
+	}
+	
+	@Test
+	public void testGetResult_success_2() {
+		List<String> result = iterResultSet.getResult(1, NUM_ELEM);
+		
+		for (int i=0; i<NUM_ELEM; i++) {
+			assertEquals(list.get(i), result.get(i));
+			iter.next();
+		}
+		verify(mockResultSet).close();
+	}
+
+	@Test
+	public void testGetResult_success_3() {
+		for (int i = 1; i < NUM_ELEM; i+= FETCH_SIZE)
+			iterResultSet.getResult(i, i + FETCH_SIZE-1);
+		verify(mockResultSet, times(1)).close();
+	}
+	
+	@Test
+	public void testGetResult_success_4() {
+		iterResultSet.getResult(1, NUM_ELEM + 1);
+		verify(mockResultSet, times(1)).close();
+	}
+	
+	@Test
+	public void testGetResultSet_success_1() {
+		assertNotNull(iterResultSet.getResultSet());
+	}
+
+	@Test
+	public void testGetSize_fail_1() {
+		iterResultSet.getResult(1, 8);
+		assertNotSame(7, iterResultSet.getSize());
+		assertNotSame(9, iterResultSet.getSize());
+	}
+	
+	@Test
+	public void testGetSize_success_1() {
+		iterResultSet.getResult(1, 8);
+		assertEquals(FETCH_SIZE, iterResultSet.getSize());
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSet.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSet.java	(revision 45117)
@@ -0,0 +1,57 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.enabling.tools.ServiceResolver;
+import eu.dnetlib.miscutils.collections.MappedCollection;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+public class ParallelMappedResultSet extends MappedResultSet {
+
+	private ExecutorService executor;
+
+	public ParallelMappedResultSet(final W3CEndpointReference source, final UnaryFunction<String, String> mapper, final ServiceResolver serviceResolver,
+			final ExecutorService executor) {
+		super(source, mapper, serviceResolver);
+		this.executor = executor;
+	}
+
+	@Override
+	public List<String> getResult(int fromPosition, int toPosition) {
+
+//		log.info("Parallel page " + (toPosition - fromPosition + 1));
+
+		List<Future<String>> results = Lists.newArrayList();
+
+		for (final String input : getResultFromSource(fromPosition, toPosition)) {
+			results.add(executor.submit(new Callable<String>() {
+				@Override
+				public String call() throws Exception {
+					return getMapper().evaluate(input);
+				}
+			}));
+		}
+
+		return MappedCollection.listMap(results, new UnaryFunction<String, Future<String>>() {
+			@Override
+			public String evaluate(Future<String> arg) {
+				try {
+					return arg.get();
+				} catch (InterruptedException e) {
+					throw new IllegalStateException(e);
+				} catch (ExecutionException e) {
+					throw new IllegalStateException(e);
+				}
+			}
+		});
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactoryTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactoryTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactoryTest.java	(revision 45117)
@@ -0,0 +1,139 @@
+package eu.dnetlib.enabling.resultset; // NOPMD
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.List;
+
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
+import eu.dnetlib.enabling.tools.ServiceResolver;
+
+/**
+ * test xslt resultset.
+ *
+ * @author marko
+ *
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class XSLTMappedResultSetFactoryTest {
+
+	/**
+	 * instance under test.
+	 */
+	private transient XSLTMappedResultSetFactory factory;
+
+	/**
+	 * resultset factory mock.
+	 */
+	@Mock
+	private transient ResultSetFactory resultSetFactory;
+
+	/**
+	 * service resolver.
+	 */
+	@Mock
+	private transient ServiceResolver serviceResolver;
+
+	/**
+	 * resultset service mock.
+	 */
+	@Mock
+	private transient ResultSetService resultSetService;
+	
+	/**
+	 * underlying resultSet mock
+	 */
+	@Mock
+	private transient ResultSet resultSet;
+
+	/**
+	 * Common setup.
+	 *
+	 */
+	@Before
+	public void setUp() {
+		factory = new XSLTMappedResultSetFactory();
+		factory.setResultSetFactory(resultSetFactory);
+		factory.setServiceResolver(serviceResolver);
+	}
+
+	/**
+	 * test invalid xslt.
+	 *
+	 * @throws TransformerConfigurationException
+	 *             could happen
+	 */
+	@Test(expected = IllegalStateException.class)
+	public void testInvalidXslt() throws TransformerConfigurationException {
+		factory.createMappedResultSet(null, "<bla/>");
+	}
+
+	/**
+	 * test xslt.
+	 *
+	 * @throws TransformerConfigurationException
+	 *             could happen
+	 * @throws IOException
+	 *             could happen
+	 * @throws ResultSetException mock
+	 */
+	@Test
+	public void testXslt() throws TransformerConfigurationException, IOException, ResultSetException {
+		when(serviceResolver.getService(eq(ResultSetService.class), (W3CEndpointReference) anyObject())).thenReturn(resultSetService);
+		when(serviceResolver.getResourceIdentifier((W3CEndpointReference) anyObject())).thenReturn("123");
+
+		when(resultSetService.getNumberOfElements(anyString())).thenReturn(1);
+		when(resultSetService.getResult("123", 1, 1, "waiting")).thenReturn(Lists.newArrayList("<first>something</first>"));
+		when(resultSetService.getRSStatus("123")).thenReturn("closed");
+		
+		when(resultSet.isOpen()).thenReturn(true);
+		
+		final StringWriter xsltSource = new StringWriter();
+		IOUtils.copy(getClass().getResourceAsStream("test.xsl"), xsltSource);
+		factory.createMappedResultSet(null, xsltSource.toString());
+
+		verify(resultSetFactory, times(1)).createResultSet(argThat(new ArgumentMatcher<ResultSetListener>() {
+
+			@Override
+			public boolean matches(final Object argument) {
+				final MappedResultSet listener = (MappedResultSet) argument;
+				listener.setResultSet(resultSet);
+				final List<String> res = listener.getResult(1, 1);
+
+				assertNotNull("null result", res);
+				assertFalse("empty result", res.isEmpty());
+
+				assertNotNull("null element", res.get(0));
+
+				assertTrue("transformed correctly", res.get(0).contains("<second>something</second>"));
+
+				return true;
+			}
+		}));
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetListener.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetListener.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetListener.java	(revision 45117)
@@ -0,0 +1,61 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
+import eu.dnetlib.enabling.tools.ServiceResolver;
+
+public class CachingResultSetListener implements ResultSetListener {
+	private static final Log log = LogFactory.getLog(CachingResultSetListener.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	
+	private ResultSetService service;
+	private String rsId;
+
+	private ArrayList<String> storage = new ArrayList<String>();
+
+	public CachingResultSetListener(W3CEndpointReference epr, ServiceResolver serviceResolver) {
+		this.service = serviceResolver.getService(ResultSetService.class, epr);
+		this.rsId = serviceResolver.getResourceIdentifier(epr);
+	}
+
+	@Override
+	public List<String> getResult(int fromPosition, int toPosition) {
+		if (storage.get(fromPosition) != null)
+			return cached(fromPosition, toPosition);
+		try {
+			List<String> data = service.getResult(rsId, fromPosition, toPosition, "waiting");
+			cache(data, fromPosition, toPosition);
+			return data;
+		} catch (ResultSetException e) {
+			throw new IllegalStateException(e);
+		}
+	}
+
+	private void cache(List<String> data, int fromPosition, int toPosition) {
+		for(String value : data)
+			storage.set(fromPosition++, value);
+	}
+
+	private List<String> cached(int fromPosition, int toPosition) {
+		log.info("found cached page " + fromPosition + ", " + toPosition);
+		return storage.subList(fromPosition-1, toPosition);
+	}
+
+	@Override
+	public int getSize() {
+		try {
+			return service.getNumberOfElements(rsId);
+		} catch (ResultSetException e) {
+			throw new IllegalStateException(e);
+		}
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/SizedIterable.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/SizedIterable.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/SizedIterable.java	(revision 45117)
@@ -0,0 +1,7 @@
+package eu.dnetlib.enabling.resultset;
+
+public interface SizedIterable<T> extends Iterable<T> {
+
+	public int getNumberOfElements();
+	
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/StreamingResultSetListenerTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/StreamingResultSetListenerTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/StreamingResultSetListenerTest.java	(revision 45117)
@@ -0,0 +1,62 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.*;
+
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+public class StreamingResultSetListenerTest {
+
+	private StreamingResultSetListener listener;
+	private List<String> data;
+
+	@Before
+	public void setUp() throws Exception {
+		data = Lists.newArrayList("uno", "due", "tre", "quattro");
+		listener = new StreamingResultSetListener(data.iterator(), data.size());
+	}
+
+	@Test
+	public void testGetResult() {
+		assertEquals(data.size(), listener.getSize());
+
+		final List<String> res = listener.getResult(1, 2);
+		assertEquals(2, res.size());
+		assertEquals("uno", res.get(0));
+		assertEquals("due", res.get(1));
+	}
+
+	@Test
+	public void testGetResult2() {
+		listener.getResult(1, 2);
+		final List<String> res = listener.getResult(3, 4);
+		assertEquals(2, res.size());
+		assertEquals("tre", res.get(0));
+		assertEquals("quattro", res.get(1));
+	}
+
+	@Test
+	public void testGetResult_retry() {
+		listener.getResult(1, 2);
+		final List<String> res = listener.getResult(1, 2);
+		assertEquals(2, res.size());
+		assertEquals("uno", res.get(0));
+		assertEquals("due", res.get(1));
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testGetResult_random() {
+		listener.getResult(1, 2);
+		listener.getResult(2, 3);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testGetResult_skip() {
+		listener.getResult(1, 2);
+		listener.getResult(4, 4);
+	}
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistry.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistry.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistry.java	(revision 45117)
@@ -0,0 +1,75 @@
+package eu.dnetlib.enabling.resultset;
+
+import eu.dnetlib.enabling.resultset.observer.ResultSetObserver;
+
+/**
+ * Instances of ResultSetRegistry manage a set of resultset objects and manage their garbage collection.
+ *
+ * @author marko
+ *
+ */
+public interface ResultSetRegistry extends ResultSetObserver {
+	/**
+	 * add a resultset object to the registry.
+	 *
+	 * The given resultset object from now on is managed by the resultset registry.
+	 *
+	 * @param resultSet
+	 *            a resultset object
+	 */
+	void addResultSet(ResultSet resultSet);
+	
+	/**
+	 * add a resultset object to the registry.
+	 *
+	 * The given resultset object from now on is managed by the resultset registry.
+	 *
+	 * @param resultSet
+	 *            a resultset object
+	 * @param identifier the identifier you want for the resultset
+	 */
+	void addResultSet(ResultSet resultSet, String identifier);
+
+	/**
+	 * add a resultset object to the registry.
+	 *
+	 * The given resultset object from now on is managed by the resultset registry.
+	 *
+	 * @param resultSet
+	 *            a resultset object
+	 * @param maxIdleTime
+	 *            max idle time
+	 */
+	void addResultSet(ResultSet resultSet, int maxIdleTime);
+	
+	/**
+	 * add a resultset object to the registry.
+	 *
+	 * The given resultset object from now on is managed by the resultset registry.
+	 *
+	 * @param resultSet
+	 *            a resultset object
+	 * @param identifier the identifier you want for the resultset
+	 * @param maxIdleTime max idle time
+	 */
+	void addResultSet(ResultSet resultSet, String identifier, int maxIdleTime);
+
+	/**
+	 * obtain the resultset with the given id.
+	 *
+	 * @param rsId
+	 *            resultset id
+	 * @return the resultset object matching the rsId or null
+	 */
+	ResultSet getResultSetById(String rsId);
+
+	/**
+	 * obtain the resultset's maxIdleTime parameter for a resultset with the given id.
+	 *
+	 * @param rsId
+	 *            resultset id
+	 * @return max idle time in seconds, as specified when the resultset has been registered
+	 */
+	int getMaxIdleTimeById(String rsId);
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSetFactory.java	(revision 45117)
@@ -0,0 +1,53 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.enabling.tools.ServiceResolver;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+/**
+ * Create a new resultset which takes each record of the input resultset and applies the mapping function to it.
+ *
+ * @author marko
+ *
+ */
+public class MappedResultSetFactory {
+
+	/**
+	 * underlying resultset factory, which exposes local resultsets to the world.
+	 */
+	private ResultSetFactory resultSetFactory;
+
+	/**
+	 * service resolver, transforms eprs to services.
+	 */
+	private ServiceResolver serviceResolver;
+
+	/**
+	 * Create a new resultset which takes each record of the input resultset and applies the mapping function to it.
+	 *
+	 * @param source source resultset epr
+	 * @param mapper mapper function
+	 * @return mapped resultset epr
+	 */
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final UnaryFunction<String, String> mapper) {
+		return resultSetFactory.createResultSet(new MappedResultSet(source, mapper, serviceResolver));
+	}
+
+	public ResultSetFactory getResultSetFactory() {
+		return resultSetFactory;
+	}
+
+	public void setResultSetFactory(final ResultSetFactory resultSetFactory) {
+		this.resultSetFactory = resultSetFactory;
+	}
+
+	public ServiceResolver getServiceResolver() {
+		return serviceResolver;
+	}
+
+	public void setServiceResolver(final ServiceResolver serviceResolver) {
+		this.serviceResolver = serviceResolver;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/resources/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest-context.xml
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/resources/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest-context.xml	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/resources/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest-context.xml	(revision 45117)
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
+	xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
+
+	<bean id="resultSetDescriptorPrototype" class="eu.dnetlib.enabling.resultset.push.ResultSetDescriptor"
+		p:rangeLength="200" scope="prototype" />
+
+	<bean id="resultSetDescriptorFactory" class="eu.dnetlib.springutils.beans.factory.PrototypeFactory">
+		<lookup-method name="newInstance" bean="resultSetDescriptorPrototype" />
+	</bean>
+</beans>
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetListener.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetListener.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetListener.java	(revision 45117)
@@ -0,0 +1,132 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Exposes an iterable through our resultset protocol.
+ * 
+ * <p>
+ * The resultset protocol is constructed as if it were random access. Some kind of sources, like an iterable, is not
+ * random access. The consumer of such a resultset knows that, and won't try to access the resultset randomly. However,
+ * it could ask for some data which is already sent, because of retries caused by network issues.
+ * </p>
+ * 
+ * @author marko
+ * 
+ */
+public class StreamingResultSetListener implements ResultSetListener, ResultSetAware {
+	private static final Log log = LogFactory.getLog(StreamingResultSetListener.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	private ResultSet resultSet;
+
+	private Iterable<String> iterable;
+	private Iterator<String> items;
+	private int size;
+
+	private int lastFrom = 0;
+	private int lastTo = 0;
+	private List<String> lastChunk;
+
+	public StreamingResultSetListener(Iterable<String> items, int size) {
+		this(items.iterator(), size);
+		this.iterable = items;
+	}
+
+	public StreamingResultSetListener(Iterator<String> items, int size) {
+		super();
+		this.items = items;
+		this.size = size;
+	}
+
+	protected void reset() {
+		lastFrom = 0;
+		items = iterable.iterator();
+	}
+
+	@Override
+	public List<String> getResult(int from, int to) {
+
+		log.debug("STREAM: getResult(" + from + ", " + to + ")");
+
+		// handle retry because of network error.
+		if (from == lastFrom && to == lastTo)
+			return lastChunk;
+
+		if (from != lastTo + 1) {
+			if (from == 1 && iterable != null)
+				reset();
+			else
+				throw new IllegalArgumentException("this resultset is not random access, you can only retry last chunk only, asked from " + from + " to "
+						+ to + " but lastTo = " + lastTo + ". Size = " + size);
+		}
+
+		List<String> chunk = new ArrayList<String>();
+		for (int i = from; i <= to; i++)
+			chunk.add(items.next());
+
+		if (resultSet != null && !items.hasNext())
+			resultSet.close();
+
+		lastFrom = from;
+		lastTo = to;
+		lastChunk = chunk;
+
+		return chunk;
+	}
+
+	@Override
+	public int getSize() {
+		return size;
+	}
+
+	public void setSize(int size) {
+		this.size = size;
+	}
+
+	public Iterator<String> getItems() {
+		return items;
+	}
+
+	public void setItems(Iterator<String> items) {
+		this.items = items;
+	}
+
+	public int getLastFrom() {
+		return lastFrom;
+	}
+
+	public void setLastFrom(int lastFrom) {
+		this.lastFrom = lastFrom;
+	}
+
+	public int getLastTo() {
+		return lastTo;
+	}
+
+	public void setLastTo(int lastTo) {
+		this.lastTo = lastTo;
+	}
+
+	public List<String> getLastChunk() {
+		return lastChunk;
+	}
+
+	public void setLastChunk(List<String> lastChunk) {
+		this.lastChunk = lastChunk;
+	}
+
+	public ResultSet getResultSet() {
+		return resultSet;
+	}
+
+	@Override
+	public void setResultSet(ResultSet resultSet) {
+		this.resultSet = resultSet;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/deploy.info
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/deploy.info	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/deploy.info	(revision 45117)
@@ -0,0 +1 @@
+{"type_source": "SVN", "goal": "package -U -T 4C source:jar", "url": "http://svn-public.driver.research-infrastructures.eu/driver/dnet40/modules/cnr-resultset-service/trunk/", "deploy_repository": "dnet4-snapshots", "version": "4", "mail": "sandro.labruzzo@isti.cnr.it,michele.artini@isti.cnr.it, claudio.atzori@isti.cnr.it, alessia.bardi@isti.cnr.it", "deploy_repository_url": "http://maven.research-infrastructures.eu/nexus/content/repositories/dnet4-snapshots", "name": "cnr-resultset-service"}
\ No newline at end of file
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/resources/eu/dnetlib/enabling/resultset/test.xsl
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/resources/eu/dnetlib/enabling/resultset/test.xsl	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/resources/eu/dnetlib/enabling/resultset/test.xsl	(revision 45117)
@@ -0,0 +1,6 @@
+<xsl:stylesheet version="1.0"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+	<xsl:template match="first">
+		<second><xsl:value-of select="."/></second>
+	</xsl:template>
+</xsl:stylesheet>
\ No newline at end of file
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptor.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptor.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptor.java	(revision 45117)
@@ -0,0 +1,156 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import java.io.Serializable;
+import java.util.Iterator;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Describes a push resultset.
+ *
+ * <p>
+ * A push resultset stores it's data in several ranges
+ * </p>
+ *
+ * @author marko
+ *
+ */
+public class ResultSetDescriptor implements Serializable {
+
+	/**
+	 * logger.
+	 */
+	private static final Log log = LogFactory.getLog(Range.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	/**
+	 * This class describes a range.
+	 *
+	 * @author marko
+	 *
+	 */
+	public class Range {
+		private int range;
+		private int begin;
+		private int end;
+
+		public Range(final int range, final int begin, final int end) {
+			super();
+			this.range = range;
+			this.begin = begin;
+			this.end = end;
+		}
+
+		@Override
+		public String toString() {
+			return "Range(" + range + ", " + begin + ", " + end + ")";
+		}
+
+		public int getRange() {
+			return range;
+		}
+
+		public void setRange(final int range) {
+			this.range = range;
+		}
+
+		public int getBegin() {
+			return begin;
+		}
+
+		public void setBegin(final int begin) {
+			this.begin = begin;
+		}
+
+		public int getEnd() {
+			return end;
+		}
+
+		public void setEnd(final int end) {
+			this.end = end;
+		}
+	}
+
+	/**
+	 *
+	 */
+	private static final long serialVersionUID = 7699992350256317181L;
+
+	private int rangeLength = 100;
+
+	private int ranges = 0;
+
+	public int getLastRange() {
+		return ranges - 1;
+	}
+
+	/**
+	 * @param fromPosition
+	 *            1 based count
+	 * @param toPosition
+	 *            1 based count
+	 * @return
+	 */
+	public Iterable<Range> getRangesContaining(final int fromPosition, final int toPosition) {
+
+		final int fromRange = (fromPosition - 1) / rangeLength;
+		int ttoRange = (int) Math.ceil((toPosition * 1.0) / rangeLength);
+
+		if (ttoRange > ranges)
+			ttoRange = ranges;
+
+		final int toRange = ttoRange;
+
+		log.debug("FROM range: " + fromRange);
+		log.debug("TTO range: " + ttoRange);
+		log.debug("TO range: " + toRange);
+
+		return new Iterable<Range>() {
+
+			@Override
+			public Iterator<Range> iterator() {
+				return new Iterator<Range>() {
+
+					int current = fromRange;
+
+					@Override
+					public boolean hasNext() {
+						return current < toRange;
+					}
+
+					@Override
+					public Range next() {
+						int begin = 0;
+						int end = rangeLength;
+						if (current == fromRange)
+							begin = (fromPosition - 1) % rangeLength;
+						if ((current + 1) == toRange)
+							end = (toPosition - 1) % rangeLength + 1;
+						return new Range(current++, begin, end);
+					}
+
+					@Override
+					public void remove() {
+						throw new IllegalStateException("text");
+					}
+				};
+			}
+		};
+	}
+
+	public int getRangeLength() {
+		return rangeLength;
+	}
+
+	public void setRangeLength(final int rangeLength) {
+		this.rangeLength = rangeLength;
+	}
+
+	public int getRanges() {
+		return ranges;
+	}
+
+	public void setRanges(final int ranges) {
+		this.ranges = ranges;
+	}
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactory.java	(revision 45117)
@@ -0,0 +1,75 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.Map;
+import java.util.UUID;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.core.io.Resource;
+
+import eu.dnetlib.miscutils.functional.xml.ApplyXslt;
+
+/**
+ * Create a mapped resultset using a given XSLT.
+ * 
+ * @author marko
+ * 
+ */
+public class XSLTMappedResultSetFactory extends MappedResultSetFactory {
+
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final String xslt) {
+		return createMappedResultSet(source, new ApplyXslt(xslt));
+	}
+
+	/**
+	 * Create a mapped resultset using a given XSLT.
+	 * 
+	 * @param source
+	 *            source
+	 * @param xslt
+	 *            XSLT source
+	 * @return epr of mapped resultset
+	 * @throws TransformerConfigurationException
+	 *             could happen
+	 */
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final String xslt, final String name)
+			throws TransformerConfigurationException {
+		return createMappedResultSet(source, new ApplyXslt(xslt, name));
+	}
+
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final Resource xslt) {
+		return createMappedResultSet(source, new ApplyXslt(xslt));
+	}
+
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final Source xslt) {
+		return createMappedResultSet(source, new ApplyXslt(xslt));
+	}
+	
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final Resource xslt, final Map<String, String> parameters) {
+		return createMappedResultSet(source, new ApplyXslt(xslt, parameters));
+	}
+	
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final String xslt, final Map<String, String> parameters) {
+		return createMappedResultSet(source, new ApplyXslt(xslt, "rs-" + UUID.randomUUID(), parameters));
+	}
+
+	/**
+	 * Create a mapped resultset using a given XSLT.
+	 * 
+	 * @param source
+	 *            source
+	 * @param xslt
+	 *            XSLT
+	 * @return epr of mapped resultset
+	 * @throws TransformerFactoryConfigurationError
+	 * @throws TransformerConfigurationException
+	 *             could happen
+	 */
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final Source xslt, final String name) {
+		return createMappedResultSet(source, new ApplyXslt(xslt, name));
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/observer/ResultSetObserver.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/observer/ResultSetObserver.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/observer/ResultSetObserver.java	(revision 45117)
@@ -0,0 +1,23 @@
+package eu.dnetlib.enabling.resultset.observer;
+
+import eu.dnetlib.enabling.resultset.ResultSet;
+
+
+/**
+ * Implement the same interface as JDK java.util.Observer as java interface (not as a class) and introduce static type
+ * safeness through generics.
+ * 
+ * @author marko, claudio, alessia, michele
+ * 
+ */
+public interface ResultSetObserver {
+	/**
+	 * gets notified when an observed object is updated.
+	 * 
+	 * @param observed
+	 *            observed object which modification triggered this call.
+	 * @param arg
+	 *            arg
+	 */
+	void update(ResultSet observed, Object arg);
+}

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/observer/ResultSetObserver.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/observer/DelegationObserver.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/observer/DelegationObserver.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/observer/DelegationObserver.java	(revision 45117)
@@ -0,0 +1,29 @@
+package eu.dnetlib.enabling.resultset.observer;
+
+import eu.dnetlib.enabling.resultset.ResultSet;
+import eu.dnetlib.enabling.resultset.ResultSetRegistry;
+
+/**
+ * This class delegates an observation event from the java.util.Observable producer to the real consumer which is not a
+ * java.util.Observer (as expected by java.util.Observable) but instead a miscutils Observer.
+ * 
+ * @author marko, claudio, alessia, michele
+ * 
+ */
+public class DelegationObserver implements java.util.Observer {
+	/**
+	 * 
+	 */
+	private transient final ResultSet observable;
+	private transient final ResultSetRegistry observer;
+
+	public DelegationObserver(final ResultSet observable, final ResultSetRegistry observer) {
+		this.observable = observable;
+		this.observer = observer;
+	}
+
+	@Override
+	public void update(final java.util.Observable ignored, final Object arg) {
+		observer.update(observable, arg);
+	}
+}
\ No newline at end of file

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/observer/DelegationObserver.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImpl.java	(revision 45117)
@@ -0,0 +1,123 @@
+package eu.dnetlib.enabling.resultset;
+
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.enabling.tools.UniqueIdentifierGenerator;
+import eu.dnetlib.enabling.tools.UniqueIdentifierGeneratorImpl;
+import eu.dnetlib.miscutils.cache.Cache;
+
+/**
+ * Implement a in memory resultset registry.
+ *
+ * @author marko
+ *
+ */
+public class ResultSetRegistryImpl implements ResultSetRegistry {
+
+	/**
+	 * rsId -> ResultSet mappings are stored here.
+	 */
+	private Cache<String, ResultSet> cache;
+
+	/**
+	 * rsID -> initial maxIdleTime time are store here.
+	 */
+	private Cache<String, Integer> maxIdleTimeCache;
+
+	/**
+	 * identifier generator.
+	 */
+	private UniqueIdentifierGenerator idGenerator = new UniqueIdentifierGeneratorImpl("rs-");
+
+	/**
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.ResultSetRegistry#addResultSet(eu.dnetlib.enabling.resultset.ResultSet)
+	 */
+	@Override
+	public void addResultSet(final ResultSet resultSet) {
+		addResultSet(resultSet, 0);
+	}
+
+	/** 
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.ResultSetRegistry#addResultSet(eu.dnetlib.enabling.resultset.ResultSet, java.lang.String)
+	 */
+	@Override
+	public void addResultSet(final ResultSet resultSet, final String identifier) {
+		addResultSet(resultSet, identifier, 0);
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.ResultSetRegistry#addResultSet(eu.dnetlib.enabling.resultset.ResultSet, int)
+	 */
+	@Override
+	public void addResultSet(final ResultSet resultSet, final int maxIdleTime) {
+		addResultSet(resultSet, idGenerator.generateIdentifier(), maxIdleTime);
+	}
+	
+	/** 
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.ResultSetRegistry#addResultSet(eu.dnetlib.enabling.resultset.ResultSet, java.lang.String, int)
+	 */
+	@Override
+	public void addResultSet(final ResultSet resultSet, final String identifier, final int maxIdleTime) {
+		resultSet.setIdentifier(identifier);
+		resultSet.addObserver(this);
+		cache.put(resultSet.getIdentifier(), resultSet);
+		maxIdleTimeCache.put(resultSet.getIdentifier(), maxIdleTime);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see eu.dnetlib.enabling.resultset.ResultSetRegistry#getResultSetById(java.lang.String)
+	 */
+	@Override
+	public ResultSet getResultSetById(final String rsId) {
+		return cache.get(rsId);
+	}
+
+	@Override
+	public int getMaxIdleTimeById(final String rsId) {
+		return maxIdleTimeCache.get(rsId);
+	}
+
+
+	public Cache<String, ResultSet> getCache() {
+		return cache;
+	}
+
+	@Required
+	public void setCache(final Cache<String, ResultSet> cache) {
+		this.cache = cache;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.miscutils.observer.Observer#update(eu.dnetlib.enabling.resultset.observer.Observable, java.lang.Object)
+	 */
+	@Override
+	public void update(final ResultSet observed, final Object arg) {
+		if (!observed.isOpen())
+			cache.remove(observed.getIdentifier());
+	}
+
+	public UniqueIdentifierGenerator getIdGenerator() {
+		return idGenerator;
+	}
+
+	public void setIdGenerator(final UniqueIdentifierGenerator idGenerator) {
+		this.idGenerator = idGenerator;
+	}
+
+	public Cache<String, Integer> getMaxIdleTimeCache() {
+		return maxIdleTimeCache;
+	}
+
+	@Required
+	public void setMaxIdleTimeCache(Cache<String, Integer> maxIdleTimeCache) {
+		this.maxIdleTimeCache = maxIdleTimeCache;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSetFactory.java	(revision 45117)
@@ -0,0 +1,21 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * creates a new push resultset.
+ *
+ * @author marko
+ *
+ */
+public interface PushResultSetFactory {
+
+	/**
+	 * create a new push resultset.
+	 *
+	 * @param maxIdleTime max time the resultset can be idle
+	 * @return push resultset epr
+	 */
+	W3CEndpointReference createPushResultSet(int maxIdleTime);
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistry.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistry.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistry.java	(revision 45117)
@@ -0,0 +1,75 @@
+package eu.dnetlib.enabling.resultset;
+
+import eu.dnetlib.enabling.resultset.observer.ResultSetObserver;
+
+/**
+ * Instances of ResultSetRegistry manage a set of resultset objects and manage their garbage collection.
+ *
+ * @author marko
+ *
+ */
+public interface ResultSetRegistry extends ResultSetObserver {
+	/**
+	 * add a resultset object to the registry.
+	 *
+	 * The given resultset object from now on is managed by the resultset registry.
+	 *
+	 * @param resultSet
+	 *            a resultset object
+	 */
+	void addResultSet(ResultSet resultSet);
+	
+	/**
+	 * add a resultset object to the registry.
+	 *
+	 * The given resultset object from now on is managed by the resultset registry.
+	 *
+	 * @param resultSet
+	 *            a resultset object
+	 * @param identifier the identifier you want for the resultset
+	 */
+	void addResultSet(ResultSet resultSet, String identifier);
+
+	/**
+	 * add a resultset object to the registry.
+	 *
+	 * The given resultset object from now on is managed by the resultset registry.
+	 *
+	 * @param resultSet
+	 *            a resultset object
+	 * @param maxIdleTime
+	 *            max idle time
+	 */
+	void addResultSet(ResultSet resultSet, int maxIdleTime);
+	
+	/**
+	 * add a resultset object to the registry.
+	 *
+	 * The given resultset object from now on is managed by the resultset registry.
+	 *
+	 * @param resultSet
+	 *            a resultset object
+	 * @param identifier the identifier you want for the resultset
+	 * @param maxIdleTime max idle time
+	 */
+	void addResultSet(ResultSet resultSet, String identifier, int maxIdleTime);
+
+	/**
+	 * obtain the resultset with the given id.
+	 *
+	 * @param rsId
+	 *            resultset id
+	 * @return the resultset object matching the rsId or null
+	 */
+	ResultSet getResultSetById(String rsId);
+
+	/**
+	 * obtain the resultset's maxIdleTime parameter for a resultset with the given id.
+	 *
+	 * @param rsId
+	 *            resultset id
+	 * @return max idle time in seconds, as specified when the resultset has been registered
+	 */
+	int getMaxIdleTimeById(String rsId);
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.xml
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.xml	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.xml	(revision 45117)
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
+	xmlns:sec="http://cxf.apache.org/configuration/security" xmlns:wsa="http://cxf.apache.org/ws/addressing"
+	xmlns:p="http://www.springframework.org/schema/p" xmlns:http="http://cxf.apache.org/transports/http/configuration"
+	xmlns:t="http://dnetlib.eu/springbeans/t" xmlns:template="http://dnetlib.eu/springbeans/template"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+                                    http://cxf.apache.org/ws/addressing http://cxf.apache.org/schemas/ws-addr-conf.xsd
+                                    http://cxf.apache.org/configuration/security http://cxf.apache.org/schemas/configuration/security.xsd
+                                    http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd
+                            http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
+                            http://dnetlib.eu/springbeans/template http://dnetlib.eu/springbeans/template.xsd">
+
+	<!-- beans -->
+	<bean id="resultSetCacheManager"
+		class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" />
+	<!-- p:configLocation="classpath:eu/dnetlib/enabling/resultset/ehcache.xml" -->
+
+	<bean id="resultSetRegistryCache" class="eu.dnetlib.miscutils.cache.EhCache">
+		<property name="cache">
+			<bean id="resultSetRegistryCacheCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"
+				p:cacheManager-ref="resultSetCacheManager" p:cacheName="resultSetFactoryCache"
+				p:eternal="false" p:timeToLive="0"
+				p:timeToIdle="${services.is.resultset.resultSetRegistryCache.timeToIdle}" />
+		</property>
+	</bean>
+
+	<bean id="resultSetRegistryMaxIdleTimeCache" class="eu.dnetlib.miscutils.cache.EhCache">
+		<property name="cache">
+			<bean id="resultSetRegistryMaxIdleTimeCacheCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"
+				p:cacheManager-ref="resultSetCacheManager" p:cacheName="resultSetFactoryMaxIdleTimeCache"
+				p:eternal="false" p:timeToLive="0"
+				p:timeToIdle="${services.is.resultset.resultSetRegistryMaxIdleTimeCache.timeToIdle}" />
+		</property>
+	</bean>
+
+	<!-- backing store for the pushResultSetDao -->
+	<bean id="pushResultSetStoreCache" class="eu.dnetlib.miscutils.cache.EhCache">
+		<property name="cache">
+			<bean id="pushResultSetStoreCacheCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"
+				p:eternal="false" p:timeToLive="0" p:timeToIdle="36000"
+				p:maxElementsInMemory="100" p:maxElementsOnDisk="20000"
+				p:cacheManager-ref="resultSetCacheManager" p:cacheName="pushResultSetStoreCache" />
+		</property>
+	</bean>
+
+	<!-- resultset descriptor store for the pushResultSetDao -->
+	<bean id="pushResultSetDescriptorCache" class="eu.dnetlib.miscutils.cache.EhCache">
+		<property name="cache">
+			<bean id="pushResultSetDescriptorCacheCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"
+				p:eternal="false" p:timeToLive="0" p:timeToIdle="1800"
+				p:cacheManager-ref="resultSetCacheManager" p:cacheName="pushResultSetDescriptorCache" />
+		</property>
+	</bean>
+
+	<bean id="resultSetDescriptorFactory" class="eu.dnetlib.springutils.beans.factory.PrototypeFactory">
+		<lookup-method name="newInstance" bean="resultSetDescriptorPrototype" />
+	</bean>
+
+	<bean id="resultSetDescriptorPrototype" class="eu.dnetlib.enabling.resultset.push.ResultSetDescriptor"
+		p:rangeLength="100" scope="prototype" />
+
+	<bean id="resultSetRegistry" class="eu.dnetlib.enabling.resultset.ResultSetRegistryImpl"
+		p:cache-ref="resultSetRegistryCache" p:maxIdleTimeCache-ref="resultSetRegistryMaxIdleTimeCache" />
+
+<!--
+  <bean id="resultSetEPRPool" class="eu.dnetlib.enabling.resultset.ResultSetEPRPool"
+   p:resultSetService-ref="resultSetService" />
+-->
+
+	<!-- <bean id="resultSetFactory" class="eu.dnetlib.enabling.resultset.LocalResultSetFactoryImpl" -->
+	<!-- <bean id="resultSetFactory" class="eu.dnetlib.enabling.resultset.EPRPoolingLocalResultSetFactoryImpl" p:pool-ref="resultSetEPRPool" 
+		p:resultSetService-ref="resultSetService" /> -->
+
+  <bean id="resultSetFactory" class="eu.dnetlib.enabling.resultset.LocalResultSetFactoryImpl" 
+		p:resultSetService-ref="resultSetService" /> 
+
+	<bean id="openResultSetFactory"
+		class="eu.dnetlib.enabling.resultset.LocalOpenResultSetFactoryImpl"
+		p:resultSetService-ref="resultSetService" />
+		
+<!--
+	<bean id="openResultSetFactory"
+		class="eu.dnetlib.enabling.resultset.EPRPoolingLocalOpenResultSetFactoryImpl" p:pool-ref="resultSetEPRPool"
+		p:resultSetService-ref="resultSetService" />
+-->
+	<bean id="mappedResultSetFactory" class="eu.dnetlib.enabling.resultset.MappedResultSetFactory"
+		p:serviceResolver-ref="serviceResolver" p:resultSetFactory-ref="resultSetFactory" />
+		
+	<bean id="parallelMappedResultSetFactory" class="eu.dnetlib.enabling.resultset.ParallelMappedResultSetFactory"
+		p:serviceResolver-ref="serviceResolver" p:resultSetFactory-ref="resultSetFactory" />		
+
+	<bean id="xsltResultSetFactory"
+		class="eu.dnetlib.enabling.resultset.XSLTMappedResultSetFactory"
+		p:serviceResolver-ref="serviceResolver" p:resultSetFactory-ref="resultSetFactory" />
+
+	<bean id="countingResultSetFactory" class="eu.dnetlib.enabling.resultset.CountingResultSetFactory"
+		p:serviceResolver-ref="serviceResolver" p:resultSetFactory-ref="resultSetFactory" />
+
+	<bean id="streamingResultSetFactory" class="eu.dnetlib.enabling.resultset.StreamingResultSetFactory"
+		p:resultSetFactory-ref="resultSetFactory" />
+
+	<bean id="cachingResultSetFactory" class="eu.dnetlib.enabling.resultset.CachingResultSetFactory"
+		p:resultSetFactory-ref="resultSetFactory" />
+
+	<bean id="pushResultSetFactory"
+		class="eu.dnetlib.enabling.resultset.push.TransientPushResultSetFactory"
+		p:dao-ref="pushResultSetDao" p:resultSetService-ref="resultSetService" />
+
+	<bean id="iterableResultSetFactory" class="eu.dnetlib.enabling.resultset.IterableResultSetFactory"
+		p:fetchSize="10" p:resultSetFactory-ref="openResultSetFactory"
+		lazy-init="true" />
+
+
+	<bean id="pushResultSetDao"
+		class="eu.dnetlib.enabling.resultset.push.CacheTransientResultSetDaoImpl"
+		p:cache-ref="pushResultSetStoreCache" p:resultSetCache-ref="pushResultSetDescriptorCache" />
+
+	<bean id="customResultSetPropertyDao" class="eu.dnetlib.enabling.resultset.ResultSetPropertyDaoImpl" />
+
+	<bean id="resultSetService" class="eu.dnetlib.enabling.resultset.ResultSetServiceImpl"
+		init-method="start" p:resultsetRegistry-ref="resultSetRegistry"
+		p:pushFactory-ref="pushResultSetFactory" p:endpoint-ref="resultSetServiceEndpoint"
+		p:eprBuilder-ref="jaxwsEndpointReferenceBuilder" p:customPropertyDao-ref="customResultSetPropertyDao" />
+		
+	<!-- endpoints -->
+	<jaxws:endpoint id="resultSetServiceEndpoint"
+		implementor="#resultSetService" implementorClass="eu.dnetlib.enabling.resultset.rmi.ResultSetService"
+		address="/resultSet" />
+
+	<template:instance name="serviceRegistrationManager"
+		t:serviceRegistrationManagerClass="eu.dnetlib.enabling.tools.registration.ValidatingServiceRegistrationManagerImpl"
+		t:name="resultSetServiceRegistrationManager" t:service="resultSetService"
+		t:endpoint="resultSetServiceEndpoint" t:jobScheduler="jobScheduler" />
+
+</beans>
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/push/AbstractTransientPushResultSetDaoTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/push/AbstractTransientPushResultSetDaoTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/push/AbstractTransientPushResultSetDaoTest.java	(revision 45117)
@@ -0,0 +1,223 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import static org.junit.Assert.*; // NOPMD
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.miscutils.cache.Cache;
+
+/**
+ * subclass this unit test class and provide a concrete transient push resultset dao implementation.
+ *
+ * @author marko
+ *
+ */
+@Ignore
+public abstract class AbstractTransientPushResultSetDaoTest {
+	/**
+	 * logger.
+	 */
+	private static final Log log = LogFactory.getLog(AbstractTransientPushResultSetDaoTest.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	/**
+	 * test first element.
+	 */
+	private static final String TWO = "two";
+
+	/**
+	 * test second element.
+	 */
+	private static final String ONE = "one";
+
+	/**
+	 * some key.
+	 */
+	private static final String RS_ID = "123";
+
+	/**
+	 * instance under test.
+	 */
+	private TransientPushResultSetDao dao;
+
+	/**
+	 * prepare the instance under test.
+	 *
+	 */
+	@Before
+	public void setUp() {
+		setDao(newInstance());
+	}
+
+	/**
+	 * specific unit tests will override this method and provide a concrete instance to test.
+	 *
+	 * @return new transient push resultset dao instance
+	 */
+	protected abstract TransientPushResultSetDao newInstance();
+
+	/**
+	 * test add elements.
+	 */
+	@Test
+	public void testAddElements() {
+		final List<String> freshGet = getDao().getElements(RS_ID, 1, 0);
+		assertNotNull("fresh get", freshGet);
+		assertEquals("fresh get", 0, freshGet.size());
+
+		final List<String> list = new ArrayList<String>();
+		list.add(ONE);
+
+		getDao().addElements(RS_ID, list);
+
+		final List<String> firstGet = getDao().getElements(RS_ID, 1, 1);
+		assertEquals("first get", 1, firstGet.size());
+		assertEquals("first get", ONE, firstGet.get(0));
+
+		final List<String> listAppend = new ArrayList<String>();
+		listAppend.add(TWO);
+
+		getDao().addElements(RS_ID, listAppend);
+
+		final List<String> secondGet = getDao().getElements(RS_ID, 1, 2);
+		assertEquals("second get", 2, secondGet.size());
+		assertEquals("second get", ONE, secondGet.get(0));
+		assertEquals("second get", TWO, secondGet.get(1));
+
+		final List<String> listBig = new ArrayList<String>();
+		for (int i = 0; i < 90; i++)
+			listBig.add(Integer.toString(i));
+
+		getDao().addElements(RS_ID, listBig);
+
+		final List<String> thirdGet = getDao().getElements(RS_ID, 3, 90);
+		assertEquals("third get", 88, thirdGet.size());
+		assertEquals("third get", "0", thirdGet.get(0));
+		assertEquals("third get", "1", thirdGet.get(1));
+	}
+
+	/**
+	 * check get elements.
+	 */
+	@Test
+	public void testGetElements() {
+		final List<String> list = new ArrayList<String>();
+		list.add(ONE);
+
+		getDao().addElements(RS_ID, list);
+
+		final List<String> res = getDao().getElements(RS_ID, 1, 1);
+		assertEquals("check size", 1, res.size());
+		assertEquals("check element", ONE, res.get(0));
+	}
+
+	/**
+	 * introduced for reproducing of #904. Thanks to Jochen for this one.
+	 */
+	@Test(expected = IllegalArgumentException.class)
+	public void testAddElementsDifferentSize() {
+		List<Integer> sizes = Lists.newArrayList(100, 200, 300, 99);
+		int run = 0;
+		int total = 0;
+
+		List<String> records = new LinkedList<String>();
+		for (int size : sizes) {
+			for (int i = 0; i < size; i++)
+				records.add("bla-" + run + "-" + i);
+
+			dao.addElements(RS_ID, records);
+			records.clear();
+
+			total += size;
+			run++;
+		}
+
+		assertEquals("check size", total, dao.getSize(RS_ID));
+	}
+
+	/**
+	 * introduced for reproducing of #904. with correct size (limited by 100)
+	 */
+	@Test
+	public void testAddElementsDifferentSizeCorrectSize() {
+		List<Integer> sizes = Lists.newArrayList(51, 51, 51, 51);
+
+		int total = 0;
+		int run = 0;
+		String lastName = null;
+
+		List<String> records = new LinkedList<String>();
+		for (int size : sizes) {
+			for (int i = 0; i < size; i++) {
+				lastName = "bla-" + run + "-" + i;
+				records.add(lastName);
+			}
+
+			dao.addElements(RS_ID, records);
+			records.clear();
+
+			total += size;
+			run++;
+		}
+
+		inspect();
+
+		assertEquals("check size", total, dao.getSize(RS_ID));
+		assertEquals("check last", lastName, dao.getElements(RS_ID, total, total).get(0));
+
+		assertEquals("check first page", "bla-0-11", dao.getElements(RS_ID, 12, 12).get(0));
+		assertEquals("check last page", "bla-1-11", dao.getElements(RS_ID, 51 + 12, 51 + 12).get(0));
+
+		assertEquals("check range", 10, dao.getElements(RS_ID, 1, 10).size());
+		assertEquals("check range", 10, dao.getElements(RS_ID, 51 + 1, 51 + 10).size());
+		assertEquals("check range", 51, dao.getElements(RS_ID, 1, 51).size());
+		assertEquals("check range", 52, dao.getElements(RS_ID, 1, 52).size());
+		assertEquals("check range", 51, dao.getElements(RS_ID, 2, 52).size());
+
+		assertEquals("check range", 100, dao.getElements(RS_ID, 1, 100).size());
+		assertEquals("check range", 99, dao.getElements(RS_ID, 2, 100).size());
+		assertEquals("check range", 100, dao.getElements(RS_ID, 2, 101).size());
+
+		assertEquals("check range", 200, dao.getElements(RS_ID, 2, 201).size());
+	}
+
+	private void inspect() {
+		CacheTransientResultSetDaoImpl dao = (CacheTransientResultSetDaoImpl) this.dao;
+		ResultSetDescriptor desc = dao.getResultSetCache().get(RS_ID);
+		Cache<String, List<String>> cache = dao.getCache();
+
+		log.debug("----------------");
+		log.debug("ranges: " + desc.getRanges());
+		log.debug("last range index: " + desc.getLastRange());
+		for (int i = 0; i < desc.getRanges(); i++) {
+			final List<String> range = cache.get(RS_ID + "-" + i);
+			log.debug("range: " + i + " has " + range.size() + " elements");
+			log.debug(" " + range);
+		}
+
+		log.debug("----------------");
+	}
+
+	@Test
+	public void testSizeOfEmpty() {
+		assertEquals("empty size", 0, dao.getSize(RS_ID));
+	}
+
+	public TransientPushResultSetDao getDao() {
+		return dao;
+	}
+
+	public void setDao(final TransientPushResultSetDao dao) {
+		this.dao = dao;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSet.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSet.java	(revision 45117)
@@ -0,0 +1,116 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * an open ResultSet that can be iterated to get it's data results.
+ * 
+ * @author claudio
+ * 
+ */
+public class IterableResultSet implements ResultSetListener, ResultSetAware {
+
+	/**
+	 * logger.
+	 */
+	private static final Log log = LogFactory.getLog(IterableResultSet.class);
+
+	/**
+	 * the container for the data results.
+	 */
+	private ResultSet resultSet;
+
+	/**
+	 * the list that provides data for this resultSet.
+	 */
+	private FetchList<String> fetchList;
+
+	private int optionalNumberOfElements;
+
+	/**
+	 * 
+	 * @param iter
+	 * @param fetchSize
+	 */
+	protected IterableResultSet(Iterable<String> iter, int fetchSize) {
+		fetchList = new FetchList<String>(iter.iterator(), fetchSize);
+		if (iter instanceof SizedIterable<?>) {
+			optionalNumberOfElements = ((SizedIterable<?>) iter).getNumberOfElements();
+		} else {
+			optionalNumberOfElements = -1;
+		}
+	}
+
+	/**
+	 * @param fromPosition
+	 * @param toPosition
+	 * @return <T> List
+	 */
+	@Override
+	public List<String> getResult(int fromPosition, int toPosition) {
+
+		log.debug(" - getting result from " + fromPosition + " to " + toPosition + ", consumedElements: " + fetchList.getConsumedElements());
+
+		if (fromPosition != fetchList.getConsumedElements() + 1)
+			throw new RuntimeException("Unexpected value for 'fromPosition' parameter");
+		if (toPosition < fromPosition)
+			throw new RuntimeException("'fromPosition' must be lower or equal than 'toPosition'");
+
+		List<String> result = new ArrayList<String>();
+
+		for (int i = fromPosition; i <= toPosition; i++) {
+			if (fetchList.size() > 0)
+				result.add(fetchList.poll());
+			else
+				break;
+		}
+
+		ensureClosed();
+
+		return result;
+	}
+
+	private void ensureClosed() {
+		if (fetchList.size() == 0 && resultSet.isOpen()) {
+			log.info(">>>>>>>>>>> closing resultset <<<<<<<<<<<<<");
+			close();
+		}
+	}
+
+	public String getRSStatus() {
+		if (resultSet.isOpen())
+			return "open";
+		return "closed";
+	}
+
+	@Override
+	public int getSize() {
+		ensureClosed();
+
+		if (optionalNumberOfElements == -1)
+			return fetchList.getTotalElements();
+		else
+			return optionalNumberOfElements;
+	}
+
+	/**
+	 * closes the resultset.
+	 */
+	protected void close() {
+		resultSet.close();
+	}
+
+	@Override
+	public void setResultSet(ResultSet resultSet) {
+		this.resultSet = resultSet;
+	}
+
+	public ResultSet getResultSet() {
+		return resultSet;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetListener.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetListener.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetListener.java	(revision 45117)
@@ -0,0 +1,132 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Exposes an iterable through our resultset protocol.
+ * 
+ * <p>
+ * The resultset protocol is constructed as if it were random access. Some kind of sources, like an iterable, is not
+ * random access. The consumer of such a resultset knows that, and won't try to access the resultset randomly. However,
+ * it could ask for some data which is already sent, because of retries caused by network issues.
+ * </p>
+ * 
+ * @author marko
+ * 
+ */
+public class StreamingResultSetListener implements ResultSetListener, ResultSetAware {
+	private static final Log log = LogFactory.getLog(StreamingResultSetListener.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	private ResultSet resultSet;
+
+	private Iterable<String> iterable;
+	private Iterator<String> items;
+	private int size;
+
+	private int lastFrom = 0;
+	private int lastTo = 0;
+	private List<String> lastChunk;
+
+	public StreamingResultSetListener(Iterable<String> items, int size) {
+		this(items.iterator(), size);
+		this.iterable = items;
+	}
+
+	public StreamingResultSetListener(Iterator<String> items, int size) {
+		super();
+		this.items = items;
+		this.size = size;
+	}
+
+	protected void reset() {
+		lastFrom = 0;
+		items = iterable.iterator();
+	}
+
+	@Override
+	public List<String> getResult(int from, int to) {
+
+		log.debug("STREAM: getResult(" + from + ", " + to + ")");
+
+		// handle retry because of network error.
+		if (from == lastFrom && to == lastTo)
+			return lastChunk;
+
+		if (from != lastTo + 1) {
+			if (from == 1 && iterable != null)
+				reset();
+			else
+				throw new IllegalArgumentException("this resultset is not random access, you can only retry last chunk only, asked from " + from + " to "
+						+ to + " but lastTo = " + lastTo + ". Size = " + size);
+		}
+
+		List<String> chunk = new ArrayList<String>();
+		for (int i = from; i <= to; i++)
+			chunk.add(items.next());
+
+		if (resultSet != null && !items.hasNext())
+			resultSet.close();
+
+		lastFrom = from;
+		lastTo = to;
+		lastChunk = chunk;
+
+		return chunk;
+	}
+
+	@Override
+	public int getSize() {
+		return size;
+	}
+
+	public void setSize(int size) {
+		this.size = size;
+	}
+
+	public Iterator<String> getItems() {
+		return items;
+	}
+
+	public void setItems(Iterator<String> items) {
+		this.items = items;
+	}
+
+	public int getLastFrom() {
+		return lastFrom;
+	}
+
+	public void setLastFrom(int lastFrom) {
+		this.lastFrom = lastFrom;
+	}
+
+	public int getLastTo() {
+		return lastTo;
+	}
+
+	public void setLastTo(int lastTo) {
+		this.lastTo = lastTo;
+	}
+
+	public List<String> getLastChunk() {
+		return lastChunk;
+	}
+
+	public void setLastChunk(List<String> lastChunk) {
+		this.lastChunk = lastChunk;
+	}
+
+	public ResultSet getResultSet() {
+		return resultSet;
+	}
+
+	@Override
+	public void setResultSet(ResultSet resultSet) {
+		this.resultSet = resultSet;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactoryTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactoryTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactoryTest.java	(revision 45117)
@@ -0,0 +1,139 @@
+package eu.dnetlib.enabling.resultset; // NOPMD
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.List;
+
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
+import eu.dnetlib.enabling.tools.ServiceResolver;
+
+/**
+ * test xslt resultset.
+ *
+ * @author marko
+ *
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class XSLTMappedResultSetFactoryTest {
+
+	/**
+	 * instance under test.
+	 */
+	private transient XSLTMappedResultSetFactory factory;
+
+	/**
+	 * resultset factory mock.
+	 */
+	@Mock
+	private transient ResultSetFactory resultSetFactory;
+
+	/**
+	 * service resolver.
+	 */
+	@Mock
+	private transient ServiceResolver serviceResolver;
+
+	/**
+	 * resultset service mock.
+	 */
+	@Mock
+	private transient ResultSetService resultSetService;
+	
+	/**
+	 * underlying resultSet mock
+	 */
+	@Mock
+	private transient ResultSet resultSet;
+
+	/**
+	 * Common setup.
+	 *
+	 */
+	@Before
+	public void setUp() {
+		factory = new XSLTMappedResultSetFactory();
+		factory.setResultSetFactory(resultSetFactory);
+		factory.setServiceResolver(serviceResolver);
+	}
+
+	/**
+	 * test invalid xslt.
+	 *
+	 * @throws TransformerConfigurationException
+	 *             could happen
+	 */
+	@Test(expected = IllegalStateException.class)
+	public void testInvalidXslt() throws TransformerConfigurationException {
+		factory.createMappedResultSet(null, "<bla/>");
+	}
+
+	/**
+	 * test xslt.
+	 *
+	 * @throws TransformerConfigurationException
+	 *             could happen
+	 * @throws IOException
+	 *             could happen
+	 * @throws ResultSetException mock
+	 */
+	@Test
+	public void testXslt() throws TransformerConfigurationException, IOException, ResultSetException {
+		when(serviceResolver.getService(eq(ResultSetService.class), (W3CEndpointReference) anyObject())).thenReturn(resultSetService);
+		when(serviceResolver.getResourceIdentifier((W3CEndpointReference) anyObject())).thenReturn("123");
+
+		when(resultSetService.getNumberOfElements(anyString())).thenReturn(1);
+		when(resultSetService.getResult("123", 1, 1, "waiting")).thenReturn(Lists.newArrayList("<first>something</first>"));
+		when(resultSetService.getRSStatus("123")).thenReturn("closed");
+		
+		when(resultSet.isOpen()).thenReturn(true);
+		
+		final StringWriter xsltSource = new StringWriter();
+		IOUtils.copy(getClass().getResourceAsStream("test.xsl"), xsltSource);
+		factory.createMappedResultSet(null, xsltSource.toString());
+
+		verify(resultSetFactory, times(1)).createResultSet(argThat(new ArgumentMatcher<ResultSetListener>() {
+
+			@Override
+			public boolean matches(final Object argument) {
+				final MappedResultSet listener = (MappedResultSet) argument;
+				listener.setResultSet(resultSet);
+				final List<String> res = listener.getResult(1, 1);
+
+				assertNotNull("null result", res);
+				assertFalse("empty result", res.isEmpty());
+
+				assertNotNull("null element", res.get(0));
+
+				assertTrue("transformed correctly", res.get(0).contains("<second>something</second>"));
+
+				return true;
+			}
+		}));
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/AbstractPushResultSetFactoryImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/AbstractPushResultSetFactoryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/AbstractPushResultSetFactoryImpl.java	(revision 45117)
@@ -0,0 +1,44 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.enabling.resultset.ResultSetServiceImpl;
+
+/**
+ * push resultset factory.
+ *
+ * @author marko
+ *
+ */
+public abstract class AbstractPushResultSetFactoryImpl implements PushResultSetFactory {
+	/**
+	 * resultset service.
+	 */
+	private ResultSetServiceImpl resultSetService;
+
+	/**
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.push.PushResultSetFactory#createPushResultSet(int)
+	 */
+	@Override
+	public W3CEndpointReference createPushResultSet(final int maxIdleTime) {
+		final PushResultSet resultSet = newInstance();
+		resultSetService.getResultsetRegistry().addResultSet(resultSet, maxIdleTime);
+		return resultSetService.getEprBuilder().getEndpointReference(resultSetService.getEndpoint(), resultSet.getIdentifier());
+	}
+
+	/**
+	 * subclasses should override it and create a new push resultset instance.
+	 * @return push resultset instance
+	 */
+	protected abstract PushResultSet newInstance();
+
+	public ResultSetServiceImpl getResultSetService() {
+		return resultSetService;
+	}
+
+	public void setResultSetService(final ResultSetServiceImpl resultSetService) {
+		this.resultSetService = resultSetService;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptor.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptor.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptor.java	(revision 45117)
@@ -0,0 +1,156 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import java.io.Serializable;
+import java.util.Iterator;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Describes a push resultset.
+ *
+ * <p>
+ * A push resultset stores it's data in several ranges
+ * </p>
+ *
+ * @author marko
+ *
+ */
+public class ResultSetDescriptor implements Serializable {
+
+	/**
+	 * logger.
+	 */
+	private static final Log log = LogFactory.getLog(Range.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	/**
+	 * This class describes a range.
+	 *
+	 * @author marko
+	 *
+	 */
+	public class Range {
+		private int range;
+		private int begin;
+		private int end;
+
+		public Range(final int range, final int begin, final int end) {
+			super();
+			this.range = range;
+			this.begin = begin;
+			this.end = end;
+		}
+
+		@Override
+		public String toString() {
+			return "Range(" + range + ", " + begin + ", " + end + ")";
+		}
+
+		public int getRange() {
+			return range;
+		}
+
+		public void setRange(final int range) {
+			this.range = range;
+		}
+
+		public int getBegin() {
+			return begin;
+		}
+
+		public void setBegin(final int begin) {
+			this.begin = begin;
+		}
+
+		public int getEnd() {
+			return end;
+		}
+
+		public void setEnd(final int end) {
+			this.end = end;
+		}
+	}
+
+	/**
+	 *
+	 */
+	private static final long serialVersionUID = 7699992350256317181L;
+
+	private int rangeLength = 100;
+
+	private int ranges = 0;
+
+	public int getLastRange() {
+		return ranges - 1;
+	}
+
+	/**
+	 * @param fromPosition
+	 *            1 based count
+	 * @param toPosition
+	 *            1 based count
+	 * @return
+	 */
+	public Iterable<Range> getRangesContaining(final int fromPosition, final int toPosition) {
+
+		final int fromRange = (fromPosition - 1) / rangeLength;
+		int ttoRange = (int) Math.ceil((toPosition * 1.0) / rangeLength);
+
+		if (ttoRange > ranges)
+			ttoRange = ranges;
+
+		final int toRange = ttoRange;
+
+		log.debug("FROM range: " + fromRange);
+		log.debug("TTO range: " + ttoRange);
+		log.debug("TO range: " + toRange);
+
+		return new Iterable<Range>() {
+
+			@Override
+			public Iterator<Range> iterator() {
+				return new Iterator<Range>() {
+
+					int current = fromRange;
+
+					@Override
+					public boolean hasNext() {
+						return current < toRange;
+					}
+
+					@Override
+					public Range next() {
+						int begin = 0;
+						int end = rangeLength;
+						if (current == fromRange)
+							begin = (fromPosition - 1) % rangeLength;
+						if ((current + 1) == toRange)
+							end = (toPosition - 1) % rangeLength + 1;
+						return new Range(current++, begin, end);
+					}
+
+					@Override
+					public void remove() {
+						throw new IllegalStateException("text");
+					}
+				};
+			}
+		};
+	}
+
+	public int getRangeLength() {
+		return rangeLength;
+	}
+
+	public void setRangeLength(final int rangeLength) {
+		this.rangeLength = rangeLength;
+	}
+
+	public int getRanges() {
+		return ranges;
+	}
+
+	public void setRanges(final int ranges) {
+		this.ranges = ranges;
+	}
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetDao.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetDao.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetDao.java	(revision 45117)
@@ -0,0 +1,45 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import java.util.List;
+
+/**
+ * offer access to the underlying in-memory or pseudo-memory (serialization backed caches) storage for the transient
+ * push-resultsets.
+ *
+ * This type of push resultsets doesn't even try to make efficient access to records, they just keep them as big lists
+ * on the underlying storage. Actual implementations may decide to keep them on the heap or to use some caching
+ * technology like ehcache.
+ *
+ * @author marko
+ *
+ */
+public interface TransientPushResultSetDao {
+	/**
+	 * add elements to a given key.
+	 *
+	 * @param key
+	 *            usually a rsid.
+	 * @param elements
+	 *            list of elements
+	 */
+	void addElements(String key, List<String> elements);
+
+	/**
+	 * obtain content for a given key (resultset) in a given range (1 based).
+	 *
+	 * @param key
+	 *            usually a rsid
+	 * @param fromPosition from position (1 based, inclusive)
+	 * @param toPosition to position (1 based, inclusive)
+	 * @return all the elements for a given key
+	 */
+	List<String> getElements(String key, int fromPosition, int toPosition);
+
+	/**
+	 * get the resultset size (number of elements).
+	 *
+	 * @param key usually a rsid
+	 * @return resultset size
+	 */
+	int getSize(String key);
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/JaxbResultsetListenerWrapper.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/JaxbResultsetListenerWrapper.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/JaxbResultsetListenerWrapper.java	(revision 45117)
@@ -0,0 +1,68 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import javax.xml.bind.JAXBException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.miscutils.collections.MappedCollection;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+import eu.dnetlib.miscutils.jaxb.JaxbFactory;
+
+/**
+ * Given a jaxb factory for a given type, wraps TypedResultsetListeners to ResultSetListeners, serializing objects
+ * according to the jaxb factory.
+ * 
+ * @author marko
+ * 
+ * @param <T>
+ */
+public class JaxbResultsetListenerWrapper<T> {
+	private static final Log log = LogFactory.getLog(JaxbResultsetListenerWrapper.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	private JaxbFactory<T> factory;
+
+	/**
+	 * Returns a listener which serializes each item according to the jaxb factory.
+	 * 
+	 * @param listener
+	 *            listener which returns T
+	 * @return listener which returns strings
+	 */
+	public ResultSetListener wrap(final TypedResultSetListener<T> listener) {
+		return new ResultSetListener() {
+
+			@Override
+			public List<String> getResult(final int fromPosition, final int toPosition) {
+				return Lists.newArrayList(new MappedCollection<String, T>(listener.getResult(fromPosition, toPosition), new UnaryFunction<String, T>() {
+					@Override
+					public String evaluate(final T value) {
+						try {
+							return factory.serialize(value);
+						} catch (final JAXBException e) {
+							log.warn("cannot serialize", e);
+							throw new RuntimeException(e);
+						}
+					}
+				}));
+			}
+
+			@Override
+			public int getSize() {
+				return listener.getSize();
+			}
+		};
+	}
+
+	public JaxbFactory<T> getFactory() {
+		return factory;
+	}
+
+	public void setFactory(final JaxbFactory<T> factory) {
+		this.factory = factory;
+	}
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSetFactory.java	(revision 45117)
@@ -0,0 +1,49 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+public class ParallelMappedResultSetFactory extends MappedResultSetFactory {
+
+	private ExecutorService executor;
+
+	private static final int QUEUE_SIZE = 40;
+
+	private int queueSize = QUEUE_SIZE;
+
+	private int cpus = 0;
+
+	public ParallelMappedResultSetFactory() {
+		super();
+
+		if (cpus == 0)
+			cpus = getNumberOfCPUs();
+		executor = new ThreadPoolExecutor(cpus, cpus, 5, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(queueSize),
+				new ThreadPoolExecutor.CallerRunsPolicy());
+	}
+
+	@Override
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final UnaryFunction<String, String> mapper) {
+		return getResultSetFactory().createResultSet(new ParallelMappedResultSet(source, mapper, getServiceResolver(), executor));
+	}
+
+	private int getNumberOfCPUs() {
+		return Runtime.getRuntime().availableProcessors();
+	}
+
+	public int getCpus() {
+		return cpus;
+	}
+
+	public void setCpus(int cpus) {
+		if(cpus > 0)
+			this.cpus = cpus;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDaoImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDaoImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDaoImpl.java	(revision 45117)
@@ -0,0 +1,23 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * fake resultset property dao.
+ * 
+ * @author marko
+ *
+ */
+public class ResultSetPropertyDaoImpl implements ResultSetPropertyDao {
+
+	/** 
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.ResultSetPropertyDao#getProperties(eu.dnetlib.enabling.resultset.ResultSet)
+	 */
+	@Override
+	public Map<String, String> getProperties(final ResultSet resultSet) {
+		return new HashMap<String, String>();
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSetFactory.java	(revision 45117)
@@ -0,0 +1,21 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * creates a new push resultset.
+ *
+ * @author marko
+ *
+ */
+public interface PushResultSetFactory {
+
+	/**
+	 * create a new push resultset.
+	 *
+	 * @param maxIdleTime max time the resultset can be idle
+	 * @return push resultset epr
+	 */
+	W3CEndpointReference createPushResultSet(int maxIdleTime);
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/StreamingResultSetListenerTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/StreamingResultSetListenerTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/java/eu/dnetlib/enabling/resultset/StreamingResultSetListenerTest.java	(revision 45117)
@@ -0,0 +1,62 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.*;
+
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+public class StreamingResultSetListenerTest {
+
+	private StreamingResultSetListener listener;
+	private List<String> data;
+
+	@Before
+	public void setUp() throws Exception {
+		data = Lists.newArrayList("uno", "due", "tre", "quattro");
+		listener = new StreamingResultSetListener(data.iterator(), data.size());
+	}
+
+	@Test
+	public void testGetResult() {
+		assertEquals(data.size(), listener.getSize());
+
+		final List<String> res = listener.getResult(1, 2);
+		assertEquals(2, res.size());
+		assertEquals("uno", res.get(0));
+		assertEquals("due", res.get(1));
+	}
+
+	@Test
+	public void testGetResult2() {
+		listener.getResult(1, 2);
+		final List<String> res = listener.getResult(3, 4);
+		assertEquals(2, res.size());
+		assertEquals("tre", res.get(0));
+		assertEquals("quattro", res.get(1));
+	}
+
+	@Test
+	public void testGetResult_retry() {
+		listener.getResult(1, 2);
+		final List<String> res = listener.getResult(1, 2);
+		assertEquals(2, res.size());
+		assertEquals("uno", res.get(0));
+		assertEquals("due", res.get(1));
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testGetResult_random() {
+		listener.getResult(1, 2);
+		listener.getResult(2, 3);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testGetResult_skip() {
+		listener.getResult(1, 2);
+		listener.getResult(4, 4);
+	}
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/JaxbResultsetListenerWrapper.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/JaxbResultsetListenerWrapper.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/JaxbResultsetListenerWrapper.java	(revision 45117)
@@ -0,0 +1,68 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import javax.xml.bind.JAXBException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.miscutils.collections.MappedCollection;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+import eu.dnetlib.miscutils.jaxb.JaxbFactory;
+
+/**
+ * Given a jaxb factory for a given type, wraps TypedResultsetListeners to ResultSetListeners, serializing objects
+ * according to the jaxb factory.
+ * 
+ * @author marko
+ * 
+ * @param <T>
+ */
+public class JaxbResultsetListenerWrapper<T> {
+	private static final Log log = LogFactory.getLog(JaxbResultsetListenerWrapper.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	private JaxbFactory<T> factory;
+
+	/**
+	 * Returns a listener which serializes each item according to the jaxb factory.
+	 * 
+	 * @param listener
+	 *            listener which returns T
+	 * @return listener which returns strings
+	 */
+	public ResultSetListener wrap(final TypedResultSetListener<T> listener) {
+		return new ResultSetListener() {
+
+			@Override
+			public List<String> getResult(final int fromPosition, final int toPosition) {
+				return Lists.newArrayList(new MappedCollection<String, T>(listener.getResult(fromPosition, toPosition), new UnaryFunction<String, T>() {
+					@Override
+					public String evaluate(final T value) {
+						try {
+							return factory.serialize(value);
+						} catch (final JAXBException e) {
+							log.warn("cannot serialize", e);
+							throw new RuntimeException(e);
+						}
+					}
+				}));
+			}
+
+			@Override
+			public int getSize() {
+				return listener.getSize();
+			}
+		};
+	}
+
+	public JaxbFactory<T> getFactory() {
+		return factory;
+	}
+
+	public void setFactory(final JaxbFactory<T> factory) {
+		this.factory = factory;
+	}
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/resources/eu/dnetlib/enabling/resultset/test.xsl
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/resources/eu/dnetlib/enabling/resultset/test.xsl	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1/src/test/resources/eu/dnetlib/enabling/resultset/test.xsl	(revision 45117)
@@ -0,0 +1,6 @@
+<xsl:stylesheet version="1.0"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+	<xsl:template match="first">
+		<second><xsl:value-of select="."/></second>
+	</xsl:template>
+</xsl:stylesheet>
\ No newline at end of file
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1	(revision 45117)

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.1
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,5 ##
+.project
+.classpath
+.settings
+target
+
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/deploy.info
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/deploy.info	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/deploy.info	(revision 45117)
@@ -0,0 +1 @@
+{"type_source": "SVN", "goal": "package -U -T 4C source:jar", "url": "http://svn-public.driver.research-infrastructures.eu/driver/dnet40/modules/cnr-resultset-service/trunk/", "deploy_repository": "dnet4-snapshots", "version": "4", "mail": "sandro.labruzzo@isti.cnr.it,michele.artini@isti.cnr.it, claudio.atzori@isti.cnr.it, alessia.bardi@isti.cnr.it", "deploy_repository_url": "http://maven.research-infrastructures.eu/nexus/content/repositories/dnet4-snapshots", "name": "cnr-resultset-service"}
\ No newline at end of file
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/observer/ResultSetObserver.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/observer/ResultSetObserver.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/observer/ResultSetObserver.java	(revision 45117)
@@ -0,0 +1,23 @@
+package eu.dnetlib.enabling.resultset.observer;
+
+import eu.dnetlib.enabling.resultset.ResultSet;
+
+
+/**
+ * Implement the same interface as JDK java.util.Observer as java interface (not as a class) and introduce static type
+ * safeness through generics.
+ * 
+ * @author marko, claudio, alessia, michele
+ * 
+ */
+public interface ResultSetObserver {
+	/**
+	 * gets notified when an observed object is updated.
+	 * 
+	 * @param observed
+	 *            observed object which modification triggered this call.
+	 * @param arg
+	 *            arg
+	 */
+	void update(ResultSet observed, Object arg);
+}

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/observer/ResultSetObserver.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImpl.java	(revision 45117)
@@ -0,0 +1,123 @@
+package eu.dnetlib.enabling.resultset;
+
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.enabling.tools.UniqueIdentifierGenerator;
+import eu.dnetlib.enabling.tools.UniqueIdentifierGeneratorImpl;
+import eu.dnetlib.miscutils.cache.Cache;
+
+/**
+ * Implement a in memory resultset registry.
+ *
+ * @author marko
+ *
+ */
+public class ResultSetRegistryImpl implements ResultSetRegistry {
+
+	/**
+	 * rsId -> ResultSet mappings are stored here.
+	 */
+	private Cache<String, ResultSet> cache;
+
+	/**
+	 * rsID -> initial maxIdleTime time are store here.
+	 */
+	private Cache<String, Integer> maxIdleTimeCache;
+
+	/**
+	 * identifier generator.
+	 */
+	private UniqueIdentifierGenerator idGenerator = new UniqueIdentifierGeneratorImpl("rs-");
+
+	/**
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.ResultSetRegistry#addResultSet(eu.dnetlib.enabling.resultset.ResultSet)
+	 */
+	@Override
+	public void addResultSet(final ResultSet resultSet) {
+		addResultSet(resultSet, 0);
+	}
+
+	/** 
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.ResultSetRegistry#addResultSet(eu.dnetlib.enabling.resultset.ResultSet, java.lang.String)
+	 */
+	@Override
+	public void addResultSet(final ResultSet resultSet, final String identifier) {
+		addResultSet(resultSet, identifier, 0);
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.ResultSetRegistry#addResultSet(eu.dnetlib.enabling.resultset.ResultSet, int)
+	 */
+	@Override
+	public void addResultSet(final ResultSet resultSet, final int maxIdleTime) {
+		addResultSet(resultSet, idGenerator.generateIdentifier(), maxIdleTime);
+	}
+	
+	/** 
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.ResultSetRegistry#addResultSet(eu.dnetlib.enabling.resultset.ResultSet, java.lang.String, int)
+	 */
+	@Override
+	public void addResultSet(final ResultSet resultSet, final String identifier, final int maxIdleTime) {
+		resultSet.setIdentifier(identifier);
+		resultSet.addObserver(this);
+		cache.put(resultSet.getIdentifier(), resultSet);
+		maxIdleTimeCache.put(resultSet.getIdentifier(), maxIdleTime);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see eu.dnetlib.enabling.resultset.ResultSetRegistry#getResultSetById(java.lang.String)
+	 */
+	@Override
+	public ResultSet getResultSetById(final String rsId) {
+		return cache.get(rsId);
+	}
+
+	@Override
+	public int getMaxIdleTimeById(final String rsId) {
+		return maxIdleTimeCache.get(rsId);
+	}
+
+
+	public Cache<String, ResultSet> getCache() {
+		return cache;
+	}
+
+	@Required
+	public void setCache(final Cache<String, ResultSet> cache) {
+		this.cache = cache;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.miscutils.observer.Observer#update(eu.dnetlib.enabling.resultset.observer.Observable, java.lang.Object)
+	 */
+	@Override
+	public void update(final ResultSet observed, final Object arg) {
+		if (!observed.isOpen())
+			cache.remove(observed.getIdentifier());
+	}
+
+	public UniqueIdentifierGenerator getIdGenerator() {
+		return idGenerator;
+	}
+
+	public void setIdGenerator(final UniqueIdentifierGenerator idGenerator) {
+		this.idGenerator = idGenerator;
+	}
+
+	public Cache<String, Integer> getMaxIdleTimeCache() {
+		return maxIdleTimeCache;
+	}
+
+	@Required
+	public void setMaxIdleTimeCache(Cache<String, Integer> maxIdleTimeCache) {
+		this.maxIdleTimeCache = maxIdleTimeCache;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalOpenResultSetFactoryImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalOpenResultSetFactoryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalOpenResultSetFactoryImpl.java	(revision 45117)
@@ -0,0 +1,23 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+public class EPRPoolingLocalOpenResultSetFactoryImpl extends LocalOpenResultSetFactoryImpl {
+	private ResultSetEPRPool pool;
+	
+	@Override
+	public W3CEndpointReference registerResultSet(ResultSet resultSet) {
+		return pool.registerResultSet(resultSet);
+	}
+
+	public ResultSetEPRPool getPool() {
+		return pool;
+	}
+
+	@Required
+	public void setPool(ResultSetEPRPool pool) {
+		this.pool = pool;
+	}
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSet.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSet.java	(revision 45117)
@@ -0,0 +1,116 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * an open ResultSet that can be iterated to get it's data results.
+ * 
+ * @author claudio
+ * 
+ */
+public class IterableResultSet implements ResultSetListener, ResultSetAware {
+
+	/**
+	 * logger.
+	 */
+	private static final Log log = LogFactory.getLog(IterableResultSet.class);
+
+	/**
+	 * the container for the data results.
+	 */
+	private ResultSet resultSet;
+
+	/**
+	 * the list that provides data for this resultSet.
+	 */
+	private FetchList<String> fetchList;
+
+	private int optionalNumberOfElements;
+
+	/**
+	 * 
+	 * @param iter
+	 * @param fetchSize
+	 */
+	protected IterableResultSet(Iterable<String> iter, int fetchSize) {
+		fetchList = new FetchList<String>(iter.iterator(), fetchSize);
+		if (iter instanceof SizedIterable<?>) {
+			optionalNumberOfElements = ((SizedIterable<?>) iter).getNumberOfElements();
+		} else {
+			optionalNumberOfElements = -1;
+		}
+	}
+
+	/**
+	 * @param fromPosition
+	 * @param toPosition
+	 * @return <T> List
+	 */
+	@Override
+	public List<String> getResult(int fromPosition, int toPosition) {
+
+		log.debug(" - getting result from " + fromPosition + " to " + toPosition + ", consumedElements: " + fetchList.getConsumedElements());
+
+		if (fromPosition != fetchList.getConsumedElements() + 1)
+			throw new RuntimeException("Unexpected value for 'fromPosition' parameter");
+		if (toPosition < fromPosition)
+			throw new RuntimeException("'fromPosition' must be lower or equal than 'toPosition'");
+
+		List<String> result = new ArrayList<String>();
+
+		for (int i = fromPosition; i <= toPosition; i++) {
+			if (fetchList.size() > 0)
+				result.add(fetchList.poll());
+			else
+				break;
+		}
+
+		ensureClosed();
+
+		return result;
+	}
+
+	private void ensureClosed() {
+		if (fetchList.size() == 0 && resultSet.isOpen()) {
+			log.info(">>>>>>>>>>> closing resultset <<<<<<<<<<<<<");
+			close();
+		}
+	}
+
+	public String getRSStatus() {
+		if (resultSet.isOpen())
+			return "open";
+		return "closed";
+	}
+
+	@Override
+	public int getSize() {
+		ensureClosed();
+
+		if (optionalNumberOfElements == -1)
+			return fetchList.getTotalElements();
+		else
+			return optionalNumberOfElements;
+	}
+
+	/**
+	 * closes the resultset.
+	 */
+	protected void close() {
+		resultSet.close();
+	}
+
+	@Override
+	public void setResultSet(ResultSet resultSet) {
+		this.resultSet = resultSet;
+	}
+
+	public ResultSet getResultSet() {
+		return resultSet;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSetFactory.java	(revision 45117)
@@ -0,0 +1,26 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * Create a new resultset which takes each record of the input resultset and counts them.
+ * 
+ * @author claudio
+ * 
+ */
+public class CountingResultSetFactory extends MappedResultSetFactory {
+
+	/**
+	 * Create a new resultset which takes each record of the input resultset and counts them.
+	 * 
+	 * @param source
+	 *            source resultset epr
+	 * @param mapper
+	 *            mapper function
+	 * @return mapped resultset epr
+	 */
+	public W3CEndpointReference createCountingResultSet(final W3CEndpointReference source) {
+		return getResultSetFactory().createResultSet(new CountingResultSet(source, getServiceResolver()));
+	}
+
+}

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSetFactory.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/AbstractPushResultSetFactoryImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/AbstractPushResultSetFactoryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/AbstractPushResultSetFactoryImpl.java	(revision 45117)
@@ -0,0 +1,44 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.enabling.resultset.ResultSetServiceImpl;
+
+/**
+ * push resultset factory.
+ *
+ * @author marko
+ *
+ */
+public abstract class AbstractPushResultSetFactoryImpl implements PushResultSetFactory {
+	/**
+	 * resultset service.
+	 */
+	private ResultSetServiceImpl resultSetService;
+
+	/**
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.push.PushResultSetFactory#createPushResultSet(int)
+	 */
+	@Override
+	public W3CEndpointReference createPushResultSet(final int maxIdleTime) {
+		final PushResultSet resultSet = newInstance();
+		resultSetService.getResultsetRegistry().addResultSet(resultSet, maxIdleTime);
+		return resultSetService.getEprBuilder().getEndpointReference(resultSetService.getEndpoint(), resultSet.getIdentifier());
+	}
+
+	/**
+	 * subclasses should override it and create a new push resultset instance.
+	 * @return push resultset instance
+	 */
+	protected abstract PushResultSet newInstance();
+
+	public ResultSetServiceImpl getResultSetService() {
+		return resultSetService;
+	}
+
+	public void setResultSetService(final ResultSetServiceImpl resultSetService) {
+		this.resultSetService = resultSetService;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSetFactory.java	(revision 45117)
@@ -0,0 +1,49 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+public class ParallelMappedResultSetFactory extends MappedResultSetFactory {
+
+	private ExecutorService executor;
+
+	private static final int QUEUE_SIZE = 40;
+
+	private int queueSize = QUEUE_SIZE;
+
+	private int cpus = 0;
+
+	public ParallelMappedResultSetFactory() {
+		super();
+
+		if (cpus == 0)
+			cpus = getNumberOfCPUs();
+		executor = new ThreadPoolExecutor(cpus, cpus, 5, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(queueSize),
+				new ThreadPoolExecutor.CallerRunsPolicy());
+	}
+
+	@Override
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final UnaryFunction<String, String> mapper) {
+		return getResultSetFactory().createResultSet(new ParallelMappedResultSet(source, mapper, getServiceResolver(), executor));
+	}
+
+	private int getNumberOfCPUs() {
+		return Runtime.getRuntime().availableProcessors();
+	}
+
+	public int getCpus() {
+		return cpus;
+	}
+
+	public void setCpus(int cpus) {
+		if(cpus > 0)
+			this.cpus = cpus;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetDao.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetDao.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetDao.java	(revision 45117)
@@ -0,0 +1,45 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import java.util.List;
+
+/**
+ * offer access to the underlying in-memory or pseudo-memory (serialization backed caches) storage for the transient
+ * push-resultsets.
+ *
+ * This type of push resultsets doesn't even try to make efficient access to records, they just keep them as big lists
+ * on the underlying storage. Actual implementations may decide to keep them on the heap or to use some caching
+ * technology like ehcache.
+ *
+ * @author marko
+ *
+ */
+public interface TransientPushResultSetDao {
+	/**
+	 * add elements to a given key.
+	 *
+	 * @param key
+	 *            usually a rsid.
+	 * @param elements
+	 *            list of elements
+	 */
+	void addElements(String key, List<String> elements);
+
+	/**
+	 * obtain content for a given key (resultset) in a given range (1 based).
+	 *
+	 * @param key
+	 *            usually a rsid
+	 * @param fromPosition from position (1 based, inclusive)
+	 * @param toPosition to position (1 based, inclusive)
+	 * @return all the elements for a given key
+	 */
+	List<String> getElements(String key, int fromPosition, int toPosition);
+
+	/**
+	 * get the resultset size (number of elements).
+	 *
+	 * @param key usually a rsid
+	 * @return resultset size
+	 */
+	int getSize(String key);
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDaoImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDaoImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDaoImpl.java	(revision 45117)
@@ -0,0 +1,23 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * fake resultset property dao.
+ * 
+ * @author marko
+ *
+ */
+public class ResultSetPropertyDaoImpl implements ResultSetPropertyDao {
+
+	/** 
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.ResultSetPropertyDao#getProperties(eu.dnetlib.enabling.resultset.ResultSet)
+	 */
+	@Override
+	public Map<String, String> getProperties(final ResultSet resultSet) {
+		return new HashMap<String, String>();
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/FetchList.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/FetchList.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/FetchList.java	(revision 45117)
@@ -0,0 +1,102 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+
+/**
+ * a LinkedList populated by a given iterable, which provides a fetch window of elements
+ * 
+ * @author claudio
+ * 
+ * @param <T>
+ *            The FetchList type
+ */
+public class FetchList<T> extends LinkedList<T> {
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 7135272008563693321L;
+
+	/**
+	 * represents the number of elements ready to be pulled out of the list
+	 */
+	private int fetchSize;
+
+	/**
+	 * represents the number of elements already consumed by a poll call
+	 */
+	private int consumedElements;
+
+	/**
+	 * the given itarable used to populate the list
+	 */
+	private Iterator<T> iter;
+
+	/**
+	 * @param iter
+	 * @param fetchSize
+	 */
+	public FetchList(Iterator<T> iter, int fetchSize) {
+		super();
+		this.consumedElements = 0;
+		this.fetchSize = fetchSize;
+		this.iter = iter;
+	}
+
+	/**
+	 * used to fill the list
+	 */
+	public void fill() {
+		for (int i = 0; i < fetchSize; i++) {
+			if (!iter.hasNext())
+				break;
+			this.add(iter.next());
+		}
+	}
+
+	/**
+	 * return the first element and makes the list to be filled in case its size is zero
+	 */
+	@Override
+	public T poll() {
+		if (this.isEmpty())
+			fill();
+
+		if (this.size() > 0) {
+			consumedElements++;
+			return super.poll();
+		}
+		return null;
+	}
+
+	/**
+	 * @return the number of elements already consumed by a "poll"
+	 */
+	public int getConsumedElements() {
+		return consumedElements;
+	}
+
+	/**
+	 * @return the actual number of elements of the list
+	 */
+	public int getTotalElements() {
+		return consumedElements + this.size();
+	}
+
+	/**
+	 * to provide an actual size, fills the list if there are elements to fill it
+	 */
+	@Override
+	public int size() {
+		if (this.isEmpty() && iter.hasNext())
+			fill();
+		return super.size();
+	}
+
+	@Override
+	public boolean isEmpty() {
+		return super.size() == 0;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalOpenResultSetFactoryImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalOpenResultSetFactoryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalOpenResultSetFactoryImpl.java	(revision 45117)
@@ -0,0 +1,23 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+public class EPRPoolingLocalOpenResultSetFactoryImpl extends LocalOpenResultSetFactoryImpl {
+	private ResultSetEPRPool pool;
+	
+	@Override
+	public W3CEndpointReference registerResultSet(ResultSet resultSet) {
+		return pool.registerResultSet(resultSet);
+	}
+
+	public ResultSetEPRPool getPool() {
+		return pool;
+	}
+
+	@Required
+	public void setPool(ResultSetEPRPool pool) {
+		this.pool = pool;
+	}
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSetFactory.java	(revision 45117)
@@ -0,0 +1,26 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * Create a new resultset which takes each record of the input resultset and counts them.
+ * 
+ * @author claudio
+ * 
+ */
+public class CountingResultSetFactory extends MappedResultSetFactory {
+
+	/**
+	 * Create a new resultset which takes each record of the input resultset and counts them.
+	 * 
+	 * @param source
+	 *            source resultset epr
+	 * @param mapper
+	 *            mapper function
+	 * @return mapped resultset epr
+	 */
+	public W3CEndpointReference createCountingResultSet(final W3CEndpointReference source) {
+		return getResultSetFactory().createResultSet(new CountingResultSet(source, getServiceResolver()));
+	}
+
+}

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSetFactory.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetListener.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetListener.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetListener.java	(revision 45117)
@@ -0,0 +1,15 @@
+package eu.dnetlib.enabling.resultset;
+
+
+/**
+ * A ResultSetListener is a pull interface to a ResultSet.
+ * 
+ * The Resultset will call method of ResultSetListener implementors whenever it needs to pull some data and provide it
+ * to clients. The ResultSet service acts as a decouple point between the producer and the consumer.
+ * 
+ * @author marko
+ * 
+ */
+public interface ResultSetListener extends TypedResultSetListener<String> {
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/TypedResultSetListener.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/TypedResultSetListener.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/TypedResultSetListener.java	(revision 45117)
@@ -0,0 +1,34 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+/**
+ * A TypedResultSetListener is a pull interface to a ResultSet.
+ * 
+ * The Resultset will call method of ResultSetListener implementors whenever it needs to pull some data and provide it
+ * to clients. The ResultSet service acts as a decouple point between the producer and the consumer.
+ * 
+ * @author marko
+ * 
+ */
+public interface TypedResultSetListener<T> {
+
+	/**
+	 * get a single page of results.
+	 * 
+	 * @param fromPosition
+	 *            from 1
+	 * @param toPosition
+	 *            last included
+	 * @return page of results
+	 */
+	List<T> getResult(int fromPosition, int toPosition);
+
+	/**
+	 * get number of elements.
+	 * 
+	 * @return number of elements
+	 */
+	int getSize();
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetListener.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetListener.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetListener.java	(revision 45117)
@@ -0,0 +1,15 @@
+package eu.dnetlib.enabling.resultset;
+
+
+/**
+ * A ResultSetListener is a pull interface to a ResultSet.
+ * 
+ * The Resultset will call method of ResultSetListener implementors whenever it needs to pull some data and provide it
+ * to clients. The ResultSet service acts as a decouple point between the producer and the consumer.
+ * 
+ * @author marko
+ * 
+ */
+public interface ResultSetListener extends TypedResultSetListener<String> {
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSetFactory.java	(revision 45117)
@@ -0,0 +1,67 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+/**
+ * 
+ * @author claudio
+ *
+ */
+public class IterableResultSetFactory {
+
+	/**
+	 * {@link ResultSetFactory}
+	 */
+	private LocalOpenResultSetFactoryImpl resultSetFactory;
+	
+	/**
+	 * 
+	 */
+	private int fetchSize;
+	
+	/**
+	 * 
+	 * @param source
+	 * @return
+	 */
+	public W3CEndpointReference createIterableResultSet(final Iterable<String> source) {
+		return resultSetFactory.createResultSet(new IterableResultSet(source, fetchSize));
+	}
+	
+	/**
+	 * 
+	 * @return
+	 */
+	public LocalOpenResultSetFactoryImpl getResultSetFactory() {
+		return resultSetFactory;
+	}
+
+	/**
+	 * 
+	 * @param resultSetFactory
+	 */
+	@Required
+	public void setResultSetFactory(final LocalOpenResultSetFactoryImpl resultSetFactory) {
+		this.resultSetFactory = resultSetFactory;
+	}
+	
+	/**
+	 * 
+	 * @param fetchSize
+	 */
+	@Required
+	public void setFetchSize(int fetchSize) {
+		this.fetchSize = fetchSize;
+	}
+
+	/**
+	 * 
+	 * @return
+	 */
+	public int getFetchSize() {
+		return fetchSize;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetAware.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetAware.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetAware.java	(revision 45117)
@@ -0,0 +1,16 @@
+package eu.dnetlib.enabling.resultset;
+
+/**
+ * ResultSet listeners can add this interface in order to receive the ResultSet they are bound to.
+ * 
+ * @author marko
+ *
+ */
+public interface ResultSetAware {
+	/**
+	 * sets the resultset instance.
+	 * 
+	 * @param resultSet the resultset instance
+	 */
+	void setResultSet(ResultSet resultSet);
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/IterableResultSetFactory.java	(revision 45117)
@@ -0,0 +1,67 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+/**
+ * 
+ * @author claudio
+ *
+ */
+public class IterableResultSetFactory {
+
+	/**
+	 * {@link ResultSetFactory}
+	 */
+	private LocalOpenResultSetFactoryImpl resultSetFactory;
+	
+	/**
+	 * 
+	 */
+	private int fetchSize;
+	
+	/**
+	 * 
+	 * @param source
+	 * @return
+	 */
+	public W3CEndpointReference createIterableResultSet(final Iterable<String> source) {
+		return resultSetFactory.createResultSet(new IterableResultSet(source, fetchSize));
+	}
+	
+	/**
+	 * 
+	 * @return
+	 */
+	public LocalOpenResultSetFactoryImpl getResultSetFactory() {
+		return resultSetFactory;
+	}
+
+	/**
+	 * 
+	 * @param resultSetFactory
+	 */
+	@Required
+	public void setResultSetFactory(final LocalOpenResultSetFactoryImpl resultSetFactory) {
+		this.resultSetFactory = resultSetFactory;
+	}
+	
+	/**
+	 * 
+	 * @param fetchSize
+	 */
+	@Required
+	public void setFetchSize(int fetchSize) {
+		this.fetchSize = fetchSize;
+	}
+
+	/**
+	 * 
+	 * @return
+	 */
+	public int getFetchSize() {
+		return fetchSize;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.properties
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.properties	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.properties	(revision 45117)
@@ -0,0 +1,6 @@
+services.is.resultset.resultSetRegistryCache.timeToIdle = 240
+services.is.resultset.resultSetRegistryMaxIdleTimeCache.timeToIdle = 240
+
+# jaxwsEndpointReferenceBuilder | staticResultSetServiceEprBuilder
+services.resultset.eprbuilder.bean = jaxwsEndpointReferenceBuilder
+services.resultset.endpoint.static.address = ${transport.soap.baseAddress}/resultSet
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetAware.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetAware.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetAware.java	(revision 45117)
@@ -0,0 +1,16 @@
+package eu.dnetlib.enabling.resultset;
+
+/**
+ * ResultSet listeners can add this interface in order to receive the ResultSet they are bound to.
+ * 
+ * @author marko
+ *
+ */
+public interface ResultSetAware {
+	/**
+	 * sets the resultset instance.
+	 * 
+	 * @param resultSet the resultset instance
+	 */
+	void setResultSet(ResultSet resultSet);
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/FetchList.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/FetchList.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/FetchList.java	(revision 45117)
@@ -0,0 +1,102 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+
+/**
+ * a LinkedList populated by a given iterable, which provides a fetch window of elements
+ * 
+ * @author claudio
+ * 
+ * @param <T>
+ *            The FetchList type
+ */
+public class FetchList<T> extends LinkedList<T> {
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 7135272008563693321L;
+
+	/**
+	 * represents the number of elements ready to be pulled out of the list
+	 */
+	private int fetchSize;
+
+	/**
+	 * represents the number of elements already consumed by a poll call
+	 */
+	private int consumedElements;
+
+	/**
+	 * the given itarable used to populate the list
+	 */
+	private Iterator<T> iter;
+
+	/**
+	 * @param iter
+	 * @param fetchSize
+	 */
+	public FetchList(Iterator<T> iter, int fetchSize) {
+		super();
+		this.consumedElements = 0;
+		this.fetchSize = fetchSize;
+		this.iter = iter;
+	}
+
+	/**
+	 * used to fill the list
+	 */
+	public void fill() {
+		for (int i = 0; i < fetchSize; i++) {
+			if (!iter.hasNext())
+				break;
+			this.add(iter.next());
+		}
+	}
+
+	/**
+	 * return the first element and makes the list to be filled in case its size is zero
+	 */
+	@Override
+	public T poll() {
+		if (this.isEmpty())
+			fill();
+
+		if (this.size() > 0) {
+			consumedElements++;
+			return super.poll();
+		}
+		return null;
+	}
+
+	/**
+	 * @return the number of elements already consumed by a "poll"
+	 */
+	public int getConsumedElements() {
+		return consumedElements;
+	}
+
+	/**
+	 * @return the actual number of elements of the list
+	 */
+	public int getTotalElements() {
+		return consumedElements + this.size();
+	}
+
+	/**
+	 * to provide an actual size, fills the list if there are elements to fill it
+	 */
+	@Override
+	public int size() {
+		if (this.isEmpty() && iter.hasNext())
+			fill();
+		return super.size();
+	}
+
+	@Override
+	public boolean isEmpty() {
+		return super.size() == 0;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/LocalOpenResultSetFactoryImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/LocalOpenResultSetFactoryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/LocalOpenResultSetFactoryImpl.java	(revision 45117)
@@ -0,0 +1,23 @@
+package eu.dnetlib.enabling.resultset;
+
+/**
+ * Creates an "open" (unbounded, unfreezed) local resultset.
+ * 
+ * @author marko
+ *
+ */
+public class LocalOpenResultSetFactoryImpl extends LocalResultSetFactoryImpl {
+
+	/** 
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.LocalResultSetFactoryImpl#createInstance(eu.dnetlib.enabling.resultset.ResultSetListener)
+	 */
+	@Override
+	protected LocalResultSetImpl createInstance(final ResultSetListener provider) {
+		final LocalResultSetImpl instance = super.createInstance(provider);
+		instance.setOpen(true);
+		return instance;
+	}
+
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/TypedResultSetListener.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/TypedResultSetListener.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/TypedResultSetListener.java	(revision 45117)
@@ -0,0 +1,34 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+/**
+ * A TypedResultSetListener is a pull interface to a ResultSet.
+ * 
+ * The Resultset will call method of ResultSetListener implementors whenever it needs to pull some data and provide it
+ * to clients. The ResultSet service acts as a decouple point between the producer and the consumer.
+ * 
+ * @author marko
+ * 
+ */
+public interface TypedResultSetListener<T> {
+
+	/**
+	 * get a single page of results.
+	 * 
+	 * @param fromPosition
+	 *            from 1
+	 * @param toPosition
+	 *            last included
+	 * @return page of results
+	 */
+	List<T> getResult(int fromPosition, int toPosition);
+
+	/**
+	 * get number of elements.
+	 * 
+	 * @return number of elements
+	 */
+	int getSize();
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetFactory.java	(revision 45117)
@@ -0,0 +1,19 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * Creates a resultset service from a producer.
+ * 
+ * @author marko
+ *
+ */
+public interface ResultSetFactory {
+	/**
+	 * TODO other parameters like expiration time etc.
+	 * 
+	 * @param provider a resultset listener which provides the data
+	 * @return an EPR to the resultset.
+	 */
+	W3CEndpointReference createResultSet(ResultSetListener provider);
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/LocalOpenResultSetFactoryImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/LocalOpenResultSetFactoryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/LocalOpenResultSetFactoryImpl.java	(revision 45117)
@@ -0,0 +1,23 @@
+package eu.dnetlib.enabling.resultset;
+
+/**
+ * Creates an "open" (unbounded, unfreezed) local resultset.
+ * 
+ * @author marko
+ *
+ */
+public class LocalOpenResultSetFactoryImpl extends LocalResultSetFactoryImpl {
+
+	/** 
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.LocalResultSetFactoryImpl#createInstance(eu.dnetlib.enabling.resultset.ResultSetListener)
+	 */
+	@Override
+	protected LocalResultSetImpl createInstance(final ResultSetListener provider) {
+		final LocalResultSetImpl instance = super.createInstance(provider);
+		instance.setOpen(true);
+		return instance;
+	}
+
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.properties
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.properties	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.properties	(revision 45117)
@@ -0,0 +1,6 @@
+services.is.resultset.resultSetRegistryCache.timeToIdle = 240
+services.is.resultset.resultSetRegistryMaxIdleTimeCache.timeToIdle = 240
+
+# jaxwsEndpointReferenceBuilder | staticResultSetServiceEprBuilder
+services.resultset.eprbuilder.bean = jaxwsEndpointReferenceBuilder
+services.resultset.endpoint.static.address = ${transport.soap.baseAddress}/resultSet
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetFactory.java	(revision 45117)
@@ -0,0 +1,19 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * Creates a resultset service from a producer.
+ * 
+ * @author marko
+ *
+ */
+public interface ResultSetFactory {
+	/**
+	 * TODO other parameters like expiration time etc.
+	 * 
+	 * @param provider a resultset listener which provides the data
+	 * @return an EPR to the resultset.
+	 */
+	W3CEndpointReference createResultSet(ResultSetListener provider);
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImplTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImplTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImplTest.java	(revision 45117)
@@ -0,0 +1,166 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import static org.junit.Assert.*; // NOPMD
+import static org.mockito.Mockito.*; // NOPMD
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.enabling.resultset.ResultSetRegistry;
+
+/**
+ * test the transient push resultset.
+ *
+ * @author marko
+ *
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class TransientPushResultSetImplTest {
+
+	/**
+	 * first test value.
+	 */
+	private static final String ONE = "one";
+
+	/**
+	 * second test value.
+	 */
+	private static final String TWO = "two";
+
+	/**
+	 * test rs id.
+	 */
+	private static final String RS_ID = "123";
+
+	/**
+	 * instance to be tested.
+	 */
+	private transient TransientPushResultSetImpl resultSet;
+
+	/**
+	 * dao mock.
+	 */
+	@Mock
+	private transient TransientPushResultSetDao dao;
+
+	/**
+	 * resultset registry mock.
+	 */
+	@Mock
+	private transient ResultSetRegistry registry;
+
+	/**
+	 * setup class to be tested.
+	 *
+	 * @throws Exception
+	 */
+	@Before
+	public void setUp() {
+		resultSet = new TransientPushResultSetImpl(dao);
+		resultSet.setIdentifier(RS_ID);
+		resultSet.getDao(); // getter code coverage hack
+	}
+
+	/**
+	 * test adding elements.
+	 */
+	@Test
+	public void testAddElements() {
+		final List<String> list = new ArrayList<String>();
+		list.add(ONE);
+
+		resultSet.addElements(list);
+
+		verify(dao).addElements(RS_ID, list);
+		assertNotNull("dummy", resultSet);
+	}
+
+	/**
+	 * test get number of results.
+	 */
+	@Test
+	public void testGetNumberOfResults() {
+		when(dao.getSize(RS_ID)).thenReturn(1);
+
+		assertEquals("check size", 1, resultSet.getNumberOfResults());
+	}
+
+	/**
+	 * get result.
+	 */
+	@Test
+	public void testGetResults() {
+		final List<String> list = new ArrayList<String>();
+		list.add(TWO);
+
+		when(dao.getSize(RS_ID)).thenReturn(2);
+		when(dao.getElements(RS_ID, 2, 2)).thenReturn(list);
+
+		assertEquals("check list", TWO, resultSet.getResults(2, 2).get(0));
+		assertEquals("check size", 1, resultSet.getResults(2, 2).size());
+	}
+
+	/**
+	 * test when indices are out of range, trailing stuff should be skipped.
+	 */
+	@Test
+	public void testGetResultOutOfRange() {
+		final List<String> list = new ArrayList<String>();
+		list.add(TWO);
+
+		when(dao.getSize(RS_ID)).thenReturn(2);
+		when(dao.getElements(RS_ID, 2, 2)).thenReturn(list);
+
+		assertEquals("check list", TWO, resultSet.getResults(2, 2 + 1).get(0));
+		assertEquals("check size", 1, resultSet.getResults(2, 2 + 1).size());
+	}
+
+	/**
+	 * open.
+	 */
+	@Test
+	public void testIsOpen() {
+		assertTrue("check is open by default", resultSet.isOpen());
+	}
+
+	/**
+	 * test close.
+	 */
+	@Test
+	public void testClose() {
+		resultSet.addObserver(registry);
+		assertEquals("observer should be added", 1, resultSet.countObservers());
+
+		resultSet.destroy();
+		assertTrue("should be destroyed", resultSet.isDestroyed());
+
+		assertEquals("observers should be cleared", 0, resultSet.countObservers());
+		verify(registry, times(1)).update(resultSet, null);
+	}
+
+	@Test
+	public void testFromAfterSize() {
+		final List<String> list = new ArrayList<String>();
+		list.add(TWO);
+
+		when(dao.getSize(RS_ID)).thenReturn(2);
+		when(dao.getElements(RS_ID, 2, 2)).thenReturn(list);
+
+		resultSet.getResults(3, 2);
+	}
+
+	@Test(expected = IllegalStateException.class)
+	public void testWriteClosed() {
+		resultSet.close();
+		resultSet.addElements(Lists.newArrayList("test"));
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/CacheTransientPushResultSetDaoTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/CacheTransientPushResultSetDaoTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/CacheTransientPushResultSetDaoTest.java	(revision 45117)
@@ -0,0 +1,78 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import java.util.List;
+
+import net.sf.ehcache.CacheManager;
+
+import org.junit.After;
+
+import eu.dnetlib.miscutils.cache.Cache;
+import eu.dnetlib.miscutils.cache.EhCache;
+import eu.dnetlib.miscutils.factory.Factory;
+
+/**
+ * concrete push resultset dao test.
+ * 
+ * @author marko
+ * 
+ */
+public class CacheTransientPushResultSetDaoTest extends AbstractTransientPushResultSetDaoTest { // NOPMD
+
+	/**
+	 * max in memory elements.
+	 */
+	private static final int MAX_IN_MEM = 100;
+
+	/**
+	 * default time.
+	 */
+	private static final int DEFAULT_TTI = 1000;
+
+	/**
+	 * default time to live.
+	 */
+	private static final int DEFAULT_TTL = 1000;
+
+	/**
+	 * cache manager.
+	 */
+	private final transient CacheManager cacheManager = CacheManager.create();
+
+	/**
+	 * clean cache after test.
+	 */
+	@After
+	public void cleanCache() {
+		cacheManager.removeAllCaches();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.push.AbstractTransientPushResultSetDaoTest#newInstance()
+	 */
+	@Override
+	protected TransientPushResultSetDao newInstance() {
+		final net.sf.ehcache.Cache ehcache = new net.sf.ehcache.Cache("testCache", MAX_IN_MEM, false, false, DEFAULT_TTL, DEFAULT_TTI);
+		cacheManager.addCache(ehcache);
+
+		final net.sf.ehcache.Cache rsehcache = new net.sf.ehcache.Cache("rsetCache", MAX_IN_MEM, false, false, DEFAULT_TTL, DEFAULT_TTI);
+		cacheManager.addCache(rsehcache);
+
+		final CacheTransientResultSetDaoImpl resultSet = new CacheTransientResultSetDaoImpl();
+		final Cache<String, List<String>> cache = new EhCache<String, List<String>>(ehcache);
+		final Cache<String, ResultSetDescriptor> rscache = new EhCache<String, ResultSetDescriptor>(rsehcache);
+		resultSet.setCache(cache);
+		resultSet.setResultSetCache(rscache);
+
+		resultSet.setResultSetDescriptorFactory(new Factory<ResultSetDescriptor>() {
+
+			@Override
+			public ResultSetDescriptor newInstance() {
+				return new ResultSetDescriptor();
+			}
+		});
+		return resultSet;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/LocalResultSetImplTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/LocalResultSetImplTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/LocalResultSetImplTest.java	(revision 45117)
@@ -0,0 +1,174 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.*; // NOPMD
+import static org.mockito.Mockito.*; // NOPMD by marko on 11/26/08 9:13 PM
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+/**
+ * test the resultset concrete implementation.
+ * 
+ * @author marko
+ * 
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class LocalResultSetImplTest {
+
+	/**
+	 * This class could be an anonymous class, but is here to be shared among tests.
+	 * 
+	 * @author marko
+	 * 
+	 */
+	private static final class TestResultSetListener implements ResultSetListener {
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see eu.dnetlib.enabling.resultset.ResultSetListener#getResult(int, int)
+		 */
+		@Override
+		public List<String> getResult(final int fromPosition, final int toPosition) {
+			final List<String> res = new ArrayList<String>();
+			for (int i = fromPosition; i <= toPosition; i++)
+				res.add(((Integer) (i - 1)).toString());
+			return res;
+		}
+
+		@Override
+		public int getSize() {
+			return RESULT_SIZE;
+		}
+	}
+
+	/**
+	 * Mockito lacks of multiple interfaces mocking.
+	 * 
+	 * @author marko
+	 * 
+	 */
+	private abstract static class AbstractResultSetAware implements ResultSetListener, ResultSetAware {
+	}
+
+	/**
+	 * resultset registry mock.
+	 */
+	@Mock
+	private transient ResultSetRegistry registry;
+
+	/**
+	 * object under test.
+	 */
+	private transient LocalResultSetImpl resultSet;
+
+	/**
+	 * number of returned test results.
+	 */
+	private static final int RESULT_SIZE = 3;
+
+	/**
+	 * provides data to the resultset under test.
+	 */
+	private transient TestResultSetListener resultSetListener;
+
+	/**
+	 * prepare.
+	 * 
+	 */
+	@Before
+	public void setUp() {
+		resultSetListener = new TestResultSetListener();
+		resultSet = new LocalResultSetImpl(resultSetListener);
+	}
+
+	/**
+	 * test the get number of results method.
+	 */
+	@Test
+	public void testGetNumberOfResults() {
+		assertEquals("check number of results", RESULT_SIZE, resultSet.getNumberOfResults());
+	}
+
+	/**
+	 * test the get result method.
+	 */
+	@Test
+	public void testGetResults() {
+		final List<String> res = resultSet.getResults(1, RESULT_SIZE); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("whole length", RESULT_SIZE, res.size());
+		for (int i = 0; i < RESULT_SIZE; i++)
+			assertEquals("check element", ((Integer) i).toString(), res.get(i));
+
+		final List<String> res2 = resultSet.getResults(1, RESULT_SIZE - 1); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("shorter", RESULT_SIZE - 1, res2.size());
+
+		final List<String> res3 = resultSet.getResults(1, RESULT_SIZE + 1); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("to out of bounds", RESULT_SIZE, res3.size());
+
+		final List<String> res4 = resultSet.getResults(RESULT_SIZE + 1, RESULT_SIZE); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("from out of bounds", 0, res4.size());
+		
+		final List<String> res5 = resultSet.getResults(0, RESULT_SIZE); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("from lesser than 1", RESULT_SIZE, res5.size());		
+
+		final List<String> res6 = resultSet.getResults(RESULT_SIZE, 1); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("inverted from and to", 1, res6.size());		
+		
+		resultSet.setOpen(true);
+		final List<String> res7 = resultSet.getResults(1, RESULT_SIZE + 1); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("to out of bounds - pass through", RESULT_SIZE + 1, res7.size());
+	}
+
+	/**
+	 * test observer/observable pattern.
+	 */
+	@Test
+	public void testDestroy() {
+		resultSet.addObserver(registry);
+		assertEquals("observer should be added", 1, resultSet.countObservers());
+
+		resultSet.destroy();
+		assertTrue("should be destroyed", resultSet.isDestroyed());
+
+		assertEquals("observers should be cleared", 0, resultSet.countObservers());
+		verify(registry, times(1)).update(resultSet, null);
+	}
+
+	/**
+	 * test getter ... let's make code coverage happy.
+	 */
+	@Test
+	public void testGetListener() {
+		assertEquals("test getter?", resultSetListener, resultSet.getListener());
+	}
+
+	/**
+	 * test setter ... let's make code coverage happy.
+	 */
+	@Test
+	public void testSetListener() {
+		assertEquals("test getter?", resultSetListener, resultSet.getListener());
+		resultSet.setListener(null);
+		assertNull("test setter?", resultSet.getListener());
+	}
+
+	/**
+	 * test.
+	 */
+	@Test
+	public void testResultSetAware() {
+		final AbstractResultSetAware abr = mock(AbstractResultSetAware.class);
+		resultSet = new LocalResultSetImpl(abr);
+		assertNotNull("dummy", resultSet);
+		
+		verify(abr).setResultSet((ResultSet) anyObject());
+		
+	}
+
+}

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/LocalResultSetImplTest.java
___________________________________________________________________
Added: svn:mergeinfo
## -0,0 +0,0 ##
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorTest.java	(revision 45117)
@@ -0,0 +1,44 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.junit.Before;
+import org.junit.Test;
+
+import eu.dnetlib.enabling.resultset.push.ResultSetDescriptor.Range;
+
+public class ResultSetDescriptorTest {
+
+	private static final Log log = LogFactory.getLog(ResultSetDescriptorTest.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	private transient ResultSetDescriptor descriptor;
+
+	@Before
+	public void setUp() throws Exception {
+		descriptor = new ResultSetDescriptor();
+	}
+
+	@Test
+	public void testGetRangesContaining() {
+		log.debug("--- 1, 1");
+		for(Range i : descriptor.getRangesContaining(1, 1))
+			log.debug("i " + i);
+
+		log.debug("--- 2, 1000");
+		for(Range i : descriptor.getRangesContaining(2, 1000))
+			log.debug("i " + i);
+
+		log.debug("--- 5, 2000");
+		for(Range i : descriptor.getRangesContaining(5, 2000))
+			log.debug("i " + i);
+
+		log.debug("--- 5, 2001");
+		for(Range i : descriptor.getRangesContaining(5, 2001))
+			log.debug("i " + i);
+	}
+
+	@Test
+	public void testNext() {
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/CacheTransientPushResultSetDaoTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/CacheTransientPushResultSetDaoTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/CacheTransientPushResultSetDaoTest.java	(revision 45117)
@@ -0,0 +1,78 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import java.util.List;
+
+import net.sf.ehcache.CacheManager;
+
+import org.junit.After;
+
+import eu.dnetlib.miscutils.cache.Cache;
+import eu.dnetlib.miscutils.cache.EhCache;
+import eu.dnetlib.miscutils.factory.Factory;
+
+/**
+ * concrete push resultset dao test.
+ * 
+ * @author marko
+ * 
+ */
+public class CacheTransientPushResultSetDaoTest extends AbstractTransientPushResultSetDaoTest { // NOPMD
+
+	/**
+	 * max in memory elements.
+	 */
+	private static final int MAX_IN_MEM = 100;
+
+	/**
+	 * default time.
+	 */
+	private static final int DEFAULT_TTI = 1000;
+
+	/**
+	 * default time to live.
+	 */
+	private static final int DEFAULT_TTL = 1000;
+
+	/**
+	 * cache manager.
+	 */
+	private final transient CacheManager cacheManager = CacheManager.create();
+
+	/**
+	 * clean cache after test.
+	 */
+	@After
+	public void cleanCache() {
+		cacheManager.removeAllCaches();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.push.AbstractTransientPushResultSetDaoTest#newInstance()
+	 */
+	@Override
+	protected TransientPushResultSetDao newInstance() {
+		final net.sf.ehcache.Cache ehcache = new net.sf.ehcache.Cache("testCache", MAX_IN_MEM, false, false, DEFAULT_TTL, DEFAULT_TTI);
+		cacheManager.addCache(ehcache);
+
+		final net.sf.ehcache.Cache rsehcache = new net.sf.ehcache.Cache("rsetCache", MAX_IN_MEM, false, false, DEFAULT_TTL, DEFAULT_TTI);
+		cacheManager.addCache(rsehcache);
+
+		final CacheTransientResultSetDaoImpl resultSet = new CacheTransientResultSetDaoImpl();
+		final Cache<String, List<String>> cache = new EhCache<String, List<String>>(ehcache);
+		final Cache<String, ResultSetDescriptor> rscache = new EhCache<String, ResultSetDescriptor>(rsehcache);
+		resultSet.setCache(cache);
+		resultSet.setResultSetCache(rscache);
+
+		resultSet.setResultSetDescriptorFactory(new Factory<ResultSetDescriptor>() {
+
+			@Override
+			public ResultSetDescriptor newInstance() {
+				return new ResultSetDescriptor();
+			}
+		});
+		return resultSet;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorTest.java	(revision 45117)
@@ -0,0 +1,44 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.junit.Before;
+import org.junit.Test;
+
+import eu.dnetlib.enabling.resultset.push.ResultSetDescriptor.Range;
+
+public class ResultSetDescriptorTest {
+
+	private static final Log log = LogFactory.getLog(ResultSetDescriptorTest.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	private transient ResultSetDescriptor descriptor;
+
+	@Before
+	public void setUp() throws Exception {
+		descriptor = new ResultSetDescriptor();
+	}
+
+	@Test
+	public void testGetRangesContaining() {
+		log.debug("--- 1, 1");
+		for(Range i : descriptor.getRangesContaining(1, 1))
+			log.debug("i " + i);
+
+		log.debug("--- 2, 1000");
+		for(Range i : descriptor.getRangesContaining(2, 1000))
+			log.debug("i " + i);
+
+		log.debug("--- 5, 2000");
+		for(Range i : descriptor.getRangesContaining(5, 2000))
+			log.debug("i " + i);
+
+		log.debug("--- 5, 2001");
+		for(Range i : descriptor.getRangesContaining(5, 2001))
+			log.debug("i " + i);
+	}
+
+	@Test
+	public void testNext() {
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/MappedResultSetTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/MappedResultSetTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/MappedResultSetTest.java	(revision 45117)
@@ -0,0 +1,137 @@
+package eu.dnetlib.enabling.resultset; // NOPMD
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.runners.MockitoJUnit44Runner;
+import org.mockito.stubbing.Answer;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
+import eu.dnetlib.enabling.tools.ServiceResolver;
+import eu.dnetlib.miscutils.factory.Factory;
+import eu.dnetlib.miscutils.functional.ThreadSafeUnaryFunction;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+/**
+ * test xslt resultset.
+ *
+ * @author marko
+ *
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class MappedResultSetTest {
+
+	/**
+	 * instance under test.
+	 */
+	private transient MappedResultSet mappedResultSet;
+
+	/**
+	 * service resolver.
+	 */
+	@Mock
+	private transient ServiceResolver serviceResolver;
+
+	/**
+	 * resultset service mock.
+	 */
+	@Mock
+	private transient ResultSetService resultSetService;
+	
+	/**
+	 * resultset mock.
+	 */
+	@Mock
+	private transient ResultSet resultSet;	
+
+	private Answer<Object> resultSetAnswer = new Answer<Object>() {
+
+		private List<String> list = Lists.newArrayList("1","2","3","4","5","6","7","8","9","10");
+		
+		@Override
+		public Object answer(InvocationOnMock invocation) throws Throwable {
+			String method = invocation.getMethod().getName();
+			if (method.equals("getResult") || method.equals("getResults")) {
+				int from = (Integer) invocation.getArguments()[1];
+				int to = (Integer) invocation.getArguments()[2];
+				
+				return list.subList(from-1, to);
+			}
+			if (method.equals("getNumberOfElements") || method.equals("getNumberOfResults")) {
+				return list.size();
+			}
+			if (method.equals("getRSStatus")) {
+				return "closed";
+			}
+			if (method.equals("isOpen")) {
+				return false;
+			}			
+			System.out.println(invocation.toString());
+			return null;
+		}		
+	};
+
+	/**
+	 * Common setup.
+	 * @throws ResultSetException 
+	 *
+	 */
+	@Before
+	public void setUp() throws ResultSetException {
+		
+		when(serviceResolver.getService(eq(ResultSetService.class), (W3CEndpointReference) anyObject())).thenReturn(resultSetService);
+		when(serviceResolver.getResourceIdentifier((W3CEndpointReference) anyObject())).thenReturn("123");
+
+		when(resultSetService.getNumberOfElements(anyString())).thenAnswer(resultSetAnswer);
+		when(resultSetService.getResult(anyString(), anyInt(), anyInt(), anyString())).thenAnswer(resultSetAnswer );
+		when(resultSetService.getRSStatus(anyString())).thenAnswer(resultSetAnswer);
+		
+		when(resultSet.getNumberOfResults()).thenAnswer(resultSetAnswer);
+		when(resultSet.getResults(anyInt(), anyInt())).thenAnswer(resultSetAnswer );
+		when(resultSet.isOpen()).thenAnswer(resultSetAnswer);		
+	}
+	
+	@Test
+	public void testThreadSafeMappedResultSet_1() {
+		
+		final Factory<UnaryFunction<String, String>> functionFactory = new Factory<UnaryFunction<String,String>>() {
+			@Override
+			public UnaryFunction<String, String> newInstance() {
+				return new UnaryFunction<String, String>() {
+					@Override
+					public String evaluate(String arg) {
+						return "mapped-" + arg;
+					}
+				};
+			}
+		}; 
+		mappedResultSet = new MappedResultSet(null, new ThreadSafeUnaryFunction<String, String>(functionFactory), serviceResolver);
+		mappedResultSet.setResultSet(resultSet);
+
+		for (String s : mappedResultSet.getResult(1, 10)) {
+			assertNotNull("null result", s);
+			assertFalse("empty result", s.isEmpty());
+			assertNotNull("null element", s);
+			assertTrue("transformed correctly", s.startsWith("mapped-"));	
+		}
+	}
+}
+

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/MappedResultSetTest.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/FetchListTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/FetchListTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/FetchListTest.java	(revision 45117)
@@ -0,0 +1,75 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+@RunWith(MockitoJUnit44Runner.class)
+public class FetchListTest {
+	
+	/**
+	 * object to test
+	 */
+	private FetchList<String> fetchList;
+	
+	private List<String> list;
+	private Iterator<String> iter;
+	
+	private int FETCH_SIZE = 10;
+	
+	private int TOTAL_ELEMENTS = 100;
+
+	@Before
+	public void setUp() throws Exception {
+		list = new ArrayList<String>();
+		for (int i = 0; i < TOTAL_ELEMENTS; i++) {
+			list.add("XXX" + i);
+		}
+		this.iter = list.iterator();
+		fetchList = new FetchList<String>(iter, FETCH_SIZE);
+		
+	}
+
+	@Test
+	public void testFetchList() {
+		assertNotNull(fetchList);
+	}
+
+	@Test
+	public void testPoll_consumedElements() {
+		assertEquals(0, fetchList.getConsumedElements());
+		fetchList.poll();
+		assertEquals(1, fetchList.getConsumedElements());
+	}
+	
+	@Test
+	public void testFill_totalElements() {
+		assertEquals(FETCH_SIZE, fetchList.getTotalElements());
+	}
+	
+	@Test
+	public void testPoll() {
+		for (int i = 0; i < TOTAL_ELEMENTS; i++) {
+			assertEquals(i, fetchList.getConsumedElements());
+			assertEquals(list.get(i), fetchList.poll());
+		}
+		assertEquals(TOTAL_ELEMENTS, fetchList.getConsumedElements());
+		assertEquals(TOTAL_ELEMENTS, fetchList.getTotalElements());
+	}
+	
+	@Test
+	public void testPoll_null() {
+		for (int i = 0; i < TOTAL_ELEMENTS; i++) {
+			fetchList.poll();
+		}
+		assertNull(fetchList.poll());
+		assertNull(fetchList.poll());
+		assertNull(fetchList.poll());
+	}
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImplTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImplTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImplTest.java	(revision 45117)
@@ -0,0 +1,166 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import static org.junit.Assert.*; // NOPMD
+import static org.mockito.Mockito.*; // NOPMD
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.enabling.resultset.ResultSetRegistry;
+
+/**
+ * test the transient push resultset.
+ *
+ * @author marko
+ *
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class TransientPushResultSetImplTest {
+
+	/**
+	 * first test value.
+	 */
+	private static final String ONE = "one";
+
+	/**
+	 * second test value.
+	 */
+	private static final String TWO = "two";
+
+	/**
+	 * test rs id.
+	 */
+	private static final String RS_ID = "123";
+
+	/**
+	 * instance to be tested.
+	 */
+	private transient TransientPushResultSetImpl resultSet;
+
+	/**
+	 * dao mock.
+	 */
+	@Mock
+	private transient TransientPushResultSetDao dao;
+
+	/**
+	 * resultset registry mock.
+	 */
+	@Mock
+	private transient ResultSetRegistry registry;
+
+	/**
+	 * setup class to be tested.
+	 *
+	 * @throws Exception
+	 */
+	@Before
+	public void setUp() {
+		resultSet = new TransientPushResultSetImpl(dao);
+		resultSet.setIdentifier(RS_ID);
+		resultSet.getDao(); // getter code coverage hack
+	}
+
+	/**
+	 * test adding elements.
+	 */
+	@Test
+	public void testAddElements() {
+		final List<String> list = new ArrayList<String>();
+		list.add(ONE);
+
+		resultSet.addElements(list);
+
+		verify(dao).addElements(RS_ID, list);
+		assertNotNull("dummy", resultSet);
+	}
+
+	/**
+	 * test get number of results.
+	 */
+	@Test
+	public void testGetNumberOfResults() {
+		when(dao.getSize(RS_ID)).thenReturn(1);
+
+		assertEquals("check size", 1, resultSet.getNumberOfResults());
+	}
+
+	/**
+	 * get result.
+	 */
+	@Test
+	public void testGetResults() {
+		final List<String> list = new ArrayList<String>();
+		list.add(TWO);
+
+		when(dao.getSize(RS_ID)).thenReturn(2);
+		when(dao.getElements(RS_ID, 2, 2)).thenReturn(list);
+
+		assertEquals("check list", TWO, resultSet.getResults(2, 2).get(0));
+		assertEquals("check size", 1, resultSet.getResults(2, 2).size());
+	}
+
+	/**
+	 * test when indices are out of range, trailing stuff should be skipped.
+	 */
+	@Test
+	public void testGetResultOutOfRange() {
+		final List<String> list = new ArrayList<String>();
+		list.add(TWO);
+
+		when(dao.getSize(RS_ID)).thenReturn(2);
+		when(dao.getElements(RS_ID, 2, 2)).thenReturn(list);
+
+		assertEquals("check list", TWO, resultSet.getResults(2, 2 + 1).get(0));
+		assertEquals("check size", 1, resultSet.getResults(2, 2 + 1).size());
+	}
+
+	/**
+	 * open.
+	 */
+	@Test
+	public void testIsOpen() {
+		assertTrue("check is open by default", resultSet.isOpen());
+	}
+
+	/**
+	 * test close.
+	 */
+	@Test
+	public void testClose() {
+		resultSet.addObserver(registry);
+		assertEquals("observer should be added", 1, resultSet.countObservers());
+
+		resultSet.destroy();
+		assertTrue("should be destroyed", resultSet.isDestroyed());
+
+		assertEquals("observers should be cleared", 0, resultSet.countObservers());
+		verify(registry, times(1)).update(resultSet, null);
+	}
+
+	@Test
+	public void testFromAfterSize() {
+		final List<String> list = new ArrayList<String>();
+		list.add(TWO);
+
+		when(dao.getSize(RS_ID)).thenReturn(2);
+		when(dao.getElements(RS_ID, 2, 2)).thenReturn(list);
+
+		resultSet.getResults(3, 2);
+	}
+
+	@Test(expected = IllegalStateException.class)
+	public void testWriteClosed() {
+		resultSet.close();
+		resultSet.addElements(Lists.newArrayList("test"));
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/ResultSetServiceImplTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/ResultSetServiceImplTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/ResultSetServiceImplTest.java	(revision 45117)
@@ -0,0 +1,101 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.*; // NOPMD
+import static org.mockito.Mockito.*; // NOPMD
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+
+/**
+ * resultset service rmi implementation test.
+ *  
+ * @author marko
+ *
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class ResultSetServiceImplTest {
+
+	/**
+	 * mock resultset id.
+	 */
+	private static final String RS_ID = "123";
+
+	/**
+	 * instance under test.
+	 */
+	private transient ResultSetServiceImpl service;
+	
+	/**
+	 * custom property dao mock.
+	 */
+	@Mock
+	private transient ResultSetPropertyDao customPropertyDao;
+	
+	/**
+	 * resultset registry mock. 
+	 */
+	@Mock
+	private transient ResultSetRegistry resultsetRegistry;
+	
+	/**
+	 * resultset instance mock. 
+	 */
+	@Mock
+	private transient ResultSet resultSet;
+	
+	/**
+	 * setup. 
+	 */
+	@Before
+	public void setUp() {
+		service = new ResultSetServiceImpl();
+		service.setCustomPropertyDao(customPropertyDao);
+		service.setResultsetRegistry(resultsetRegistry);
+		
+		when(resultsetRegistry.getResultSetById(RS_ID)).thenReturn(resultSet);
+		when(resultSet.getIdentifier()).thenReturn(RS_ID);
+	}
+
+	/**
+	 * test get property.
+	 * @throws ResultSetException shouldn't happen
+	 */
+	@Test
+	public void testGetProperty() throws ResultSetException {
+		final Map<String, String> properties = new HashMap<String, String>();
+		properties.put("prefetch", "true");
+		
+		when(customPropertyDao.getProperties(resultSet)).thenReturn(properties);
+		when(resultSet.getNumberOfResults()).thenReturn(1);
+		
+		assertEquals("test builtin", "1", service.getProperty(RS_ID, "total"));
+		assertEquals("test builtin", RS_ID, service.getProperty(RS_ID, "rsId"));
+		
+		assertEquals("test custom", "true", service.getProperty(RS_ID, "prefetch"));
+		assertNull("test custom", service.getProperty(RS_ID, "unexistent"));
+	}
+
+	/**
+	 * get resultset status.
+	 * 
+	 * @throws ResultSetException shouldn't happen
+	 */
+	@Test
+	public void testGetRSStatus() throws ResultSetException {
+		when(resultSet.isOpen()).thenReturn(true);
+		
+		assertEquals("check open", service.getRSStatus(RS_ID), "open");
+		
+		when(resultSet.isOpen()).thenReturn(false);
+		assertEquals("check closed", service.getRSStatus(RS_ID), "closed");
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/LocalResultSetImplTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/LocalResultSetImplTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/LocalResultSetImplTest.java	(revision 45117)
@@ -0,0 +1,174 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.*; // NOPMD
+import static org.mockito.Mockito.*; // NOPMD by marko on 11/26/08 9:13 PM
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+/**
+ * test the resultset concrete implementation.
+ * 
+ * @author marko
+ * 
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class LocalResultSetImplTest {
+
+	/**
+	 * This class could be an anonymous class, but is here to be shared among tests.
+	 * 
+	 * @author marko
+	 * 
+	 */
+	private static final class TestResultSetListener implements ResultSetListener {
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see eu.dnetlib.enabling.resultset.ResultSetListener#getResult(int, int)
+		 */
+		@Override
+		public List<String> getResult(final int fromPosition, final int toPosition) {
+			final List<String> res = new ArrayList<String>();
+			for (int i = fromPosition; i <= toPosition; i++)
+				res.add(((Integer) (i - 1)).toString());
+			return res;
+		}
+
+		@Override
+		public int getSize() {
+			return RESULT_SIZE;
+		}
+	}
+
+	/**
+	 * Mockito lacks of multiple interfaces mocking.
+	 * 
+	 * @author marko
+	 * 
+	 */
+	private abstract static class AbstractResultSetAware implements ResultSetListener, ResultSetAware {
+	}
+
+	/**
+	 * resultset registry mock.
+	 */
+	@Mock
+	private transient ResultSetRegistry registry;
+
+	/**
+	 * object under test.
+	 */
+	private transient LocalResultSetImpl resultSet;
+
+	/**
+	 * number of returned test results.
+	 */
+	private static final int RESULT_SIZE = 3;
+
+	/**
+	 * provides data to the resultset under test.
+	 */
+	private transient TestResultSetListener resultSetListener;
+
+	/**
+	 * prepare.
+	 * 
+	 */
+	@Before
+	public void setUp() {
+		resultSetListener = new TestResultSetListener();
+		resultSet = new LocalResultSetImpl(resultSetListener);
+	}
+
+	/**
+	 * test the get number of results method.
+	 */
+	@Test
+	public void testGetNumberOfResults() {
+		assertEquals("check number of results", RESULT_SIZE, resultSet.getNumberOfResults());
+	}
+
+	/**
+	 * test the get result method.
+	 */
+	@Test
+	public void testGetResults() {
+		final List<String> res = resultSet.getResults(1, RESULT_SIZE); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("whole length", RESULT_SIZE, res.size());
+		for (int i = 0; i < RESULT_SIZE; i++)
+			assertEquals("check element", ((Integer) i).toString(), res.get(i));
+
+		final List<String> res2 = resultSet.getResults(1, RESULT_SIZE - 1); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("shorter", RESULT_SIZE - 1, res2.size());
+
+		final List<String> res3 = resultSet.getResults(1, RESULT_SIZE + 1); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("to out of bounds", RESULT_SIZE, res3.size());
+
+		final List<String> res4 = resultSet.getResults(RESULT_SIZE + 1, RESULT_SIZE); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("from out of bounds", 0, res4.size());
+		
+		final List<String> res5 = resultSet.getResults(0, RESULT_SIZE); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("from lesser than 1", RESULT_SIZE, res5.size());		
+
+		final List<String> res6 = resultSet.getResults(RESULT_SIZE, 1); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("inverted from and to", 1, res6.size());		
+		
+		resultSet.setOpen(true);
+		final List<String> res7 = resultSet.getResults(1, RESULT_SIZE + 1); // NOPMD by marko on 11/27/08 3:00 AM
+		assertEquals("to out of bounds - pass through", RESULT_SIZE + 1, res7.size());
+	}
+
+	/**
+	 * test observer/observable pattern.
+	 */
+	@Test
+	public void testDestroy() {
+		resultSet.addObserver(registry);
+		assertEquals("observer should be added", 1, resultSet.countObservers());
+
+		resultSet.destroy();
+		assertTrue("should be destroyed", resultSet.isDestroyed());
+
+		assertEquals("observers should be cleared", 0, resultSet.countObservers());
+		verify(registry, times(1)).update(resultSet, null);
+	}
+
+	/**
+	 * test getter ... let's make code coverage happy.
+	 */
+	@Test
+	public void testGetListener() {
+		assertEquals("test getter?", resultSetListener, resultSet.getListener());
+	}
+
+	/**
+	 * test setter ... let's make code coverage happy.
+	 */
+	@Test
+	public void testSetListener() {
+		assertEquals("test getter?", resultSetListener, resultSet.getListener());
+		resultSet.setListener(null);
+		assertNull("test setter?", resultSet.getListener());
+	}
+
+	/**
+	 * test.
+	 */
+	@Test
+	public void testResultSetAware() {
+		final AbstractResultSetAware abr = mock(AbstractResultSetAware.class);
+		resultSet = new LocalResultSetImpl(abr);
+		assertNotNull("dummy", resultSet);
+		
+		verify(abr).setResultSet((ResultSet) anyObject());
+		
+	}
+
+}

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/LocalResultSetImplTest.java
___________________________________________________________________
Added: svn:mergeinfo
## -0,0 +0,0 ##
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/resources/log4j.properties
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/resources/log4j.properties	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/resources/log4j.properties	(revision 45117)
@@ -0,0 +1,29 @@
+org.apache.cxf.Logger=org.apache.cxf.common.logging.Log4jLogger
+
+log4j.rootLogger=WARN, CONSOLE
+log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
+log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
+log4j.appender.CONSOLE.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
+
+log4j.logger.eu.dnetlib=INFO
+log4j.logger.eu.dnetlib.enabling.is.sn=INFO
+#log4j.logger.org.apache.cxf.interceptor=FATAL
+log4j.logger.org.apache.cxf.ws.addressing.ContextUtils=FATAL
+log4j.logger.eu.dnetlib.enabling.tools.AbstractBaseService=INFO
+log4j.logger.eu.dnetlib.enabling.inspector=DEBUG
+log4j.logger.eu.dnetlib.xml.database.LoggingTrigger=FATAL
+#log4j.logger.eu.dnetlib.enabling.tools.registration=DEBUG
+log4j.logger.eu.dnetlib.enabling.tools.registration.ServiceRegistrator=INFO
+log4j.logger.eu.dnetlib.enabling.inspector=FATAL
+log4j.logger.eu.dnetlib.enabling.resultset=DEBUG
+log4j.logger.eu.dnetlib.enabling.inspector.SubscriptionController=DEBUG
+log4j.logger.eu.dnetlib.springutils.stringtemplate.StringTemplateViewResolver=FATAL
+log4j.logger.eu.dnetlib.enabling.is.sn.SynchronousNotificationSenderImpl=WARN
+
+log4j.logger.eu.dnetlib.enabling.manager.msro.wf.RefreshIndexJob=DEBUG
+log4j.logger.eu.dnetlib.enabling.ui=DEBUG
+log4j.logger.eu.dnetlib.enabling.manager.msro.wf.RefreshIndexJob=DEBUG
+
+log4j.logger.org.apache.zookeeper.ClientCnxn=FATAL
+
+log4j.logger.eu.dnetlib.enabling.resultset.push=DEBUG
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/FetchListTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/FetchListTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/FetchListTest.java	(revision 45117)
@@ -0,0 +1,75 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+@RunWith(MockitoJUnit44Runner.class)
+public class FetchListTest {
+	
+	/**
+	 * object to test
+	 */
+	private FetchList<String> fetchList;
+	
+	private List<String> list;
+	private Iterator<String> iter;
+	
+	private int FETCH_SIZE = 10;
+	
+	private int TOTAL_ELEMENTS = 100;
+
+	@Before
+	public void setUp() throws Exception {
+		list = new ArrayList<String>();
+		for (int i = 0; i < TOTAL_ELEMENTS; i++) {
+			list.add("XXX" + i);
+		}
+		this.iter = list.iterator();
+		fetchList = new FetchList<String>(iter, FETCH_SIZE);
+		
+	}
+
+	@Test
+	public void testFetchList() {
+		assertNotNull(fetchList);
+	}
+
+	@Test
+	public void testPoll_consumedElements() {
+		assertEquals(0, fetchList.getConsumedElements());
+		fetchList.poll();
+		assertEquals(1, fetchList.getConsumedElements());
+	}
+	
+	@Test
+	public void testFill_totalElements() {
+		assertEquals(FETCH_SIZE, fetchList.getTotalElements());
+	}
+	
+	@Test
+	public void testPoll() {
+		for (int i = 0; i < TOTAL_ELEMENTS; i++) {
+			assertEquals(i, fetchList.getConsumedElements());
+			assertEquals(list.get(i), fetchList.poll());
+		}
+		assertEquals(TOTAL_ELEMENTS, fetchList.getConsumedElements());
+		assertEquals(TOTAL_ELEMENTS, fetchList.getTotalElements());
+	}
+	
+	@Test
+	public void testPoll_null() {
+		for (int i = 0; i < TOTAL_ELEMENTS; i++) {
+			fetchList.poll();
+		}
+		assertNull(fetchList.poll());
+		assertNull(fetchList.poll());
+		assertNull(fetchList.poll());
+	}
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/MappedResultSetTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/MappedResultSetTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/MappedResultSetTest.java	(revision 45117)
@@ -0,0 +1,137 @@
+package eu.dnetlib.enabling.resultset; // NOPMD
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.runners.MockitoJUnit44Runner;
+import org.mockito.stubbing.Answer;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
+import eu.dnetlib.enabling.tools.ServiceResolver;
+import eu.dnetlib.miscutils.factory.Factory;
+import eu.dnetlib.miscutils.functional.ThreadSafeUnaryFunction;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+/**
+ * test xslt resultset.
+ *
+ * @author marko
+ *
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class MappedResultSetTest {
+
+	/**
+	 * instance under test.
+	 */
+	private transient MappedResultSet mappedResultSet;
+
+	/**
+	 * service resolver.
+	 */
+	@Mock
+	private transient ServiceResolver serviceResolver;
+
+	/**
+	 * resultset service mock.
+	 */
+	@Mock
+	private transient ResultSetService resultSetService;
+	
+	/**
+	 * resultset mock.
+	 */
+	@Mock
+	private transient ResultSet resultSet;	
+
+	private Answer<Object> resultSetAnswer = new Answer<Object>() {
+
+		private List<String> list = Lists.newArrayList("1","2","3","4","5","6","7","8","9","10");
+		
+		@Override
+		public Object answer(InvocationOnMock invocation) throws Throwable {
+			String method = invocation.getMethod().getName();
+			if (method.equals("getResult") || method.equals("getResults")) {
+				int from = (Integer) invocation.getArguments()[1];
+				int to = (Integer) invocation.getArguments()[2];
+				
+				return list.subList(from-1, to);
+			}
+			if (method.equals("getNumberOfElements") || method.equals("getNumberOfResults")) {
+				return list.size();
+			}
+			if (method.equals("getRSStatus")) {
+				return "closed";
+			}
+			if (method.equals("isOpen")) {
+				return false;
+			}			
+			System.out.println(invocation.toString());
+			return null;
+		}		
+	};
+
+	/**
+	 * Common setup.
+	 * @throws ResultSetException 
+	 *
+	 */
+	@Before
+	public void setUp() throws ResultSetException {
+		
+		when(serviceResolver.getService(eq(ResultSetService.class), (W3CEndpointReference) anyObject())).thenReturn(resultSetService);
+		when(serviceResolver.getResourceIdentifier((W3CEndpointReference) anyObject())).thenReturn("123");
+
+		when(resultSetService.getNumberOfElements(anyString())).thenAnswer(resultSetAnswer);
+		when(resultSetService.getResult(anyString(), anyInt(), anyInt(), anyString())).thenAnswer(resultSetAnswer );
+		when(resultSetService.getRSStatus(anyString())).thenAnswer(resultSetAnswer);
+		
+		when(resultSet.getNumberOfResults()).thenAnswer(resultSetAnswer);
+		when(resultSet.getResults(anyInt(), anyInt())).thenAnswer(resultSetAnswer );
+		when(resultSet.isOpen()).thenAnswer(resultSetAnswer);		
+	}
+	
+	@Test
+	public void testThreadSafeMappedResultSet_1() {
+		
+		final Factory<UnaryFunction<String, String>> functionFactory = new Factory<UnaryFunction<String,String>>() {
+			@Override
+			public UnaryFunction<String, String> newInstance() {
+				return new UnaryFunction<String, String>() {
+					@Override
+					public String evaluate(String arg) {
+						return "mapped-" + arg;
+					}
+				};
+			}
+		}; 
+		mappedResultSet = new MappedResultSet(null, new ThreadSafeUnaryFunction<String, String>(functionFactory), serviceResolver);
+		mappedResultSet.setResultSet(resultSet);
+
+		for (String s : mappedResultSet.getResult(1, 10)) {
+			assertNotNull("null result", s);
+			assertFalse("empty result", s.isEmpty());
+			assertNotNull("null element", s);
+			assertTrue("transformed correctly", s.startsWith("mapped-"));	
+		}
+	}
+}
+

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/MappedResultSetTest.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/resources/log4j.properties
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/resources/log4j.properties	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/resources/log4j.properties	(revision 45117)
@@ -0,0 +1,29 @@
+org.apache.cxf.Logger=org.apache.cxf.common.logging.Log4jLogger
+
+log4j.rootLogger=WARN, CONSOLE
+log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
+log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
+log4j.appender.CONSOLE.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
+
+log4j.logger.eu.dnetlib=INFO
+log4j.logger.eu.dnetlib.enabling.is.sn=INFO
+#log4j.logger.org.apache.cxf.interceptor=FATAL
+log4j.logger.org.apache.cxf.ws.addressing.ContextUtils=FATAL
+log4j.logger.eu.dnetlib.enabling.tools.AbstractBaseService=INFO
+log4j.logger.eu.dnetlib.enabling.inspector=DEBUG
+log4j.logger.eu.dnetlib.xml.database.LoggingTrigger=FATAL
+#log4j.logger.eu.dnetlib.enabling.tools.registration=DEBUG
+log4j.logger.eu.dnetlib.enabling.tools.registration.ServiceRegistrator=INFO
+log4j.logger.eu.dnetlib.enabling.inspector=FATAL
+log4j.logger.eu.dnetlib.enabling.resultset=DEBUG
+log4j.logger.eu.dnetlib.enabling.inspector.SubscriptionController=DEBUG
+log4j.logger.eu.dnetlib.springutils.stringtemplate.StringTemplateViewResolver=FATAL
+log4j.logger.eu.dnetlib.enabling.is.sn.SynchronousNotificationSenderImpl=WARN
+
+log4j.logger.eu.dnetlib.enabling.manager.msro.wf.RefreshIndexJob=DEBUG
+log4j.logger.eu.dnetlib.enabling.ui=DEBUG
+log4j.logger.eu.dnetlib.enabling.manager.msro.wf.RefreshIndexJob=DEBUG
+
+log4j.logger.org.apache.zookeeper.ClientCnxn=FATAL
+
+log4j.logger.eu.dnetlib.enabling.resultset.push=DEBUG
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/ResultSetServiceImplTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/ResultSetServiceImplTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0/src/test/java/eu/dnetlib/enabling/resultset/ResultSetServiceImplTest.java	(revision 45117)
@@ -0,0 +1,101 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.*; // NOPMD
+import static org.mockito.Mockito.*; // NOPMD
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+
+/**
+ * resultset service rmi implementation test.
+ *  
+ * @author marko
+ *
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class ResultSetServiceImplTest {
+
+	/**
+	 * mock resultset id.
+	 */
+	private static final String RS_ID = "123";
+
+	/**
+	 * instance under test.
+	 */
+	private transient ResultSetServiceImpl service;
+	
+	/**
+	 * custom property dao mock.
+	 */
+	@Mock
+	private transient ResultSetPropertyDao customPropertyDao;
+	
+	/**
+	 * resultset registry mock. 
+	 */
+	@Mock
+	private transient ResultSetRegistry resultsetRegistry;
+	
+	/**
+	 * resultset instance mock. 
+	 */
+	@Mock
+	private transient ResultSet resultSet;
+	
+	/**
+	 * setup. 
+	 */
+	@Before
+	public void setUp() {
+		service = new ResultSetServiceImpl();
+		service.setCustomPropertyDao(customPropertyDao);
+		service.setResultsetRegistry(resultsetRegistry);
+		
+		when(resultsetRegistry.getResultSetById(RS_ID)).thenReturn(resultSet);
+		when(resultSet.getIdentifier()).thenReturn(RS_ID);
+	}
+
+	/**
+	 * test get property.
+	 * @throws ResultSetException shouldn't happen
+	 */
+	@Test
+	public void testGetProperty() throws ResultSetException {
+		final Map<String, String> properties = new HashMap<String, String>();
+		properties.put("prefetch", "true");
+		
+		when(customPropertyDao.getProperties(resultSet)).thenReturn(properties);
+		when(resultSet.getNumberOfResults()).thenReturn(1);
+		
+		assertEquals("test builtin", "1", service.getProperty(RS_ID, "total"));
+		assertEquals("test builtin", RS_ID, service.getProperty(RS_ID, "rsId"));
+		
+		assertEquals("test custom", "true", service.getProperty(RS_ID, "prefetch"));
+		assertNull("test custom", service.getProperty(RS_ID, "unexistent"));
+	}
+
+	/**
+	 * get resultset status.
+	 * 
+	 * @throws ResultSetException shouldn't happen
+	 */
+	@Test
+	public void testGetRSStatus() throws ResultSetException {
+		when(resultSet.isOpen()).thenReturn(true);
+		
+		assertEquals("check open", service.getRSStatus(RS_ID), "open");
+		
+		when(resultSet.isOpen()).thenReturn(false);
+		assertEquals("check closed", service.getRSStatus(RS_ID), "closed");
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0	(revision 45117)

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-2.0.0
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,5 ##
+.project
+.classpath
+.settings
+target
+
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetServiceImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetServiceImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetServiceImpl.java	(revision 45117)
@@ -0,0 +1,258 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import javax.jws.WebService;
+import javax.xml.ws.Endpoint;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.common.rmi.UnimplementedException;
+import eu.dnetlib.enabling.resultset.push.PushResultSet;
+import eu.dnetlib.enabling.resultset.push.PushResultSetFactory;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
+import eu.dnetlib.enabling.tools.AbstractBaseService;
+import eu.dnetlib.soap.EndpointReferenceBuilder;
+
+/**
+ * This component dispatches the service method calls to stateful datastructure instances and to the singleton core.
+ * 
+ * @author marko
+ * 
+ */
+@WebService(targetNamespace = "http://services.dnetlib.eu/")
+public class ResultSetServiceImpl extends AbstractBaseService implements ResultSetService {
+
+	/**
+	 * logger.
+	 */
+	private static final Log log = LogFactory.getLog(ResultSetServiceImpl.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	/**
+	 * Maps resultset identifiers to resultsets and manages expiration etc.
+	 */
+	private ResultSetRegistry resultsetRegistry;
+
+	/**
+	 * push resultset factory.
+	 */
+	private PushResultSetFactory pushFactory;
+
+	/**
+	 * Service endpoint.
+	 */
+	private Endpoint endpoint;
+
+	/**
+	 * injected epr builder.
+	 */
+	private EndpointReferenceBuilder<Endpoint> eprBuilder;
+
+	/**
+	 * custom resultset properties.
+	 */
+	private ResultSetPropertyDao customPropertyDao;
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#closeRS(java.lang.String)
+	 */
+	@Override
+	public void closeRS(final String rsId) {
+		try {
+			final ResultSet resultSet = getResultSetById(rsId);
+			resultSet.close();
+		} catch (ResultSetException e) {
+			log.warn("should throw checked exception but wasn't declared in cnr-rmi-api", e);
+			throw new IllegalStateException(e);
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#createPullRS(java.lang.String, java.lang.String, int, int, java.lang.String,
+	 *      java.lang.Integer, java.lang.Integer)
+	 */
+	@Override
+	public W3CEndpointReference createPullRS(final String providerAddress,
+			final String bdId,
+			final int initialPageSize,
+			final int expiryTime,
+			final String styleSheet,
+			final Integer keepAliveTime,
+			final Integer total) {
+		throw new UnimplementedException();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#createPullRSEPR(javax.xml.ws.wsaddressing.W3CEndpointReference,
+	 *      java.lang.String, int, int, java.lang.String, java.lang.Integer, java.lang.Integer)
+	 */
+	@Override
+	public W3CEndpointReference createPullRSEPR(final W3CEndpointReference dataProviderEPR,
+			final String bdId,
+			final int initialPageSize,
+			final int expiryTime,
+			final String styleSheet,
+			final Integer keepAliveTime,
+			final Integer total) {
+		throw new UnimplementedException();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#getNumberOfElements(java.lang.String)
+	 */
+	@Override
+	public int getNumberOfElements(final String rsId) throws ResultSetException {
+		final ResultSet resultSet = getResultSetById(rsId); // NOPMD
+		return resultSet.getNumberOfResults();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#getResult(java.lang.String, int, int, java.lang.String)
+	 */
+	@Override
+	public List<String> getResult(final String rsId, final int fromPosition, final int toPosition, final String requestMode) throws ResultSetException {
+		final ResultSet resultSet = getResultSetById(rsId); // NOPMD
+		return resultSet.getResults(fromPosition, toPosition);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#createPushRS(int, int)
+	 */
+	@Override
+	public W3CEndpointReference createPushRS(final int expiryTime, final int keepAliveTime) throws ResultSetException {
+		return pushFactory.createPushResultSet(expiryTime);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#getProperty(java.lang.String, java.lang.String)
+	 */
+	@Override
+	public String getProperty(final String rsId, final String name) throws ResultSetException {
+		final ResultSet resultSet = getResultSetById(rsId); // NOPMD
+
+		if ("rsId".equals(name)) return resultSet.getIdentifier();
+		else if ("total".equals(name)) return Integer.toString(resultSet.getNumberOfResults());
+		else if ("maxExpiryTime".equals(name)) return Integer.toString(resultsetRegistry.getMaxIdleTimeById(rsId));
+		else if ("expiryTime".equals(name)) return Integer.toString(resultsetRegistry.getMaxIdleTimeById(rsId));
+		else if ("keepAliveTime".equals(name)) return Integer.toString(resultsetRegistry.getMaxIdleTimeById(rsId));
+		// ...
+
+		return customPropertyDao.getProperties(resultSet).get(name);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#getRSStatus(java.lang.String)
+	 */
+	@Override
+	public String getRSStatus(final String rsId) throws ResultSetException {
+		final ResultSet resultSet = getResultSetById(rsId); // NOPMD
+		if (resultSet.isOpen()) return "open";
+		return "closed";
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.rmi.ResultSetService#populateRS(java.lang.String, java.util.List)
+	 */
+	@Override
+	public String populateRS(final String rsId, final List<String> elements) throws ResultSetException {
+		final ResultSet resultSet = getResultSetById(rsId); // NOPMD
+		if (resultSet instanceof PushResultSet) {
+			((PushResultSet) resultSet).addElements(elements);
+		} else throw new ResultSetException("ResultSet '" + rsId + "' is not a push resultset");
+
+		return "1";
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.common.rmi.BaseService#start()
+	 */
+	@Override
+	public void start() {
+		// TODO Auto-generated method stub
+
+	}
+
+	/**
+	 * obtain the resultset object for a given id.
+	 * 
+	 * @param rsId
+	 *            resultset id
+	 * @return resultset object, never null
+	 * @throws ResultSetException
+	 *             thrown when the id doesn't exist;
+	 */
+	private ResultSet getResultSetById(final String rsId) throws ResultSetException {
+		final ResultSet resultSet = resultsetRegistry.getResultSetById(rsId); // NOPMD
+		if (resultSet == null) throw new ResultSetException("resultset with id '" + rsId + "' doesn't exist");
+		return resultSet;
+	}
+
+	public ResultSetRegistry getResultsetRegistry() {
+		return resultsetRegistry;
+	}
+
+	@Required
+	public void setResultsetRegistry(final ResultSetRegistry resultsetRegistry) {
+		this.resultsetRegistry = resultsetRegistry;
+	}
+
+	public EndpointReferenceBuilder<Endpoint> getEprBuilder() {
+		return eprBuilder;
+	}
+
+	@Required
+	public void setEprBuilder(final EndpointReferenceBuilder<Endpoint> eprBuilder) {
+		this.eprBuilder = eprBuilder;
+	}
+
+	public Endpoint getEndpoint() {
+		return endpoint;
+	}
+
+	@Required
+	public void setEndpoint(final Endpoint endpoint) {
+		this.endpoint = endpoint;
+	}
+
+	public PushResultSetFactory getPushFactory() {
+		return pushFactory;
+	}
+
+	@Required
+	public void setPushFactory(final PushResultSetFactory pushFactory) {
+		this.pushFactory = pushFactory;
+	}
+
+	public ResultSetPropertyDao getCustomPropertyDao() {
+		return customPropertyDao;
+	}
+
+	public void setCustomPropertyDao(final ResultSetPropertyDao customPropertyDao) {
+		this.customPropertyDao = customPropertyDao;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/pom.xml
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/pom.xml	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/pom.xml	(revision 45117)
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<parent>
+		<groupId>eu.dnetlib</groupId>
+		<artifactId>dnet-parent</artifactId>
+		<version>1.0.0</version>
+		<relativePath />
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>eu.dnetlib</groupId>
+	<artifactId>cnr-resultset-service</artifactId>
+	<packaging>jar</packaging>
+	<version>1.0.0</version>
+	<scm>
+	  <developerConnection>scm:svn:https://svn.driver.research-infrastructures.eu/driver/dnet40/modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0</developerConnection>
+	</scm>
+	<dependencies>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>${junit.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>com.google.guava</groupId>
+			<artifactId>guava</artifactId>
+			<version>${google.guava.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>cglib</groupId>
+			<artifactId>cglib-nodep</artifactId>
+			<version>2.2</version>
+		</dependency>
+		<dependency>
+			<groupId>org.mockito</groupId>
+			<artifactId>mockito-core</artifactId>
+			<version>1.6</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-test</artifactId>
+			<version>${spring.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-context-support</artifactId>
+			<version>${spring.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>eu.dnetlib</groupId>
+			<artifactId>cnr-rmi-api</artifactId>
+			<version>[2.0.0,3.0.0)</version>
+		</dependency>
+		<dependency>
+			<groupId>eu.dnetlib</groupId>
+			<artifactId>cnr-spring-utils</artifactId>
+			<version>[1.0.0,2.0.0)</version>
+		</dependency>
+		<dependency>
+			<groupId>eu.dnetlib</groupId>
+			<artifactId>cnr-service-common</artifactId>
+			<version>[1.0.0,2.0.0)</version>
+		</dependency>
+	</dependencies>
+</project>
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/observer/Observable.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/observer/Observable.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/observer/Observable.java	(revision 45117)
@@ -0,0 +1,18 @@
+package eu.dnetlib.enabling.resultset.observer;
+
+import eu.dnetlib.enabling.resultset.ResultSetRegistry;
+
+/**
+ * Declares the JDK-like standard observable pattern as a java interface.
+ * 
+ * @author marko, claudio, alessia, michele
+ */
+public interface Observable {
+	/**
+	 * add a given observer to this object.
+	 * 
+	 * @param observer
+	 *            observer
+	 */
+	void addObserver(ResultSetRegistry observer);
+}

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/observer/Observable.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSet.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSet.java	(revision 45117)
@@ -0,0 +1,151 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
+import eu.dnetlib.enabling.tools.ServiceResolver;
+import eu.dnetlib.miscutils.collections.MappedCollection;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+/**
+ * A resultset filter. Applies a transformation for every resultset record.
+ * 
+ * @author marko
+ * 
+ */
+public class MappedResultSet implements ResultSetListener, ResultSetAware {
+
+	/**
+	 * input resultset.
+	 */
+	private ResultSetService resultSetService;
+
+	/**
+	 * input resultset id.
+	 */
+	private String rsId;
+
+	/**
+	 * mapper function.
+	 */
+	private UnaryFunction<String, String> mapper;
+
+	/**
+	 * service resolver.
+	 */
+	private ServiceResolver serviceResolver;
+
+	private ResultSet resultSet;
+
+	/**
+	 * Create a new mapped resultset.
+	 * 
+	 * @param epr
+	 *            input resultset epr
+	 * @param mapper
+	 *            mapper function
+	 * @param serviceResolver
+	 *            service resolver
+	 */
+	public MappedResultSet(final W3CEndpointReference epr, final UnaryFunction<String, String> mapper, final ServiceResolver serviceResolver) {
+		super();
+
+		this.resultSetService = serviceResolver.getService(ResultSetService.class, epr);
+		this.rsId = serviceResolver.getResourceIdentifier(epr);
+
+		this.mapper = mapper;
+
+		this.serviceResolver = serviceResolver;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSetListener#getResult(int, int)
+	 */
+	@Override
+	public List<String> getResult(final int fromPosition, final int toPosition) {
+		return MappedCollection.listMap(getResultFromSource(fromPosition, toPosition), mapper);
+
+	}
+
+	protected List<String> getResultFromSource(final int fromPosition, final int toPosition) {
+		try {
+			List<String> res = resultSetService.getResult(rsId, fromPosition, toPosition, "waiting");
+			checkStatus();
+			return res;
+		} catch (final ResultSetException e) {
+			throw new IllegalStateException(e);
+		}
+	}
+
+	private void checkStatus() throws ResultSetException {
+		if (getResultSet().isOpen() && resultSetService.getRSStatus(rsId).equals("closed")) {
+			getResultSet().close();
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSetListener#getSize()
+	 */
+	@Override
+	public int getSize() {
+		try {
+			int numberOfElements = resultSetService.getNumberOfElements(rsId);
+			checkStatus();		
+			return numberOfElements;
+		} catch (final ResultSetException e) {
+			throw new IllegalStateException(e);
+		}
+	}
+
+	public ResultSetService getResultSetService() {
+		return resultSetService;
+	}
+
+	public void setResultSetService(final ResultSetService resultSetService) {
+		this.resultSetService = resultSetService;
+	}
+
+	public UnaryFunction<String, String> getMapper() {
+		return mapper;
+	}
+
+	public void setMapper(final UnaryFunction<String, String> mapper) {
+		this.mapper = mapper;
+	}
+
+	public ServiceResolver getServiceResolver() {
+		return serviceResolver;
+	}
+
+	@Required
+	public void setServiceResolver(final ServiceResolver serviceResolver) {
+		this.serviceResolver = serviceResolver;
+	}
+
+	@Override
+	public void setResultSet(ResultSet resultSet) {
+		this.resultSet = resultSet;
+	}
+
+	public ResultSet getResultSet() {
+		return resultSet;
+	}
+
+	public String getRsId() {
+		return rsId;
+	}
+
+	public void setRsId(String rsId) {
+		this.rsId = rsId;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSet.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSet.java	(revision 45117)
@@ -0,0 +1,71 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import eu.dnetlib.enabling.resultset.observer.Observable;
+
+/**
+ * A ResultSet represents a set of data results.
+ * 
+ * @author marko
+ * 
+ */
+public interface ResultSet extends Observable {
+	/**
+	 * get the resource identifier.
+	 * 
+	 * @return rsId
+	 */
+	String getIdentifier();
+
+	/**
+	 * sets the resource identifier. The ResultSetRegistry will assign a new rsId.
+	 * 
+	 * @param rsId allocated resultset identifier
+	 */
+	void setIdentifier(String rsId);
+
+	/**
+	 * get a 'page' of results.
+	 * 
+	 * @param fromPosition
+	 *            from 1
+	 * @param toPosition
+	 *            last included
+	 * @return a page of data
+	 */
+	List<String> getResults(int fromPosition, int toPosition);
+
+	/**
+	 * get the number of result elements present in the resultset.
+	 * 
+	 * @return number of results
+	 */
+	int getNumberOfResults();
+
+	/**
+	 * Tells if the resultset is open or closed.
+	 * 
+	 * @return true if open
+	 */
+	boolean isOpen();
+
+	/**
+	 * close a resultset.
+	 */
+	void close();
+	
+	/**
+	 * Tells if the resultset is destroyed.
+	 * 
+	 * @return true if the resultset is destroyed. 
+	 */
+	boolean isDestroyed();
+	
+	/**
+	 * Destroy the resultset and free associated resources, remove it from the ResultSetRegistry.
+	 * After calling this method, the resultset is no more accessible from other services.
+	 */
+	void destroy();
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/AbstractObservableResultset.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/AbstractObservableResultset.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/AbstractObservableResultset.java	(revision 45117)
@@ -0,0 +1,155 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import eu.dnetlib.enabling.resultset.observer.DelegationObserver;
+import eu.dnetlib.enabling.resultset.observer.Observable;
+
+
+/**
+ * Common stuff for resultset implementations bound to a ResultSetRegistry.
+ * 
+ * @author marko
+ * 
+ */
+public abstract class AbstractObservableResultset implements ResultSet, Observable {
+	/**
+	 * true if the resultset is destroyed.
+	 */
+	private boolean destroyed = false;
+
+	/**
+	 * true if the resultset is open.
+	 */
+	private boolean open;
+
+	/**
+	 * delegate the real job to a java.util.Observable object.
+	 */
+	private transient final java.util.Observable observable = new DelegationObservable();
+
+	/**
+	 * weak map for removing single observers later on.
+	 */
+	private transient Map<ResultSetRegistry, DelegationObserver> observers = new WeakHashMap<ResultSetRegistry, DelegationObserver>();
+
+	/**
+	 * java.util.Observable requires a "change" in the object to be made for the notifyObservers methods to trigger
+	 * actually the notification. We don't think this should be part of the base Observable/Observer pattern and thus
+	 * hide this fact. If an user of AbstractObservable wants this behavior it should implement her own change tracking
+	 * and avoid calling notifyObservers altogether. The rationale behind this choice is that not all dirty states can
+	 * be expressed using a stateful boolean instance variable like that implemented by java.util.Observable; some users
+	 * may prefer/need a lazy dirty flag instead.
+	 * 
+	 * @author marko
+	 * 
+	 */
+	static class DelegationObservable extends java.util.Observable {
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see java.util.Observable#notifyObservers()
+		 */
+		@Override
+		public void notifyObservers() {
+			setChanged();
+			super.notifyObservers();
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see java.util.Observable#notifyObservers(java.lang.Object)
+		 */
+		@Override
+		public void notifyObservers(final Object arg) {
+			setChanged();
+			super.notifyObservers(arg);
+		}
+
+	}	
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#destroy()
+	 */
+	@Override
+	public void destroy() {
+		if (!isDestroyed()) {
+			setDestroyed(true);
+			notifyObservers();
+			deleteObservers();
+		}
+	}
+
+	public void setDestroyed(final boolean destroyed) {
+		this.destroyed = destroyed;
+	}
+
+	@Override
+	public boolean isDestroyed() {
+		return destroyed;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#isOpen()
+	 */
+	@Override
+	public boolean isOpen() {
+		return open;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#close()
+	 */
+	@Override
+	public void close() {
+		open = false;
+	}
+
+	public void setOpen(final boolean open) {
+		this.open = open;
+	}
+
+	@Override
+	public void addObserver(final ResultSetRegistry observer) {
+		final DelegationObserver delegate = new DelegationObserver(this, observer);
+		observers.put(observer, delegate);
+		observable.addObserver(delegate);
+	}
+
+	protected void notifyObservers() {
+		observable.notifyObservers();
+	}
+
+	protected void notifyObservers(final Object arg) {
+		observable.notifyObservers(arg);
+	}
+
+	public int countObservers() {
+		return observable.countObservers();
+	}
+
+	public void deleteObserver(final java.util.Observer observer) {
+		observable.deleteObserver(observer);
+	}
+
+	public void deleteObserver(ResultSetRegistry observer) {
+		DelegationObserver delegate = observers.get(observer);
+		if(delegate != null) {
+			observable.deleteObserver(delegate);
+		}
+	}	
+
+	public void deleteObservers() {
+		observable.deleteObservers();
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetFactoryImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetFactoryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetFactoryImpl.java	(revision 45117)
@@ -0,0 +1,38 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * This factory creates resultset bound to a given resultset registry shared with a resultset service which exposed them
+ * to the outside world.
+ *
+ * It's tightly coupled with a local instance of the ResultSetService.
+ *
+ * @see eu.dnetlib.enabling.resultset.ResultSetServiceImpl
+ *
+ * @author marko
+ *
+ */
+public class LocalResultSetFactoryImpl extends AbstractResultSetFactory {
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see eu.dnetlib.enabling.resultset.ResultSetFactory#createResultSet(eu.dnetlib.enabling.resultset.ResultSetListener)
+	 */
+	@Override
+	public W3CEndpointReference createResultSet(final ResultSetListener provider) {
+		return registerResultSet(createInstance(provider));
+	}
+
+	/**
+	 * create a new local resultset instance. Subclasses may override this to supply additional configuration.
+	 *
+	 * @param provider provider
+	 * @return a new resultset instance.
+	 */
+	protected LocalResultSetImpl createInstance(final ResultSetListener provider) {
+		return new LocalResultSetImpl(provider);
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetImpl.java	(revision 45117)
@@ -0,0 +1,98 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Resultset backing implementation.
+ * 
+ * @author marko
+ * 
+ */
+public class LocalResultSetImpl extends AbstractObservableResultset implements ResultSet {
+
+	/**
+	 * rsId.
+	 */
+	private String identifier;
+
+	/**
+	 * this listener will provide the data to this local resultset by listening to events.
+	 */
+	private ResultSetListener listener;
+
+	/**
+	 * Construct a new local ResultSet which pulls data from the listener. If the listener implements ResultSetAware, it
+	 * will be injected with this instance.
+	 * 
+	 * @param listener
+	 *            a resultset listener
+	 */
+	public LocalResultSetImpl(final ResultSetListener listener) {
+		super();
+		this.listener = listener;
+
+		if (listener instanceof ResultSetAware)
+			((ResultSetAware) listener).setResultSet(this);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#getNumberOfResults()
+	 */
+	@Override
+	public int getNumberOfResults() {
+		return listener.getSize();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#getResults(int, int)
+	 */
+	@Override
+	public List<String> getResults(final int fromPosition, final int toPosition) {
+		int toPos = toPosition;
+		int fromPos = fromPosition;
+		if (!isOpen()) {
+			final int size = getNumberOfResults();
+			
+			if (size == 0)
+				return Lists.newArrayList();
+			
+			if (fromPos > size)
+				return Lists.newArrayList();
+
+			if (toPos > size)
+				toPos = size;
+		}
+		
+		if (fromPos < 1)
+			fromPos = 1;
+		if (toPos < fromPos)
+			toPos = fromPos;
+
+		return listener.getResult(fromPos, toPos);
+	}
+
+	@Override
+	public String getIdentifier() {
+		return identifier;
+	}
+
+	@Override
+	public void setIdentifier(final String identifier) {
+		this.identifier = identifier;
+	}
+
+	public ResultSetListener getListener() {
+		return listener;
+	}
+
+	public void setListener(final ResultSetListener listener) {
+		this.listener = listener;
+	}
+
+}

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/LocalResultSetImpl.java
___________________________________________________________________
Added: svn:mergeinfo
## -0,0 +0,0 ##
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/CacheTransientResultSetDaoImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/CacheTransientResultSetDaoImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/CacheTransientResultSetDaoImpl.java	(revision 45117)
@@ -0,0 +1,179 @@
+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<String, List<String>> cache;
+
+	/**
+	 * resultsets
+	 */
+	private Cache<String, ResultSetDescriptor> resultSetCache;
+
+	/**
+	 * resultset descriptor factory.
+	 */
+	@Resource
+	private Factory<ResultSetDescriptor> 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<String> 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<String> lastRange = cache.get(key + "-" + lastRangeIndex);
+			log.debug("stored last range: " + lastRange);
+
+			if (lastRange == null) {
+				lastRange = new ArrayList<String>();
+				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<String> nextRange = new ArrayList<String>(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<String> 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<String> res = new ArrayList<String>();
+
+		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<String, List<String>> getCache() {
+		return cache;
+	}
+
+	@Required
+	public void setCache(final Cache<String, List<String>> cache) {
+		this.cache = cache;
+	}
+
+	public Cache<String, ResultSetDescriptor> getResultSetCache() {
+		return resultSetCache;
+	}
+
+	@Required
+	public void setResultSetCache(final Cache<String, ResultSetDescriptor> resultSetCache) {
+		this.resultSetCache = resultSetCache;
+	}
+
+	public Factory<ResultSetDescriptor> getResultSetDescriptorFactory() {
+		return resultSetDescriptorFactory;
+	}
+
+	public void setResultSetDescriptorFactory(final Factory<ResultSetDescriptor> resultSetDescriptorFactory) {
+		this.resultSetDescriptorFactory = resultSetDescriptorFactory;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetImpl.java	(revision 45117)
@@ -0,0 +1,99 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import eu.dnetlib.enabling.resultset.AbstractObservableResultset;
+
+/**
+ * a push resultset which holds it's data in a transient cache.
+ *
+ * @author marko
+ *
+ */
+public class TransientPushResultSetImpl extends AbstractObservableResultset implements PushResultSet {
+
+	/**
+	 * logger.
+	 */
+	private static final Log log = LogFactory.getLog(TransientPushResultSetImpl.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	/**
+	 * dao.
+	 */
+	private final transient TransientPushResultSetDao dao;
+
+	/**
+	 * rsId.
+	 */
+	private String identifier;
+
+	/**
+	 * constructed by the transient push resultset factory.
+	 *
+	 * @param dao dao
+	 */
+	public TransientPushResultSetImpl(final TransientPushResultSetDao dao) {
+		super();
+		this.dao = dao;
+		setOpen(true);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see eu.dnetlib.enabling.resultset.push.PushResultSet#addElements(java.util.List)
+	 */
+	@Override
+	public void addElements(final List<String> elements) {
+		log.debug("adding to push RS: " + elements);
+
+		if (isOpen())
+			dao.addElements(getIdentifier(), elements);
+		else
+			throw new IllegalStateException("cannot write to a closed push resultset");
+	}
+
+	@Override
+	public int getNumberOfResults() {
+		return dao.getSize(getIdentifier());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see eu.dnetlib.enabling.resultset.ResultSet#getResults(int, int)
+	 */
+	@Override
+	public List<String> getResults(final int fromPosition, final int toPosition) {
+
+		final int size = getNumberOfResults();
+		int toPos = toPosition;
+		int fromPos = fromPosition;
+		if (fromPos > size)
+			fromPos = size;
+		if (toPos > size)
+			toPos = size;
+
+		log.debug("calling get elements: " + getIdentifier() + " from " + fromPos + " to " + toPos);
+		return dao.getElements(getIdentifier(), fromPos, toPos);
+	}
+
+	public TransientPushResultSetDao getDao() {
+		return dao;
+	}
+
+	@Override
+	public String getIdentifier() {
+		return identifier;
+	}
+
+	@Override
+	public void setIdentifier(final String identifier) {
+		this.identifier = identifier;
+	}
+
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/TransientPushResultSetFactory.java	(revision 45117)
@@ -0,0 +1,34 @@
+package eu.dnetlib.enabling.resultset.push;
+
+
+/**
+ * creates a transient push resultset.
+ * 
+ * @author marko
+ *
+ */
+public class TransientPushResultSetFactory extends AbstractPushResultSetFactoryImpl {
+
+	/**
+	 * dao.
+	 */
+	private TransientPushResultSetDao dao;
+	
+	/** 
+	 * {@inheritDoc}
+	 * @see eu.dnetlib.enabling.resultset.push.AbstractPushResultSetFactoryImpl#newInstance()
+	 */
+	@Override
+	protected PushResultSet newInstance() {
+		return new TransientPushResultSetImpl(dao);
+	}
+
+	public TransientPushResultSetDao getDao() {
+		return dao;
+	}
+
+	public void setDao(final TransientPushResultSetDao dao) {
+		this.dao = dao;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactory.java	(revision 45117)
@@ -0,0 +1,7 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import eu.dnetlib.miscutils.factory.Factory;
+
+public interface ResultSetDescriptorFactory extends Factory<ResultSetDescriptor> {
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalResultSetFactoryImpl.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalResultSetFactoryImpl.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/EPRPoolingLocalResultSetFactoryImpl.java	(revision 45117)
@@ -0,0 +1,27 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+public class EPRPoolingLocalResultSetFactoryImpl extends LocalResultSetFactoryImpl {
+
+	private ResultSetEPRPool pool;
+	
+	@Override
+	public W3CEndpointReference registerResultSet(ResultSet resultSet) {
+		return pool.registerResultSet(resultSet);
+	}
+
+	public ResultSetEPRPool getPool() {
+		return pool;
+	}
+
+	@Required
+	public void setPool(ResultSetEPRPool pool) {
+		this.pool = pool;
+	}
+
+	
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSet.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/push/PushResultSet.java	(revision 45117)
@@ -0,0 +1,22 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import java.util.List;
+
+import eu.dnetlib.enabling.resultset.ResultSet;
+
+/**
+ * resultset which receive data through the "push" interface, i.e. data is directly appended to it.
+ * 
+ * @author marko
+ *
+ */
+public interface PushResultSet extends ResultSet {
+
+	/**
+	 * add a list of elements at the end of the resultset.
+	 * 
+	 * @param elements list of elements
+	 */
+	void addElements(List<String> elements);
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSet.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ParallelMappedResultSet.java	(revision 45117)
@@ -0,0 +1,57 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.enabling.tools.ServiceResolver;
+import eu.dnetlib.miscutils.collections.MappedCollection;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+public class ParallelMappedResultSet extends MappedResultSet {
+
+	private ExecutorService executor;
+
+	public ParallelMappedResultSet(final W3CEndpointReference source, final UnaryFunction<String, String> mapper, final ServiceResolver serviceResolver,
+			final ExecutorService executor) {
+		super(source, mapper, serviceResolver);
+		this.executor = executor;
+	}
+
+	@Override
+	public List<String> getResult(int fromPosition, int toPosition) {
+
+//		log.info("Parallel page " + (toPosition - fromPosition + 1));
+
+		List<Future<String>> results = Lists.newArrayList();
+
+		for (final String input : getResultFromSource(fromPosition, toPosition)) {
+			results.add(executor.submit(new Callable<String>() {
+				@Override
+				public String call() throws Exception {
+					return getMapper().evaluate(input);
+				}
+			}));
+		}
+
+		return MappedCollection.listMap(results, new UnaryFunction<String, Future<String>>() {
+			@Override
+			public String evaluate(Future<String> arg) {
+				try {
+					return arg.get();
+				} catch (InterruptedException e) {
+					throw new IllegalStateException(e);
+				} catch (ExecutionException e) {
+					throw new IllegalStateException(e);
+				}
+			}
+		});
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetEPRPool.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetEPRPool.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetEPRPool.java	(revision 45117)
@@ -0,0 +1,137 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import javax.annotation.PostConstruct;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.enabling.tools.UniqueIdentifierGenerator;
+import eu.dnetlib.enabling.tools.UniqueIdentifierGeneratorImpl;
+
+public class ResultSetEPRPool {
+	private static final Log log = LogFactory.getLog(ResultSetEPRPool.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	static class PreparedResultSet {
+		private String rsId;
+		private W3CEndpointReference epr;
+
+		public PreparedResultSet(final String rsId, final W3CEndpointReference epr) {
+			super();
+			this.rsId = rsId;
+			this.epr = epr;
+		}
+
+		public String getRsId() {
+			return rsId;
+		}
+
+		public void setRsId(final String rsId) {
+			this.rsId = rsId;
+		}
+
+		public W3CEndpointReference getEpr() {
+			return epr;
+		}
+
+		public void setEpr(final W3CEndpointReference epr) {
+			this.epr = epr;
+		}
+	}
+
+	class PoolFiller implements Runnable {
+
+		@Override
+		public void run() {
+			while (true)
+				try {
+					final PreparedResultSet resultSet = prepareResultSet();
+					pool.put(resultSet);
+				} catch (final InterruptedException e) {
+					// eat this exception
+					log.debug("cannot add resultset to pool", e);
+				}
+		}
+
+		private PreparedResultSet prepareResultSet() {
+			final String rsId = idGenerator.generateIdentifier();
+			return new PreparedResultSet(rsId, createEPR(rsId));
+		}
+
+		private W3CEndpointReference createEPR(final String rsId) {
+			return getResultSetService().getEprBuilder().getEndpointReference(getResultSetService().getEndpoint(), rsId);
+		}
+	}
+
+	/**
+	 * resultset service.
+	 */
+	private ResultSetServiceImpl resultSetService;
+
+	private int capacity = 1000;
+	private int fillerThreads = 10;
+	private final BlockingQueue<PreparedResultSet> pool = new LinkedBlockingQueue<PreparedResultSet>(capacity);
+
+	/**
+	 * identifier generator.
+	 */
+	private UniqueIdentifierGenerator idGenerator = new UniqueIdentifierGeneratorImpl("rs-");
+
+	@PostConstruct
+	public void init() {
+		log.info("-------<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>> Starting fill threads");
+		for (int i = 0; i < fillerThreads; i++)
+			startFillter();
+	}
+
+	protected void startFillter() {
+		final Thread filler = new Thread(new PoolFiller());
+		filler.setDaemon(true);
+		filler.start();
+	}
+
+	public W3CEndpointReference registerResultSet(final ResultSet resultSet) {
+		final PreparedResultSet prepared = nextPreparedResultSet();
+		if (prepared == null) {
+			log.info("EPR cache is empty, creating EPR in caller thread");
+			return getResultSetService().getEprBuilder().getEndpointReference(getResultSetService().getEndpoint(), idGenerator.generateIdentifier());
+		}
+
+		getResultSetService().getResultsetRegistry().addResultSet(resultSet, prepared.getRsId());
+		return prepared.getEpr();
+	}
+
+	private PreparedResultSet nextPreparedResultSet() {
+		log.info(">>>> fetching a prepared resultset from the pool");
+		return pool.poll();
+	}
+
+	public int getCapacity() {
+		return capacity;
+	}
+
+	public void setCapacity(int capacity) {
+		this.capacity = capacity;
+	}
+
+	public UniqueIdentifierGenerator getIdGenerator() {
+		return idGenerator;
+	}
+
+	public void setIdGenerator(UniqueIdentifierGenerator idGenerator) {
+		this.idGenerator = idGenerator;
+	}
+
+	public ResultSetServiceImpl getResultSetService() {
+		return resultSetService;
+	}
+
+	@Required
+	public void setResultSetService(ResultSetServiceImpl resultSetService) {
+		this.resultSetService = resultSetService;
+	}
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetFactory.java	(revision 45117)
@@ -0,0 +1,46 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.annotation.Resource;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.enabling.tools.ServiceResolver;
+
+public class CachingResultSetFactory {
+	/**
+	 * underlying resultset factory, which exposes local resultsets to the world.
+	 */
+	private ResultSetFactory resultSetFactory;
+
+	@Resource
+	private ServiceResolver serviceResolver;
+	
+	/**
+	 * @param items
+	 * @param size
+	 *            the size of the iterable
+	 * @return
+	 */
+	public W3CEndpointReference createCachingResultSet(W3CEndpointReference epr) {
+		return resultSetFactory.createResultSet(new CachingResultSetListener(epr, serviceResolver));
+	}
+
+	public ResultSetFactory getResultSetFactory() {
+		return resultSetFactory;
+	}
+
+	@Required
+	public void setResultSetFactory(ResultSetFactory resultSetFactory) {
+		this.resultSetFactory = resultSetFactory;
+	}
+
+	public ServiceResolver getServiceResolver() {
+		return serviceResolver;
+	}
+
+	public void setServiceResolver(ServiceResolver serviceResolver) {
+		this.serviceResolver = serviceResolver;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSet.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSet.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSet.java	(revision 45117)
@@ -0,0 +1,60 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.List;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.enabling.tools.ServiceResolver;
+import eu.dnetlib.miscutils.functional.IdentityFunction;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+/**
+ * A resultset record counter.
+ * 
+ * @author claudio
+ * 
+ */
+public class CountingResultSet extends MappedResultSet {
+
+	/**
+	 * counter.
+	 */
+	private int count;
+
+
+	/**
+	 * @param epr
+	 * @param serviceResolver
+	 */
+	public CountingResultSet(final W3CEndpointReference epr, final ServiceResolver serviceResolver) {
+		this(epr, new IdentityFunction<String>(), serviceResolver);
+	}
+
+	/**
+	 * @param epr
+	 * @param mapper
+	 * @param serviceResolver
+	 */
+	public CountingResultSet(final W3CEndpointReference epr, final UnaryFunction<String, String> mapper, final ServiceResolver serviceResolver) {
+		super(epr, mapper, serviceResolver);
+		count = 0;
+	}
+
+	/**
+	 * method sets the counter to the higher allowed value of toPosition.
+	 */
+	@Override
+	public List<String> getResult(int fromPosition, int toPosition) {
+
+		if (toPosition > count)
+			count = toPosition;
+		if (toPosition > super.getSize())
+			count = super.getSize();
+
+		return super.getResult(fromPosition, toPosition);
+	}
+
+	public int getCount() {
+		return count;
+	}
+}

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/CountingResultSet.java
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/StreamingResultSetFactory.java	(revision 45117)
@@ -0,0 +1,32 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+public class StreamingResultSetFactory {
+	/**
+	 * underlying resultset factory, which exposes local resultsets to the world.
+	 */
+	private ResultSetFactory resultSetFactory;
+
+	/**
+	 * @param items
+	 * @param size the size of the iterable
+	 * @return
+	 */
+	public W3CEndpointReference createStreamingResultSet(final Iterable<String> items, int size) {
+		return resultSetFactory.createResultSet(new StreamingResultSetListener(items.iterator(), size));
+	}
+
+	
+	public ResultSetFactory getResultSetFactory() {
+		return resultSetFactory;
+	}
+
+	@Required
+	public void setResultSetFactory(ResultSetFactory resultSetFactory) {
+		this.resultSetFactory = resultSetFactory;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetListener.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetListener.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/CachingResultSetListener.java	(revision 45117)
@@ -0,0 +1,61 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
+import eu.dnetlib.enabling.tools.ServiceResolver;
+
+public class CachingResultSetListener implements ResultSetListener {
+	private static final Log log = LogFactory.getLog(CachingResultSetListener.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	
+	private ResultSetService service;
+	private String rsId;
+
+	private ArrayList<String> storage = new ArrayList<String>();
+
+	public CachingResultSetListener(W3CEndpointReference epr, ServiceResolver serviceResolver) {
+		this.service = serviceResolver.getService(ResultSetService.class, epr);
+		this.rsId = serviceResolver.getResourceIdentifier(epr);
+	}
+
+	@Override
+	public List<String> getResult(int fromPosition, int toPosition) {
+		if (storage.get(fromPosition) != null)
+			return cached(fromPosition, toPosition);
+		try {
+			List<String> data = service.getResult(rsId, fromPosition, toPosition, "waiting");
+			cache(data, fromPosition, toPosition);
+			return data;
+		} catch (ResultSetException e) {
+			throw new IllegalStateException(e);
+		}
+	}
+
+	private void cache(List<String> data, int fromPosition, int toPosition) {
+		for(String value : data)
+			storage.set(fromPosition++, value);
+	}
+
+	private List<String> cached(int fromPosition, int toPosition) {
+		log.info("found cached page " + fromPosition + ", " + toPosition);
+		return storage.subList(fromPosition-1, toPosition);
+	}
+
+	@Override
+	public int getSize() {
+		try {
+			return service.getNumberOfElements(rsId);
+		} catch (ResultSetException e) {
+			throw new IllegalStateException(e);
+		}
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/AbstractResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/AbstractResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/AbstractResultSetFactory.java	(revision 45117)
@@ -0,0 +1,38 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * Resultset factories bound to a resultset service, from which it takes the resultset registry and the epr builder.
+ *
+ * @author marko
+ *
+ */
+public abstract class AbstractResultSetFactory implements ResultSetFactory {
+
+	/**
+	 * resultset service.
+	 */
+	private ResultSetServiceImpl resultSetService;
+
+	/**
+	 * Register a resultset instance to the underlying resultset registry and returns
+	 * and EPR to accessible through the resultset service.
+	 *
+	 * @param resultSet resultset instance
+	 * @return epr to the newly created resultset
+	 */
+	public W3CEndpointReference registerResultSet(final ResultSet resultSet) {
+		resultSetService.getResultsetRegistry().addResultSet(resultSet);
+		return resultSetService.getEprBuilder().getEndpointReference(resultSetService.getEndpoint(), resultSet.getIdentifier());
+	}
+
+	public ResultSetServiceImpl getResultSetService() {
+		return resultSetService;
+	}
+
+	public void setResultSetService(final ResultSetServiceImpl resultSetService) {
+		this.resultSetService = resultSetService;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/SizedIterable.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/SizedIterable.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/SizedIterable.java	(revision 45117)
@@ -0,0 +1,7 @@
+package eu.dnetlib.enabling.resultset;
+
+public interface SizedIterable<T> extends Iterable<T> {
+
+	public int getNumberOfElements();
+	
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDao.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDao.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/ResultSetPropertyDao.java	(revision 45117)
@@ -0,0 +1,19 @@
+package eu.dnetlib.enabling.resultset;
+
+import java.util.Map;
+
+/**
+ * access resultset properties.
+ * 
+ * @author marko
+ *
+ */
+public interface ResultSetPropertyDao {
+	/**
+	 * return a map of custom resultset properties.
+	 * 
+	 * @param resultSet resultset
+	 * @return property map
+	 */
+	Map<String, String> getProperties(ResultSet resultSet);
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSetFactory.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSetFactory.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/java/eu/dnetlib/enabling/resultset/MappedResultSetFactory.java	(revision 45117)
@@ -0,0 +1,53 @@
+package eu.dnetlib.enabling.resultset;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.enabling.tools.ServiceResolver;
+import eu.dnetlib.miscutils.functional.UnaryFunction;
+
+/**
+ * Create a new resultset which takes each record of the input resultset and applies the mapping function to it.
+ *
+ * @author marko
+ *
+ */
+public class MappedResultSetFactory {
+
+	/**
+	 * underlying resultset factory, which exposes local resultsets to the world.
+	 */
+	private ResultSetFactory resultSetFactory;
+
+	/**
+	 * service resolver, transforms eprs to services.
+	 */
+	private ServiceResolver serviceResolver;
+
+	/**
+	 * Create a new resultset which takes each record of the input resultset and applies the mapping function to it.
+	 *
+	 * @param source source resultset epr
+	 * @param mapper mapper function
+	 * @return mapped resultset epr
+	 */
+	public W3CEndpointReference createMappedResultSet(final W3CEndpointReference source, final UnaryFunction<String, String> mapper) {
+		return resultSetFactory.createResultSet(new MappedResultSet(source, mapper, serviceResolver));
+	}
+
+	public ResultSetFactory getResultSetFactory() {
+		return resultSetFactory;
+	}
+
+	public void setResultSetFactory(final ResultSetFactory resultSetFactory) {
+		this.resultSetFactory = resultSetFactory;
+	}
+
+	public ServiceResolver getServiceResolver() {
+		return serviceResolver;
+	}
+
+	public void setServiceResolver(final ServiceResolver serviceResolver) {
+		this.serviceResolver = serviceResolver;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest.java	(revision 45117)
@@ -0,0 +1,36 @@
+package eu.dnetlib.enabling.resultset.push;
+
+
+import static org.junit.Assert.*;
+
+import javax.annotation.Resource;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import eu.dnetlib.miscutils.factory.Factory;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration
+public class ResultSetDescriptorFactoryTest {
+
+	@Resource
+	Factory<ResultSetDescriptor> factory;
+
+	@Before
+	public void setUp() throws Exception {
+	}
+
+	@Test
+	public void testFactory() {
+		ResultSetDescriptor desc1 = factory.newInstance();
+		ResultSetDescriptor desc2 = factory.newInstance();
+
+		assertTrue("check different instances", desc1 != desc2);
+		assertEquals("check that it's a spring prototype", 200, desc1.getRangeLength());
+		assertEquals("check that it's a spring prototype", 200, desc2.getRangeLength());
+	}
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.xml
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.xml	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/main/resources/eu/dnetlib/enabling/resultset/applicationContext-resultset.xml	(revision 45117)
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
+	xmlns:sec="http://cxf.apache.org/configuration/security" xmlns:wsa="http://cxf.apache.org/ws/addressing"
+	xmlns:p="http://www.springframework.org/schema/p" xmlns:http="http://cxf.apache.org/transports/http/configuration"
+	xmlns:t="http://dnetlib.eu/springbeans/t" xmlns:template="http://dnetlib.eu/springbeans/template"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+                                    http://cxf.apache.org/ws/addressing http://cxf.apache.org/schemas/ws-addr-conf.xsd
+                                    http://cxf.apache.org/configuration/security http://cxf.apache.org/schemas/configuration/security.xsd
+                                    http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd
+                            http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
+                            http://dnetlib.eu/springbeans/template http://dnetlib.eu/springbeans/template.xsd">
+
+	<!-- beans -->
+	<bean id="resultSetCacheManager"
+		class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" />
+	<!-- p:configLocation="classpath:eu/dnetlib/enabling/resultset/ehcache.xml" -->
+
+	<bean id="resultSetRegistryCache" class="eu.dnetlib.miscutils.cache.EhCache">
+		<property name="cache">
+			<bean id="resultSetRegistryCacheCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"
+				p:cacheManager-ref="resultSetCacheManager" p:cacheName="resultSetFactoryCache"
+				p:eternal="false" p:timeToLive="0"
+				p:timeToIdle="${services.is.resultset.resultSetRegistryCache.timeToIdle}" />
+		</property>
+	</bean>
+
+	<bean id="resultSetRegistryMaxIdleTimeCache" class="eu.dnetlib.miscutils.cache.EhCache">
+		<property name="cache">
+			<bean id="resultSetRegistryMaxIdleTimeCacheCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"
+				p:cacheManager-ref="resultSetCacheManager" p:cacheName="resultSetFactoryMaxIdleTimeCache"
+				p:eternal="false" p:timeToLive="0"
+				p:timeToIdle="${services.is.resultset.resultSetRegistryMaxIdleTimeCache.timeToIdle}" />
+		</property>
+	</bean>
+
+	<!-- backing store for the pushResultSetDao -->
+	<bean id="pushResultSetStoreCache" class="eu.dnetlib.miscutils.cache.EhCache">
+		<property name="cache">
+			<bean id="pushResultSetStoreCacheCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"
+				p:eternal="false" p:timeToLive="0" p:timeToIdle="36000"
+				p:maxElementsInMemory="100" p:maxElementsOnDisk="20000"
+				p:cacheManager-ref="resultSetCacheManager" p:cacheName="pushResultSetStoreCache" />
+		</property>
+	</bean>
+
+	<!-- resultset descriptor store for the pushResultSetDao -->
+	<bean id="pushResultSetDescriptorCache" class="eu.dnetlib.miscutils.cache.EhCache">
+		<property name="cache">
+			<bean id="pushResultSetDescriptorCacheCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"
+				p:eternal="false" p:timeToLive="0" p:timeToIdle="1800"
+				p:cacheManager-ref="resultSetCacheManager" p:cacheName="pushResultSetDescriptorCache" />
+		</property>
+	</bean>
+
+	<bean id="resultSetDescriptorFactory" class="eu.dnetlib.springutils.beans.factory.PrototypeFactory">
+		<lookup-method name="newInstance" bean="resultSetDescriptorPrototype" />
+	</bean>
+
+	<bean id="resultSetDescriptorPrototype" class="eu.dnetlib.enabling.resultset.push.ResultSetDescriptor"
+		p:rangeLength="100" scope="prototype" />
+
+	<bean id="resultSetRegistry" class="eu.dnetlib.enabling.resultset.ResultSetRegistryImpl"
+		p:cache-ref="resultSetRegistryCache" p:maxIdleTimeCache-ref="resultSetRegistryMaxIdleTimeCache" />
+
+<!--
+  <bean id="resultSetEPRPool" class="eu.dnetlib.enabling.resultset.ResultSetEPRPool"
+   p:resultSetService-ref="resultSetService" />
+-->
+
+	<!-- <bean id="resultSetFactory" class="eu.dnetlib.enabling.resultset.LocalResultSetFactoryImpl" -->
+	<!-- <bean id="resultSetFactory" class="eu.dnetlib.enabling.resultset.EPRPoolingLocalResultSetFactoryImpl" p:pool-ref="resultSetEPRPool" 
+		p:resultSetService-ref="resultSetService" /> -->
+
+  <bean id="resultSetFactory" class="eu.dnetlib.enabling.resultset.LocalResultSetFactoryImpl" 
+		p:resultSetService-ref="resultSetService" /> 
+
+	<bean id="openResultSetFactory"
+		class="eu.dnetlib.enabling.resultset.LocalOpenResultSetFactoryImpl"
+		p:resultSetService-ref="resultSetService" />
+		
+<!--
+	<bean id="openResultSetFactory"
+		class="eu.dnetlib.enabling.resultset.EPRPoolingLocalOpenResultSetFactoryImpl" p:pool-ref="resultSetEPRPool"
+		p:resultSetService-ref="resultSetService" />
+-->
+	<bean id="mappedResultSetFactory" class="eu.dnetlib.enabling.resultset.MappedResultSetFactory"
+		p:serviceResolver-ref="serviceResolver" p:resultSetFactory-ref="resultSetFactory" />
+		
+	<bean id="parallelMappedResultSetFactory" class="eu.dnetlib.enabling.resultset.ParallelMappedResultSetFactory"
+		p:serviceResolver-ref="serviceResolver" p:resultSetFactory-ref="resultSetFactory" />		
+
+	<bean id="xsltResultSetFactory"
+		class="eu.dnetlib.enabling.resultset.XSLTMappedResultSetFactory"
+		p:serviceResolver-ref="serviceResolver" p:resultSetFactory-ref="resultSetFactory" />
+
+	<bean id="countingResultSetFactory" class="eu.dnetlib.enabling.resultset.CountingResultSetFactory"
+		p:serviceResolver-ref="serviceResolver" p:resultSetFactory-ref="resultSetFactory" />
+
+	<bean id="streamingResultSetFactory" class="eu.dnetlib.enabling.resultset.StreamingResultSetFactory"
+		p:resultSetFactory-ref="resultSetFactory" />
+
+	<bean id="cachingResultSetFactory" class="eu.dnetlib.enabling.resultset.CachingResultSetFactory"
+		p:resultSetFactory-ref="resultSetFactory" />
+
+	<bean id="pushResultSetFactory"
+		class="eu.dnetlib.enabling.resultset.push.TransientPushResultSetFactory"
+		p:dao-ref="pushResultSetDao" p:resultSetService-ref="resultSetService" />
+
+	<bean id="iterableResultSetFactory" class="eu.dnetlib.enabling.resultset.IterableResultSetFactory"
+		p:fetchSize="10" p:resultSetFactory-ref="openResultSetFactory"
+		lazy-init="true" />
+
+
+	<bean id="pushResultSetDao"
+		class="eu.dnetlib.enabling.resultset.push.CacheTransientResultSetDaoImpl"
+		p:cache-ref="pushResultSetStoreCache" p:resultSetCache-ref="pushResultSetDescriptorCache" />
+
+	<bean id="customResultSetPropertyDao" class="eu.dnetlib.enabling.resultset.ResultSetPropertyDaoImpl" />
+
+	<bean id="resultSetService" class="eu.dnetlib.enabling.resultset.ResultSetServiceImpl"
+		init-method="start" p:resultsetRegistry-ref="resultSetRegistry"
+		p:pushFactory-ref="pushResultSetFactory" p:endpoint-ref="resultSetServiceEndpoint"
+		p:eprBuilder-ref="jaxwsEndpointReferenceBuilder" p:customPropertyDao-ref="customResultSetPropertyDao" />
+		
+	<!-- endpoints -->
+	<jaxws:endpoint id="resultSetServiceEndpoint"
+		implementor="#resultSetService" implementorClass="eu.dnetlib.enabling.resultset.rmi.ResultSetService"
+		address="/resultSet" />
+
+	<template:instance name="serviceRegistrationManager"
+		t:serviceRegistrationManagerClass="eu.dnetlib.enabling.tools.registration.ValidatingServiceRegistrationManagerImpl"
+		t:name="resultSetServiceRegistrationManager" t:service="resultSetService"
+		t:endpoint="resultSetServiceEndpoint" t:jobScheduler="jobScheduler" />
+
+</beans>
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImplTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImplTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/ResultSetRegistryImplTest.java	(revision 45117)
@@ -0,0 +1,184 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.matches;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import net.sf.ehcache.Cache;
+import net.sf.ehcache.CacheManager;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+import eu.dnetlib.miscutils.cache.EhCache;
+
+/**
+ * Test ResultSetRegistryImpl.
+ * 
+ * @author marko
+ * 
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class ResultSetRegistryImplTest {
+
+	/**
+	 * max in memory elements.
+	 */
+	private static final int MAX_IN_MEM = 100;
+
+	/**
+	 * default time.
+	 */
+	private static final int DEFAULT_TTI = 1000;
+
+	/**
+	 * default time to live.
+	 */
+	private static final int DEFAULT_TTL = 1000;
+
+	/**
+	 * class under test.
+	 */
+	private transient ResultSetRegistryImpl registry;
+
+	/**
+	 * mock of a resultset object.
+	 */
+	@Mock
+	private transient ResultSet resultSet;
+
+	/**
+	 * ehcache manager.
+	 */
+	private final transient CacheManager cacheManager = CacheManager.create();
+
+	/**
+	 * Set up basic mocks.
+	 */
+	@Before
+	public void setUp() {
+		final Cache ehCache = new net.sf.ehcache.Cache("testCache", MAX_IN_MEM, false, false, DEFAULT_TTL, DEFAULT_TTI);
+		cacheManager.addCache(ehCache);
+
+		final Cache mtEhCache = new net.sf.ehcache.Cache("testMTCache", MAX_IN_MEM, false, false, DEFAULT_TTL, DEFAULT_TTI);
+		cacheManager.addCache(mtEhCache);
+
+		final EhCache<String, ResultSet> cache = new EhCache<String, ResultSet>(ehCache);
+		cache.setCache(ehCache);
+
+		final EhCache<String, Integer> mtCache = new EhCache<String, Integer>(mtEhCache);
+		mtCache.setCache(mtEhCache);
+
+		registry = new ResultSetRegistryImpl();
+		registry.setCache(cache);
+		registry.setMaxIdleTimeCache(mtCache);
+
+		when(resultSet.getIdentifier()).thenReturn("123456");
+		when(resultSet.isOpen()).thenReturn(true);
+	}
+
+	/**
+	 * remove ehcache from ehcachemanager.
+	 */
+	@After
+	public void tearDown() {
+		cacheManager.removeAllCaches();
+	}
+
+	/**
+	 * Test that registered resultsets are really registered.
+	 */
+	@Test
+	public void testAddResultSet() {
+
+		final String rsId = resultSet.getIdentifier();
+		assertNotNull("the resultset should not be null", rsId);
+
+		registry.addResultSet(resultSet);
+		verify(resultSet).setIdentifier(matches("rs-" + registry.getIdGenerator().getRegEx()));
+
+		final ResultSet res = registry.getResultSetById(rsId); // NOPMD
+		assertNotNull("the resultset is not found", res);
+		assertEquals("the resultsets don't have the same id", rsId, res.getIdentifier());
+		assertEquals("the resultsets are not the same instance", resultSet, res);
+	}
+
+	/**
+	 * Test that registered resultsets are really registered.
+	 */
+	@Test
+	public void testAddResultSetWithId() {
+		resultSet = mock(ResultSet.class);
+		when(resultSet.getIdentifier()).thenReturn("123");
+
+		final String rsId = resultSet.getIdentifier();
+
+		registry.addResultSet(resultSet, rsId);
+		verify(resultSet).setIdentifier(rsId);
+
+		final ResultSet res = registry.getResultSetById(rsId); // NOPMD
+		assertNotNull("the resultset is not found", res);
+		assertEquals("the resultsets don't have the same id", rsId, res.getIdentifier());
+		assertEquals("the resultsets are not the same instance", resultSet, res);
+	}
+
+	/**
+	 * try to obtain a inexistent resultset.
+	 */
+	@Test
+	public void testInexistentResultSet() {
+		final String rsId = resultSet.getIdentifier();
+		assertNull("inexisten resultset returns null", registry.getResultSetById(rsId));
+	}
+
+	/**
+	 * test closing of resultset and its pruning from the registry.
+	 */
+	@Test
+	public void testResultSetClose() {
+		final String rsId = resultSet.getIdentifier();
+
+		assertTrue("check if resultset is open", resultSet.isOpen());
+
+		registry.addResultSet(resultSet);
+		verify(resultSet).addObserver(registry);
+
+		// simulate a resultset close on the mock
+		when(resultSet.isOpen()).thenReturn(false);
+		registry.update(resultSet, null);
+
+		assertFalse("check if resultset is closed", resultSet.isOpen());
+		assertNull("check if the object is pruned from the registry", registry.getResultSetById(rsId));
+	}
+
+	/**
+	 * same as testResultSetClose() but with a real observer/observable mechanism, i.e. without resultset mock class.
+	 * 
+	 */
+	@Test
+	public void testWithRealObservable() {
+		final LocalResultSetImpl rset = new LocalResultSetImpl(null);
+		rset.setIdentifier("123456");
+		resultSet = rset;
+
+		final String rsId = resultSet.getIdentifier();
+
+		assertFalse("check if resultset is not destroyed", resultSet.isDestroyed());
+
+		registry.addResultSet(resultSet);
+		resultSet.destroy();
+
+		assertTrue("check if resultset is destroyed", resultSet.isDestroyed());
+		assertNull("check if the object is pruned from the registry", registry.getResultSetById(rsId));
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/AbstractTransientPushResultSetDaoTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/AbstractTransientPushResultSetDaoTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/push/AbstractTransientPushResultSetDaoTest.java	(revision 45117)
@@ -0,0 +1,223 @@
+package eu.dnetlib.enabling.resultset.push;
+
+import static org.junit.Assert.*; // NOPMD
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.miscutils.cache.Cache;
+
+/**
+ * subclass this unit test class and provide a concrete transient push resultset dao implementation.
+ *
+ * @author marko
+ *
+ */
+@Ignore
+public abstract class AbstractTransientPushResultSetDaoTest {
+	/**
+	 * logger.
+	 */
+	private static final Log log = LogFactory.getLog(AbstractTransientPushResultSetDaoTest.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+	/**
+	 * test first element.
+	 */
+	private static final String TWO = "two";
+
+	/**
+	 * test second element.
+	 */
+	private static final String ONE = "one";
+
+	/**
+	 * some key.
+	 */
+	private static final String RS_ID = "123";
+
+	/**
+	 * instance under test.
+	 */
+	private TransientPushResultSetDao dao;
+
+	/**
+	 * prepare the instance under test.
+	 *
+	 */
+	@Before
+	public void setUp() {
+		setDao(newInstance());
+	}
+
+	/**
+	 * specific unit tests will override this method and provide a concrete instance to test.
+	 *
+	 * @return new transient push resultset dao instance
+	 */
+	protected abstract TransientPushResultSetDao newInstance();
+
+	/**
+	 * test add elements.
+	 */
+	@Test
+	public void testAddElements() {
+		final List<String> freshGet = getDao().getElements(RS_ID, 1, 0);
+		assertNotNull("fresh get", freshGet);
+		assertEquals("fresh get", 0, freshGet.size());
+
+		final List<String> list = new ArrayList<String>();
+		list.add(ONE);
+
+		getDao().addElements(RS_ID, list);
+
+		final List<String> firstGet = getDao().getElements(RS_ID, 1, 1);
+		assertEquals("first get", 1, firstGet.size());
+		assertEquals("first get", ONE, firstGet.get(0));
+
+		final List<String> listAppend = new ArrayList<String>();
+		listAppend.add(TWO);
+
+		getDao().addElements(RS_ID, listAppend);
+
+		final List<String> secondGet = getDao().getElements(RS_ID, 1, 2);
+		assertEquals("second get", 2, secondGet.size());
+		assertEquals("second get", ONE, secondGet.get(0));
+		assertEquals("second get", TWO, secondGet.get(1));
+
+		final List<String> listBig = new ArrayList<String>();
+		for (int i = 0; i < 90; i++)
+			listBig.add(Integer.toString(i));
+
+		getDao().addElements(RS_ID, listBig);
+
+		final List<String> thirdGet = getDao().getElements(RS_ID, 3, 90);
+		assertEquals("third get", 88, thirdGet.size());
+		assertEquals("third get", "0", thirdGet.get(0));
+		assertEquals("third get", "1", thirdGet.get(1));
+	}
+
+	/**
+	 * check get elements.
+	 */
+	@Test
+	public void testGetElements() {
+		final List<String> list = new ArrayList<String>();
+		list.add(ONE);
+
+		getDao().addElements(RS_ID, list);
+
+		final List<String> res = getDao().getElements(RS_ID, 1, 1);
+		assertEquals("check size", 1, res.size());
+		assertEquals("check element", ONE, res.get(0));
+	}
+
+	/**
+	 * introduced for reproducing of #904. Thanks to Jochen for this one.
+	 */
+	@Test(expected = IllegalArgumentException.class)
+	public void testAddElementsDifferentSize() {
+		List<Integer> sizes = Lists.newArrayList(100, 200, 300, 99);
+		int run = 0;
+		int total = 0;
+
+		List<String> records = new LinkedList<String>();
+		for (int size : sizes) {
+			for (int i = 0; i < size; i++)
+				records.add("bla-" + run + "-" + i);
+
+			dao.addElements(RS_ID, records);
+			records.clear();
+
+			total += size;
+			run++;
+		}
+
+		assertEquals("check size", total, dao.getSize(RS_ID));
+	}
+
+	/**
+	 * introduced for reproducing of #904. with correct size (limited by 100)
+	 */
+	@Test
+	public void testAddElementsDifferentSizeCorrectSize() {
+		List<Integer> sizes = Lists.newArrayList(51, 51, 51, 51);
+
+		int total = 0;
+		int run = 0;
+		String lastName = null;
+
+		List<String> records = new LinkedList<String>();
+		for (int size : sizes) {
+			for (int i = 0; i < size; i++) {
+				lastName = "bla-" + run + "-" + i;
+				records.add(lastName);
+			}
+
+			dao.addElements(RS_ID, records);
+			records.clear();
+
+			total += size;
+			run++;
+		}
+
+		inspect();
+
+		assertEquals("check size", total, dao.getSize(RS_ID));
+		assertEquals("check last", lastName, dao.getElements(RS_ID, total, total).get(0));
+
+		assertEquals("check first page", "bla-0-11", dao.getElements(RS_ID, 12, 12).get(0));
+		assertEquals("check last page", "bla-1-11", dao.getElements(RS_ID, 51 + 12, 51 + 12).get(0));
+
+		assertEquals("check range", 10, dao.getElements(RS_ID, 1, 10).size());
+		assertEquals("check range", 10, dao.getElements(RS_ID, 51 + 1, 51 + 10).size());
+		assertEquals("check range", 51, dao.getElements(RS_ID, 1, 51).size());
+		assertEquals("check range", 52, dao.getElements(RS_ID, 1, 52).size());
+		assertEquals("check range", 51, dao.getElements(RS_ID, 2, 52).size());
+
+		assertEquals("check range", 100, dao.getElements(RS_ID, 1, 100).size());
+		assertEquals("check range", 99, dao.getElements(RS_ID, 2, 100).size());
+		assertEquals("check range", 100, dao.getElements(RS_ID, 2, 101).size());
+
+		assertEquals("check range", 200, dao.getElements(RS_ID, 2, 201).size());
+	}
+
+	private void inspect() {
+		CacheTransientResultSetDaoImpl dao = (CacheTransientResultSetDaoImpl) this.dao;
+		ResultSetDescriptor desc = dao.getResultSetCache().get(RS_ID);
+		Cache<String, List<String>> cache = dao.getCache();
+
+		log.debug("----------------");
+		log.debug("ranges: " + desc.getRanges());
+		log.debug("last range index: " + desc.getLastRange());
+		for (int i = 0; i < desc.getRanges(); i++) {
+			final List<String> range = cache.get(RS_ID + "-" + i);
+			log.debug("range: " + i + " has " + range.size() + " elements");
+			log.debug(" " + range);
+		}
+
+		log.debug("----------------");
+	}
+
+	@Test
+	public void testSizeOfEmpty() {
+		assertEquals("empty size", 0, dao.getSize(RS_ID));
+	}
+
+	public TransientPushResultSetDao getDao() {
+		return dao;
+	}
+
+	public void setDao(final TransientPushResultSetDao dao) {
+		this.dao = dao;
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/IterableResultSetTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/IterableResultSetTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/IterableResultSetTest.java	(revision 45117)
@@ -0,0 +1,150 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+/**
+ * tests the IterableResult class
+ * 
+ * @author claudio
+ *
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class IterableResultSetTest {
+
+	/**
+	 * number of total elements 
+	 */
+	private static int NUM_ELEM = 100;
+	
+	/**
+	 * number of elements available to fetch
+	 */
+	private static int FETCH_SIZE = 10;
+	
+	@Mock
+	private ResultSet mockResultSet;
+	
+	/**
+	 * a list used to compare elements.
+	 */
+	private List<String> list;
+	
+	/**
+	 * Iterator associated with the test list.
+	 */
+	private Iterator<String> iter;
+	
+	/**
+	 * Object to test.
+	 */
+	private IterableResultSet iterResultSet;
+
+	@Before
+	public void setUp() {
+		list = new ArrayList<String>();
+		for (int i=0; i< NUM_ELEM; i++)
+			list.add("XXXXX " + i);
+				
+		iter = list.iterator();
+		when(mockResultSet.isOpen()).thenReturn(iter.hasNext());
+		
+		iterResultSet = new IterableResultSet(list, FETCH_SIZE);
+		iterResultSet.setResultSet(mockResultSet);
+	}
+	
+	@Test
+	public void testIterableResultSet() {
+		assertNotNull(iterResultSet);
+		assertTrue(iterResultSet.getSize() > 0);
+	}
+
+	@Test(expected=RuntimeException.class)
+	public void testGetResult_fail_1() {
+		iterResultSet.getResult(0, 5);
+	}
+
+	@Test(expected=RuntimeException.class)
+	public void testGetResult_fail_2() {
+		iterResultSet.getResult(1, 5);
+		iterResultSet.getResult(1, 5);
+	}
+	
+	@Test(expected=RuntimeException.class)
+	public void testGetResult_fail_3() {
+		iterResultSet.getResult(1, 5);
+		iterResultSet.getResult(6, 5);
+	}
+	
+	@Test(expected=RuntimeException.class)
+	public void testGetResult_fail_4() {
+		iterResultSet.getResult(1, 5);
+		iterResultSet.getResult(7, 10);
+	}
+	
+	@Test
+	public void testGetResult_success_1() {
+		List<String> result = iterResultSet.getResult(1, NUM_ELEM);
+		for (int i=0; i<NUM_ELEM; i++) {
+			assertEquals(list.get(i), result.get(i));
+		}
+	}
+	
+	@Test
+	public void testGetResult_success_2() {
+		List<String> result = iterResultSet.getResult(1, NUM_ELEM);
+		
+		for (int i=0; i<NUM_ELEM; i++) {
+			assertEquals(list.get(i), result.get(i));
+			iter.next();
+		}
+		verify(mockResultSet).close();
+	}
+
+	@Test
+	public void testGetResult_success_3() {
+		for (int i = 1; i < NUM_ELEM; i+= FETCH_SIZE)
+			iterResultSet.getResult(i, i + FETCH_SIZE-1);
+		verify(mockResultSet, times(1)).close();
+	}
+	
+	@Test
+	public void testGetResult_success_4() {
+		iterResultSet.getResult(1, NUM_ELEM + 1);
+		verify(mockResultSet, times(1)).close();
+	}
+	
+	@Test
+	public void testGetResultSet_success_1() {
+		assertNotNull(iterResultSet.getResultSet());
+	}
+
+	@Test
+	public void testGetSize_fail_1() {
+		iterResultSet.getResult(1, 8);
+		assertNotSame(7, iterResultSet.getSize());
+		assertNotSame(9, iterResultSet.getSize());
+	}
+	
+	@Test
+	public void testGetSize_success_1() {
+		iterResultSet.getResult(1, 8);
+		assertEquals(FETCH_SIZE, iterResultSet.getSize());
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/resources/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest-context.xml
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/resources/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest-context.xml	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/resources/eu/dnetlib/enabling/resultset/push/ResultSetDescriptorFactoryTest-context.xml	(revision 45117)
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
+	xmlns:p="http://www.springframework.org/schema/p"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
+
+	<bean id="resultSetDescriptorPrototype" class="eu.dnetlib.enabling.resultset.push.ResultSetDescriptor"
+		p:rangeLength="200" scope="prototype" />
+
+	<bean id="resultSetDescriptorFactory" class="eu.dnetlib.springutils.beans.factory.PrototypeFactory">
+		<lookup-method name="newInstance" bean="resultSetDescriptorPrototype" />
+	</bean>
+</beans>
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactoryTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactoryTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/XSLTMappedResultSetFactoryTest.java	(revision 45117)
@@ -0,0 +1,139 @@
+package eu.dnetlib.enabling.resultset; // NOPMD
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.List;
+
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnit44Runner;
+
+import com.google.common.collect.Lists;
+
+import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
+import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
+import eu.dnetlib.enabling.tools.ServiceResolver;
+
+/**
+ * test xslt resultset.
+ *
+ * @author marko
+ *
+ */
+@RunWith(MockitoJUnit44Runner.class)
+public class XSLTMappedResultSetFactoryTest {
+
+	/**
+	 * instance under test.
+	 */
+	private transient XSLTMappedResultSetFactory factory;
+
+	/**
+	 * resultset factory mock.
+	 */
+	@Mock
+	private transient ResultSetFactory resultSetFactory;
+
+	/**
+	 * service resolver.
+	 */
+	@Mock
+	private transient ServiceResolver serviceResolver;
+
+	/**
+	 * resultset service mock.
+	 */
+	@Mock
+	private transient ResultSetService resultSetService;
+	
+	/**
+	 * underlying resultSet mock
+	 */
+	@Mock
+	private transient ResultSet resultSet;
+
+	/**
+	 * Common setup.
+	 *
+	 */
+	@Before
+	public void setUp() {
+		factory = new XSLTMappedResultSetFactory();
+		factory.setResultSetFactory(resultSetFactory);
+		factory.setServiceResolver(serviceResolver);
+	}
+
+	/**
+	 * test invalid xslt.
+	 *
+	 * @throws TransformerConfigurationException
+	 *             could happen
+	 */
+	@Test(expected = IllegalStateException.class)
+	public void testInvalidXslt() throws TransformerConfigurationException {
+		factory.createMappedResultSet(null, "<bla/>");
+	}
+
+	/**
+	 * test xslt.
+	 *
+	 * @throws TransformerConfigurationException
+	 *             could happen
+	 * @throws IOException
+	 *             could happen
+	 * @throws ResultSetException mock
+	 */
+	@Test
+	public void testXslt() throws TransformerConfigurationException, IOException, ResultSetException {
+		when(serviceResolver.getService(eq(ResultSetService.class), (W3CEndpointReference) anyObject())).thenReturn(resultSetService);
+		when(serviceResolver.getResourceIdentifier((W3CEndpointReference) anyObject())).thenReturn("123");
+
+		when(resultSetService.getNumberOfElements(anyString())).thenReturn(1);
+		when(resultSetService.getResult("123", 1, 1, "waiting")).thenReturn(Lists.newArrayList("<first>something</first>"));
+		when(resultSetService.getRSStatus("123")).thenReturn("closed");
+		
+		when(resultSet.isOpen()).thenReturn(true);
+		
+		final StringWriter xsltSource = new StringWriter();
+		IOUtils.copy(getClass().getResourceAsStream("test.xsl"), xsltSource);
+		factory.createMappedResultSet(null, xsltSource.toString());
+
+		verify(resultSetFactory, times(1)).createResultSet(argThat(new ArgumentMatcher<ResultSetListener>() {
+
+			@Override
+			public boolean matches(final Object argument) {
+				final MappedResultSet listener = (MappedResultSet) argument;
+				listener.setResultSet(resultSet);
+				final List<String> res = listener.getResult(1, 1);
+
+				assertNotNull("null result", res);
+				assertFalse("empty result", res.isEmpty());
+
+				assertNotNull("null element", res.get(0));
+
+				assertTrue("transformed correctly", res.get(0).contains("<second>something</second>"));
+
+				return true;
+			}
+		}));
+	}
+
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/StreamingResultSetListenerTest.java
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/StreamingResultSetListenerTest.java	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/java/eu/dnetlib/enabling/resultset/StreamingResultSetListenerTest.java	(revision 45117)
@@ -0,0 +1,62 @@
+package eu.dnetlib.enabling.resultset;
+
+import static org.junit.Assert.*;
+
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+public class StreamingResultSetListenerTest {
+
+	private StreamingResultSetListener listener;
+	private List<String> data;
+
+	@Before
+	public void setUp() throws Exception {
+		data = Lists.newArrayList("uno", "due", "tre", "quattro");
+		listener = new StreamingResultSetListener(data.iterator(), data.size());
+	}
+
+	@Test
+	public void testGetResult() {
+		assertEquals(data.size(), listener.getSize());
+
+		final List<String> res = listener.getResult(1, 2);
+		assertEquals(2, res.size());
+		assertEquals("uno", res.get(0));
+		assertEquals("due", res.get(1));
+	}
+
+	@Test
+	public void testGetResult2() {
+		listener.getResult(1, 2);
+		final List<String> res = listener.getResult(3, 4);
+		assertEquals(2, res.size());
+		assertEquals("tre", res.get(0));
+		assertEquals("quattro", res.get(1));
+	}
+
+	@Test
+	public void testGetResult_retry() {
+		listener.getResult(1, 2);
+		final List<String> res = listener.getResult(1, 2);
+		assertEquals(2, res.size());
+		assertEquals("uno", res.get(0));
+		assertEquals("due", res.get(1));
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testGetResult_random() {
+		listener.getResult(1, 2);
+		listener.getResult(2, 3);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testGetResult_skip() {
+		listener.getResult(1, 2);
+		listener.getResult(4, 4);
+	}
+}
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/resources/eu/dnetlib/enabling/resultset/test.xsl
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/resources/eu/dnetlib/enabling/resultset/test.xsl	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0/src/test/resources/eu/dnetlib/enabling/resultset/test.xsl	(revision 45117)
@@ -0,0 +1,6 @@
+<xsl:stylesheet version="1.0"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+	<xsl:template match="first">
+		<second><xsl:value-of select="."/></second>
+	</xsl:template>
+</xsl:stylesheet>
\ No newline at end of file
Index: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0
===================================================================
--- modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0	(nonexistent)
+++ modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0	(revision 45117)

Property changes on: modules/cnr-resultset-service/tags/cnr-resultset-service-1.0.0
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,5 ##
+.project
+.classpath
+.settings
+target
+
