/** * */ package jalview.ws.rest; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Hashtable; import java.util.Vector; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.event.MenuEvent; import javax.swing.event.MenuListener; import com.sun.org.apache.bcel.internal.generic.ISHL; 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; /** * @author JimP * */ public class RestClient extends WSClient implements WSClientI, WSMenuEntryProviderI { RestServiceDescription service; public RestClient(RestServiceDescription rsd) { service = rsd; } /** * parent alignframe for this job */ AlignFrame af; /** * alignment view which provides data for job. */ AlignViewport av; /** * get the alignFrame for the associated input data if it exists. * * @return */ protected AlignFrame recoverAlignFrameForView() { return jalview.gui.Desktop.getAlignFrameFor(av); } public RestClient(RestServiceDescription service2, AlignFrame alignFrame) { service = service2; af = alignFrame; av = alignFrame.getViewport(); constructJob(); } public void setWebserviceInfo(boolean headless) { WebServiceJobTitle = service.details.Action + " using " + service.details.Name; WebServiceName = service.details.Name; WebServiceReference = "No reference - go to url for more info"; if (service.details.description != null) { WebServiceReference = service.details.description; } if (!headless) { wsInfo = new WebserviceInfo(WebServiceJobTitle, WebServiceName + "\n" + WebServiceReference); wsInfo.setRenderAsHtml(true); } } @Override public boolean isCancellable() { // TODO define process for cancelling rsbws jobs return false; } @Override public boolean canMergeResults() { // TODO process service definition to identify if the results might be // mergeable // TODO: change comparison for annotation merge return false; } @Override public void cancelJob() { System.err.println("Cannot cancel this job type: " + service); } @Override public void attachWSMenuEntry(final JMenu wsmenu, final AlignFrame alignFrame) { JMenuItem submit = new JMenuItem(service.details.Name); submit.setToolTipText(service.details.Action+" using "+service.details.Name); submit.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { new RestClient(service, alignFrame); } }); wsmenu.add(submit); // TODO: menu listener should enable/disable entry depending upon selection // state of the alignment wsmenu.addMenuListener(new MenuListener() { @Override public void menuSelected(MenuEvent e) { // TODO Auto-generated method stub } @Override public void menuDeselected(MenuEvent e) { // TODO Auto-generated method stub } @Override public void menuCanceled(MenuEvent e) { // TODO Auto-generated method stub } }); } /** * record of initial undoredo hash for the alignFrame providing data for this * job. */ long[] undoredo = null; /** * Compare the original input data to the data currently presented to the * user. // LOGIC: compare undo/redo - if same, merge regardless (coping with * any changes in hidden columns as normal) // if different undo/redo then * compare region that was submitted // if same, then merge as before, if * different then prompt user to open a new window. * * @return */ protected boolean isAlignmentModified() { if (undoredo == null || av==null || av.getAlignment()==null) { // always return modified if we don't have access to live GUI elements anymore. return true; } if (av.isUndoRedoHashModified(undoredo)) { // alignment has been modified in some way. return true; } // TODO: look deeper into modification of selection state, etc that may affect RestJobThread.realiseResults(boolean merge); return false; } /** * TODO: combine to form a dataset+alignment+annotation context */ AlignmentView _input; /** * input data context */ jalview.io.packed.JalviewDataset jds; protected void constructJob() { service.setInvolvesFlags(); // record all aspects of alignment view so we can merge back or recreate // later undoredo = av.getUndoRedoHash(); /** * delete ? Vector sgs = av.getAlignment().getGroups(); if (sgs!=null) { * _sgs = new SequenceGroup[sgs.size()]; sgs.copyInto(_sgs); } else { _sgs = * new SequenceGroup[0]; } */ boolean selExists = (av.getSelectionGroup() != null) && (av.getSelectionGroup().getSize() > 1); // TODO: revise to full focus+context+dataset input data staging model if (selExists) { if (service.partitiondata) { if (av.getAlignment().getGroups()!=null && av.getAlignment().getGroups().size() > 0) { // intersect groups with selected region _input = new AlignmentView(av.getAlignment(), av.getColumnSelection(), av.getSelectionGroup(), av.hasHiddenColumns(), true, true); } else { // use selected region to partition alignment _input = new AlignmentView(av.getAlignment(), av.getColumnSelection(), av.getSelectionGroup(), av.hasHiddenColumns(), false, true); } // TODO: verify that some kind of partition can be constructed from input } else { // just take selected region intersection _input = new AlignmentView(av.getAlignment(), av.getColumnSelection(), av.getSelectionGroup(), av.hasHiddenColumns(), true, true); } } else { // standard alignment view without selection present _input = new AlignmentView(av.getAlignment(), av.getColumnSelection(), null, av.hasHiddenColumns(), false, true); } RestJobThread jobsthread = new RestJobThread(this); if (jobsthread.isValid()) { setWebserviceInfo(false); wsInfo.setthisService(this); jobsthread.setWebServiceInfo(wsInfo); jobsthread.start(); } 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); } } public static RestClient makeShmmrRestClient() { String action = "Analyse", description = "Sequence Harmony and Multi-Relief (UNSTABLE!)", name = "SHMR"; Hashtable iparams = new Hashtable(); jalview.ws.rest.params.JobConstant toolp; //toolp = new jalview.ws.rest.JobConstant("tool","jalview"); //iparams.put(toolp.token, toolp); toolp = new jalview.ws.rest.params.JobConstant("mbjob[method]","shmr"); iparams.put(toolp.token, toolp); toolp = new jalview.ws.rest.params.JobConstant("mbjob[description]","step 1"); iparams.put(toolp.token, toolp); toolp = new jalview.ws.rest.params.JobConstant("start_search","1"); iparams.put(toolp.token, toolp); toolp = new jalview.ws.rest.params.JobConstant("blast","0"); iparams.put(toolp.token, toolp); jalview.ws.rest.params.Alignment aliinput = new jalview.ws.rest.params.Alignment(); aliinput.token = "ali_file"; aliinput.writeAsFile=true; iparams.put("ali_file", aliinput); jalview.ws.rest.params.SeqGroupIndexVector sgroups = new jalview.ws.rest.params.SeqGroupIndexVector(); iparams.put("groups", sgroups); sgroups.token = "groups"; sgroups.sep = " "; RestServiceDescription shmrService = new RestServiceDescription( action, description, 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; } }