species-products-discovery/src/main/java/org/gcube/data/spd/utils/RemoteDispatcher.java

573 lines
19 KiB
Java

package org.gcube.data.spd.utils;
import static org.gcube.data.streams.dsl.Streams.convert;
import java.net.URI;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.data.spd.Constants;
import org.gcube.data.spd.exception.MaxRetriesReachedException;
import org.gcube.data.spd.manager.AppInitializer;
import org.gcube.data.spd.model.Condition;
import org.gcube.data.spd.model.PluginDescription;
import org.gcube.data.spd.model.binding.Bindings;
import org.gcube.data.spd.model.exceptions.ExternalRepositoryException;
import org.gcube.data.spd.model.exceptions.IdNotValidException;
import org.gcube.data.spd.model.exceptions.StreamBlockingException;
import org.gcube.data.spd.model.exceptions.StreamNonBlockingException;
import org.gcube.data.spd.model.products.OccurrencePoint;
import org.gcube.data.spd.model.products.ResultElement;
import org.gcube.data.spd.model.products.ResultItem;
import org.gcube.data.spd.model.products.TaxonomyItem;
import org.gcube.data.spd.model.service.exceptions.InvalidIdentifierException;
import org.gcube.data.spd.model.service.exceptions.UnsupportedCapabilityException;
import org.gcube.data.spd.model.service.types.PluginDescriptions;
import org.gcube.data.spd.model.service.types.SearchCondition;
import org.gcube.data.spd.model.service.types.SearchRequest;
import org.gcube.data.spd.plugin.fwk.AbstractPlugin;
import org.gcube.data.spd.plugin.fwk.Searchable;
import org.gcube.data.spd.plugin.fwk.writers.ClosableWriter;
import org.gcube.data.spd.plugin.fwk.writers.Writer;
import org.gcube.data.spd.plugin.fwk.writers.rswrapper.ResultWrapper;
import org.gcube.data.streams.Stream;
import org.gcube.smartgears.ApplicationManagerProvider;
import org.gcube.smartgears.ContextProvider;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.thoughtworks.xstream.XStream;
@Path("remote")
public class RemoteDispatcher {
private static Logger logger = LoggerFactory.getLogger(RemoteDispatcher.class);
ApplicationContext ctx = ContextProvider.get();
AppInitializer initializer = (AppInitializer) ApplicationManagerProvider.get(AppInitializer.class);
public RemoteDispatcher(){
super();
}
//only for test
public RemoteDispatcher(AbstractPlugin plugin, ExecutorService executor) {
this.plugin = plugin;
}
//only for test is not null
AbstractPlugin plugin=null;
private AbstractPlugin getPlugin(String pluginName){
if (plugin==null)
return initializer.getPluginManager().plugins().get(pluginName);
else return plugin;
}
/* (non-Javadoc)
* @see org.gcube.data.spd.remotedispatcher.RemoteDispatcher#search(org.gcube.data.spd.remotedispatcher.types.SearchRequest)
*/
/* @GET
@Path("retrieve/search")
@Consumes(MediaType.APPLICATION_XML)
public String search(SearchRequest request)
throws RemoteException {
logger.trace("searchByScienficName called in scope "+ScopeProvider.instance.get());
AbstractPlugin localPlugin = getPlugin(request.getPluginName());
logger.trace("plugin "+request.getPluginName()+" have been retrieved, it is null?"+(localPlugin==null));
List<Condition> properties = Collections.emptyList();
if (request.getProperties()!=null){
properties = new ArrayList<Condition>(request.getProperties().size());
for (SearchCondition prop : request.getProperties()){
Object value = new XStream().fromXML(prop.getValue());
properties.add(new Condition(prop.getType(), value,prop.getOperator()));
}
}
try{
if (request.getResultType().equals(Constants.TAXON_RETURN_TYPE)){
ResultWrapper<TaxonomyItem> wrapper = new ResultWrapper<TaxonomyItem>();
Writer<TaxonomyItem> writer = new Writer<TaxonomyItem>(wrapper);
ExecutorsContainer.execSearch(new RemoteSearch<TaxonomyItem>(localPlugin.getClassificationInterface(), writer, request.getWord(), properties));
return wrapper.getLocator();
}else if (request.getResultType().equals(Constants.OCCURRENCE_RETURN_TYPE)){
ResultWrapper<OccurrencePoint> wrapper = new ResultWrapper<OccurrencePoint>();
Writer<OccurrencePoint> writer = new Writer<OccurrencePoint>(wrapper);
ExecutorsContainer.execSearch(new RemoteSearch<OccurrencePoint>(localPlugin.getOccurrencesInterface(), writer, request.getWord(), properties));
return wrapper.getLocator();
}else {
ResultWrapper<ResultItem> wrapper = new ResultWrapper<ResultItem>();
Writer<ResultItem> writer = new Writer<ResultItem>(wrapper);
ExecutorsContainer.execSearch(new RemoteSearch<ResultItem>(localPlugin, writer, request.getWord(), properties));
return wrapper.getLocator();
}
}catch (Exception e) {
logger.error("search error for remote plugin", e);
throw new RemoteException(e.getMessage());
}
}
//TAXON functions
(non-Javadoc)
* @see org.gcube.data.spd.remotedispatcher.RemoteDispatcher#getSynonymsById(java.lang.String, java.lang.String)
@GET
@Path("taxon/synonyms")
public String getSynonymsById(@QueryParam("id") final String id, @QueryParam("plugin") String pluginName)
throws RemoteException, InvalidIdentifierException {
final AbstractPlugin localPlugin = getPlugin(pluginName);
try{
final ResultWrapper<TaxonomyItem> wrapper = new ResultWrapper<TaxonomyItem>();
ExecutorsContainer.execSearch(new Runnable() {
@Override
public void run() {
final Writer<TaxonomyItem> writer = new Writer<TaxonomyItem>(wrapper);
try {
new JobRetryCall<VOID, Exception>() {
@Override
protected VOID execute() throws ExternalRepositoryException, Exception {
localPlugin.getClassificationInterface().getSynonymnsById(writer, id);
return VOID.instance();
}
}.call();
} catch (Exception e) {
logger.error("getSynonymsById for remote plugin",e);
writer.write(new StreamBlockingException(localPlugin.getRepositoryName(),id));
} finally{
writer.close();
}
}
});
return wrapper.getLocator();
} catch (Exception e) {
logger.error("error getting locator ",e);
throw new RemoteException(e.getMessage());
}
}
(non-Javadoc)
* @see org.gcube.data.spd.remotedispatcher.RemoteDispatcher#retrieveTaxonChildrenByTaxonId(java.lang.String, java.lang.String)
@GET
@Path("taxon/children/{key}")
public String retrieveTaxonChildrenByTaxonId(
@PathParam("id") final String id, @QueryParam("plugin") final String pluginName)
throws RemoteException, InvalidIdentifierException {
final AbstractPlugin localPlugin = getPlugin(pluginName);
try{
final ResultWrapper<TaxonomyItem> wrapper = new ResultWrapper<TaxonomyItem>();
ExecutorsContainer.execSearch(new Runnable() {
@Override
public void run() {
Writer<TaxonomyItem> writer = new Writer<TaxonomyItem>(wrapper);
try {
List<TaxonomyItem> items = new JobRetryCall<List<TaxonomyItem>, IdNotValidException>() {
@Override
protected List<TaxonomyItem> execute() throws ExternalRepositoryException, IdNotValidException {
return localPlugin.getClassificationInterface().retrieveTaxonChildrenByTaxonId(id);
}
}.call();
for (TaxonomyItem item :items)
writer.write(item);
} catch (Exception e) {
logger.error("error retreiving children by id",e);
writer.write(new StreamBlockingException(localPlugin.getRepositoryName(), id));
}finally{
writer.close();
}
}
});
return wrapper.getLocator();
} catch (Exception e) {
logger.error("error getting locator ",e);
throw new RemoteException(e.getMessage());
}
}
(non-Javadoc)
* @see org.gcube.data.spd.remotedispatcher.RemoteDispatcher#retrieveTaxaByIds(java.lang.String, java.lang.String)
@GET
@Path("taxon/tree/{plugin}/{key}")
public String retrieveTaxaByIds(@PathParam("key") final String idsLocator, @PathParam("plugin") String pluginName)
throws RemoteException {
final AbstractPlugin localPlugin = getPlugin(pluginName);
try{
final ResultWrapper<TaxonomyItem> wrapper = new ResultWrapper<TaxonomyItem>();
ExecutorsContainer.execSearch(new Runnable() {
@Override
public void run() {
final Stream<String> idsStream = convert(URI.create(idsLocator)).ofStrings().withDefaults();;
final Writer<TaxonomyItem> writer = new Writer<TaxonomyItem>(wrapper);
new JobRetryCall<VOID, Exception>() {
@Override
protected VOID execute()
throws ExternalRepositoryException, Exception {
localPlugin.getClassificationInterface().retrieveTaxonByIds(idsStream, writer);
return VOID.instance();
}
};
writer.close();
}
});
return wrapper.getLocator();
} catch (Exception e) {
logger.error("error getting locator ",e);
throw new RemoteException(e.getMessage());
}
}
(non-Javadoc)
* @see org.gcube.data.spd.remotedispatcher.RemoteDispatcher#getTaxonById(java.lang.String, java.lang.String)
@GET
@Path("taxon/ids/{idsLocator}")
public String getTaxonById(@PathParam("idsLocator") final String id, @QueryParam("plugin") String pluginName)
throws RemoteException, InvalidIdentifierException {
AbstractPlugin plugin = getPlugin(pluginName);
try {
return Bindings.toXml(plugin.getClassificationInterface().retrieveTaxonById(id));
} catch (IdNotValidException e) {
logger.error("error in getTaxonById",e);
throw new InvalidIdentifierException();
} catch (Exception e) {
logger.error("error in getTaxonById",e);
throw new RemoteException(e.getMessage());
}
}
//END: TAXON functions
//occurrence functions
(non-Javadoc)
* @see org.gcube.data.spd.remotedispatcher.RemoteDispatcher#getOccurrencesByProductKeys(java.lang.String, java.lang.String)
@GET
@Path("occurrence/keys/{productKeysLocator}")
public String getOccurrencesByProductKeys(
@PathParam("productKeysLocator") final String productKeysLocator, @QueryParam("plugin") String pluginName) throws RemoteException {
final AbstractPlugin localPlugin = getPlugin(pluginName);
try{
final ResultWrapper<OccurrencePoint> wrapper = new ResultWrapper<OccurrencePoint>();
ExecutorsContainer.execSearch(new Runnable() {
@Override
public void run() {
logger.debug("searching remote occurrence for plugin "+localPlugin.getRepositoryName());
final Stream<String> keysStream = convert(URI.create(productKeysLocator)).ofStrings().withDefaults();
final Writer<OccurrencePoint> writer = new Writer<OccurrencePoint>(wrapper);
try {
new JobRetryCall<VOID, Exception>() {
@Override
protected VOID execute()
throws ExternalRepositoryException, Exception {
localPlugin.getOccurrencesInterface().getOccurrencesByProductKeys(writer, keysStream);
return VOID.instance();
}
}.call();
} catch (Exception e) {
writer.write(new StreamBlockingException(localPlugin.getRepositoryName()));
}
writer.close();
}
});
return wrapper.getLocator();
} catch (Exception e) {
logger.error("error getting locator ",e);
throw new RemoteException(e.getMessage());
}
}
(non-Javadoc)
* @see org.gcube.data.spd.remotedispatcher.RemoteDispatcher#getOccurrencesByIds(java.lang.String, java.lang.String)
@GET
@Path("occurrence/ids/{IdsLocator}")
public String getOccurrencesByIds(final String idsLocator, String pluginName)
throws RemoteException {
final AbstractPlugin localPlugin = getPlugin(pluginName);
try{
final ResultWrapper<OccurrencePoint> wrapper = new ResultWrapper<OccurrencePoint>();
ExecutorsContainer.execSearch(new Runnable() {
@Override
public void run() {
final Stream<String> idsStream = convert(URI.create(idsLocator)).ofStrings().withDefaults();
final Writer<OccurrencePoint> writer = new Writer<OccurrencePoint>(wrapper);
try {
new JobRetryCall<VOID, Exception>() {
@Override
protected VOID execute()
throws ExternalRepositoryException, Exception {
localPlugin.getOccurrencesInterface().getOccurrencesByIds(writer, idsStream);
return VOID.instance();
}
}.call();
} catch (Exception e) {
writer.write(new StreamBlockingException(localPlugin.getRepositoryName()));
}
writer.close();
}
});
return wrapper.getLocator();
} catch (Exception e) {
logger.error("error getting locator ",e);
throw new RemoteException(e.getMessage());
}
}
//END : occurrence functions
//RESOLVE CAPABILITIES
(non-Javadoc)
* @see org.gcube.data.spd.remotedispatcher.RemoteDispatcher#namesMapping(java.lang.String, java.lang.String)
@GET
@Path("extensions/mapping/{commonName}")
public String namesMapping(@PathParam("commonName") final String commonName, @QueryParam("name") String pluginName)
throws RemoteException {
logger.trace("requesting plugin "+pluginName);
final AbstractPlugin localPlugin = getPlugin(pluginName);
if (plugin==null) throw new RemoteException("error executing namesMapping on "+pluginName);
try{
final ResultWrapper<String> wrapper = new ResultWrapper<String>();
ExecutorsContainer.execSearch(new Runnable() {
@Override
public void run() {
final Writer<String> writer = new Writer<String>(wrapper);
logger.trace("calling names mapping on "+localPlugin.getRepositoryName());
try{
new QueryRetryCall(){
@Override
protected VOID execute()
throws ExternalRepositoryException {
localPlugin.getMappingInterface().getRelatedScientificNames(writer, commonName);
return VOID.instance();
}
}.call();
} catch (MaxRetriesReachedException e) {
logger.error("error retreiving namesMapping on remote plugin",e);
writer.write(new StreamBlockingException(localPlugin.getRepositoryName()));
}finally{
writer.close();
}
}
});
return wrapper.getLocator();
} catch (Exception e) {
logger.error("error getting locator ",e);
throw new RemoteException(e.getMessage());
}
}
//END : RESOLVE CAPABILITIES
//EXPAND CAPABILITIES
(non-Javadoc)
* @see org.gcube.data.spd.remotedispatcher.RemoteDispatcher#expandWithSynonyms(java.lang.String, java.lang.String)
@GET
@Path("extensions/expand/{scientificName}")
public String expandWithSynonyms(@PathParam("scientificName") final String scientificName,@QueryParam("plugin") String pluginName)
throws RemoteException {
final AbstractPlugin localPlugin = getPlugin(pluginName);
try{
final ResultWrapper<String> wrapper = new ResultWrapper<String>();
ExecutorsContainer.execSearch(new Runnable() {
@Override
public void run() {
final Writer<String> writer = new Writer<String>(wrapper);
try {
//"synonyms expansion is not suported in "+plugin.getRepositoryName()
if (localPlugin.getExpansionInterface()==null) throw new UnsupportedCapabilityException();
else{
new QueryRetryCall(){
@Override
protected VOID execute()
throws ExternalRepositoryException {
localPlugin.getExpansionInterface().getSynonyms(writer, scientificName);
return VOID.instance();
}
}.call();
}
} catch (Exception e) {
logger.error("error getting synonyms for remote plugin",e);
}finally{
writer.close();
}
}
});
return wrapper.getLocator();
} catch (Exception e) {
logger.error("error getting locator ",e);
throw new RemoteException(e.getMessage());
}
}
//END: EXPAND CAPABILITIES
//UNFOLD CAPABILITIES
(non-Javadoc)
* @see org.gcube.data.spd.remotedispatcher.RemoteDispatcher#unfold(java.lang.String, java.lang.String)
@GET
@Path("extensions/unfold/{scientificName}")
public String unfold(@PathParam("scientificName") final String scientificName,@QueryParam("plugin") String pluginName)
throws RemoteException {
final AbstractPlugin localPlugin = getPlugin(pluginName);
try{
final ResultWrapper<String> wrapper = new ResultWrapper<String>();
ExecutorsContainer.execSearch(new Runnable() {
@Override
public void run() {
final Writer<String> writer = new Writer<String>(wrapper);
try {
//"synonyms expansion is not suported in "+plugin.getRepositoryName()
if (localPlugin.getUnfoldInterface()==null) throw new UnsupportedCapabilityException();
else{
new QueryRetryCall(){
@Override
protected VOID execute()
throws ExternalRepositoryException {
localPlugin.getUnfoldInterface().unfold(writer, scientificName);
return VOID.instance();
}
}.call();
}
} catch (Exception e) {
logger.error("error getting synonyms for remote plugin",e);
}finally{
writer.close();
}
}
});
return wrapper.getLocator();
} catch (Exception e) {
logger.error("error getting locator ",e);
throw new RemoteException(e.getMessage());
}
}
//END: UNFOLD CAPABILITIES
class RemoteSearch<T extends ResultElement> implements Runnable {
private final Searchable<T> searchable;
private final ClosableWriter<T> writer;
private final String word;
private final Condition[] conditions;
public RemoteSearch(Searchable<T> searchable,
ClosableWriter<T> writer, String word,
List<Condition> conditions) {
super();
this.searchable = searchable;
this.writer = writer;
this.word = word;
this.conditions = new Condition[conditions.size()];
conditions.toArray(this.conditions);
}
public void run() {
try{
new QueryRetryCall() {
@Override
protected VOID execute() throws ExternalRepositoryException {
searchable.searchByScientificName(word, writer, conditions);
return VOID.instance();
}
}.call();
} catch (MaxRetriesReachedException e) {
writer.write(new StreamNonBlockingException(word));
}finally{
writer.close();
}
}
}
@PUT
@Path("exchange")
@Consumes(MediaType.APPLICATION_XML)
@Produces(MediaType.APPLICATION_XML)
public PluginDescriptions exchangePlugins(PluginDescriptions remotePlugins,@QueryParam("gCoreEndpointId") String gCoreEndpointId)
throws RemoteException {
initializer.getPluginManager().addRemotePlugins(remotePlugins.getDescriptions(), gCoreEndpointId);
List<PluginDescription> descriptions = new ArrayList<PluginDescription>();
for (AbstractPlugin plugin :initializer.getPluginManager().plugins().values())
if(!plugin.isRemote())
descriptions.add(Utils.getPluginDescription(plugin));
return new PluginDescriptions(descriptions);
}
@DELETE
@Path("remove/{gCoreEndpointId}")
public void removeAll(@PathParam("gCoreEndpointId") String gCoreEndpointId)
throws RemoteException {
initializer.getPluginManager().removeRemotePlugin(gCoreEndpointId);
}
*/
}