package org.xins.common.spec;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import org.w3c.dom.Element;
import org.xins.common.xml.ElementList;
import org.xins.common.xml.ElementFormatter;
import org.xins.common.xml.Viewer;
public class SpecGUI {
private JFrame specFrame;
private JPanel specPanel;
private JMenuBar specMenuBar;
private JLabel jlAPIName;
private JTextField jtfEnvironment;
private JTextField jtfQuery;
private Viewer xmlViewer;
private APISpec specs;
private Dimension screenDim = Toolkit.getDefaultToolkit().getScreenSize();
public SpecGUI() {
JFrame mainFrame = new JFrame();
initUI(mainFrame);
initData();
mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
mainFrame.setVisible(true);
}
public SpecGUI(JFrame mainFrame) {
initUI(mainFrame);
initData();
}
protected void initUI(JFrame mainFrame) {
specPanel = new JPanel();
xmlViewer = new Viewer();
xmlViewer.setPreferredSize(new Dimension(500, 400));
specPanel.setLayout(new BorderLayout(5,5));
JPanel queryPanel = createQueryPanel();
specPanel.add(queryPanel, BorderLayout.NORTH);
JScrollPane scrollXMLViewer = new JScrollPane(xmlViewer);
scrollXMLViewer.setBorder(new EmptyBorder(5,5,5,5));
specPanel.add(scrollXMLViewer, BorderLayout.CENTER);
createMenuBar();
if (mainFrame != null) {
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
URL iconLocation = SpecGUI.class.getResource("/org/xins/common/servlet/container/xins.gif");
if (iconLocation != null) {
mainFrame.setIconImage(new ImageIcon(iconLocation).getImage());
}
mainFrame.setTitle("XINS Specification Viewer");
mainFrame.setJMenuBar(getMenuBar());
mainFrame.getContentPane().add(getMainPanel());
mainFrame.pack();
Dimension appDim = mainFrame.getSize();
mainFrame.setLocation((screenDim.width - appDim.width) / 2,(screenDim.height - appDim.height) / 2);
specFrame = mainFrame;
}
}
protected void initData() {
try {
Element webapp = ElementFormatter.parse(getClass().getResourceAsStream("/WEB-INF/web.xml"));
String apiClassName = null;
Element servletElement = new ElementList(webapp, "servlet").getUniqueChildElement();
for (Element initParam : new ElementList(servletElement, "init-param")) {
String paramName = new ElementList(initParam, "param-name").getUniqueChildElement().getTextContent();
if (paramName.equals("org.xins.api.class")) {
apiClassName = new ElementList(initParam, "param-value").getUniqueChildElement().getTextContent();
}
}
Class apiClass = Class.forName(apiClassName);
specs = new APISpec(apiClass, getClass().getResource("/WEB-INF/specs/").toString());
jlAPIName.setToolTipText(specs.getDescription());
} catch (Exception ex) {
ex.printStackTrace();
}
}
protected JPanel createQueryPanel() {
JPanel queryPanel = new JPanel(new BorderLayout());
jtfEnvironment = new JTextField("http://localhost:8080/?_convention=_xins-std");
jtfQuery = new JTextField();
jtfQuery.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
query(jtfQuery.getText());
}
});
JPanel queryLabelPanel = new JPanel();
queryLabelPanel.setLayout(new GridLayout(2,1,5,5));
jlAPIName = new JLabel("API") {
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
Color background = getBackground();
Paint oldPaint = g2.getPaint();
GradientPaint gradient = new GradientPaint(0.0f, 0.0f, background.brighter(),
specPanel.getWidth() + 0.1f, getHeight() + 0.1f, background.darker());
g2.setPaint(gradient);
g2.fill(new Rectangle(specPanel.getWidth(), getHeight()));
g2.setPaint(oldPaint);
super.paint(g);
}
};
jlAPIName.setOpaque(false);
jlAPIName.setFont(jlAPIName.getFont().deriveFont(20.0f));
queryPanel.add(jlAPIName, BorderLayout.NORTH);
queryLabelPanel.add(new JLabel("Environment: "));
queryLabelPanel.add(new JLabel("Query: "));
queryLabelPanel.setBorder(new EmptyBorder(5,5,0,0));
JPanel queryTFPanel = new JPanel();
queryTFPanel.setLayout(new GridLayout(2,1,5,5));
queryTFPanel.add(jtfEnvironment);
queryTFPanel.add(jtfQuery);
queryTFPanel.setBorder(new EmptyBorder(5,0,0,5));
queryPanel.add(queryLabelPanel, BorderLayout.WEST);
queryPanel.add(queryTFPanel, BorderLayout.CENTER);
return queryPanel;
}
protected void createMenuBar() {
JMenu fileMenu = new JMenu("File");
fileMenu.setMnemonic('f');
Action clearAction = new AbstractAction("Clear") {
public void actionPerformed(ActionEvent ae) {
xmlViewer.setText("");
}
};
fileMenu.add(clearAction);
fileMenu.add(new TestPatternAction());
fileMenu.addSeparator();
Action exitAction = new AbstractAction("Exit") {
public void actionPerformed(ActionEvent ae) {
System.exit(0);
}
};
exitAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_F4, InputEvent.ALT_MASK));
fileMenu.add(exitAction);
JMenu metaFunctionsMenu = new JMenu("Meta functions");
metaFunctionsMenu.setMnemonic('m');
metaFunctionsMenu.add(new QueryFunction("_GetVersion"));
metaFunctionsMenu.add(new QueryFunction("_GetSettings"));
metaFunctionsMenu.add(new QueryFunction("_GetStatistics"));
metaFunctionsMenu.add(new QueryFunction("_NoOp"));
metaFunctionsMenu.add(new QueryFunction("_ReloadProperties"));
metaFunctionsMenu.add(new QueryFunction("_CheckLinks"));
metaFunctionsMenu.add(new QueryFunction("_ResetStatistics"));
metaFunctionsMenu.add(new QueryFunction("_WSDL"));
metaFunctionsMenu.add(new QueryFunction("_SMD"));
metaFunctionsMenu.add(new QueryFunction("_GetFunctionList"));
metaFunctionsMenu.add(new QueryFunction("_DisableAPI"));
metaFunctionsMenu.add(new QueryFunction("_EnableAPI"));
JMenu specMenu = new JMenu("Specifications");
specMenu.setMnemonic('s');
JMenu testFormMenu = new JMenu("Test Form");
testFormMenu.setMnemonic('t');
try {
Element api = ElementFormatter.parse(getClass().getResourceAsStream("/WEB-INF/specs/api.xml"));
String apiName = api.getAttribute("name");
jlAPIName.setText(apiName + " API");
jtfEnvironment.setText("http://localhost:8080/" + apiName + "/?_convention=_xins-std");
for (Element nextFunction : new ElementList(api, "function")) {
String functionName = nextFunction.getAttribute("name");
specMenu.add(new ViewSpecAction(functionName + ".fnc"));
testFormMenu.add(new TestFormAction(functionName));
}
ElementList types = new ElementList(api, "type");
if (!types.isEmpty()) {
specMenu.addSeparator();
}
for (Element nextType : types) {
String typeName = nextType.getAttribute("name");
if (typeName.indexOf('/') != -1) {
typeName = typeName.substring(typeName.indexOf('/') + 1);
}
specMenu.add(new ViewSpecAction(typeName + ".typ"));
}
ElementList resultCodes = new ElementList(api, "resultcode");
if (!resultCodes.isEmpty()) {
specMenu.addSeparator();
}
for (Element nextResultCode : resultCodes) {
String rcdName = nextResultCode.getAttribute("name");
if (rcdName.indexOf('/') != -1) {
rcdName = rcdName.substring(rcdName.indexOf('/') + 1);
}
specMenu.add(new ViewSpecAction(rcdName + ".rcd"));
}
} catch (Exception ex) {
ex.printStackTrace();
}
JMenu helpMenu = new JMenu("Help");
helpMenu.setMnemonic('h');
Action aboutAction = new AbstractAction("About") {
public void actionPerformed(ActionEvent ae) {
Object[] aboutMessage = { "XINS", "http://www.xins.org/" };
JOptionPane optionPane = new JOptionPane();
optionPane.setMessage(aboutMessage);
optionPane.setMessageType(JOptionPane.INFORMATION_MESSAGE);
JDialog dialog = optionPane.createDialog(null, "About");
dialog.setVisible(true);
}
};
helpMenu.add(aboutAction);
specMenuBar = new JMenuBar();
specMenuBar.add(fileMenu);
specMenuBar.add(metaFunctionsMenu);
specMenuBar.add(specMenu);
specMenuBar.add(testFormMenu);
specMenuBar.add(helpMenu);
}
public JPanel getMainPanel() {
return specPanel;
}
public JMenuBar getMenuBar() {
return specMenuBar;
}
private void query(String url) {
try {
URL urlQuery = new URL(url);
xmlViewer.setIndentation(!url.endsWith("_function=_WSDL"));
xmlViewer.parse(urlQuery.openStream());
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
private void showDialog(JPanel panel, String title) {
JDialog testFormDialog = new JDialog(specFrame, title, false);
testFormDialog.getContentPane().add(panel);
testFormDialog.pack();
Dimension appDim = testFormDialog.getSize();
testFormDialog.setLocation((screenDim.width - appDim.width) / 2,(screenDim.height - appDim.height) / 2);
testFormDialog.setVisible(true);
}
class QueryMetaFunction extends AbstractAction {
QueryMetaFunction(String metaFunction) {
super(metaFunction);
}
public void actionPerformed(ActionEvent ae) {
String query = jtfEnvironment.getText() + "&_function=_" + getValue(Action.NAME);
jtfQuery.setText(query);
query(query);
}
}
class QueryFunction extends AbstractAction {
private TestFormPanel testForm;
QueryFunction(String functionName) {
super(functionName);
}
public void actionPerformed(ActionEvent ae) {
String query = jtfEnvironment.getText() + "&_function=" + getValue(Action.NAME);
if (testForm != null) {
query += testForm.getParameters();
}
jtfQuery.setText(query);
query(query);
}
void setTestForm(TestFormPanel testForm) {
this.testForm = testForm;
}
}
class ViewSpecAction extends AbstractAction {
ViewSpecAction(String specFile) {
super(specFile);
}
public void actionPerformed(ActionEvent ae) {
try {
xmlViewer.setIndentation(false);
xmlViewer.parse(getClass().getResourceAsStream("/WEB-INF/specs/" + getValue(Action.NAME)));
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
class TestFormAction extends AbstractAction {
TestFormAction(String functionName) {
super(functionName);
}
public void actionPerformed(ActionEvent ae) {
String functionName = (String) getValue(Action.NAME);
QueryFunction queryAction = new QueryFunction(functionName);
TestFormPanel testFormPanel = new TestFormPanel(specs, functionName, queryAction);
queryAction.setTestForm(testFormPanel);
showDialog(testFormPanel, specs.getName() +" API");
}
}
class TestPatternAction extends AbstractAction {
private Color tfBackground;
private Color tfInvalidColor;
private Color tfValidColor;
TestPatternAction() {
super("Test regular expression");
tfBackground = UIManager.getColor("TextField.background");
tfInvalidColor = new Color(
Math.min(tfBackground.getRed() + 30, 255),
Math.max(tfBackground.getGreen() - 15, 0),
Math.max(tfBackground.getBlue() - 20, 0));
tfValidColor = new Color(
Math.max(tfBackground.getRed() -15, 0),
Math.min(tfBackground.getGreen() + 30, 255),
Math.max(tfBackground.getBlue() - 20, 0));
}
public void actionPerformed(ActionEvent ae) {
Object[] components = new Object[4];
components[0] = "Pattern:";
final JTextField jtfPattern = new JTextField();
jtfPattern.setBackground(tfValidColor);
components[1] = jtfPattern;
components[2] = "Text to test:";
final JTextField jtfTextToTest = new JTextField();
jtfTextToTest.setBackground(tfInvalidColor);
components[3] = jtfTextToTest;
jtfPattern.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent de) {
try {
String patternText = de.getDocument().getText(0, de.getDocument().getLength());
try {
Pattern pattern = Pattern.compile(patternText);
jtfPattern.setBackground(tfValidColor);
if (pattern.matcher(jtfTextToTest.getText()).matches()) {
jtfTextToTest.setBackground(tfValidColor);
} else {
jtfTextToTest.setBackground(tfInvalidColor);
}
} catch (PatternSyntaxException psex) {
jtfPattern.setBackground(tfInvalidColor);
}
} catch (BadLocationException ble) {
ble.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void insertUpdate(DocumentEvent de) {
changedUpdate(de);
}
public void removeUpdate(DocumentEvent de) {
changedUpdate(de);
}
});
jtfTextToTest.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent de) {
try {
String patternText = jtfPattern.getText();
Pattern pattern = Pattern.compile(patternText);
if (pattern.matcher(jtfTextToTest.getText()).matches()) {
jtfTextToTest.setBackground(tfValidColor);
} else {
jtfTextToTest.setBackground(tfInvalidColor);
}
} catch (PatternSyntaxException psex) {
}
}
public void insertUpdate(DocumentEvent de) {
changedUpdate(de);
}
public void removeUpdate(DocumentEvent de) {
changedUpdate(de);
}
});
JOptionPane.showOptionDialog(specFrame, components, "Test regular expression",
JOptionPane.CLOSED_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null);
}
}
}