From f5d48464f668eb2ffd8f6cdcd0d04ff5658c54fc Mon Sep 17 00:00:00 2001 From: jprocter Date: Tue, 14 Dec 2010 18:02:26 +0000 Subject: [PATCH] more fixes and extension to allow return data types to be specified JAL-715 --- src/jalview/ws/rest/HttpResultSet.java | 73 ++++++-- src/jalview/ws/rest/InputType.java | 8 +- src/jalview/ws/rest/RestClient.java | 25 +++ src/jalview/ws/rest/RestJob.java | 224 +++++++++++++++++------ src/jalview/ws/rest/RestJobThread.java | 202 ++++++++++++++------ src/jalview/ws/rest/RestServiceDescription.java | 48 ++++- src/jalview/ws/rest/params/Alignment.java | 4 +- 7 files changed, 441 insertions(+), 143 deletions(-) diff --git a/src/jalview/ws/rest/HttpResultSet.java b/src/jalview/ws/rest/HttpResultSet.java index b99d538..5a70211 100644 --- a/src/jalview/ws/rest/HttpResultSet.java +++ b/src/jalview/ws/rest/HttpResultSet.java @@ -2,12 +2,18 @@ package jalview.ws.rest; import jalview.bin.Cache; import jalview.io.FileParse; +import jalview.io.packed.DataProvider; +import jalview.io.packed.ParsePackedSet; +import jalview.io.packed.SimpleDataProvider; +import jalview.io.packed.DataProvider.JvDataType; import jalview.ws.io.mime.JalviewMimeContentHandler; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; @@ -55,17 +61,40 @@ public class HttpResultSet extends FileParse initDataSource(con); } - private void initDataSource(HttpResponse con) throws IOException + /** + * construct a set of dataproviders to parse a result set from this service + * + * @param resSet + * @return + */ + public List createResultDataProviders() { - en = con.getEntity(); - repeatable = en.isRepeatable(); + List dp = new ArrayList(); + for (JvDataType type : restJob.rsd.getResultDataTypes()) + { + dp.add(new SimpleDataProvider(type, this, null)); + } + return dp; + } + + public Object[] parseResultSet() throws Exception, Error + { + List dp = new ArrayList(); + Object[] results = null; + if (en == null) + { + throw new Error( + "Implementation Error: need to have an HttpResponse to process."); + } + jalview.io.packed.JalviewDataset ds = restJob.newJalviewDataset(); + // Decide how we deal with content. if (en instanceof MultipartEntity) { + // Multipart messages should be properly typed, so we parse them as we go. MultipartEntity mpe = (MultipartEntity) en; // multipart - jalview.io.packed.JalviewDataset ds = restJob.newJalviewDataset(); - ContentHandler handler = new JalviewMimeContentHandler(ds); + JalviewMimeContentHandler handler = new JalviewMimeContentHandler(ds); MimeStreamParser parser = new MimeStreamParser(); parser.setContentHandler(handler); try @@ -78,15 +107,35 @@ public class HttpResultSet extends FileParse Cache.log.warn("Failed to parse MIME multipart content", me); en.consumeContent(); } + return new ParsePackedSet().getAlignment(ds, + handler.getJalviewDataProviders()); } else { + // Need to use hints from rest service description. + dp = createResultDataProviders(); + ParsePackedSet pps = new ParsePackedSet(); + return pps.getAlignment(ds, dp); + } + } + + private void initDataSource(HttpResponse con) throws IOException + { + en = con.getEntity(); + repeatable = en.isRepeatable(); + + if (!(en instanceof MultipartEntity)) + { // assume content is simple text stream that can be read from - String enc = (en.getContentEncoding()==null) ? null : en.getContentEncoding().getValue(); - if (en.getContentType()!=null) { - Cache.log.info("Result Type: " + en.getContentType().toString()); - } else { - Cache.log.info("No Result Type Specified."); + String enc = (en.getContentEncoding() == null) ? null : en + .getContentEncoding().getValue(); + if (en.getContentType() != null) + { + Cache.log.debug("Result Type: " + en.getContentType().toString()); + } + else + { + Cache.log.debug("No Result Type Specified."); } if (enc == null || enc.length() < 1) { @@ -94,7 +143,7 @@ public class HttpResultSet extends FileParse } else { - Cache.log.debug("Result Encoded as : "+enc); + Cache.log.debug("Result Encoded as : " + enc); } // attempt to identify file and construct an appropriate DataSource // identifier for it. @@ -118,7 +167,7 @@ public class HttpResultSet extends FileParse if (br != null) { dataIn = new BufferedReader(br); - error=false; + error = false; } } } diff --git a/src/jalview/ws/rest/InputType.java b/src/jalview/ws/rest/InputType.java index 77583b7..9a4f297 100644 --- a/src/jalview/ws/rest/InputType.java +++ b/src/jalview/ws/rest/InputType.java @@ -15,8 +15,12 @@ import org.apache.http.entity.mime.content.StringBody; import sun.io.CharacterEncoding; import sun.misc.CharacterEncoder; -/** Service Input info { a sequence of [ Sequence Id vector (min,max,moltype, separator,regex,colrange(start-end)), Sequence(format-bare or alignment, moltype, min, max, separator)), Alignment(format, moltype), - */ +/*** + * InputType is the abstract model of each input parameter that a rest service might take. + * It enables the engine to validate input by providing + * { formatter for type, parser for type } + * + */ public abstract class InputType { /** * not used yet diff --git a/src/jalview/ws/rest/RestClient.java b/src/jalview/ws/rest/RestClient.java index 5a4cf61..04c9561 100644 --- a/src/jalview/ws/rest/RestClient.java +++ b/src/jalview/ws/rest/RestClient.java @@ -20,8 +20,10 @@ import jalview.datamodel.AlignmentView; import jalview.datamodel.SequenceGroup; import jalview.gui.AlignFrame; import jalview.gui.AlignViewport; +import jalview.gui.AlignmentPanel; import jalview.gui.Desktop; import jalview.gui.WebserviceInfo; +import jalview.io.packed.DataProvider.JvDataType; import jalview.ws.WSClient; import jalview.ws.WSClientI; import jalview.ws.WSMenuEntryProviderI; @@ -82,6 +84,7 @@ public class RestClient extends WSClient implements WSClientI, { wsInfo = new WebserviceInfo(WebServiceJobTitle, WebServiceName + "\n" + WebServiceReference); + wsInfo.setRenderAsHtml(true); } } @@ -266,6 +269,7 @@ public class RestClient extends WSClient implements WSClientI, } else { + // TODO: try to tell the user why the job couldn't be started. JOptionPane.showMessageDialog(Desktop.desktop, "Unable to start web service analysis", "Internal Jalview Error", JOptionPane.WARNING_MESSAGE); @@ -302,7 +306,28 @@ public class RestClient extends WSClient implements WSClientI, name, "http://www.ibi.vu.nl/programs/shmrwww/index.php?tool=jalview",// ?tool=jalview&mbjob[method]=shmr&mbjob[description]=step1", "?tool=jalview", iparams, true, false, '-'); + // a priori knowledge of the data returned from the service + shmrService.addResultDatatype(JvDataType.ANNOTATION); return new RestClient(shmrService); } + public AlignmentPanel recoverAlignPanelForView() + { + AlignmentPanel[] aps = Desktop.getAlignmentPanels(av.getSequenceSetId()); + for (AlignmentPanel alp:aps) + { + if (alp.av == av) + { + return alp; + } + } + return null; + } + + public boolean isShowResultsInNewView() + { + // TODO make this a property of the service + return true; + } + } diff --git a/src/jalview/ws/rest/RestJob.java b/src/jalview/ws/rest/RestJob.java index c7df482..80f4ac6 100644 --- a/src/jalview/ws/rest/RestJob.java +++ b/src/jalview/ws/rest/RestJob.java @@ -1,83 +1,137 @@ package jalview.ws.rest; +import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Hashtable; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.Vector; import jalview.datamodel.AlignmentI; +import jalview.datamodel.AlignmentOrder; import jalview.datamodel.AlignmentView; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; +import jalview.io.packed.DataProvider; import jalview.io.packed.JalviewDataset; +import jalview.io.packed.ParsePackedSet; +import jalview.io.packed.SimpleDataProvider; +import jalview.io.packed.DataProvider.JvDataType; import jalview.ws.AWsJob; import jalview.ws.rest.params.Alignment; import jalview.ws.rest.params.SeqGroupIndexVector; public class RestJob extends AWsJob { - + // TODO: input alignmentview and other data for this job RestServiceDescription rsd; + // boolean submitted; boolean gotresponse; + boolean error; + boolean waiting; + boolean gotresult; + Hashtable squniq; - + + /** + * dataset associated with this input data. + */ + AlignmentI dsForIO; + + AlignmentOrder inputOrder; + + /** + * context of input data with respect to an AlignmentView's visible contigs. + */ + int[] origviscontig; + + private AlignmentI contextAl=null; + /** - * create a rest job using data bounded by the given start/end column. + * create a rest job using data bounded by the given start/end column. + * * @param addJobPane * @param restJobThread * @param _input + * @param viscontigs + * visible contigs of an alignment view from which _input was derived */ public RestJob(int jobNum, RestJobThread restJobThread, - AlignmentI _input) + AlignmentI _input, int[] viscontigs) { rsd = restJobThread.restClient.service; jobnum = jobNum; + if (viscontigs != null) + { + origviscontig = new int[viscontigs.length]; + System.arraycopy(viscontigs, 0, origviscontig, 0, viscontigs.length); + } // get sequences for the alignmentI // get groups trimmed to alignment columns // get any annotation trimmed to start/end columns, too. - + // prepare input - // form alignment+groups+annotation,preprocess and then record references for formatters + // form alignment+groups+annotation,preprocess and then record references + // for formatters ArrayList alinp = new ArrayList(); - int paramsWithData=0; - // we cheat for moment - since we know a-priori what data is available and what inputs we have implemented so far - for (Map.Entryprm: rsd.inputParams.entrySet()) + int paramsWithData = 0; + // we cheat for moment - since we know a-priori what data is available and + // what inputs we have implemented so far + for (Map.Entry prm : rsd.inputParams.entrySet()) { if (!prm.getValue().isConstant()) { if (prm.getValue() instanceof Alignment) - { - alinp.add(prm.getValue()); - } else - { - if ((prm.getValue() instanceof SeqGroupIndexVector) - &&(_input.getGroups()!=null && _input.getGroups().size()>0)) { alinp.add(prm.getValue()); } - } - } else { + else + { + if ((prm.getValue() instanceof SeqGroupIndexVector) + && (_input.getGroups() != null && _input.getGroups() + .size() > 0)) + { + alinp.add(prm.getValue()); + } + } + } + else + { paramsWithData++; } } - if ((paramsWithData+alinp.size())==rsd.inputParams.size()) + if ((paramsWithData + alinp.size()) == rsd.inputParams.size()) { + inputOrder = new AlignmentOrder(_input); + if ((dsForIO = _input.getDataset()) == null) + { + _input.setDataset(null); + } + dsForIO = _input.getDataset(); + if (contextAl==null) + { + contextAl = _input; + } setAlignmentForInputs(alinp, _input); - validInput=true; - } else { + validInput = true; + } + else + { // not enough data, so we bail. - validInput=false; + validInput = false; } } - boolean validInput=false; + + boolean validInput = false; + @Override public boolean hasResults() { @@ -93,7 +147,8 @@ public class RestJob extends AWsJob @Override public boolean isRunning() { - return running; // TODO: can we check the response body for status messages ? + return running; // TODO: can we check the response body for status messages + // ? } @Override @@ -105,7 +160,7 @@ public class RestJob extends AWsJob @Override public boolean isFinished() { - return resSet!=null; + return resSet != null; } @Override @@ -136,6 +191,7 @@ public class RestJob extends AWsJob } protected String statMessage = null; + public HttpResultSet resSet; @Override @@ -147,34 +203,37 @@ public class RestJob extends AWsJob @Override public boolean hasResponse() { - return statMessage!=null || resSet!=null; + return statMessage != null || resSet != null; } @Override public void clearResponse() { - // only clear the transient server response + // only clear the transient server response // statMessage=null; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see jalview.ws.AWsJob#getState() */ @Override public String getState() { - // TODO generate state string - prolly should have a default abstract method for this + // TODO generate state string - prolly should have a default abstract method + // for this return "Job is clueless"; } public String getPostUrl() { - + // TODO Auto-generated method stub return rsd.postUrl; } - public Set> getInputParams() + public Set> getInputParams() { return rsd.inputParams.entrySet(); } @@ -187,30 +246,40 @@ public class RestJob extends AWsJob /** * - * @return new context for parsing results from service + * @return the context for parsing results from service */ public JalviewDataset newJalviewDataset() { - /* - * TODO: initialise dataset with correct input context - */ - JalviewDataset njd = new JalviewDataset(); - return njd; + if (context == null) + { + context = new JalviewDataset(dsForIO, null, squniq, null); + if (contextAl!=null) + { + context.addAlignment(contextAl); + } + + } + return context; } /** - * Extract list of sequence IDs for input parameter 'token' with given molecule type + * Extract list of sequence IDs for input parameter 'token' with given + * molecule type + * * @param token * @param type * @return */ - public SequenceI[] getSequencesForInput(String token, InputType.molType type) throws NoValidInputDataException + public SequenceI[] getSequencesForInput(String token, + InputType.molType type) throws NoValidInputDataException { Object sgdat = inputData.get(token); // can we form an alignment from this data ? - if (sgdat==null) + if (sgdat == null) { - throw new NoValidInputDataException("No Sequence vector data bound to input '"+token+"' for service at "+rsd.postUrl); + throw new NoValidInputDataException( + "No Sequence vector data bound to input '" + token + + "' for service at " + rsd.postUrl); } if (sgdat instanceof AlignmentI) { @@ -218,49 +287,61 @@ public class RestJob extends AWsJob } if (sgdat instanceof SequenceGroup) { - return ((SequenceGroup)sgdat).getSequencesAsArray(null); + return ((SequenceGroup) sgdat).getSequencesAsArray(null); } if (sgdat instanceof Vector) { - if (((Vector)sgdat).size()>0 && ((Vector)sgdat).get(0) instanceof SequenceI) + if (((Vector) sgdat).size() > 0 + && ((Vector) sgdat).get(0) instanceof SequenceI) { - SequenceI[] sq = new SequenceI[((Vector)sgdat).size()]; - ((Vector)sgdat).copyInto(sq); + SequenceI[] sq = new SequenceI[((Vector) sgdat).size()]; + ((Vector) sgdat).copyInto(sq); return sq; } } - throw new NoValidInputDataException("No Sequence vector data bound to input '"+token+"' for service at "+rsd.postUrl); + throw new NoValidInputDataException( + "No Sequence vector data bound to input '" + token + + "' for service at " + rsd.postUrl); } + /** - * binding between input data (AlignmentI, SequenceGroup, NJTree) and input param names. + * binding between input data (AlignmentI, SequenceGroup, NJTree) and input + * param names. */ - private Hashtable inputData=new Hashtable(); + private Hashtable inputData = new Hashtable(); + /** * is the job fully submitted to server and apparently in progress ? */ - public boolean running=false; + public boolean running = false; + /** * * @param itypes - * @param al - reference to object to be stored as input. Note - input data may be modifed by formatter + * @param al + * - reference to object to be stored as input. Note - input data may + * be modifed by formatter */ - public void setAlignmentForInputs(Collection itypes, AlignmentI al) + public void setAlignmentForInputs(Collection itypes, + AlignmentI al) { - for (InputType itype: itypes) { + for (InputType itype : itypes) + { if (!rsd.inputParams.values().contains(itype)) { - throw new IllegalArgumentException("InputType "+itype.getClass()+ - " is not valid for service at "+rsd.postUrl); + throw new IllegalArgumentException("InputType " + itype.getClass() + + " is not valid for service at " + rsd.postUrl); } if (itype instanceof AlignmentProcessor) { - ((AlignmentProcessor)itype).prepareAlignment(al); + ((AlignmentProcessor) itype).prepareAlignment(al); } // stash a reference for recall when the alignment data is formatted inputData.put(itype.token, al); } - + } + /** * * @param token @@ -268,30 +349,51 @@ public class RestJob extends AWsJob * @return alignment object bound to the given token * @throws NoValidInputDataException */ - public AlignmentI getAlignmentForInput(String token, InputType.molType type) throws NoValidInputDataException + public AlignmentI getAlignmentForInput(String token, + InputType.molType type) throws NoValidInputDataException { Object al = inputData.get(token); // can we form an alignment from this data ? - if (al==null || !(al instanceof AlignmentI)) + if (al == null || !(al instanceof AlignmentI)) { - throw new NoValidInputDataException("No alignment data bound to input '"+token+"' for service at "+rsd.postUrl); + throw new NoValidInputDataException( + "No alignment data bound to input '" + token + + "' for service at " + rsd.postUrl); } return (AlignmentI) al; } /** * test to see if the job has data of type cl that's needed for the job to run + * * @param cl * @return true or false */ public boolean hasDataOfType(Class cl) { - if (AlignmentI.class.isAssignableFrom(cl)) { + if (AlignmentI.class.isAssignableFrom(cl)) + { return true; } - // TODO: add more source data types - + // TODO: add more source data types + return false; } + /** + * context used to parse results from service + */ + JalviewDataset context = null; + + Object[] jvresultobj = null; + + /** + * process the results obtained from the server into jalview datamodel objects + * ready to be merged/added to the users' view. + */ + public void parseResultSet() throws Exception, Error + { + jvresultobj = resSet.parseResultSet(); + } + } diff --git a/src/jalview/ws/rest/RestJobThread.java b/src/jalview/ws/rest/RestJobThread.java index bd71813..67ccd3a 100644 --- a/src/jalview/ws/rest/RestJobThread.java +++ b/src/jalview/ws/rest/RestJobThread.java @@ -2,6 +2,8 @@ package jalview.ws.rest; import jalview.bin.Cache; import jalview.datamodel.AlignmentI; +import jalview.datamodel.ColumnSelection; +import jalview.gui.AlignFrame; import jalview.gui.WebserviceInfo; import jalview.io.packed.DataProvider; import jalview.io.packed.JalviewDataset; @@ -11,6 +13,7 @@ import jalview.io.packed.DataProvider.JvDataType; import jalview.ws.AWSThread; import jalview.ws.AWsJob; +import java.awt.Desktop; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; @@ -60,13 +63,15 @@ public class RestJobThread extends AWSThread jobs = new RestJob[1]; jobs[0] = new RestJob(0, this, restClient._input.getVisibleAlignment(restClient.service - .getGapCharacter())); + .getGapCharacter()), + restClient._input.getVisibleContigs()); // need a function to get a range on a view/alignment and return both // annotation, groups and selection subsetted to just that region. } else { + int[] viscontig = restClient._input.getVisibleContigs(); AlignmentI[] viscontigals = restClient._input .getVisibleContigAlignments(restClient.service .getGapCharacter()); @@ -75,13 +80,15 @@ public class RestJobThread extends AWSThread jobs = new RestJob[viscontigals.length]; for (int j = 0; j < jobs.length; j++) { + int[] visc = new int[] + { viscontig[j * 2], viscontig[j * 2 + 1] }; if (j != 0) { - jobs[j] = new RestJob(j, this, viscontigals[j]); + jobs[j] = new RestJob(j, this, viscontigals[j], visc); } else { - jobs[j] = new RestJob(0, this, viscontigals[j]); + jobs[j] = new RestJob(0, this, viscontigals[j], visc); } } } @@ -178,7 +185,8 @@ public class RestJobThread extends AWSThread throws Exception { StringBuffer respText = new StringBuffer(); - // con.setContentHandlerFactory(new jalview.ws.io.mime.HttpContentHandler()); + // con.setContentHandlerFactory(new + // jalview.ws.io.mime.HttpContentHandler()); HttpRequestBase request = null; String messages = ""; if (stg == Stage.SUBMIT) @@ -244,8 +252,12 @@ public class RestJobThread extends AWSThread processResultSet(rj, response, request); break; case 202: - rj.statMessage = "Job submitted successfully. Results available at this URL:\n" - + rj.getJobId() + "\n"; + rj.statMessage = "
Job submitted successfully. Results available at this URL:\n" + + "" + + rj.getJobId() + + "
"; rj.running = true; break; case 302: @@ -274,6 +286,7 @@ public class RestJobThread extends AWSThread rj.setAllowedServerExceptions(0); rj.setSubjobComplete(true); rj.error = true; + rj.running = false; completeStatus(rj, response, "" + getStage(stg) + "failed. Reason below:\n"); break; @@ -346,9 +359,24 @@ public class RestJobThread extends AWSThread } HttpEntity en = con.getEntity(); /* - * Just show the content as a string. + * Just append the content as a string. */ - rj.statMessage = EntityUtils.toString(en); + String f; + StringBuffer content = new StringBuffer(f = EntityUtils.toString(en)); + f = f.toLowerCase(); + int body = f.indexOf(" -1) + { + content.delete(0, f.indexOf(">", body)); + } + if (body > -1 && sb.length() > 0) + { + sb.append("\n"); + content.insert(0, sb); + sb = null; + } + f = null; + rj.statMessage = content.toString(); } @Override @@ -379,51 +407,90 @@ public class RestJobThread extends AWSThread public void parseResult() { // crazy users will see this message - System.err.println("WARNING: Rest job result parser is INCOMPLETE!"); + // TODO: finish this! and remove the message below! + Cache.log.warn("Rest job result parser is currently INCOMPLETE!"); + int validres = 0; for (RestJob rj : (RestJob[]) jobs) { - // TODO: call each jobs processResults() method and collect valid - // contexts. if (rj.hasResponse() && rj.resSet != null && rj.resSet.isValid()) { String ln = null; - System.out.println("Parsing data for job " + rj.getJobId()); - if (!restClient.isAlignmentModified()) + try { - try - { - /* - * while ((ln=rj.resSet.nextLine())!=null) { System.out.println(ln); - * } } - */ - List dp = new ArrayList(); - restClient.af.newView_actionPerformed(null); - dp.add(new SimpleDataProvider(JvDataType.ANNOTATION, rj.resSet, null)); - JalviewDataset context = new JalviewDataset(restClient.av.getAlignment().getDataset(), null, null,restClient.av.getAlignment()); - ParsePackedSet pps = new ParsePackedSet(); - pps.getAlignment(context, dp); - - // do an ap.refresh restClient.av.alignmentChanged(Desktop.getAlignmentPanels(restClient.av.getViewId())[0]); - System.out.println("Finished parsing data for job " - + rj.getJobId()); - - } catch (Exception ex) + Cache.log.debug("Parsing data for job " + rj.getJobId()); + rj.parseResultSet(); + if (rj.hasResults()) { - System.out.println("Failed to finish parsing data for job " - + rj.getJobId()); - ex.printStackTrace(); + validres++; } + Cache.log.debug("Finished parsing data for job " + rj.getJobId()); + + } catch (Error ex) + { + Cache.log.warn("Failed to finish parsing data for job " + + rj.getJobId()); + ex.printStackTrace(); + } catch (Exception ex) + { + Cache.log.warn("Failed to finish parsing data for job " + + rj.getJobId()); + ex.printStackTrace(); } } } - /** - * decisions based on job result content + state of alignFrame that - * originated the job: - */ - /* - * 1. Can/Should this job automatically open a new window for results - */ - wsInfo.setViewResultsImmediatly(false); + if (validres > 0) + { + // add listeners and activate result display gui elements + /** + * decisions based on job result content + state of alignFrame that + * originated the job: + */ + /* + * 1. Can/Should this job automatically open a new window for results + */ + if (true) + { + wsInfo.setViewResultsImmediatly(false); + } + else + { + // realiseResults(true, true); + } + // otherwise, should automatically view results + + // TODO: check if at least one or more contexts are valid - if so, enable + // gui + wsInfo.showResultsNewFrame.addActionListener(new ActionListener() + { + + @Override + public void actionPerformed(ActionEvent e) + { + realiseResults(false); + } + + }); + wsInfo.mergeResults.addActionListener(new ActionListener() + { + + @Override + public void actionPerformed(ActionEvent e) + { + realiseResults(true); + } + + }); + + wsInfo.setResultsReady(); + } + else + { + // tell the user nothing was returned. + } + } + + public void realiseResults(boolean merge) + { /* * 2. Should the job modify the parent alignment frame/view(s) (if they * still exist and the alignment hasn't been edited) in order to display new @@ -457,30 +524,45 @@ public class RestJobThread extends AWSThread * aligned to it ? * */ - // TODO: check if at least one or more contexts are valid - if so, enable - // gui - wsInfo.showResultsNewFrame.addActionListener(new ActionListener() + jalview.gui.AlignmentPanel destPanel = null; + if (merge) { - - @Override - public void actionPerformed(ActionEvent e) + if (!restClient.isAlignmentModified()) { - // TODO: call method to show results in new window + destPanel = restClient.recoverAlignPanelForView(); + if (restClient.isShowResultsInNewView()) + { + destPanel = destPanel.alignFrame.newView(false); + } } - - }); - wsInfo.mergeResults.addActionListener(new ActionListener() + } + if (destPanel == null) { - - @Override - public void actionPerformed(ActionEvent e) + Object[] idat = input.getAlignmentAndColumnSelection(restClient.av.getGapCharacter()); + AlignFrame af = new AlignFrame((AlignmentI) idat[0], + (ColumnSelection) idat[1], AlignFrame.DEFAULT_WIDTH, + AlignFrame.DEFAULT_HEIGHT); + jalview.gui.Desktop.addInternalFrame(af, + "Results for " + restClient.service.details.Name + " " + + restClient.service.details.Action + " on " + + restClient.af.getTitle(), AlignFrame.DEFAULT_WIDTH, + AlignFrame.DEFAULT_HEIGHT); + destPanel = af.alignPanel; + // create totally new alignment from stashed data/results + } + else + { + for (int j = 0; j < jobs.length; j++) { - // TODO: call method to merge results into existing window + RestJob rj = (RestJob) jobs[j]; + if (rj.jvresultobj!=null && rj.jvresultobj.length>0) { + // transfer results onto panel + + } } - - }); - - wsInfo.setResultsReady(); + } + destPanel.adjustAnnotationHeight(); + } diff --git a/src/jalview/ws/rest/RestServiceDescription.java b/src/jalview/ws/rest/RestServiceDescription.java index 6794a8d..befae8f 100644 --- a/src/jalview/ws/rest/RestServiceDescription.java +++ b/src/jalview/ws/rest/RestServiceDescription.java @@ -19,14 +19,19 @@ package jalview.ws.rest; import jalview.datamodel.SequenceI; +import jalview.io.packed.DataProvider; +import jalview.io.packed.SimpleDataProvider; +import jalview.io.packed.DataProvider.JvDataType; import jalview.util.GroupUrlLink.UrlStringTooLongException; import jalview.util.Platform; import jalview.ws.rest.params.Alignment; import jalview.ws.rest.params.AnnotationFile; import jalview.ws.rest.params.SeqGroupIndexVector; +import java.util.ArrayList; import java.util.HashMap; import java.util.Hashtable; +import java.util.List; import java.util.Map; @@ -76,16 +81,26 @@ public class RestServiceDescription */ String urlSuffix; - /*** - * modelling the io: - * validation of input - * { formatter for type, parser for type } - * - */ /** input info given as key/value pairs - mapped to post arguments */ Map inputParams=new HashMap(); /** + * assigns the given inputType it to its corresponding input parameter token it.token + * @param it + */ + public void setInputParam(InputType it) + { + inputParams.put(it.token, it); + } + /** + * remove the given input type it from the set of service input parameters. + * @param it + */ + public void removeInputParam(InputType it) + { + inputParams.remove(it.token); + } + /** * service requests alignment data */ boolean aligndata; @@ -908,4 +923,25 @@ public class RestServiceDescription // TODO: correctly write ?/& appropriate to result URL format. return jobId+urlSuffix; } + private List resultData; + public void addResultDatatype(JvDataType dt) + { + if (resultData==null) + { + resultData = new ArrayList(); + } + resultData.add(dt); + } + public boolean removeRsultDatatype(JvDataType dt) + { + if (resultData!=null) + { + return resultData.remove(dt); + } + return false; + } + public List getResultDataTypes() + { + return resultData; + } } diff --git a/src/jalview/ws/rest/params/Alignment.java b/src/jalview/ws/rest/params/Alignment.java index 23c8746..922f933 100644 --- a/src/jalview/ws/rest/params/Alignment.java +++ b/src/jalview/ws/rest/params/Alignment.java @@ -53,8 +53,8 @@ public class Alignment extends InputType { throw new NoValidInputDataException("Couldn't write out alignment to file.",ex); } } else { - StringBody sb = new StringBody(new jalview.io.FormatAdapter().formatSequences(format, alignment, jvsuffix), "text/plain", Charset.forName("UTF-8")); - sb.getContentTypeParameters().put("filename", "alignment.fa"); + StringBody sb = new StringBody(new jalview.io.FormatAdapter().formatSequences(format, alignment, jvsuffix)); // , "text/plain", Charset.forName("UTF-8")); + // sb.getContentTypeParameters().put("filename", "alignment.fa"); return sb; } } -- 1.7.10.2