/*
* Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
* Copyright (C) $$Year-Rel$$ The Jalview Authors
*
* 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 .
* The Jalview Authors are detailed in the 'AUTHORS' file.
*/
package jalview.gui;
import jalview.io.packed.DataProvider.JvDataType;
import jalview.jbgui.GRestServiceEditorPane;
import jalview.util.MessageManager;
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(
MessageManager.getString("label.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()
{
Map inputTypes = 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(MessageManager.formatMessage(
"label.parsing_failed_syntax_errors_shown_below_param",
new String[]
{ rsd.getInvalidMessage() }));
parseWarnings.setVisible(true);
}
} catch (Throwable e)
{
e.printStackTrace();
parseRes.setText(MessageManager.formatMessage(
"label.parsing_failed_unrecoverable_exception_thrown_param",
new String[]
{ e.toString() }));
parseWarnings.setVisible(true);
}
}
paste.revalidate();
}
}
}
/**
* @j2sIgnore
* @param args
*/
public static void main(String[] args)
{
if (args.length == 0)
{
new Thread(new Runnable()
{
boolean visible = true;
@Override
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;
}
}