/*******************************************************************************
* Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
* Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle
*
* This file is part of Jalview.
*
* Jalview is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* Jalview is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with Jalview. If not, see .
*******************************************************************************/
package jalview.gui;
import jalview.io.packed.DataProvider.JvDataType;
import jalview.jbgui.GRestServiceEditorPane;
import jalview.ws.rest.InputType;
import jalview.ws.rest.RestServiceDescription;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class RestServiceEditorPane extends GRestServiceEditorPane
{
/**
* the latest version of the service definition.
*/
jalview.ws.rest.RestServiceDescription currentservice = null;
/**
* original service passed to editor if we are modifying an existing service
* definition
*/
jalview.ws.rest.RestServiceDescription oldservice = null;
public RestServiceEditorPane()
{
super();
// begin with initial text description box enabled.
urldesc.addKeyListener(new KeyListener()
{
@Override
public void keyTyped(KeyEvent e)
{
}
@Override
public void keyReleased(KeyEvent e)
{
refreshCutnPaste(true);
}
@Override
public void keyPressed(KeyEvent e)
{
}
});
panels.addChangeListener(new ChangeListener()
{
/**
* last panel selected - used to decide whether the service or the GUI has the latest info
*/
Object lastComp;
@Override
public void stateChanged(ChangeEvent e)
{
if (lastComp!=paste) {
updateServiceFromGui();
refreshCutnPaste(false);
} else {
refreshCutnPaste(true);
}
lastComp = panels.getSelectedComponent();
}
});
currentservice = new RestServiceDescription("Analysis", "service description", "service name", "http://localhost/", "", null, false, false, '-');
initGuiWith(currentservice);
refreshCutnPaste(false);
updateButtons();
}
public RestServiceEditorPane(RestServiceDescription toedit)
{
this();
oldservice = toedit;
if (oldservice!=null)
{ currentservice = new RestServiceDescription(toedit);
} else {
currentservice = new RestServiceDescription("Analysis", "service description", "service name", "http://localhost/", "", null, false, false, '-');
}
initGuiWith(currentservice);
refreshCutnPaste(false);
updateButtons();
}
/**
* refresh the buttons based on model state
*/
public void updateButtons()
{
cancelButton.setEnabled(true);
okButton.setEnabled(currentservice != null && currentservice.isValid());
}
Vector _iparam = new Vector();
Vector _rparam = new Vector();
/**
* generate an editable URL service string and parameter list using the
* service
*
* @param currentservice2
*/
private void initGuiWith(RestServiceDescription currentservice)
{
_iparam.clear();
_rparam.clear();
action.removeAllItems();
action.addItem("Alignment");
action.addItem("Analysis");
gapChar.removeAllItems();
gapChar.addItem(".");
gapChar.addItem(" ");
gapChar.addItem("-");
if (currentservice==null)
{
name.setText("");
descr.setText("");
url.setText("");
urlsuff.setText("");
action.setSelectedItem("Analysis");
gapChar.setSelectedItem("-");
} else {
name.setText(currentservice.getName());
descr.setText(currentservice.getDescription());
url.setText(currentservice.getPostUrl());
urlsuff.setText(currentservice.getUrlSuffix());
for (Map.Entry inparam : currentservice
.getInputParams().entrySet())
{
_iparam.add(inparam.getKey() + " "
+ inparam.getValue().getURLtokenPrefix() + ":"
+ inparam.getValue().getURLEncodedParameter().toString());
}
for (JvDataType oparam : currentservice.getResultDataTypes())
{
_rparam.add(oparam.name());
}
iprms.setListData(_iparam);
rdata.setListData(_rparam);
action.setSelectedItem(currentservice.getAction());
gapChar.setSelectedItem(""+currentservice.getGapCharacter());
}
revalidate();
}
private String getSelectedInputToken()
{
if (iprms.getSelectedIndex()>-1)
{
String toktoedit = (String) iprms.getSelectedValue();
toktoedit=toktoedit.substring(0, toktoedit.indexOf(" "));
return toktoedit;
}
return null;
}
@Override
protected void iprmListSelection_doubleClicked()
{
String toktoedit = getSelectedInputToken();
if (toktoedit!=null)
{
InputType toedit = currentservice.getInputParams().get(toktoedit);
String oldParam=toktoedit;
RestInputParamEditDialog dialog=new RestInputParamEditDialog(this, currentservice, toedit);
if (dialog.wasUpdated()) {
currentservice.getInputParams().remove(oldParam);
currentservice.getInputParams().put(dialog.current.token, dialog.current);
initGuiWith(currentservice);
}
}
}
@Override
protected void iprmsAdd_actionPerformed(ActionEvent e)
{
RestInputParamEditDialog dialog=new RestInputParamEditDialog(this, currentservice, "param"+(1+currentservice.getInputParams().size()));
if (dialog.wasUpdated()) {
currentservice.getInputParams().put(dialog.current.token, dialog.current);
initGuiWith(currentservice);
}
}
@Override
protected void iprmsRem_actionPerformed(ActionEvent e)
{
String toktoedit = getSelectedInputToken();
if (toktoedit!=null)
{
currentservice.getInputParams().remove(toktoedit);
initGuiWith(currentservice);
}
}
@Override
protected void rdata_rightClicked(MouseEvent mouse)
{
final int rdatasel = rdata.getSelectedIndex();
if (rdatasel>-1)
{
JPopupMenu popup = new JPopupMenu("Select return type");
for (final JvDataType type:JvDataType.values()) {
popup.add(new JMenuItem(type.name())).addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
currentservice.getResultDataTypes().set(rdatasel, type);
initGuiWith(currentservice);
rdata.setSelectedIndex(rdatasel);
}
});
}
popup.show(rdata, mouse.getX(), mouse.getY());
}
}
@Override
protected void rdataAdd_actionPerformed(ActionEvent e)
{
int p;
if ((p=rdata.getSelectedIndex())>-1)
{
currentservice.getResultDataTypes().add(p+1, JvDataType.ANNOTATION);
} else {
currentservice.addResultDatatype(JvDataType.ANNOTATION);
}
initGuiWith(currentservice);
rdata.setSelectedIndex(p==-1 ? currentservice.getResultDataTypes().size()-1 : p+1);
}
@Override
protected void rdataNdown_actionPerformed(ActionEvent e)
{
int p;
if ((p=rdata.getSelectedIndex())>-1 && p<_rparam.size()-1)
{
List rtypes = currentservice.getResultDataTypes();
JvDataType below = rtypes.get(p+1);
rtypes.set(p+1, rtypes.get(p));
rtypes.set(p, below);
initGuiWith(currentservice);
rdata.setSelectedIndex(p+1);
}
}
@Override
protected void rdataNup_actionPerformed(ActionEvent e)
{
int p;
if ((p=rdata.getSelectedIndex())>0)
{
List rtypes = currentservice.getResultDataTypes();
JvDataType above = rtypes.get(p-1);
rtypes.set(p-1, rtypes.get(p));
rtypes.set(p, above);
initGuiWith(currentservice);
rdata.setSelectedIndex(p-1);
}
}
@Override
protected void rdataRem_actionPerformed(ActionEvent e)
{
if (rdata.getSelectedIndex()>-1)
{
currentservice.getResultDataTypes().remove(rdata.getSelectedIndex());
initGuiWith(currentservice);
}
}
private boolean updateServiceFromGui() {
MapinputTypes = new HashMap();
StringBuffer warnings=new StringBuffer();
for (String its:_iparam)
{
Matcher mtch = Pattern.compile("(\\S+)\\s(\\S+):\\[(.+)]").matcher(its);
if (mtch.find()) {
if (!RestServiceDescription.parseTypeString(mtch.group(2)+":"+mtch.group(3), mtch.group(1), mtch.group(2),mtch.group(3), inputTypes, warnings))
{
System.err.println("IMPLEMENTATION PROBLEM: Cannot parse RestService input parameter string '"+its+"'"+"\n"+warnings);
}
}
}
char gc = gapChar.getSelectedItem()==null ? ' ' : ((String)gapChar.getSelectedItem()).charAt(0);
RestServiceDescription newService = new RestServiceDescription((String) action.getSelectedItem(),
descr.getText().trim(), name.getText().trim(), url.getText().trim(), urlsuff.getText().trim(), inputTypes, hSeparable.isSelected(), vSeparable.isSelected(), gc);
if (newService.isValid())
{
for (String its:_rparam)
{
JvDataType dtype;
try {
dtype = JvDataType.valueOf(its);
newService.addResultDatatype(dtype);
}
catch (Throwable x)
{
System.err.println("IMPLEMENTATION PROBLEM: Cannot parse RestService output parameter string '"+its+"'"+"\n"+warnings);
}
}
currentservice = newService;
return true;
} else {
System.err.println("IMPLEMENTATION PROBLEM: Restservice generated from GUI is invalid\n"+warnings);
}
return false;
}
protected void refreshCutnPaste(boolean reparse)
{
if (!reparse && currentservice.isValid())
{
urldesc.setText(currentservice.toString());
parseWarnings.setVisible(false);
}
else
{
if (reparse)
{
String txt = urldesc.getText().trim();
if (txt.length() > 0)
{
RestServiceDescription rsd = null;
try
{
rsd = new RestServiceDescription(txt);
if (rsd.isValid())
{
parseWarnings.setVisible(false);
parseRes.setText("");
initGuiWith(currentservice=rsd);
}
else
{
parseRes.setText("Parsing failed. Syntax errors shown below\n"
+ rsd.getInvalidMessage());
parseWarnings.setVisible(true);
}
} catch (Throwable e)
{
e.printStackTrace();
parseRes.setText("\nParsing failed. An unrecoverable exception was thrown:\n"
+ e.toString());
parseWarnings.setVisible(true);
}
}
paste.revalidate();
}
}
}
public static void main(String[] args)
{
if (args.length == 0)
{
new Thread(new Runnable()
{
boolean visible = true;
public void run()
{
boolean nulserv=true;
while (visible)
{
final Thread runner = Thread.currentThread();
JFrame df = new JFrame();
df.getContentPane().setLayout(new BorderLayout());
df.getContentPane().add(
(nulserv=!nulserv) ? new RestServiceEditorPane(jalview.ws.rest.RestClient
.makeShmmrRestClient().getRestDescription()) : new RestServiceEditorPane(),
BorderLayout.CENTER);
df.setBounds(100, 100, 600, 400);
df.addComponentListener(new ComponentListener()
{
@Override
public void componentShown(ComponentEvent e)
{
}
@Override
public void componentResized(ComponentEvent e)
{
}
@Override
public void componentMoved(ComponentEvent e)
{
}
@Override
public void componentHidden(ComponentEvent e)
{
visible = false;
runner.interrupt();
}
});
df.setVisible(true);
while (visible)
{
try
{
Thread.sleep(10000);
} catch (Exception x)
{
}
;
}
visible = true;
}
}
}).start();
}
}
String finalService=null;
public void showDialog(String title)
{
if (oldservice!=null)
{
finalService = oldservice.toString();
}
JalviewDialog jvd = new JalviewDialog()
{
@Override
protected void raiseClosed()
{
// TODO Auto-generated method stub
}
@Override
protected void okPressed()
{
updateServiceFromGui();
finalService = currentservice.toString();
}
@Override
protected void cancelPressed()
{
}
};
JPanel pane = new JPanel(new BorderLayout()),okcancel=new JPanel(new FlowLayout());
pane.add(this,BorderLayout.CENTER);
okcancel.add(jvd.ok);
okcancel.add(jvd.cancel);
pane.add(okcancel, BorderLayout.SOUTH);
jvd.initDialogFrame(pane, true, true, title, 600,350);
jvd.waitForInput();
}
public String getEditedRestService()
{
return finalService;
}
}