added dnet-core-services, which embeds old cnr-notifications-common, cnr-blackboard-common, cnr-resultset-service

master
Claudio Atzori 5 years ago
parent ec964c0c47
commit c121531bdc

@ -16,10 +16,14 @@ import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
@Ignore
// TODO investigate why it takes so long to run
// Time elapsed: 303.806 sec - in eu.dnetlib.miscutils.iterators.xml.IterableXmlParserTest
public class IterableXmlParserTest {
private Resource xmlZip = new ClassPathResource("eu/dnetlib/miscutils/iterators/xml/opendoar.zip");

@ -0,0 +1,22 @@
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>eu.dnetlib</groupId>
<artifactId>dnet-core</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>dnet-core-services</artifactId>
<groupId>eu.dnetlib</groupId>
<packaging>jar</packaging>
<version>1.0.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>eu.dnetlib</groupId>
<artifactId>dnet-core-components</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

@ -0,0 +1,61 @@
package eu.dnetlib.enabling.hcm;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Required;
import eu.dnetlib.enabling.hcm.rmi.HostingContextManagerService;
import eu.dnetlib.enabling.tools.AbstractBaseService;
import eu.dnetlib.enabling.tools.blackboard.NotificationHandler;
/**
* CNR HostingContextManagerService implementation. Will conflict with NKUA! yes this is ok.
*
* @author marko
*
*/
public class HostingContextManagerServiceImpl extends AbstractBaseService implements HostingContextManagerService {
/**
* logger.
*/
private static final Log log = LogFactory.getLog(HostingContextManagerServiceImpl.class); // NOPMD by marko on 11/24/08 5:02 PM
/**
* notification handler.
*/
private NotificationHandler notificationHandler; // NOPMD
@Override
public void notify(String subscrId, String topic, String isId, String message) {
if (log.isDebugEnabled()) {
log.debug("---- service got notification ----");
log.debug("subscrId: " + subscrId);
log.debug("topic " + topic);
log.debug("isId " + isId);
log.debug("msg: " + message);
log.debug("____ now processing the notification ____");
}
getNotificationHandler().notified(subscrId, topic, isId, message);
}
/**
* {@inheritDoc}
*
* @see eu.dnetlib.enabling.tools.AbstractBaseService#start()
*/
@Override
public void start() {
log.info("staring hosting context manager");
}
public NotificationHandler getNotificationHandler() {
return notificationHandler;
}
@Required
public void setNotificationHandler(NotificationHandler notificationHandler) {
this.notificationHandler = notificationHandler;
}
}

@ -0,0 +1,17 @@
package eu.dnetlib.enabling.hcm.sn;
import eu.dnetlib.enabling.is.sn.rmi.ISSNException;
/**
* This component takes care of subscribing the MSRO service to interesting events.
*
* @author marko
*
*/
public interface HCMSubscriber {
/**
* performs the subscription.
* @throws ISSNException could happen
*/
void subscribeAll() throws ISSNException;
}

@ -0,0 +1,117 @@
package eu.dnetlib.enabling.hcm.sn;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
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.enabling.actions.SubscriptionAction;
import eu.dnetlib.enabling.is.sn.rmi.ISSNException;
import eu.dnetlib.enabling.is.sn.rmi.ISSNService;
import eu.dnetlib.enabling.locators.UniqueServiceLocator;
import eu.dnetlib.soap.EndpointReferenceBuilder;
/**
* This component takes care of subscribing the SubscriptionAction(s) to interesting events.
*
* @author claudio
*
*/
public class HCMSubscriberImpl implements HCMSubscriber {
/**
* logger.
*/
private static final Log log = LogFactory.getLog(HCMSubscriberImpl.class);
/**
* notification endpoint (normally the msro service).
*/
private Endpoint endpoint;
/**
* service locator.
*/
private UniqueServiceLocator serviceLocator;
/**
* injected EPR builder.
*/
@Resource(name = "jaxwsEndpointReferenceBuilder")
private EndpointReferenceBuilder<Endpoint> eprBuilder;
/**
* subscription actions.
*/
private List<SubscriptionAction> actions;
@PostConstruct
public void printList() {
log.info(getActions());
}
/**
* {@inheritDoc}
*
* @throws ISSNException
* could happen
* @see eu.dnetlib.enabling.hcm.sn.HCMSubscriber#subscribeAll()
*/
@Override
public void subscribeAll() throws ISSNException {
final W3CEndpointReference endpointReference = eprBuilder
.getEndpointReference(getEndpoint());
if (getActions() != null) {
for (final SubscriptionAction action : getActions()) {
log.info("dynamically subscribing to "
+ action.getTopicExpression());
serviceLocator.getService(ISSNService.class, true).subscribe(endpointReference,
action.getTopicExpression(), 0);
}
}
}
public void setEndpoint(final Endpoint endpoint) {
this.endpoint = endpoint;
}
public Endpoint getEndpoint() {
return endpoint;
}
public void setEprBuilder(
final EndpointReferenceBuilder<Endpoint> eprBuilder) {
this.eprBuilder = eprBuilder;
}
public EndpointReferenceBuilder<Endpoint> getEprBuilder() {
return eprBuilder;
}
public List<SubscriptionAction> getActions() {
return actions;
}
@Required
public void setActions(final List<SubscriptionAction> actions) {
this.actions = actions;
}
public UniqueServiceLocator getServiceLocator() {
return serviceLocator;
}
@Required
public void setServiceLocator(final UniqueServiceLocator serviceLocator) {
this.serviceLocator = serviceLocator;
}
}

@ -0,0 +1,57 @@
package eu.dnetlib.enabling.hcm.sn;
import java.util.List;
import com.google.common.collect.Lists;
import eu.dnetlib.enabling.actions.SubscriptionAction;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
/**
* This class acts as a simple registry of msro subscription actions.
*
* <p>
* Subscription actions are autodetected using spring autowiring from the current application context and are available for the manager for
* handling subscriptions and delivering notification to particular code interested in those notifications.
* </p>
*
* @author marko
*
*/
@SuppressWarnings("rawtypes")
public class HCMSubscriptionListFactory implements FactoryBean<List<SubscriptionAction>> {
/**
* actions. Spring injects all the declared SubscriptionActions here.
*/
@Autowired(required = false)
private List<SubscriptionAction> actions = Lists.newArrayList();
public List<SubscriptionAction> getActions() {
return actions;
}
public void setActions(final List<SubscriptionAction> actions) {
this.actions = actions;
}
/**
* {@inheritDoc}
*
* @see org.springframework.beans.factory.FactoryBean#getObject()
*/
@Override
public List<SubscriptionAction> getObject() {
return getActions();
}
@Override
public Class<List> getObjectType() {
return List.class;
}
@Override
public boolean isSingleton() {
return false;
}
}

@ -0,0 +1,19 @@
package eu.dnetlib.enabling.hnm;
import eu.dnetlib.enabling.hnm.rmi.HostingNodeManagerService;
import eu.dnetlib.enabling.tools.AbstractBaseService;
/**
* HNMService implementation.
*
* @author michele
*
*/
public class HostingNodeManagerServiceImpl extends AbstractBaseService implements HostingNodeManagerService {
@Override
public String echo(String s) {
return s;
}
}

@ -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();
}
}

@ -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;
}
}

@ -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;
}
}

@ -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);
}
}
}

@ -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;
}
}

@ -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()));
}
}

@ -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;
}
}

@ -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;
}
}

@ -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;
}
}

@ -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;
}
}

@ -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;
}
}

@ -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;
}
}

@ -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;
}
}

@ -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);
}
}

@ -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;
}
}

@ -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;
}
}

@ -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;
}
}

@ -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);
}
}
});
}
}

@ -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;
}
}

@ -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();
}

@ -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);
}

@ -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;
}
}

@ -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);
}

@ -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> {
}

@ -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);
}

@ -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>();
}
}

@ -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);
}

@ -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;
}
}

@ -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;
}
}

@ -0,0 +1,7 @@
package eu.dnetlib.enabling.resultset;
public interface SizedIterable<T> extends Iterable<T> {
public int getNumberOfElements();
}

@ -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;
}
}

@ -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;
}
}

@ -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();
}

@ -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));
}
}

@ -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);
}
}

@ -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);
}

@ -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);
}

@ -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;
}
}

@ -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;
}
}

@ -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);
}

@ -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);
}

@ -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;
}
}

@ -0,0 +1,7 @@
package eu.dnetlib.enabling.resultset.push;
import eu.dnetlib.miscutils.factory.Factory;
public interface ResultSetDescriptorFactory extends Factory<ResultSetDescriptor> {
}

@ -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);
}

@ -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;
}
}

@ -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;
}
}

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:jaxws="http://cxf.apache.org/jaxws" 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"
xmlns:util="http://www.springframework.org/schema/util" xmlns:template="http://dnetlib.eu/springbeans/template"
xmlns:t="http://dnetlib.eu/springbeans/t"
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
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://dnetlib.eu/springbeans/template http://dnetlib.eu/springbeans/template.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!-- beans -->
<bean id="hcmService"
class="eu.dnetlib.enabling.hcm.HostingContextManagerServiceImpl"
init-method="start" destroy-method="stop"
p:notificationHandler-ref="hcmNotificationHandler"/>
<bean id="hcmNotificationHandler" class="eu.dnetlib.enabling.tools.blackboard.NotificationHandlerChainImpl"
p:handlers-ref="dynamicSubscriptionActions">
<property name="handlerExecutor">
<bean class="org.springframework.core.task.SyncTaskExecutor" />
</property>
</bean>
<bean id="dynamicSubscriptionActions"
class="eu.dnetlib.enabling.hcm.sn.HCMSubscriptionListFactory" />
<bean id="hcmSubscriber" class="eu.dnetlib.enabling.hcm.sn.HCMSubscriberImpl"
p:endpoint-ref="hcmServiceEndpoint" p:serviceLocator-ref="uniqueServiceLocator"
p:actions-ref="dynamicSubscriptionActions" />
<bean t:id="hcmJobSchedulerAccessor"
class="org.springframework.scheduling.quartz.SchedulerAccessorBean"
p:scheduler-ref="jobScheduler">
<property name="triggers">
<list>
<bean id="hcmSubscriptionTrigger"
class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"
p:startDelay="6000" p:repeatCount="0">
<property name="jobDetail">
<bean id="hcmSubscriptionJobDetails"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"
p:targetObject-ref="hcmSubscriber" p:targetMethod="subscribeAll" />
</property>
</bean>
</list>
</property>
</bean>
<!-- endpoints -->
<jaxws:endpoint id="hcmServiceEndpoint" implementor="#hcmService"
implementorClass="eu.dnetlib.enabling.hcm.rmi.HostingContextManagerService"
address="/hcm" />
<template:instance name="serviceRegistrationManager"
t:serviceRegistrationManagerClass="eu.dnetlib.enabling.tools.registration.ValidatingServiceRegistrationManagerImpl"
t:name="hcmServiceRegistrationManager" t:service="hcmService"
t:endpoint="hcmServiceEndpoint" t:jobScheduler="jobScheduler" />
</beans>

@ -0,0 +1,45 @@
<?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="hnmService" class="eu.dnetlib.enabling.hnm.HostingNodeManagerServiceImpl"
init-method="start" destroy-method="stop"/>
<!-- endpoints -->
<jaxws:endpoint id="hnmServiceEndpoint"
implementor="#hnmService" implementorClass="eu.dnetlib.enabling.hnm.rmi.HostingNodeManagerService"
address="/hnm" />
<template:instance name="serviceRegistrationManager"
t:serviceRegistrationManagerClass="eu.dnetlib.enabling.tools.registration.ValidatingServiceRegistrationManagerImpl"
t:name="hnmServiceRegistrationManager" t:service="hnmService"
t:endpoint="hnmServiceEndpoint" t:jobScheduler="jobScheduler"
t:serviceRegistrator="hnmServiceRegistrator" />
<bean id="hnmServiceRegistrator"
class="eu.dnetlib.enabling.tools.registration.BlackboardServiceRegistrator"
p:serviceLocator-ref="uniqueServiceLocator"
p:serviceNameResolver-ref="defaultServiceNameResolver"
p:eprBuilder-ref="jaxwsEndpointReferenceBuilder">
<property name="serviceProperties">
<map>
<entry key="name" value="unknown" />
<entry key="latitude" value="0" />
<entry key="longitude" value="0" />
<entry key="timezone" value="0" />
</map>
</property>
</bean>
</beans>

@ -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

@ -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>

@ -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.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.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());
}
}

@ -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.junit.MockitoJUnitRunner;
/**
* tests the IterableResult class
*
* @author claudio
*
*/
@RunWith(MockitoJUnitRunner.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());
}
}

@ -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.junit.MockitoJUnitRunner;
/**
* test the resultset concrete implementation.
*
* @author marko
*
*/
@RunWith(MockitoJUnitRunner.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());
}
}

@ -0,0 +1,140 @@
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.ArgumentMatchers.any;
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.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.junit.MockitoJUnitRunner;
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(MockitoJUnitRunner.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), any(W3CEndpointReference.class))).thenReturn(resultSetService);
when(serviceResolver.getResourceIdentifier(any(W3CEndpointReference.class))).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
@Ignore
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-"));
}
}
}

@ -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.junit.MockitoJUnitRunner;
import eu.dnetlib.miscutils.cache.EhCache;
/**
* Test ResultSetRegistryImpl.
*
* @author marko
*
*/
@RunWith(MockitoJUnitRunner.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));
}
}

@ -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.junit.MockitoJUnitRunner;
import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
/**
* resultset service rmi implementation test.
*
* @author marko
*
*/
@RunWith(MockitoJUnitRunner.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");
}
}

@ -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);
}
}

@ -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.junit.MockitoJUnitRunner;
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(MockitoJUnitRunner.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 ResultSetListener 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;
}
}));
}
}

@ -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;
}
}

@ -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;
}
}

@ -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());
}
}

@ -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() {
}
}

@ -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.junit.MockitoJUnitRunner;
import com.google.common.collect.Lists;
import eu.dnetlib.enabling.resultset.ResultSetRegistry;
/**
* test the transient push resultset.
*
* @author marko
*
*/
@RunWith(MockitoJUnitRunner.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"));
}
}

@ -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>

@ -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>

@ -10,6 +10,7 @@
<modules>
<module>dnet-core-components</module>
<module>dnet-core-services</module>
</modules>
@ -141,13 +142,6 @@
<artifactId>gson</artifactId>
<version>${google.gson.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
@ -230,6 +224,12 @@
<version>1.7</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
@ -336,7 +336,16 @@
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>

Loading…
Cancel
Save