package uk.co.flax.biosolr.pdbe.fasta;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import javax.xml.rpc.ServiceException;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.search.xjoin.XJoinResults;
import org.apache.solr.search.xjoin.XJoinResultsFactory;
import uk.ac.ebi.webservices.axis1.stubs.fasta.InputParameters;
import uk.ac.ebi.webservices.axis1.stubs.fasta.JDispatcherService_PortType;
import uk.ac.ebi.webservices.axis1.stubs.fasta.JDispatcherService_Service;
import uk.ac.ebi.webservices.axis1.stubs.fasta.JDispatcherService_ServiceLocator;
import uk.ac.ebi.webservices.axis1.stubs.fasta.WsResultType;
/**
* Connect to FASTA service and generate a PDB id filter based on a user
* supplied sequence.
*/
public class FastaXJoinResultsFactory implements XJoinResultsFactory<String> {
// initialisation parameters
public static final String INIT_EMAIL = "email";
public static final String INIT_PROGRAM = "program";
public static final String INIT_DATABASE = "database";
public static final String INIT_STYPE = "stype";
public static final String INIT_DEBUG_FILE = "debug.file";
// request parameters
public static final String FASTA_EXPLOWLIM = "explowlim";
public static final String FASTA_EXPUPPERLIM = "expupperlim";
public static final String FASTA_SEQUENCE = "sequence";
public static final String FASTA_SCORES = "scores";
public static final String FASTA_ALIGNMENTS = "alignments";
public static final String FASTA_UNIQUE_PDB_IDS = "unique_pdb_ids";
private JDispatcherService_PortType fasta;
private String email;
private String program;
private String database;
private String sType;
@Override
@SuppressWarnings("rawtypes")
public void init(NamedList args) {
String debugFile = (String) args.get(INIT_DEBUG_FILE);
if (debugFile != null) {
try {
byte[] result = Files.readAllBytes(Paths.get(debugFile));
fasta = mock(JDispatcherService_PortType.class);
when(fasta.getStatus(null)).thenReturn(FastaStatus.DONE);
WsResultType[] types = new WsResultType[] { mock(WsResultType.class) };
when(fasta.getResultTypes(null)).thenReturn(types);
when(fasta.getResult(null, null, null)).thenReturn(result);
} catch (IOException e) {
throw new RuntimeException(e);
}
} else {
JDispatcherService_Service service = new JDispatcherService_ServiceLocator();
try {
fasta = service.getJDispatcherServiceHttpPort();
} catch (ServiceException e) {
throw new RuntimeException(e);
}
}
email = (String) args.get(INIT_EMAIL);
program = (String) args.get(INIT_PROGRAM);
database = (String) args.get(INIT_DATABASE);
sType = (String) args.get(INIT_STYPE);
}
private String getParam(SolrParams params, String name) {
String value = params.get(name);
if (value == null || value.length() == 0) {
throw new RuntimeException("Missing or empty " + name);
}
return value;
}
/**
* Call out to the FASTA service and add a filter query based on the response.
*/
@Override
public XJoinResults<String> getResults(SolrParams params) throws IOException {
InputParameters input = new InputParameters();
input.setProgram(program);
input.setDatabase(new String[] { database });
input.setStype(sType);
input.setSequence(getParam(params, FASTA_SEQUENCE));
input.setExplowlim(new Double(getParam(params, FASTA_EXPLOWLIM)));
input.setExpupperlim(new Double(getParam(params, FASTA_EXPUPPERLIM)));
input.setScores(new Integer(getParam(params, FASTA_SCORES)));
input.setAlignments(new Integer(getParam(params, FASTA_ALIGNMENTS)));
FastaJob job = new FastaJob(fasta, email, input);
job.run();
if (!job.resultsOk()) {
if (job.getException() != null) {
throw new RuntimeException(job.getException());
}
if (!FastaStatus.DONE.equals(job.getStatus())) {
throw new RuntimeException("Unexpected FASTA job status: "
+ job.getStatus());
}
if (job.isInterrupted()) {
throw new RuntimeException("FASTA job was interrupted");
}
throw new RuntimeException("No results");
}
return new Results(job.getResults());
}
public static class Results implements XJoinResults<String> {
private FastaJobResults results;
public Results(FastaJobResults results) {
this.results = results;
}
@Override
public Iterable<String> getJoinIds() {
Set<PDb.Id> pdbIds = results.getAlignments().keySet();
String[] entries = new String[pdbIds.size()];
int i = 0;
for (PDb.Id pdbId : pdbIds) {
entries[i++] = pdbId.toString().toLowerCase();
}
Arrays.sort(entries);
return Arrays.asList(entries);
}
@Override
public Collection<PDb.Alignment> getResult(String joinId) {
Map<String, PDb.Alignment> map = results.getAlignments().get(new PDb.Id(joinId.toUpperCase()));
return map != null ? map.values() : null;
}
public int getNumChains() {
return results.getNumChains();
}
public int getNumEntries() {
return results.getNumEntries();
}
}
}