1 package jalview.ws.rest;
3 import java.io.IOException;
4 import java.sql.ResultSet;
5 import java.util.ArrayList;
6 import java.util.Collection;
7 import java.util.Hashtable;
10 import java.util.Map.Entry;
12 import java.util.Vector;
14 import jalview.datamodel.AlignmentI;
15 import jalview.datamodel.AlignmentOrder;
16 import jalview.datamodel.AlignmentView;
17 import jalview.datamodel.SequenceGroup;
18 import jalview.datamodel.SequenceI;
19 import jalview.io.packed.DataProvider;
20 import jalview.io.packed.JalviewDataset;
21 import jalview.io.packed.ParsePackedSet;
22 import jalview.io.packed.SimpleDataProvider;
23 import jalview.io.packed.DataProvider.JvDataType;
24 import jalview.ws.AWsJob;
25 import jalview.ws.rest.params.Alignment;
26 import jalview.ws.rest.params.SeqGroupIndexVector;
28 public class RestJob extends AWsJob
31 // TODO: input alignmentview and other data for this job
32 RestServiceDescription rsd;
46 * dataset associated with this input data.
50 AlignmentOrder inputOrder;
53 * context of input data with respect to an AlignmentView's visible contigs.
57 private AlignmentI contextAl=null;
60 * create a rest job using data bounded by the given start/end column.
63 * @param restJobThread
66 * visible contigs of an alignment view from which _input was derived
68 public RestJob(int jobNum, RestJobThread restJobThread,
69 AlignmentI _input, int[] viscontigs)
71 rsd = restJobThread.restClient.service;
73 if (viscontigs != null)
75 origviscontig = new int[viscontigs.length];
76 System.arraycopy(viscontigs, 0, origviscontig, 0, viscontigs.length);
78 // get sequences for the alignmentI
79 // get groups trimmed to alignment columns
80 // get any annotation trimmed to start/end columns, too.
83 // form alignment+groups+annotation,preprocess and then record references
85 ArrayList<InputType> alinp = new ArrayList<InputType>();
86 int paramsWithData = 0;
87 // we cheat for moment - since we know a-priori what data is available and
88 // what inputs we have implemented so far
89 for (Map.Entry<String, InputType> prm : rsd.inputParams.entrySet())
91 if (!prm.getValue().isConstant())
93 if (prm.getValue() instanceof Alignment)
95 alinp.add(prm.getValue());
99 if ((prm.getValue() instanceof SeqGroupIndexVector)
100 && (_input.getGroups() != null && _input.getGroups()
103 alinp.add(prm.getValue());
112 if ((paramsWithData + alinp.size()) == rsd.inputParams.size())
114 inputOrder = new AlignmentOrder(_input);
115 if ((dsForIO = _input.getDataset()) == null)
117 _input.setDataset(null);
119 dsForIO = _input.getDataset();
124 setAlignmentForInputs(alinp, _input);
129 // not enough data, so we bail.
134 boolean validInput = false;
137 public boolean hasResults()
139 return gotresult && (parsedResults ? validJvresults : true);
143 public boolean hasValidInput()
149 public boolean isRunning()
151 return running; // TODO: can we check the response body for status messages
156 public boolean isQueued()
162 public boolean isFinished()
164 return resSet != null;
168 public boolean isFailed()
170 // TODO logic for error
175 public boolean isBroken()
177 // TODO logic for error
182 public boolean isServerError()
184 // TODO logic for error
189 public boolean hasStatus()
191 return statMessage != null;
194 protected String statMessage = null;
196 public HttpResultSet resSet;
199 public String getStatus()
205 public boolean hasResponse()
207 return statMessage != null || resSet != null;
211 public void clearResponse()
213 // only clear the transient server response
220 * @see jalview.ws.AWsJob#getState()
223 public String getState()
225 // TODO generate state string - prolly should have a default abstract method
227 return "Job is clueless";
230 public String getPostUrl()
233 // TODO Auto-generated method stub
237 public Set<Map.Entry<String, InputType>> getInputParams()
239 return rsd.inputParams.entrySet();
242 // return the URL that should be polled for this job
243 public String getPollUrl()
245 return rsd.getDecoratedResultUrl(jobId);
250 * @return the context for parsing results from service
252 public JalviewDataset newJalviewDataset()
256 context = new JalviewDataset(dsForIO, null, squniq, null);
259 context.addAlignment(contextAl);
267 * Extract list of sequence IDs for input parameter 'token' with given
274 public SequenceI[] getSequencesForInput(String token,
275 InputType.molType type) throws NoValidInputDataException
277 Object sgdat = inputData.get(token);
278 // can we form an alignment from this data ?
281 throw new NoValidInputDataException(
282 "No Sequence vector data bound to input '" + token
283 + "' for service at " + rsd.postUrl);
285 if (sgdat instanceof AlignmentI)
287 return ((AlignmentI) sgdat).getSequencesArray();
289 if (sgdat instanceof SequenceGroup)
291 return ((SequenceGroup) sgdat).getSequencesAsArray(null);
293 if (sgdat instanceof Vector)
295 if (((Vector) sgdat).size() > 0
296 && ((Vector) sgdat).get(0) instanceof SequenceI)
298 SequenceI[] sq = new SequenceI[((Vector) sgdat).size()];
299 ((Vector) sgdat).copyInto(sq);
303 throw new NoValidInputDataException(
304 "No Sequence vector data bound to input '" + token
305 + "' for service at " + rsd.postUrl);
309 * binding between input data (AlignmentI, SequenceGroup, NJTree) and input
312 private Hashtable<String, Object> inputData = new Hashtable<String, Object>();
315 * is the job fully submitted to server and apparently in progress ?
317 public boolean running = false;
323 * - reference to object to be stored as input. Note - input data may
324 * be modifed by formatter
326 public void setAlignmentForInputs(Collection<InputType> itypes,
329 for (InputType itype : itypes)
331 if (!rsd.inputParams.values().contains(itype))
333 throw new IllegalArgumentException("InputType " + itype.getClass()
334 + " is not valid for service at " + rsd.postUrl);
336 if (itype instanceof AlignmentProcessor)
338 ((AlignmentProcessor) itype).prepareAlignment(al);
340 // stash a reference for recall when the alignment data is formatted
341 inputData.put(itype.token, al);
350 * @return alignment object bound to the given token
351 * @throws NoValidInputDataException
353 public AlignmentI getAlignmentForInput(String token,
354 InputType.molType type) throws NoValidInputDataException
356 Object al = inputData.get(token);
357 // can we form an alignment from this data ?
358 if (al == null || !(al instanceof AlignmentI))
360 throw new NoValidInputDataException(
361 "No alignment data bound to input '" + token
362 + "' for service at " + rsd.postUrl);
364 return (AlignmentI) al;
368 * test to see if the job has data of type cl that's needed for the job to run
371 * @return true or false
373 public boolean hasDataOfType(Class cl)
375 if (AlignmentI.class.isAssignableFrom(cl))
379 // TODO: add more source data types
385 * context used to parse results from service
387 JalviewDataset context = null;
388 protected boolean parsedResults = false;
389 protected boolean validJvresults=false;
390 Object[] jvresultobj = null;
392 * process the results obtained from the server into jalview datamodel objects
393 * ready to be merged/added to the users' view. Use hasResults to test if results were added to context.
395 public void parseResultSet() throws Exception, Error
397 if (!parsedResults) {
399 jvresultobj = resSet.parseResultSet();
400 validJvresults = true;
406 * @return true if job has an input alignment and it was annotated when results were parsed
408 public boolean isInputContextModified()
410 return contextAl!=null && validJvresults && context.getAl().get(0).isModified();
415 * @return true if the ID/metadata for the input sequences were saved and sequence IDs renamed.
417 public boolean isInputUniquified()
419 // TODO Auto-generated method stub
424 * Return map between ordering of alignment submitted as input, and ordering of alignment as provided by user
425 * @return int[sequence index in submitted data]==sequence index in input.
427 public int[] getOrderMap()
429 SequenceI[] contseq = contextAl.getSequencesArray();
430 int map[] = new int[contseq.length];
431 for (int i=0;i<contseq.length;i++)
433 // TODO: optimise for large N - build a lookup hash for IDs returning order, and then lookup each sequ's original order
434 map[i] = inputOrder.getOrder().indexOf(contseq[i]);