package org.das2.client; import java.awt.Dimension; import java.awt.Component; import java.io.IOException; import javax.swing.JPanel; import javax.swing.BoxLayout; import javax.swing.JOptionPane; import javax.swing.JCheckBox; import javax.swing.JTextArea; import javax.swing.JLabel; import javax.swing.JTextField; import javax.swing.JList; import java.util.LinkedHashMap; import java.util.ArrayList; import javax.xml.xpath.XPathFactory; import javax.xml.xpath.XPathConstants; import org.xml.sax.InputSource; import javax.xml.parsers.DocumentBuilderFactory; import java.io.StringReader; import java.util.Arrays; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.swing.JComponent; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathExpressionException; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.xml.sax.SAXException; /** * Code for editing a Das2Server parameters argument. This is a somewhat * arbitary control, but the DSDF may try to describe a GUI, using the * spec at https://github.com/das-developers/das2docs/wiki/Structured-Sub%E2%80%90values-for-Params * * * Das2ServerGUI x = new Das2ServerGUI(); * String dsdf = "param_01 = '1.5V_REF | Simulate +1.8 monitor'\n" * + "param_02 = '1.5V_WvFE'\n" * + "param_03 = '1.5V_Y180'\n" * + "param_04 = '1.8U | Power Supply'\n" * + "param_05 = '1.8V_MEM'"; * x.setSpecification(dsdf); * x.setParameters("1.5V_REF 1.5V_REF 1.8V_MEM"); * if (JOptionPane.OK_OPTION == JOptionPane.showConfirmDialog(null, x.panel)) { * System.err.println(x.getParameters()); * } * * @author jbf */ public class Das2ServerGUI { /** * Read the Das2Server container for DSDF * * @param xmlsrc * @return string array * @throws SAXException * @throws IOException * @throws ParserConfigurationException * @throws XPathExpressionException */ private String[] readXML(String xmlsrc) throws SAXException, IOException, ParserConfigurationException, XPathExpressionException { DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance(); domFactory.setNamespaceAware(true); DocumentBuilder builder = domFactory.newDocumentBuilder(); InputSource inputsrc = new InputSource(new StringReader(xmlsrc)); Document doc = builder.parse(inputsrc); XPath xp = XPathFactory.newInstance().newXPath(); Node nn = (Node) xp.evaluate("//properties", doc, XPathConstants.NODE); LinkedHashMap mm = new LinkedHashMap(); ArrayList ll = new ArrayList(100); for (int i = 0; i < 100; i++) { ll.add(i, ""); } NamedNodeMap aa = nn.getAttributes(); for (int i = 0; i < aa.getLength(); i++) { Node itm = aa.item(i); if (itm.getNodeName().startsWith("param_")) { int idx = Integer.parseInt(itm.getNodeName().substring(6)); ll.set(idx, itm.getNodeValue()); } } return (String[]) ll.toArray(new String[ll.size()]); } /** * parse integer which may start with one 0. * * @param s * @return */ private static int parseInt(String s) { s = s.trim(); if (s.startsWith("0")) { return Integer.parseInt(s.substring(1)); } else { return Integer.parseInt(s); } } /** * Read the DSDF source file */ private String[] readDsdf(String dsdfsrc) { ArrayList ll = new ArrayList(100); for (int i = 0; i < 100; i++) { ll.add(i, ""); } for (String line : dsdfsrc.split("\n")) { if (line.startsWith("param_")) { int ieq = line.indexOf("="); int idx = parseInt(line.substring(0, ieq).substring(6)); String vv = line.substring(ieq + 1).trim(); if ((vv.charAt(0) == '\'') && (vv.charAt(vv.length() - 1) == '\'')) { vv = vv.substring(1, vv.length() - 1); } ll.set(idx, vv); } } return (String[]) ll.toArray(new String[ll.size()]); } /** * if template=xxx@bb and sval=xxxJbb then return J otherwise return empty * string * * @param template * @param sval * @return */ private String checkMatch(String template, String sval) { template = template.trim(); sval = sval.trim(); if (template.indexOf("@") > -1) { int idx = template.indexOf("@"); int i = sval.length() - template.length() - idx - 1; if (template.substring(0, idx).equals(sval.substring(0, idx)) && template.substring(idx + 1).equals(sval.substring(i))) { return sval.substring(idx, (idx + sval.length() - template.length() + 1)); } else { return ""; } } else { if (template.equals(sval)) { return sval; } else { return ""; } } } private int index(String[] arr, String search) { for (int i = 0; i < arr.length; i++) { if (arr[i].equals(search)) { return i; } } return -1; } /** * return the value from paramsArr or '' (empty string). template can be a * template or a regex * * @param paramsArr * @param ss0 * @param template * @return */ private String findParamValue(String[] paramsArr, String ss0, String template) { try { if (template == null) { int idx = index(paramsArr, ss0); if (idx == -1) { return ""; } else { paramsArr[idx]= ""; return ss0; } } else { if (template.charAt(0) == '^') { String regex = template; Pattern pattern = Pattern.compile(regex); int idx=0; for (String item : paramsArr) { Matcher match = pattern.matcher(item); if (match != null) { paramsArr[idx]= ""; return item; } idx++; } return ""; } else { String[] templates = template.split("\\s+"); int i = 0; int ipa = 0; while (i < templates.length) { while ((ipa < paramsArr.length) && (i < templates.length)) { String item = paramsArr[ipa].trim(); String match = checkMatch(templates[i], item); if (match.length() == 0) { return ""; } else { if (templates[i].contains("@")) { paramsArr[ipa]=""; return match; } else { paramsArr[ipa]=""; ipa = ipa + 1; i = i + 1; } } } } return ""; } } } catch (Exception e) { e.printStackTrace(); System.out.println("param not found: " + ss0); return ""; } } private void setSelectedListItems(Component jcomponent, String[] allItems, String[] items) { // JList handling code removed... JPanel jPanel = (JPanel) jcomponent; for (Component b : jPanel.getComponents()) { JCheckBox tp = (JCheckBox) b; String item = tp.getName(); try { int idx = index(items, item); if (idx > -1) { tp.setSelected(true); } } catch (Exception e) { continue; } } } private List getSelectedListItems(Component jcomponent) { if (jcomponent instanceof JList) { return ((JList) jcomponent).getSelectedValuesList(); } else { ArrayList resultList = new ArrayList(); JPanel jList = (JPanel) jcomponent; for (Component c : jList.getComponents()) { JCheckBox b = (JCheckBox) c; if (b.isSelected()) { resultList.add(b.getText()); } } return resultList; } } private String getRegex(String t) { // "Return the regular expression for the template. The first field will be the @ symbol value"; return t.replaceAll("@", "(\\S+)"); } private String[] ll; private String[] tt; // types private String[] ff; // formats (--dftlen @) private String[] ss; // special arguments for the GUI type, like sep private JComponent[] cc; private JPanel panel; /** * set the DSDF specification for the parameters. This can be an XML document * or a list of IDL name/value pairs. * @param sss */ public void setSpecification(String sss) { if ( sss.length()<4 ) { throw new IllegalArgumentException("control string is too short"); } if ( sss.substring(0, 4).equals("[00]") ){ sss = sss.substring(10); } if ( sss.trim().startsWith("<") ) { try { ll = readXML(sss); } catch (SAXException | IOException | ParserConfigurationException | XPathExpressionException ex) { Logger.getLogger("das2").log(Level.SEVERE, null, ex); } } else { ll = readDsdf(sss); } tt = new String[101]; ff = new String[101]; ss = new String[101]; cc = new JComponent[101]; } public void setParameters(String paramz) { String delim= "\\s+"; //TODO: delim String delimRaw=" "; String[] paramsArr = paramz.split(delim); panel = new JPanel(); panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); boolean extra = false; for (int i = 0; i < 100; i++) { String itm = ll[i]; if (itm.length() > 0) { itm = itm.trim(); ss = itm.split("\\s*\\|\\s*", -2); int narg = ss.length; JComponent c2 = null; if (narg == 1) { JCheckBox c = new JCheckBox(ss[0]); String vv = findParamValue(paramsArr, ss[0], null); if (vv.length() > 0) { c.setSelected(true); } tt[i] = "JCheckBox"; panel.add(c); c2 = c; } else if (narg == 2) { JCheckBox c = new JCheckBox(ss[0] + ": " + ss[1]); String vv = findParamValue(paramsArr, ss[0], null); if (vv.length() > 0) { c.setSelected(true); } tt[i] = "JCheckBox"; panel.add(c); c2 = c; } else if (narg == 3) { panel.add(new JLabel(ss[0] + ": " + ss[1])); JTextField c = new JTextField(""); c.setMaximumSize(new Dimension(8000, c.getPreferredSize().height)); String vv = findParamValue(paramsArr, ss[0], null); ff[i] = ss[2]; vv = findParamValue(paramsArr, ss[0], ss[2]); if (vv.length() > 0) { c.setText(vv); } tt[i] = "JTextField"; panel.add(c); c2 = c; } else if (narg == 4) { if (ss[3].startsWith("set:")) { panel.add(new JLabel(ss[0] + ": " + ss[1])); String[] sepAllItems = ss[3].substring(4).trim().split("\\s+"); String[] allItems = Arrays.copyOfRange(sepAllItems, 1, sepAllItems.length); String sep = sepAllItems[0]; ss[i] = sep; JPanel panel1 = new JPanel(); panel1.setLayout(new BoxLayout(panel1, BoxLayout.X_AXIS)); for (String item : allItems) { JCheckBox b1 = new JCheckBox(item); b1.setSelected(false); panel1.add(b1); } c2 = panel1; String itemMatch = String.join("|", allItems); String regex = String.format("^(%s)(?:%s(%s))*$", itemMatch, sep, itemMatch); String vv = findParamValue(paramsArr, ss[0], regex); if (vv.length() > 0) { String[] items = vv.split(sep); setSelectedListItems(c2, allItems, items); } tt[i] = "JList"; } else { panel.add(new JLabel(ss[0] + ": " + ss[1] + " (" + ss[3] + ")")); JTextField c = new JTextField(""); c2 = c; c.setMaximumSize(new Dimension(8000, c.getPreferredSize().height)); String vv = findParamValue(paramsArr, ss[0], null); ff[i] = ss[2]; vv = findParamValue(paramsArr, ss[0], ss[2]); if (vv.length() > 0) { c.setText(vv); } tt[i] = "JTextField"; } panel.add(c2); } else { extra = true; } if (c2 != null) { panel.add(c2); cc[i] = c2; c2.setAlignmentX(Component.LEFT_ALIGNMENT); } } } StringBuilder extraArgs= new StringBuilder(); for ( int i=0; i0 ) { extraArgs.append(paramsArr[i]); } if ( i>0 ) extraArgs.append(delimRaw); } if ( extra || extraArgs.length()>0 ) { panel.add(new JLabel("Text not described in DSDF")); JTextArea c = new JTextArea(); c.setAlignmentX(Component.LEFT_ALIGNMENT); c.setText(extraArgs.toString()); c.setRows(4); panel.add(c); cc[100] = c; } } public String getParameters() { String delim = " "; StringBuilder parametersBuilder = new StringBuilder(); for (int i = 0; i < 100; i++) { if (cc[i] == null) { } else if (tt[i].equals("JCheckBox")) { if (((JCheckBox) cc[i]).isSelected()) { String txt = ((JCheckBox) cc[i]).getText(); int i2 = txt.indexOf(": "); if (i2 > -1) { txt = txt.substring(0, i2); } parametersBuilder.append(txt); parametersBuilder.append(delim); } } else if (tt[i].equals("JTextField")) { String s = ((JTextField) cc[i]).getText(); if (s.length() > 0) { s = ff[i].replace("@", s); parametersBuilder.append(s); parametersBuilder.append(delim); } } else if (tt[i].equals("JList")) { List selectedItems = getSelectedListItems(cc[i]); String sep = ss[i]; parametersBuilder.append(String.join(sep, selectedItems)); parametersBuilder.append(delim); } } if (cc[100] != null) { parametersBuilder.append(delim); String txt = ((JTextArea) cc[100]).getText().replace("\n", delim); txt = txt.trim(); parametersBuilder.append(txt); } return parametersBuilder.toString(); } /** * return the panel. See the javadoc for how this is to be called. * Note this will typically need to be put into a scrollpane. * @return */ public JPanel getPanel() { return panel; } public static void main(String[] args) { Das2ServerGUI x = new Das2ServerGUI(); int test=2; String dsdf; String params0; switch ( test ) { case 1: dsdf = "param_01 = '1.5V_REF | Simulate +1.8 monitor'\n" + "param_02 = '1.5V_WvFE'\n" + "param_03 = '1.5V_Y180'\n" + "param_04 = '1.8U | Power Supply'\n" + "param_05 = '1.8V_MEM'"; params0="1.5V_REF 1.8V_MEM Extra-Unrecognized"; break; case 2: dsdf = "param_01 = 'packet_ids|Output data from the following packet IDs (defaults to all)|@|set: , x242 x252'\n"; params0=""; break; default: throw new IllegalArgumentException("bad test number"); } x.setSpecification(dsdf); x.setParameters(params0); if (JOptionPane.OK_OPTION == JOptionPane.showConfirmDialog(null, x.panel, "Edit params", JOptionPane.OK_CANCEL_OPTION )) { System.err.println(x.getParameters()); } } }