From e0c47d1469eb56e39d14a0dbcc2cb64afeb8edd3 Mon Sep 17 00:00:00 2001 From: boccioli_m Date: Thu, 27 Aug 2015 15:32:20 +0200 Subject: [PATCH] Startup --- plugins/FilterTable.java | 74 +++ plugins/NewTest - Copy.java | 336 ++++++++++++++ plugins/NewTest.form | 240 ++++++++++ plugins/NewTest.java | 607 +++++++++++++++++++++++++ plugins/TestingListDetails - Copy.java | 465 +++++++++++++++++++ plugins/icons/settings-128px.png | Bin 0 -> 26029 bytes plugins/icons/settings-32px.png | Bin 0 -> 791 bytes plugins/icons/settings2-128px.png | Bin 0 -> 21464 bytes 8 files changed, 1722 insertions(+) create mode 100644 plugins/FilterTable.java create mode 100644 plugins/NewTest - Copy.java create mode 100644 plugins/NewTest.form create mode 100644 plugins/NewTest.java create mode 100644 plugins/TestingListDetails - Copy.java create mode 100644 plugins/icons/settings-128px.png create mode 100644 plugins/icons/settings-32px.png create mode 100644 plugins/icons/settings2-128px.png diff --git a/plugins/FilterTable.java b/plugins/FilterTable.java new file mode 100644 index 0000000..1f5b9e2 --- /dev/null +++ b/plugins/FilterTable.java @@ -0,0 +1,74 @@ +import javax.swing.*; + import javax.swing.table.*; + import java.awt.*; + import java.awt.event.*; + import java.util.regex.*; + + public class FilterTable { + public static void main(String args[]) { + Runnable runner = new Runnable() { + public void run() { + JFrame frame = new JFrame("Sorting JTable"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + Object rows[][] = { + {"AMZN", "Amazon", 41.28}, + {"EBAY", "eBay", 41.57}, + {"GOOG", "Google", 388.33}, + {"MSFT", "Microsoft", 26.56}, + {"NOK", "Nokia Corp", 17.13}, + {"ORCL", "Oracle Corp.", 12.52}, + {"SUNW", "Sun Microsystems", 3.86}, + {"TWX", "Time Warner", 17.66}, + {"VOD", "Vodafone Group", 26.02}, + {"YHOO", "Yahoo!", 37.69} + }; + Object columns[] = {"Symbol", "Name", "Price"}; + TableModel model = + new DefaultTableModel(rows, columns) { + public Class getColumnClass(int column) { + Class returnValue; + if ((column >= 0) && (column < getColumnCount())) { + returnValue = getValueAt(0, column).getClass(); + } else { + returnValue = Object.class; + } + return returnValue; + } + }; + JTable table = new JTable(model); + final TableRowSorter sorter = + new TableRowSorter(model); + table.setRowSorter(sorter); + JScrollPane pane = new JScrollPane(table); + frame.add(pane, BorderLayout.CENTER); + JPanel panel = new JPanel(new BorderLayout()); + JLabel label = new JLabel("Filter"); + panel.add(label, BorderLayout.WEST); + final JTextField filterText = + new JTextField("SUN"); + panel.add(filterText, BorderLayout.CENTER); + frame.add(panel, BorderLayout.NORTH); + JButton button = new JButton("Filter"); + button.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + String text = filterText.getText(); + if (text.length() == 0) { + sorter.setRowFilter(null); + } else { + try { + sorter.setRowFilter( + RowFilter.regexFilter(text)); + } catch (PatternSyntaxException pse) { + System.err.println("Bad regex pattern"); + } + } + } + }); + frame.add(button, BorderLayout.SOUTH); + frame.setSize(300, 250); + frame.setVisible(true); + } + }; + EventQueue.invokeLater(runner); + } + } \ No newline at end of file diff --git a/plugins/NewTest - Copy.java b/plugins/NewTest - Copy.java new file mode 100644 index 0000000..32ccab0 --- /dev/null +++ b/plugins/NewTest - Copy.java @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2015 Paul Scherrer Institute. All rights reserved. + */ + +import ch.psi.utils.swing.SwingUtils; +import java.awt.Desktop; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Properties; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.ImageIcon; +import javax.swing.JDialog; +import javax.swing.JPanel; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; +import javax.swing.table.DefaultTableModel; +import org.apache.commons.io.FilenameUtils; + +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/** + * + * @author boccioli_m + */ +public class NewTest extends javax.swing.JPanel { + + /** + * Creates new form TestingListDetails + */ + public NewTest() { + initComponents(); + } + + public NewTest(String hDetails) { + initComponents(); + + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jLabel4 = new javax.swing.JLabel(); + txtTestSuite = new javax.swing.JTextField(); + jLabel5 = new javax.swing.JLabel(); + txtTestName = new javax.swing.JTextField(); + jScrollPane1 = new javax.swing.JScrollPane(); + jTableParams = new javax.swing.JTable(); + jLabel7 = new javax.swing.JLabel(); + cmCancel = new javax.swing.JButton(); + cmOk = new javax.swing.JButton(); + jLabel8 = new javax.swing.JLabel(); + jScrollPane3 = new javax.swing.JScrollPane(); + txtTestDescription = new javax.swing.JTextArea(); + jScrollPane4 = new javax.swing.JScrollPane(); + jEditorPaneHelp = new javax.swing.JEditorPane(); + + jLabel4.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + jLabel4.setText("Test Case/Suite"); + + txtTestSuite.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + + jLabel5.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + jLabel5.setText("Test Name"); + + txtTestName.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + + jTableParams.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + jTableParams.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + "Parameter", "Value", "Description" + } + ) { + boolean[] canEdit = new boolean [] { + false, true, false + }; + + public boolean isCellEditable(int rowIndex, int columnIndex) { + return canEdit [columnIndex]; + } + }); + jTableParams.setDragEnabled(true); + jTableParams.setRowHeight(20); + jScrollPane1.setViewportView(jTableParams); + if (jTableParams.getColumnModel().getColumnCount() > 0) { + jTableParams.getColumnModel().getColumn(0).setMinWidth(150); + jTableParams.getColumnModel().getColumn(0).setPreferredWidth(150); + jTableParams.getColumnModel().getColumn(0).setMaxWidth(150); + jTableParams.getColumnModel().getColumn(1).setPreferredWidth(80); + jTableParams.getColumnModel().getColumn(1).setMaxWidth(100); + } + + jLabel7.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + jLabel7.setText("Test Parameters"); + + cmCancel.setText("Cancel"); + this.cmCancel.setVisible(false); + this.cmOk.setVisible(false); + cmCancel.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + cmCancelActionPerformed(evt); + } + }); + + cmOk.setText("Ok"); + this.cmCancel.setVisible(false); + this.cmOk.setVisible(false); + + jLabel8.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + jLabel8.setText("Test Description"); + + jScrollPane3.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + + txtTestDescription.setColumns(20); + txtTestDescription.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + txtTestDescription.setLineWrap(true); + txtTestDescription.setRows(5); + jScrollPane3.setViewportView(txtTestDescription); + + jEditorPaneHelp.setContentType("text/html"); // NOI18N + jEditorPaneHelp.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + jEditorPaneHelp.setDropMode(javax.swing.DropMode.INSERT); + jScrollPane4.setViewportView(jEditorPaneHelp); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel4) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(txtTestSuite, javax.swing.GroupLayout.PREFERRED_SIZE, 513, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel5) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(txtTestName, javax.swing.GroupLayout.PREFERRED_SIZE, 513, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel7) + .addComponent(jLabel8)) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addGroup(layout.createSequentialGroup() + .addGap(331, 331, 331) + .addComponent(cmOk, javax.swing.GroupLayout.PREFERRED_SIZE, 96, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cmCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 98, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 513, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addGap(18, 18, 18) + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 513, javax.swing.GroupLayout.PREFERRED_SIZE))))) + .addGap(18, 18, 18) + .addComponent(jScrollPane4, javax.swing.GroupLayout.DEFAULT_SIZE, 317, Short.MAX_VALUE) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel5) + .addComponent(txtTestName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(18, 18, 18) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel4) + .addComponent(txtTestSuite, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(18, 18, 18) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 81, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel8)) + .addGap(18, 18, 18) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 359, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel7) + .addGap(0, 0, Short.MAX_VALUE))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(cmCancel) + .addComponent(cmOk))) + .addGroup(layout.createSequentialGroup() + .addComponent(jScrollPane4) + .addContainerGap()))) + ); + }// //GEN-END:initComponents + + + public static Path TESTS_DEVICES_DEFAULT_DIR = Paths.get(".", "home", "script", "tests", "devices"); + public static Path TESTS_TESTS_DEFAULT_DIR = Paths.get(".", "home", "script", "tests", "tests"); + public static Path TESTS_CONFIG_DEFAULT_DIR = Paths.get(".", "home", "script", "tests", "config"); + public static String TESTS_CONFIG_FILENAME = ".config"; + public static String TESTS_HELP_FILENAME = "help.html"; + public static Path TEMPLATES_HELP_FILEPATH = Paths.get(".", "home", "script", "tests","templates","helpTemplate.html"); + public static Path TEMPLATES_TEST_FILEPATH = Paths.get(".", "home", "script", "tests","templates","testTemplate.html"); + public static Path TEMPLATES_CONFIG_FILEPATH = Paths.get(".", "home", "script", "tests","templates","configTemplate.html"); + + private void fillComponents(HashMap hDetails) { + + } + + + public void generateTestFiles(){ + HashMap hmTestParams = new HashMap(); + generateTestFiles(this.txtTestName.getText(), + this.txtTestDescription.getText(), + this.txtTestSuite.getText(), + hmTestParams); + } + + public void generateTestFiles(String sTestName, + String sTestDescription, + String sTestSuite, + HashMap hmTestParams){ + if (!TESTS_TESTS_DEFAULT_DIR.toFile().isDirectory()) { + //check that the tests suite dir exists. If not, create it + Path testSuiteDir = Paths.get(TESTS_TESTS_DEFAULT_DIR.toString(),sTestSuite); + if( !testSuiteDir.toFile().isDirectory()){ + boolean success = testSuiteDir.toFile().mkdirs(); + if (!success) { + // Directory creation failed + SwingUtils.showMessage(this, "saveSettings()", "Cannot create directory " + testSuiteDir.toString()); + }else{ + //new test directory inside tests suite dir + Path testDir = Paths.get(testSuiteDir.toString(),sTestName); + success = testDir.toFile().mkdirs(); + if (!success) { + // Directory creation failed + SwingUtils.showMessage(this, "saveSettings()", "Cannot create directory " + testDir.toString()); + } else{ + //generate test files inside test dir + generateTestConfig(testDir, + sTestName, + sTestDescription, + sTestSuite, + hmTestParams); + } + } + } + } + } + + public void generateTestScript(String sTestName, + String sTestDescription, + String sTestSuite, + HashMap hmTestParams){ + + } + + public void generateTestConfig(Path testDir, + String sTestName, + String sTestDescription, + String sTestSuite, + HashMap hmTestParams){ + //generate test config file from template + try { + Path path = Paths.get(testDir + FilenameUtils.separatorsToSystem("/"+TESTS_CONFIG_FILENAME)); + Files.copy(TEMPLATES_CONFIG_FILEPATH, path); + File configFile = path.toFile(); + Properties properties = new Properties(); + properties.setProperty("name", sTestName); + properties.setProperty("description", sTestDescription); + OutputStream is = new FileOutputStream(configFile); + properties.store(is, "Test config"); + is.close(); + } catch (FileNotFoundException ex) { + Logger.getLogger(NewTest.class.getName()).log(Level.SEVERE, null, ex); + } catch (IOException ex) { + Logger.getLogger(NewTest.class.getName()).log(Level.SEVERE, null, ex); + } + + } + + public void generateTestHelp(Path testDir, + String sTestName, + String sTestDescription, + String sTestSuite, + HashMap hmTestParams){ + //generate test config file from template + Path path = Paths.get(testDir + FilenameUtils.separatorsToSystem("/"+TESTS_HELP_FILENAME)); + try { + Files.copy(TEMPLATES_HELP_FILEPATH, path); + File configFile = path.toFile(); + } catch (IOException ex) { + Logger.getLogger(NewTest.class.getName()).log(Level.SEVERE, null, ex); + } + } + + + private void cmCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cmCancelActionPerformed + + }//GEN-LAST:event_cmCancelActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton cmCancel; + private javax.swing.JButton cmOk; + private javax.swing.JEditorPane jEditorPaneHelp; + private javax.swing.JLabel jLabel4; + private javax.swing.JLabel jLabel5; + private javax.swing.JLabel jLabel7; + private javax.swing.JLabel jLabel8; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JScrollPane jScrollPane3; + private javax.swing.JScrollPane jScrollPane4; + private javax.swing.JTable jTableParams; + private javax.swing.JTextArea txtTestDescription; + private javax.swing.JTextField txtTestName; + private javax.swing.JTextField txtTestSuite; + // End of variables declaration//GEN-END:variables +} diff --git a/plugins/NewTest.form b/plugins/NewTest.form new file mode 100644 index 0000000..8ecd9da --- /dev/null +++ b/plugins/NewTest.form @@ -0,0 +1,240 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="100" minWidth="-1" prefWidth="80" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + </TableColumnModel> + </Property> + <Property name="dragEnabled" type="boolean" value="true"/> + <Property name="rowHeight" type="int" value="20"/> + <Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor"> + <TableHeader reorderingAllowed="true" resizingAllowed="true"/> + </Property> + </Properties> + <Events> + <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="jTableParamsMouseClicked"/> + </Events> + </Component> + </SubComponents> + </Container> + <Component class="javax.swing.JLabel" name="jLabel7"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="Tahoma" size="14" style="0"/> + </Property> + <Property name="text" type="java.lang.String" value="Test Parameters"/> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="jLabel8"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="Tahoma" size="14" style="0"/> + </Property> + <Property name="text" type="java.lang.String" value="Test Description *"/> + </Properties> + </Component> + <Container class="javax.swing.JScrollPane" name="jScrollPane3"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="Tahoma" size="14" style="0"/> + </Property> + </Properties> + <AuxValues> + <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/> + </AuxValues> + + <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> + <SubComponents> + <Component class="javax.swing.JTextArea" name="txtTestDescription"> + <Properties> + <Property name="columns" type="int" value="20"/> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="Tahoma" size="14" style="0"/> + </Property> + <Property name="lineWrap" type="boolean" value="true"/> + <Property name="rows" type="int" value="5"/> + </Properties> + </Component> + </SubComponents> + </Container> + <Component class="javax.swing.JButton" name="jButtonGenerate"> + <Properties> + <Property name="text" type="java.lang.String" value="Generate"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButtonGenerateActionPerformed"/> + </Events> + </Component> + </SubComponents> +</Form> diff --git a/plugins/NewTest.java b/plugins/NewTest.java new file mode 100644 index 0000000..2dea7bc --- /dev/null +++ b/plugins/NewTest.java @@ -0,0 +1,607 @@ +/* + * Copyright (c) 2015 Paul Scherrer Institute. All rights reserved. + */ + +import ch.psi.utils.swing.SwingUtils; +import ch.psi.utils.swing.SwingUtils.OptionResult; +import ch.psi.utils.swing.SwingUtils.OptionType; +import java.awt.Desktop; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Properties; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.ImageIcon; +import javax.swing.JDialog; +import javax.swing.JPanel; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; +import javax.swing.table.DefaultTableModel; +import org.apache.commons.io.FilenameUtils; + +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/** + * + * @author boccioli_m + */ +public class NewTest extends javax.swing.JPanel { + + /** + * Creates new form TestingListDetails + */ + public NewTest() { + initComponents(); + } + + public NewTest(String hDetails) { + initComponents(); + fillComponents(); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents + private void initComponents() { + + jPopupMenuTable = new javax.swing.JPopupMenu(); + jMenuItemAddRow = new javax.swing.JMenuItem(); + jMenuItemReleteRow = new javax.swing.JMenuItem(); + jLabel4 = new javax.swing.JLabel(); + txtTestSuite = new javax.swing.JTextField(); + jLabel5 = new javax.swing.JLabel(); + txtTestName = new javax.swing.JTextField(); + jScrollPane1 = new javax.swing.JScrollPane(); + jTableParams = new javax.swing.JTable(); + jLabel7 = new javax.swing.JLabel(); + jLabel8 = new javax.swing.JLabel(); + jScrollPane3 = new javax.swing.JScrollPane(); + txtTestDescription = new javax.swing.JTextArea(); + jButtonGenerate = new javax.swing.JButton(); + + jMenuItemAddRow.setText("Add Row"); + jMenuItemAddRow.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jMenuItemAddRowActionPerformed(evt); + } + }); + jPopupMenuTable.add(jMenuItemAddRow); + + jMenuItemReleteRow.setText("Delete Row"); + jMenuItemReleteRow.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jMenuItemReleteRowActionPerformed(evt); + } + }); + jPopupMenuTable.add(jMenuItemReleteRow); + + jLabel4.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + jLabel4.setText("Test Case/Suite *"); + + txtTestSuite.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + + jLabel5.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + jLabel5.setText("Test Name *"); + + txtTestName.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + + jTableParams.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + jTableParams.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + "Parameter", "Value", "Description" + } + )); + jTableParams.setDragEnabled(true); + jTableParams.setRowHeight(20); + jTableParams.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + jTableParamsMouseClicked(evt); + } + }); + jScrollPane1.setViewportView(jTableParams); + if (jTableParams.getColumnModel().getColumnCount() > 0) { + jTableParams.getColumnModel().getColumn(0).setMinWidth(150); + jTableParams.getColumnModel().getColumn(0).setPreferredWidth(150); + jTableParams.getColumnModel().getColumn(0).setMaxWidth(150); + jTableParams.getColumnModel().getColumn(1).setPreferredWidth(80); + jTableParams.getColumnModel().getColumn(1).setMaxWidth(100); + } + + jLabel7.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + jLabel7.setText("Test Parameters"); + + jLabel8.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + jLabel8.setText("Test Description *"); + + jScrollPane3.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + + txtTestDescription.setColumns(20); + txtTestDescription.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + txtTestDescription.setLineWrap(true); + txtTestDescription.setRows(5); + jScrollPane3.setViewportView(txtTestDescription); + + jButtonGenerate.setText("Generate"); + jButtonGenerate.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButtonGenerateActionPerformed(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel4) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(txtTestSuite, javax.swing.GroupLayout.PREFERRED_SIZE, 513, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel5) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(txtTestName, javax.swing.GroupLayout.PREFERRED_SIZE, 513, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel7) + .addComponent(jLabel8)) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGap(19, 19, 19) + .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 513, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addGap(18, 18, 18) + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 513, javax.swing.GroupLayout.PREFERRED_SIZE)))) + .addComponent(jButtonGenerate, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 188, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel5) + .addComponent(txtTestName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(18, 18, 18) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel4) + .addComponent(txtTestSuite, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(18, 18, 18) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 81, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel8)) + .addGap(18, 18, 18) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel7) + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 180, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jButtonGenerate, javax.swing.GroupLayout.PREFERRED_SIZE, 33, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + ); + }// </editor-fold>//GEN-END:initComponents + + private void jButtonGenerateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonGenerateActionPerformed + // TODO add your handling code here: + if(checkDataFields()) + { + generateTestFiles(); + } + }//GEN-LAST:event_jButtonGenerateActionPerformed + + private void jTableParamsMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jTableParamsMouseClicked + // TODO add your handling code here: + if(evt.getButton() == java.awt.event.MouseEvent.BUTTON3){ + jPopupMenuTable.show(jTableParams, evt.getX(), evt.getY()); + } + }//GEN-LAST:event_jTableParamsMouseClicked + + private void jMenuItemAddRowActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemAddRowActionPerformed + // TODO add your handling code here: + DefaultTableModel model = (DefaultTableModel) jTableParams.getModel(); + model.addRow(new Object[]{"", "", ""}); + jTableParams.setModel(model); + }//GEN-LAST:event_jMenuItemAddRowActionPerformed + + private void jMenuItemReleteRowActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemReleteRowActionPerformed + // TODO add your handling code here: + int row = jTableParams.getSelectedRow(); + if(row>=0 && row<jTableParams.getRowCount()){ + DefaultTableModel model = (DefaultTableModel) jTableParams.getModel(); + model.removeRow(row); + } + }//GEN-LAST:event_jMenuItemReleteRowActionPerformed + + + public static Path TESTS_DEVICES_DEFAULT_DIR = Paths.get(".", "home", "script", "tests", "devices"); + public static Path TESTS_TESTS_DEFAULT_DIR = Paths.get(".", "home", "script", "tests", "tests"); + public static Path TESTS_CONFIG_DEFAULT_DIR = Paths.get(".", "home", "script", "tests", "config"); + public static String TESTS_CONFIG_FILENAME = ".config"; + public static String TESTS_HELP_FILENAME = "help.html"; + public static Path TEMPLATES_HELP_FILEPATH = Paths.get(".", "home", "script", "tests","templates","helpTemplate.html"); + public static Path TEMPLATES_TESTSCRIPT_FILEPATH = Paths.get(".", "home", "script", "tests","templates","testTemplate.py"); + public static Path TEMPLATES_CONFIG_FILEPATH = Paths.get(".", "home", "script", "tests","templates","template.config"); + public static String ALLOWED_CHARS = "[a-zA-Z0-9._\\-\\]\\[(){} ]*"; + + /** + * fill table with example parameters + */ + private void fillComponents() { + InputStream ist = null; + try { + Properties propTest = new Properties(); + File configFile = TEMPLATES_CONFIG_FILEPATH.toFile(); + ist = new FileInputStream(configFile); + propTest.load(ist); + String testParams = propTest.getProperty("parameters"); + if (testParams == null) { + testParams = ""; + } + ist.close(); + HashMap hParams = (HashMap) buildParametersMap(testParams); + String name="", value="", description=""; + DefaultTableModel model = (DefaultTableModel) jTableParams.getModel(); + for(Object entry : hParams.keySet()){ + Object param = entry; + if(param instanceof String){ + name = (String) param; + HashMap attributes = (HashMap) hParams.get(param); + value = (String) attributes.get("value"); + description = (String) attributes.get("description"); + model.addRow(new Object[]{name, value, description}); + } + jTableParams.setModel(model); + } + } catch (FileNotFoundException ex) { + SwingUtils.showMessage(this, "fillComponents()", "Cannot find file " + TEMPLATES_CONFIG_FILEPATH.toString()); + Logger.getLogger(NewTest.class.getName()).log(Level.SEVERE, null, ex); + } catch (IOException ex) { + SwingUtils.showMessage(this, "fillComponents()", "Cannot read file " + TEMPLATES_CONFIG_FILEPATH.toString()); + Logger.getLogger(NewTest.class.getName()).log(Level.SEVERE, null, ex); + } finally { + try { + ist.close(); + } catch (IOException ex) { + SwingUtils.showMessage(this, "fillComponents()", "Cannot close file " + TEMPLATES_CONFIG_FILEPATH.toString()); + Logger.getLogger(NewTest.class.getName()).log(Level.SEVERE, null, ex); + } + } + + } + + /** + * Build a map with optional parameters to be passed to the testing script. + * The map is like this: parameters \_ name | \_ value | \_ description \_ + * name | \_ value | \_ description ... the name 'name' is the mapping key. + * 'value' and 'description' are constant mapping keys of a nested map. + * + * @param parametersString string containing the parameters. Syntax: + * name:value:description[;name:value:description;...] + */ + private HashMap buildParametersMap(String parametersString) { + HashMap mParameters = new HashMap(); // contains name and attributes + HashMap mParameterAttributes = new HashMap(); //contians value and description + String[] dsParameterAttributes = null; + String[] dsParameters = parametersString.split(";"); + for (String sParameter : dsParameters) { + dsParameterAttributes = sParameter.split(":"); + if (dsParameterAttributes.length > 2) { + mParameterAttributes = new HashMap(); + mParameterAttributes.put("value", (Object) dsParameterAttributes[1]); + mParameterAttributes.put("description", dsParameterAttributes[2]); + //add parameter name and attributes (value + description) + mParameters.put(dsParameterAttributes[0], mParameterAttributes); + } + } + return mParameters; + } + + private HashMap getParametersFromTable(){ + HashMap mParameters = new HashMap(); // contains name and attributes + HashMap mParameterAttributes = new HashMap(); //contians value and description + for(int row=0 ; row<jTableParams.getRowCount() ; row++){ + String sParam = jTableParams.getValueAt(row, 0).toString(); + String sVal = jTableParams.getValueAt(row, 1).toString(); + String sDescr = jTableParams.getValueAt(row, 2).toString(); + mParameterAttributes = new HashMap(); + mParameterAttributes.put("value", (Object) sVal); + mParameterAttributes.put("description", sDescr); + //add parameter name and attributes (value + description) + mParameters.put(sParam, mParameterAttributes); + } + return mParameters; + } + + public boolean checkDataFields(){ + //check compulsory data fields + if(this.txtTestName.getText().isEmpty() || + this.txtTestDescription.getText().isEmpty() || + this.txtTestSuite.getText().isEmpty()){ + SwingUtils.showMessage(this, "checkDataFields()", + "Please fill-in all compulsory fields (marked with *)"); + return false; + } + if(!(txtTestName.getText().matches(ALLOWED_CHARS) && + txtTestDescription.getText().matches(ALLOWED_CHARS) && + txtTestSuite.getText().matches(ALLOWED_CHARS) + )){ + SwingUtils.showMessage(this, "checkDataFields()", + "Please remove forbidden chars: only letters, numbers, parenthesis are allowed"); + return false; + } + //check parameters table + for(int row=0 ; row<jTableParams.getRowCount() ; row++){ + String sParam = jTableParams.getValueAt(row, 0).toString(); + String sVal = jTableParams.getValueAt(row, 1).toString(); + String sDescr = jTableParams.getValueAt(row, 2).toString(); + if(sParam.isEmpty() || sVal.isEmpty() || sDescr.isEmpty()){ + SwingUtils.showMessage(this, "checkDataFields()", "You must fill-in all the values in the parameters table"); + return false; + } + if(!(sParam.matches(ALLOWED_CHARS) && + sVal.matches(ALLOWED_CHARS) && + sDescr.matches(ALLOWED_CHARS)) + ){ + SwingUtils.showMessage(this, "checkDataFields()", + "Please remove forbidden chars from parameters table: only letters, numbers, parenthesis are allowed"); + return false; + } + } + return true; + } + + + public void generateTestFiles(){ + HashMap hmTestParams = (HashMap) getParametersFromTable(); + generateTestFiles(this.txtTestName.getText(), + this.txtTestDescription.getText(), + this.txtTestSuite.getText(), + hmTestParams); + } + + public void generateTestFiles(String sTestName, + String sTestDescription, + String sTestSuite, + HashMap hmTestParams){ + if (TESTS_TESTS_DEFAULT_DIR.toFile().isDirectory()) { + //check that the tests suite dir exists. If not, create it + Path testSuiteDir = Paths.get(TESTS_TESTS_DEFAULT_DIR.toString(),sTestSuite); + if( !testSuiteDir.toFile().isDirectory()){ + boolean success = testSuiteDir.toFile().mkdirs(); + if (!success) { + // Directory creation failed + SwingUtils.showMessage(this, "generateTestFiles()", "Cannot create directory " + testSuiteDir.toString()); + return; + } + } + //new test directory inside tests suite dir + Path testDir = Paths.get(testSuiteDir.toString(),sTestName); + if( testDir.toFile().isDirectory()){ + //test already exists: ask to overwrite + OptionResult res = SwingUtils.showOption(this, "Overwrite Test?", "Test already exists. Overwrite with this new one?", OptionType.YesNo); + if (res == OptionResult.No){ + return; + } + }else{ + boolean success = testDir.toFile().mkdirs(); + if (!success) { + // Directory creation failed + SwingUtils.showMessage(this, "generateTestFiles()", "Cannot create directory " + testDir.toString()); + return; + } + } + //generate test files inside test dir + + if (!generateTestConfig(testDir, + sTestName, + sTestDescription, + sTestSuite, + hmTestParams)) return; + if (!generateTestHelp(testDir, + sTestName, + sTestDescription, + sTestSuite, + hmTestParams)) return; + if (!generateTestScript(testDir, + sTestName, + sTestDescription, + sTestSuite, + hmTestParams)) return; + SwingUtils.showMessage(this, "Test generated", "Test "+sTestName+" successfully generated in \n"+testDir.toString()); + + }else{ + SwingUtils.showMessage(this, "generateTestFiles()", "Cannot find tests default directory " + TESTS_TESTS_DEFAULT_DIR.toString()); + } + } + + public boolean generateTestScript(Path testDir, + String sTestName, + String sTestDescription, + String sTestSuite, + HashMap hmTestParams){ + boolean success = false; + Path path = Paths.get(testDir + FilenameUtils.separatorsToSystem("/"+sTestName+".py")); + try { + if(Files.exists(path)){ + Files.delete(path); + } + Files.copy(TEMPLATES_TESTSCRIPT_FILEPATH, path); + //add test parameters + String name="", value="", description=""; + DefaultTableModel model = (DefaultTableModel) jTableParams.getModel(); + String sSyntaxGetTestParameters = ""; + for(Object entry : hmTestParams.keySet()){ + Object param = entry; + if(param instanceof String){ + name = (String) param; + HashMap attributes = (HashMap) hmTestParams.get(param); + value = (String) attributes.get("value"); + description = (String) attributes.get("description"); + //build the python code for getting the test parameter + sSyntaxGetTestParameters = sSyntaxGetTestParameters + name + " = float(params[\""+name+"\"][\"value\"]) ; "; + } + } + replaceParameters(path, + new String[]{"$testName","$testDescription","#$testParameters"}, + new String[]{sTestName,sTestDescription,sSyntaxGetTestParameters}); + success = true; + } catch (IOException ex) { + SwingUtils.showMessage(this, "generateTestScript()", "Cannot copy file " + ex.toString()); + Logger.getLogger(NewTest.class.getName()).log(Level.SEVERE, null, ex); + } + return success; + } + + public boolean generateTestConfig(Path testDir, + String sTestName, + String sTestDescription, + String sTestSuite, + HashMap hmTestParams){ + //generate test config file from template + boolean success = false; + try { + Path path = Paths.get(testDir + FilenameUtils.separatorsToSystem("/"+TESTS_CONFIG_FILENAME)); + if(Files.exists(path)){ + Files.delete(path); + } + Files.copy(TEMPLATES_CONFIG_FILEPATH, path); + File configFile = path.toFile(); + //Loop among the test parameters and generate variable assignement syntax for python + String sTestParameters = ""; + String name="", value="", description=""; + for(Object entry : hmTestParams.keySet()){ + Object param = entry; + if(param instanceof String){ + name = (String) param; + HashMap attributes = (HashMap) hmTestParams.get(param); + value = (String) attributes.get("value"); + description = (String) attributes.get("description"); + //build the python code for getting the test parameter + sTestParameters = sTestParameters + name + ":" + value + ":" + description + ";" ; + } + } + String content = "#Test configuration\n"; + content +=("\nname=" + sTestName); + content +=("\ndescription=" + sTestDescription); + content +=("\nparameters=" + sTestParameters); + OutputStream is = new FileOutputStream(configFile); + Charset charset = StandardCharsets.UTF_8; + Files.write(path, content.getBytes(charset)); + is.write(content.getBytes()); + is.close(); + success = true; + } catch (FileNotFoundException ex) { + SwingUtils.showMessage(this, "generateTestConfig()", "Cannot find file: " + ex.toString()); + Logger.getLogger(NewTest.class.getName()).log(Level.SEVERE, null, ex); + } catch (IOException ex) { + SwingUtils.showMessage(this, "generateTestConfig()", "Problem with file aaccess: " + ex.toString()); + Logger.getLogger(NewTest.class.getName()).log(Level.SEVERE, null, ex); + } + return success; + } + + public boolean generateTestHelp(Path testDir, + String sTestName, + String sTestDescription, + String sTestSuite, + HashMap hmTestParams){ + //generate test config file from template + Path path = Paths.get(testDir + FilenameUtils.separatorsToSystem("/"+TESTS_HELP_FILENAME)); + boolean success = false; + try { + if(Files.exists(path)){ + Files.delete(path); + } + Files.copy(TEMPLATES_HELP_FILEPATH, path); + //Loop among the test parameters and generate parameter help + String sTestParameters = ""; + String name="", value="", description=""; + for(Object entry : hmTestParams.keySet()){ + Object param = entry; + if(param instanceof String){ + name = (String) param; + HashMap attributes = (HashMap) hmTestParams.get(param); + value = (String) attributes.get("value"); + description = (String) attributes.get("description"); + //build the python code for getting the test parameter + sTestParameters = sTestParameters + "<code>" + name + " </code>" + description + "<br/>\n" ; + } + } + success = replaceParameters(path, + new String[]{"$testName","$testDescription","$testParameters"}, + new String[]{sTestName,sTestDescription,sTestParameters}); + + } catch (IOException ex) { + SwingUtils.showMessage(this, "generateTestHelp()", "Cannot create directory " + ex.toString()); + Logger.getLogger(NewTest.class.getName()).log(Level.SEVERE, null, ex); + } + return success; + } + + + public boolean replaceParameters(Path path, + String parameterNames[], + String parameterValues[]){ + boolean success = false; + try { + //replace parameters in template + String content = new String(Files.readAllBytes(path)); + for(int i=0 ; i<parameterNames.length ; i++ ){ + content = content.replace(parameterNames[i], parameterValues[i]); + } + //System.out.print(content); + Charset charset = StandardCharsets.UTF_8; + Files.write(path, content.getBytes(charset)); + OutputStream is = new FileOutputStream(path.toFile()); + is.write(content.getBytes()); + is.close(); + success = true; + } catch (IOException ex) { + SwingUtils.showMessage(this, "replaceParameters()", "Cannot access file " + path + ". "+ ex.toString()); + Logger.getLogger(NewTest.class.getName()).log(Level.SEVERE, null, ex); + } + return success; + } + + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton jButtonGenerate; + private javax.swing.JLabel jLabel4; + private javax.swing.JLabel jLabel5; + private javax.swing.JLabel jLabel7; + private javax.swing.JLabel jLabel8; + private javax.swing.JMenuItem jMenuItemAddRow; + private javax.swing.JMenuItem jMenuItemReleteRow; + private javax.swing.JPopupMenu jPopupMenuTable; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JScrollPane jScrollPane3; + private javax.swing.JTable jTableParams; + private javax.swing.JTextArea txtTestDescription; + private javax.swing.JTextField txtTestName; + private javax.swing.JTextField txtTestSuite; + // End of variables declaration//GEN-END:variables +} diff --git a/plugins/TestingListDetails - Copy.java b/plugins/TestingListDetails - Copy.java new file mode 100644 index 0000000..9f6193f --- /dev/null +++ b/plugins/TestingListDetails - Copy.java @@ -0,0 +1,465 @@ +/* + * Copyright (c) 2015 Paul Scherrer Institute. All rights reserved. + */ + +import ch.psi.utils.swing.SwingUtils; +import java.awt.Desktop; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Properties; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.ImageIcon; +import javax.swing.JDialog; +import javax.swing.JPanel; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; +import javax.swing.table.DefaultTableModel; +import org.apache.commons.io.FilenameUtils; + +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/** + * + * @author boccioli_m + */ +public class TestingListDetails extends javax.swing.JPanel { + + /** + * Creates new form TestingListDetails + */ + public TestingListDetails() { + initComponents(); + } + + public TestingListDetails(HashMap hDetails) { + initComponents(); + fillComponents(hDetails); + } + + public static String TESTS_CONFIG_FILENAME = ".config"; + public static Path TESTS_TESTS_DEFAULT_DIR = Paths.get(".", "home", "script", "tests", "tests"); + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents + private void initComponents() { + + jLabel1 = new javax.swing.JLabel(); + txtDeviceName = new javax.swing.JTextField(); + jLabel2 = new javax.swing.JLabel(); + txtDeviceDescription = new javax.swing.JTextField(); + jLabel4 = new javax.swing.JLabel(); + txtTestSuite = new javax.swing.JTextField(); + jLabel5 = new javax.swing.JLabel(); + txtTestName = new javax.swing.JTextField(); + jLabel6 = new javax.swing.JLabel(); + jScrollPane1 = new javax.swing.JScrollPane(); + jTableParams = new javax.swing.JTable(); + jLabel7 = new javax.swing.JLabel(); + jScrollPane2 = new javax.swing.JScrollPane(); + txtTestResult = new javax.swing.JTextArea(); + jLabel8 = new javax.swing.JLabel(); + jScrollPane3 = new javax.swing.JScrollPane(); + txtTestDescription = new javax.swing.JTextArea(); + jScrollPane4 = new javax.swing.JScrollPane(); + jEditorPaneHelp = new javax.swing.JEditorPane(); + jPanel1 = new javax.swing.JPanel(); + jButtonCancel = new javax.swing.JButton(); + jButtonOk = new javax.swing.JButton(); + + jLabel1.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + jLabel1.setText("Device name"); + + txtDeviceName.setEditable(false); + txtDeviceName.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + txtDeviceName.setText("jTextField1"); + + jLabel2.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + jLabel2.setText("Device Description"); + + txtDeviceDescription.setEditable(false); + txtDeviceDescription.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + txtDeviceDescription.setText("jTextField2"); + + jLabel4.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + jLabel4.setText("Test Case/Suite"); + + txtTestSuite.setEditable(false); + txtTestSuite.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + txtTestSuite.setText("jTextField2"); + + jLabel5.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + jLabel5.setText("Test Name"); + + txtTestName.setEditable(false); + txtTestName.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + txtTestName.setText("jTextField2"); + + jLabel6.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + jLabel6.setText("Last Test Result"); + + jTableParams.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + jTableParams.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + "Parameter", "Value", "Description" + } + ) { + boolean[] canEdit = new boolean [] { + false, true, false + }; + + public boolean isCellEditable(int rowIndex, int columnIndex) { + return canEdit [columnIndex]; + } + }); + jTableParams.setDragEnabled(true); + jTableParams.setRowHeight(20); + jScrollPane1.setViewportView(jTableParams); + if (jTableParams.getColumnModel().getColumnCount() > 0) { + jTableParams.getColumnModel().getColumn(0).setMinWidth(150); + jTableParams.getColumnModel().getColumn(0).setPreferredWidth(150); + jTableParams.getColumnModel().getColumn(0).setMaxWidth(150); + jTableParams.getColumnModel().getColumn(1).setPreferredWidth(80); + jTableParams.getColumnModel().getColumn(1).setMaxWidth(100); + } + + jLabel7.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + jLabel7.setText("Test Parameters"); + + jScrollPane2.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + + txtTestResult.setEditable(false); + txtTestResult.setColumns(20); + txtTestResult.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + txtTestResult.setLineWrap(true); + txtTestResult.setRows(5); + jScrollPane2.setViewportView(txtTestResult); + + jLabel8.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + jLabel8.setText("Test Description"); + + jScrollPane3.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + + txtTestDescription.setEditable(false); + txtTestDescription.setColumns(20); + txtTestDescription.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + txtTestDescription.setLineWrap(true); + txtTestDescription.setRows(5); + jScrollPane3.setViewportView(txtTestDescription); + + jEditorPaneHelp.setContentType("text/html"); // NOI18N + jEditorPaneHelp.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N + jEditorPaneHelp.setDropMode(javax.swing.DropMode.INSERT); + jScrollPane4.setViewportView(jEditorPaneHelp); + + jButtonCancel.setText("Cancel"); + + jButtonOk.setText("Ok"); + jButtonOk.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButtonOkActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jButtonOk, javax.swing.GroupLayout.PREFERRED_SIZE, 96, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(18, 18, 18) + .addComponent(jButtonCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 98, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jButtonCancel) + .addComponent(jButtonOk)) + .addContainerGap()) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel4) + .addComponent(jLabel5) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel1) + .addComponent(jLabel2) + .addComponent(jLabel7) + .addComponent(jLabel6) + .addComponent(jLabel8)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(txtDeviceName) + .addComponent(txtDeviceDescription) + .addComponent(txtTestSuite) + .addComponent(txtTestName) + .addComponent(jScrollPane3) + .addComponent(jScrollPane2) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 513, Short.MAX_VALUE))) + .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(18, 18, 18) + .addComponent(jScrollPane4, javax.swing.GroupLayout.DEFAULT_SIZE, 317, Short.MAX_VALUE) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel1) + .addComponent(txtDeviceName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel2) + .addComponent(txtDeviceDescription, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel4) + .addComponent(txtTestSuite, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel5) + .addComponent(txtTestName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel8) + .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 81, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel6)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel7) + .addGap(0, 192, Short.MAX_VALUE)) + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)) + .addGap(18, 18, 18) + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addComponent(jScrollPane4) + .addContainerGap()))) + ); + }// </editor-fold>//GEN-END:initComponents + + private void fillComponents(HashMap hDetails) { + //add values to each text box + this.txtDeviceName.setText(hDetails.get("deviceName").toString()); + this.txtDeviceDescription.setText(hDetails.get("deviceDescription").toString()); + this.txtTestDescription.setText(hDetails.get("testDescription").toString()); + this.txtTestSuite.setText(hDetails.get("testSuite").toString()); + this.txtTestName.setText(hDetails.get("testName").toString()); + this.txtTestResult.setText(hDetails.get("time").toString() + "\n" + hDetails.get("testResult").toString()); + //help text + showHelp(String.valueOf(hDetails.get("testPath")), String.valueOf(hDetails.get("testHelp"))); + //parameters table + HashMap hParams = (HashMap) hDetails.get("parameters"); + String name="", value="", description=""; + DefaultTableModel model = (DefaultTableModel) jTableParams.getModel(); + + for(Object entry : hParams.keySet()){ + Object param = entry; + if(param instanceof String){ + name = (String) param; + HashMap attributes = (HashMap) hParams.get(param); + value = (String) attributes.get("value"); + description = (String) attributes.get("description"); + model.addRow(new Object[]{name, value, description}); + } + jTableParams.setModel(model); + } + } + + //load and show help + private void showHelp(String sTestPath, String sHelpText){ + this.jEditorPaneHelp.addHyperlinkListener(new HyperlinkListener() { + @Override + public void hyperlinkUpdate(HyperlinkEvent hle) { + if (HyperlinkEvent.EventType.ACTIVATED.equals(hle.getEventType())) { + System.out.println(hle.getURL()); + Desktop desktop = Desktop.getDesktop(); + try { + desktop.browse(hle.getURL().toURI()); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + }); + this.jEditorPaneHelp.setEditable(false); + //if there is no input, exit + if(sTestPath == "" && sHelpText == ""){ + return; + } + File fTest = new File(sTestPath); + String sParentPath = fTest.getParent().toString(); + File fHelp = new File(FilenameUtils.separatorsToSystem(sParentPath + "/help.html")); + + if(fHelp.isFile()){//if local help file existis: + try { + this.jEditorPaneHelp.setPage(fHelp.toURI().toURL()); + } catch (IOException ex) { + this.jEditorPaneHelp.setText(String.valueOf(ex)); + } + } else { //help.html file is present. see if a plain text has been given from .config file + if(sHelpText.isEmpty() || sHelpText == "null"){ + this.jEditorPaneHelp.setText("[No help available]"); + //this.jEditorPaneHelp.setVisible(false); + }else { + this.jEditorPaneHelp.setText(sHelpText); + } + } + } + + /** + * Build a map with optional parameters to be passed to the testing script. + * The map is like this: parameters \_ name | \_ value | \_ description \_ + * name | \_ value | \_ description ... the name 'name' is the mapping key. + * 'value' and 'description' are constant mapping keys of a nested map. + * + * @param parametersString string containing the parameters. Syntax: + * name:value:description[;name:value:description;...] + */ + private HashMap buildParametersMap(String parametersString) { + HashMap mParameters = new HashMap(); // contains name and attributes + HashMap mParameterAttributes = new HashMap(); //contians value and description + String[] dsParameterAttributes = null; + String[] dsParameters = parametersString.split(";"); + for (String sParameter : dsParameters) { + dsParameterAttributes = sParameter.split(":"); + if (dsParameterAttributes.length > 2) { + mParameterAttributes = new HashMap(); + mParameterAttributes.put("value", (Object) dsParameterAttributes[1]); + mParameterAttributes.put("description", dsParameterAttributes[2]); + //add parameter name and attributes (value + description) + mParameters.put(dsParameterAttributes[0], mParameterAttributes); + } + } + return mParameters; + } + + private HashMap getParametersFromTable(){ + HashMap mParameters = new HashMap(); // contains name and attributes + HashMap mParameterAttributes = new HashMap(); //contians value and description + for(int row=0 ; row<jTableParams.getRowCount() ; row++){ + String sParam = jTableParams.getValueAt(row, 0).toString(); + String sVal = jTableParams.getValueAt(row, 1).toString(); + String sDescr = jTableParams.getValueAt(row, 2).toString(); + mParameterAttributes = new HashMap(); + mParameterAttributes.put("value", (Object) sVal); + mParameterAttributes.put("description", sDescr); + //add parameter name and attributes (value + description) + mParameters.put(sParam, mParameterAttributes); + } + return mParameters; + } + + public boolean updateTestConfig(Path testDir, + String sTestName, + String sTestSuite, + HashMap hmTestParams){ + //generate test config file from template + boolean success = false; + try { + Path path = Paths.get(testDir + FilenameUtils.separatorsToSystem("/"+TESTS_CONFIG_FILENAME)); + File configFile = path.toFile(); + //Loop among the test parameters and generate variable assignement syntax for python + String sTestParameters = ""; + String name="", value="", description=""; + for(Object entry : hmTestParams.keySet()){ + Object param = entry; + if(param instanceof String){ + name = (String) param; + HashMap attributes = (HashMap) hmTestParams.get(param); + value = (String) attributes.get("value"); + description = (String) attributes.get("description"); + //build the python code for getting the test parameter + sTestParameters = sTestParameters + name + ":" + value + ":" + description + ";" ; + } + } + FileOutputStream out = new FileOutputStream(path.toFile()); + FileInputStream in = new FileInputStream(path.toFile()); + Properties props = new Properties(); + props.load(in); + in.close(); + props.setProperty("parameters", "sTestParameters"); + props.store(out, null); + out.close(); + + success = true; + } catch (FileNotFoundException ex) { + SwingUtils.showMessage(this, "generateTestConfig()", "Cannot find file: " + ex.toString()); + Logger.getLogger(NewTest.class.getName()).log(Level.SEVERE, null, ex); + } catch (IOException ex) { + SwingUtils.showMessage(this, "generateTestConfig()", "Problem with file aaccess: " + ex.toString()); + Logger.getLogger(NewTest.class.getName()).log(Level.SEVERE, null, ex); + } + return success; + } + + private void jButtonOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonOkActionPerformed + // TODO add your handling code here: + Path testPath = Paths.get(TESTS_TESTS_DEFAULT_DIR.toString(), this.txtTestSuite.getText(), this.txtTestName.getText()); + updateTestConfig(testPath, this.txtTestName.getText(), this.txtTestSuite.getText(),getParametersFromTable()); + }//GEN-LAST:event_jButtonOkActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton jButtonCancel; + private javax.swing.JButton jButtonOk; + private javax.swing.JEditorPane jEditorPaneHelp; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel4; + private javax.swing.JLabel jLabel5; + private javax.swing.JLabel jLabel6; + private javax.swing.JLabel jLabel7; + private javax.swing.JLabel jLabel8; + private javax.swing.JPanel jPanel1; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JScrollPane jScrollPane2; + private javax.swing.JScrollPane jScrollPane3; + private javax.swing.JScrollPane jScrollPane4; + private javax.swing.JTable jTableParams; + private javax.swing.JTextField txtDeviceDescription; + private javax.swing.JTextField txtDeviceName; + private javax.swing.JTextArea txtTestDescription; + private javax.swing.JTextField txtTestName; + private javax.swing.JTextArea txtTestResult; + private javax.swing.JTextField txtTestSuite; + // End of variables declaration//GEN-END:variables +} diff --git a/plugins/icons/settings-128px.png b/plugins/icons/settings-128px.png new file mode 100644 index 0000000000000000000000000000000000000000..7a3cf3ea54974cd8cb3cdf4e4fd04a686c5f8539 GIT binary patch literal 26029 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 Jmo5tZ{6BPGuG;_r literal 0 HcmV?d00001 diff --git a/plugins/icons/settings-32px.png b/plugins/icons/settings-32px.png new file mode 100644 index 0000000000000000000000000000000000000000..819ea5fc3dee8515f77fd4e0e0fb2ad550ccd63b GIT binary patch literal 791 zcmV+y1L*vTP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800006VoOIv00000 z008+zyMF)x010qNS#tmYE+YT{E+YYWr9XB600Os3L_t(oN9~roYZXxt#&`Gb-Y1q4 zYYA9HqaY%_C5Vz#f~Bcq8o>t<K@0x`8!Hn-8o^2eqDYDm!NS@~&_c0_f|vvmuLvgo z=5qIPa_-EYHC94C7<Tu}d^2-q=ge*tZR3AJ9LM`AmC991k8TQ^VN1VNBse{nW!Yk_ zR@)FslB6#Qg5S>d*e<~tWjR*-{WVe?e#)KaLcn_jIgXr6)AYWthw~9`5^`P&1bE~J z2nh+!h5VKV3A_vi^aaj~kl#|E#HXs&>bf6*wN0Yv*Wr$Y{PzLUY2+}nhi1EmqqZMd zuJw9-quFeBMDAUkWBZF&aSLAukTduj3&n3j`k|FH-)W=K5SeA|ERD8XMDAI8AUdle zc|ye4VMZszD@DQC?Rx_5xA@o$i%n4y#JFMcV>vn+iFMiaDvh<vBIm$%fFxFgWB6K* zjN_SU$IaQvxJJ@|?M08<6MA9>ld4IkL^qY)e`dY(RKqrcv+P$vUU7)q0mOH11#tE> z#PI>=iCY2j8RGQ7tC)8aXti1oLmVG)XWazw`7Ffgfo$J+6<7#ye873`Rp3L2(*f`4 zveE-9tlN#_0o#m|@YU}D8t_gbPy4FnyC4bk{Q6)rUU#{!5aTf>nM!m^uT<eD*S#un zvyUNc+XZvrZDjo?P`YuAl<x+|Yut}9*Za7#hHg{_mNf-Mh%upr?jeQzr6>vc@JLf~ zo#gqL2=|wG=dxyw;4XhPDjGrpc5*~Mquu|%DgWb?&v^;viZ=gwZp#-HUxUa&<WOO7 z4UlA)zqM+(qUpEvKcIomU9ie(37l6Uzoo&em<|P05||J9Ee(#&YbC%mB|d>1CBeJC zzWY~P3HdGsf(#K*X8SjBu1z$WZBlgDe8+Z9nppGouh>bT3z4xibmzGYXu54!_yau% VZ-;s9Tn_*M002ovPDHLkV1g_3ZAAb8 literal 0 HcmV?d00001 diff --git a/plugins/icons/settings2-128px.png b/plugins/icons/settings2-128px.png new file mode 100644 index 0000000000000000000000000000000000000000..bde040669a2807c45aac36f9353d50b05e857c04 GIT binary patch literal 21464 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�#U;S{(1X>HG`mh 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 literal 0 HcmV?d00001