package uk.ac.ebi.fg.myequivalents.webservices.client;
import java.io.IOException;
import java.io.Reader;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import uk.ac.ebi.fg.myequivalents.managers.interfaces.ServiceManager;
import uk.ac.ebi.fg.myequivalents.managers.interfaces.ServiceSearchResult;
import uk.ac.ebi.fg.myequivalents.model.Repository;
import uk.ac.ebi.fg.myequivalents.model.Service;
import uk.ac.ebi.fg.myequivalents.model.ServiceCollection;
import uk.ac.ebi.utils.io.IOUtils;
import com.sun.jersey.api.representation.Form;
/**
* The web service client implementation of {@link ServiceManager}.
*
* <dl><dt>date</dt><dd>29 Oct 2013</dd></dl>
* @author Marco Brandizi
*
*/
public class ServiceWSClient extends MyEquivalentsWSClient implements ServiceManager
{
public ServiceWSClient ()
{
super ();
}
public ServiceWSClient ( String baseUrl )
{
super ( baseUrl );
}
@Override
protected String getServicePath () {
return "/service";
}
@Override
public void storeServices ( Service ... services )
{
ServiceSearchResult serviceItems = new ServiceSearchResult ();
for ( Service service: services ) serviceItems.addService ( service );
invokeStoreReq ( serviceItems );
}
@Override
public int deleteServices ( String ... names )
{
Form req = prepareReq ();
for ( String serviceName: names ) req.add ( "service", serviceName );
return invokeIntWsReq ( "/delete", req );
}
@Override
public ServiceSearchResult getServices ( String ... names )
{
Form req = prepareReq ();
for ( String serviceName: names ) req.add ( "service", serviceName );
ServiceSearchResult result = invokeWsReq ( "/get", req, ServiceSearchResult.class );
if ( result == null ) return null;
Map<String, Repository> repos = new HashMap<String, Repository> ();
for ( Repository repo: result.getRepositories () ) repos.put ( repo.getName (), repo );
Map<String, ServiceCollection> scs = new HashMap<String, ServiceCollection> ();
for ( ServiceCollection sc: result.getServiceCollections () ) scs.put ( sc.getName (), sc );
// Now we have to reconstruct the links from services
for ( Service service: result.getServices () )
{
String repoName = service.getRepositoryName ();
if ( repoName != null ) service.setRepository ( repos.get ( repoName ) );
String scName = service.getServiceCollectionName ();
if ( scName != null ) service.setServiceCollection ( scs.get ( scName ) );
}
return result;
}
@Override
public String getServicesAs ( String outputFormat, String ... names )
{
Form req = prepareReq ();
return getRawResult ( "/get", req, outputFormat );
}
@Override
public void storeServiceCollections ( ServiceCollection ... servColls )
{
ServiceSearchResult serviceItems = new ServiceSearchResult ();
for ( ServiceCollection sc: servColls ) serviceItems.addServiceCollection ( sc );
invokeStoreReq ( serviceItems );
}
@Override
public int deleteServiceCollections ( String ... names )
{
Form req = prepareReq ();
for ( String name: names ) req.add ( "service-coll", name );
return invokeIntWsReq ( "/service-collection/delete", req );
}
@Override
public ServiceSearchResult getServiceCollections ( String ... names )
{
Form req = prepareReq ();
for ( String name: names ) req.add ( "service-coll", name );
return invokeWsReq ( "/service-collection/get", req, ServiceSearchResult.class );
}
@Override
public String getServiceCollectionsAs ( String outputFormat, String ... names )
{
Form req = prepareReq ();
return getRawResult ( "/service-collection/get", req, outputFormat );
}
@Override
public void storeRepositories ( Repository ... repos )
{
ServiceSearchResult serviceItems = new ServiceSearchResult ();
for ( Repository repo: repos ) serviceItems.addRepository ( repo );
invokeStoreReq ( serviceItems );
}
@Override
public int deleteRepositories ( String ... names )
{
Form req = prepareReq ();
for ( String name: names ) req.add ( "repository", name );
return invokeIntWsReq ( "/repository/delete", req );
}
@Override
public ServiceSearchResult getRepositories ( String ... names )
{
Form req = prepareReq ();
for ( String name: names ) req.add ( "repository", name );
return invokeWsReq ( "/repository/get", req, ServiceSearchResult.class );
}
@Override
public String getRepositoriesAs ( String outputFormat, String ... names )
{
Form req = prepareReq ();
return getRawResult ( "/repository/get", req, outputFormat );
}
@Override
public void storeServicesFromXML ( Reader reader )
{
try {
storeServicesFromXML ( IOUtils.readInputFully ( reader ) );
}
catch ( IOException ex ) {
throw new RuntimeException ( "Error while invoking the myEq web service for 'store': " + ex.getMessage (), ex );
}
}
/**
* Used to implement {@link #storeServicesFromXML(Reader). It invokes a corresponding operation's on the server side.
*/
private void storeServicesFromXML ( String serviceSearchResultXml )
{
// TODO: This should be an interface method and we should use AOP or Java 8 to provide default implementations to
// the interface.
//
Form req = prepareReq ();
req.add ( "service-items-xml", serviceSearchResultXml );
invokeVoidWsReq ( "/store", req );
}
/**
* An helper for storeXXX() methods.
*/
private void invokeStoreReq ( ServiceSearchResult serviceItems )
{
try
{
// Add the service collection and repository that the service refers to
for ( Service service: serviceItems.getServices () )
{
Repository repo = service.getRepository ();
if ( repo != null ) serviceItems.addRepository ( repo );
ServiceCollection sc = service.getServiceCollection ();
if ( sc != null ) serviceItems.addServiceCollection ( sc );
}
if ( log.isTraceEnabled () )
log.trace ( "Requesting web service: {}\n: {}", getServicePath () + "/store", serviceItems );
StringWriter xmlw = new StringWriter ();
JAXBContext context = JAXBContext.newInstance ( ServiceSearchResult.class );
Marshaller m = context.createMarshaller ();
m.marshal ( serviceItems, xmlw );
storeServicesFromXML ( xmlw.toString () );
}
catch ( JAXBException ex ) {
throw new RuntimeException ( "Error while invoking the myEq web service for 'store':" + ex.getMessage (), ex );
}
}
}