/* * To change this template, choose Tools | Templates * and open the template in the editor. */ /* * Das2ServerDataSourceEditorPanel.java * * Created on Oct 16, 2009, 12:59:27 PM */ package org.das2.datasource; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Image; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.io.StringReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; import java.text.ParseException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.swing.DefaultComboBoxModel; import javax.swing.DefaultListCellRenderer; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTree; import javax.swing.ListCellRenderer; import javax.swing.SwingUtilities; import javax.swing.text.DefaultEditorKit; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.TreeModel; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.das2.DasException; import org.das2.client.DasServer; import org.das2.datum.Datum; import org.das2.datum.DatumRange; import org.das2.datum.DatumRangeUtil; import org.das2.datum.TimeUtil; import org.das2.system.RequestProcessor; import org.das2.util.LoggerManager; import org.das2.util.monitor.ProgressMonitor; import org.autoplot.datasource.AutoplotSettings; import org.autoplot.datasource.DataSetURI; import org.autoplot.datasource.DataSourceEditorPanel; import org.autoplot.datasource.RecentComboBox; import org.autoplot.datasource.TimeRangeTool; import org.autoplot.datasource.URISplit; import org.das2.client.Das2ServerGUI; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import org.xml.sax.SAXException; /** * * @author jbf */ public class Das2ServerDataSourceEditorPanel extends javax.swing.JPanel implements DataSourceEditorPanel { private static final Logger logger= LoggerManager.getLogger("apdss.das2server"); private static final char EXAMPLE_TIMERANGE_LABEL_DELIM = '|'; //DANGER: NB gui code doesn't use this... private static final String EXAMPLE_TIME_RANGES = "Example Time Ranges"; private final String DEFAULT_TIMERANGE="2001-01-01"; private String dsdfContent; /** Creates new form Das2ServerDataSourceEditorPanel */ public Das2ServerDataSourceEditorPanel() { initComponents(); recentComboBox1.setPreferenceNode(RecentComboBox.PREF_NODE_TIMERANGE); } /** * list of servers we know about */ private List d2ss; /** 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() { das2ServerComboBox = new javax.swing.JComboBox(); jLabel1 = new javax.swing.JLabel(); jScrollPane1 = new javax.swing.JScrollPane(); jTree1 = new javax.swing.JTree(); jLabel2 = new javax.swing.JLabel(); jLabel3 = new javax.swing.JLabel(); jLabel4 = new javax.swing.JLabel(); jScrollPane2 = new javax.swing.JScrollPane(); readerParamsTextArea = new javax.swing.JTextArea(); jLabel5 = new javax.swing.JLabel(); tcaTextField = new javax.swing.JTextField(); jLabel6 = new javax.swing.JLabel(); viewDsdfButton = new javax.swing.JButton(); validRangeLabel = new javax.swing.JLabel(); discoveryCb = new javax.swing.JCheckBox(); examplesComboBox = new javax.swing.JComboBox(); jLabel7 = new javax.swing.JLabel(); descriptionLabel = new javax.swing.JLabel(); timeRangeTool = new javax.swing.JButton(); intrinsicCb = new javax.swing.JCheckBox(); recentComboBox1 = new org.autoplot.datasource.RecentComboBox(); itemsComboBox = new javax.swing.JComboBox<>(); jButton1 = new javax.swing.JButton(); setName("das2serverDataSourceEditorPanel"); // NOI18N das2ServerComboBox.setEditable(true); das2ServerComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "https://planet.physics.uiowa.edu/das/das2Server", "https://jupiter.physics.uiowa.edu/das/server" })); das2ServerComboBox.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { das2ServerComboBoxActionPerformed(evt); } }); jLabel1.setText("Das2 Server URL:"); javax.swing.tree.DefaultMutableTreeNode treeNode1 = new javax.swing.tree.DefaultMutableTreeNode("Loading DataSets List..."); jTree1.setModel(new javax.swing.tree.DefaultTreeModel(treeNode1)); jTree1.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() { public void valueChanged(javax.swing.event.TreeSelectionEvent evt) { jTree1ValueChanged(evt); } }); jScrollPane1.setViewportView(jTree1); jLabel2.setText("Data Set Id:"); jLabel3.setText("Time Range:"); jLabel4.setText("Reader Parameters:"); jLabel4.setToolTipText("Special parameters for the reader that implements the data source. "); readerParamsTextArea.setColumns(20); readerParamsTextArea.setRows(5); jScrollPane2.setViewportView(readerParamsTextArea); jLabel5.setText("Sampling Interval (sec):"); jLabel5.setToolTipText(" Interval (in seconds) to use for arbitrary resolution data.
Typically used for spacecraft positions, leave blank for most datasets.
"); tcaTextField.setText(" "); tcaTextField.setToolTipText(" Interval (in seconds) to use for TCA (ephemeris) data.
Leave blank for most datasets.
"); jLabel6.setText("TCA Item:"); jLabel6.setToolTipText("The optional item number for TCAs."); viewDsdfButton.setText("View DSDF"); viewDsdfButton.setToolTipText("View the DSDF configuration file on the server"); viewDsdfButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { viewDsdfButtonActionPerformed(evt); } }); validRangeLabel.setFont(new java.awt.Font("DejaVu LGC Sans", 0, 10)); // NOI18N validRangeLabel.setText("no valid range for dataset provided"); discoveryCb.setText("require example time"); discoveryCb.setToolTipText("Show only datasets that have identified example times. These should be a higher quality, and can be tested by a machine."); discoveryCb.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { discoveryCbActionPerformed(evt); } }); examplesComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Example Time Ranges", " " })); examplesComboBox.setToolTipText("Example times specified in the data set descriptor file"); examplesComboBox.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { examplesComboBoxActionPerformed(evt); } }); jLabel7.setText("Description:"); jLabel7.setToolTipText("Description provided by the server (in its dsdf file)"); descriptionLabel.setText(" "); timeRangeTool.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/das2/datasource/calendar.png"))); // NOI18N timeRangeTool.setToolTipText("Time Range Tool"); timeRangeTool.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { timeRangeToolActionPerformed(evt); } }); intrinsicCb.setText("Force Intrinsic Resolution"); intrinsicCb.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { intrinsicCbActionPerformed(evt); } }); recentComboBox1.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(java.awt.event.ItemEvent evt) { recentComboBox1ItemStateChanged(evt); } }); itemsComboBox.setEditable(true); itemsComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { " ", " " })); jButton1.setText("Edit Params"); jButton1.setToolTipText("The DSDF can be used to describe the parameters, and this experimental GUI will be generated."); jButton1.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton1ActionPerformed(evt); } }); org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(layout.createSequentialGroup() .addContainerGap() .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(das2ServerComboBox, 0, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .add(layout.createSequentialGroup() .add(jLabel2) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .add(discoveryCb)) .add(jScrollPane1) .add(layout.createSequentialGroup() .add(jLabel7) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(descriptionLabel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup() .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(layout.createSequentialGroup() .add(21, 21, 21) .add(validRangeLabel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 267, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(examplesComboBox, 0, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup() .add(jLabel3) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(recentComboBox1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(timeRangeTool)) .add(org.jdesktop.layout.GroupLayout.TRAILING, jScrollPane2)) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(viewDsdfButton) .add(jButton1))) .add(layout.createSequentialGroup() .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(jLabel1) .add(jLabel4) .add(layout.createSequentialGroup() .add(intrinsicCb) .add(28, 28, 28) .add(jLabel5) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(tcaTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 70, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) .add(26, 26, 26) .add(jLabel6) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(itemsComboBox, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))) .add(0, 27, Short.MAX_VALUE))) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(layout.createSequentialGroup() .addContainerGap() .add(jLabel1) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(das2ServerComboBox, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) .add(5, 5, 5) .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) .add(jLabel2) .add(discoveryCb)) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 240, Short.MAX_VALUE) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) .add(jLabel7) .add(descriptionLabel)) .add(7, 7, 7) .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(viewDsdfButton) .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) .add(jLabel3) .add(recentComboBox1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) .add(org.jdesktop.layout.GroupLayout.TRAILING, timeRangeTool)) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(examplesComboBox, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) .add(validRangeLabel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(jLabel4) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(layout.createSequentialGroup() .add(jScrollPane2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 53, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) .add(jLabel5) .add(tcaTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) .add(jLabel6) .add(intrinsicCb) .add(itemsComboBox, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))) .add(jButton1)) .addContainerGap()) ); }//
//GEN-END:initComponents private DatumRange validTimeRange= null; // some timerange believed to be valid. private final Map readerParams= new HashMap(); // from dataset url to params. private final Map otherParams= new HashMap(); // other params which are not supported by this dialog, like qubeSubset private String userTimeRange= null; private final Map tcaItem= new HashMap(); // from ID to selected TCA item. private static class Example { private String timeRange; private String label=""; private String params=""; } private final LinkedHashMap theExamples= new LinkedHashMap<>(); /** * populate the timeRange and label parts of the Example. * @param s the string * @param e null or the existing Example */ private static Example parseExample( String s, Example e ) { if ( e==null ) e= new Example(); int j= s.indexOf( EXAMPLE_TIMERANGE_LABEL_DELIM ); if ( j>-1 ) { e.timeRange= s.substring(0,j); e.label= s.substring(j+1).trim(); } else { e.timeRange= s; } return e; } private static Example addParamsToExample( String s, Example e ) { if ( e==null ) e= new Example(); e.params= s; return e; } /** * open a connection to retrieve the URL, possibly handling one redirect. * @param url the URL, such as http://jupiter.physics.uiowa.edu/das/server?server=logo * @return the input stream. * @throws IOException */ private InputStream openConnection( URL url ) throws IOException { HttpURLConnection httpConn= (HttpURLConnection)url.openConnection(); int nStatus= httpConn.getResponseCode(); if ( nStatus==301 ) { String newUrl= httpConn.getHeaderField("Location"); httpConn.disconnect(); //TODO: this is sloppy. The buffer needs to be emptied. if ( newUrl==null ) { throw new IllegalArgumentException("301 response but no new location"); } httpConn= (HttpURLConnection) new URL(newUrl).openConnection(); nStatus= ((HttpURLConnection) httpConn).getResponseCode(); //if ( conn.getHeaderField("Strict-Transport-Security")) } return httpConn.getInputStream(); } /** * this is called off the event thread for the web transaction, then hop back on it to populate the GUI. * @param url */ private void updateDataSetSelected( final URL url ) { InputStream in= null; try { in= openConnection(url); StringBuilder sb = new StringBuilder(); int by = in.read(); while (by != -1) { sb.append((char) by); by = in.read(); } in.close(); String s = sb.toString(); final int packetTagLength=10; int contentLength = Integer.parseInt(s.substring(4, packetTagLength )); // "[00]000192 " String sxml = s.substring( packetTagLength, packetTagLength + contentLength); Reader xin = new BufferedReader(new StringReader(sxml)); DocumentBuilder builder; builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); InputSource source = new InputSource(xin); final Document document = builder.parse(source); Runnable run = new Runnable() { @Override public void run() { try { validTimeRange= null; boolean isTca= false; XPathFactory factory = XPathFactory.newInstance(); XPath xpath = (XPath) factory.newXPath(); String curr= Das2ServerDataSourceEditorPanel.this.recentComboBox1.getText(); Node description= (Node) xpath.evaluate( "/stream/properties/@description", document, XPathConstants.NODE ); descriptionLabel.setText( description==null ? "" : description.getNodeValue() ); NodeList exs= (NodeList) xpath.evaluate( "/stream/properties/@*", document, XPathConstants.NODESET ); Example example= null; //String exampleParams= null; Map items= new HashMap<>(); Pattern itemPattern= Pattern.compile("item_(\\d\\d)"); for ( int i=0; i-1 ) { s= s.substring(0,ipipe); } s= s.trim(); items.put( name, s ); } } } String selectedItem= tcaItem.get( url.toString() ); if ( items.size()>0 && isTca ) { DefaultComboBoxModel aModel= new DefaultComboBoxModel(); aModel.addElement(""); // all items String e; int index=0; do { e= items.get( String.format("item_%02d", index ) ); if ( e!=null ) { if ( index==0 ) { aModel.addElement("0 ("+e+")"); } else { aModel.addElement(e); } } index++; } while ( e!=null ); itemsComboBox.setModel(aModel); } else { DefaultComboBoxModel aModel= new DefaultComboBoxModel(); aModel.addElement(""); // all items itemsComboBox.setModel(aModel); } if ( selectedItem!=null ) { itemsComboBox.setSelectedItem(selectedItem); } if ( example!=null && curr.equals(DEFAULT_TIMERANGE) ) { // DANGER: what if they are the same? Das2ServerDataSourceEditorPanel.this.recentComboBox1.setText( example.timeRange ); } if ( example!=null ) { try { validTimeRange= DatumRangeUtil.parseTimeRange(example.timeRange); } catch (ParseException ex) { logger.info("default timerange doesn't parse!"); } } if ( theExamples.size()>0 ) { List keys= new ArrayList<>(theExamples.size()); keys.add("LABEL"); if ( theExamples.containsKey("example") ) { keys.add( "example" ); } for ( String k: theExamples.keySet() ) { if ( !k.equals("example") ) keys.add(k); } if ( theExamples.size()>0 ) { String anExample; anExample= theExamples.entrySet().iterator().next().getValue().timeRange; if ( Das2ServerDataSourceEditorPanel.this.userTimeRange!=null ) { anExample= Das2ServerDataSourceEditorPanel.this.userTimeRange; } Das2ServerDataSourceEditorPanel.this.recentComboBox1.setText( anExample ); } DefaultComboBoxModel model= new DefaultComboBoxModel( keys.toArray() ); Das2ServerDataSourceEditorPanel.this.examplesComboBox.setModel( model ); Das2ServerDataSourceEditorPanel.this.examplesComboBox.setEnabled(true); } else { DefaultComboBoxModel model= new DefaultComboBoxModel( new String[] { "NONEFOUND" } ); Das2ServerDataSourceEditorPanel.this.examplesComboBox.setModel( model ); Das2ServerDataSourceEditorPanel.this.examplesComboBox.setEnabled(false); } Das2ServerDataSourceEditorPanel.this.examplesComboBox.setRenderer( new ListCellRenderer() { @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { JLabel def= new JLabel(); if ( value.equals("LABEL") ) { def.setText(String.format( Locale.US, "Example Time Ranges (%d)", theExamples.size() )); } else if ( value.equals("NONEFOUND") ) { def.setText(String.format( Locale.US, "No example time ranges found..." ) ); } else { Example e= theExamples.get((String)value); def.setText( "" + e.timeRange + " "+ e.label + "" ); } return def; } }); if ( example==null ) { // legacy Node exampleRange= (Node) xpath.evaluate( "/stream/properties/@x_range", document, XPathConstants.NODE ); if ( exampleRange!=null && curr.equals(DEFAULT_TIMERANGE) ) { Das2ServerDataSourceEditorPanel.this.recentComboBox1.setText( exampleRange.getNodeValue() ); } if ( exampleRange!=null ) { try { validTimeRange= DatumRangeUtil.parseTimeRange(exampleRange.getNodeValue()); } catch (ParseException ex) { logger.info("example timerange doesn't parse!"); } } } String rp= readerParams.get( getDataSetId(url) ); readerParamsTextArea.setText( rp==null ? "" : rp ); Node validRange= (Node) xpath.evaluate( "/stream/properties/@validRange", document, XPathConstants.NODE ); if ( validRange!=null ) { Das2ServerDataSourceEditorPanel.this.validRangeLabel.setText( "valid range: " + validRange.getNodeValue() ); } else { Das2ServerDataSourceEditorPanel.this.validRangeLabel.setText("no valid range for dataset provided"); } if ( isTca ) { tcaTextField.setText("60"); } else { tcaTextField.setText(""); } } catch ( XPathExpressionException ex ) { logger.log(Level.SEVERE, ex.getMessage(), ex); } } }; SwingUtilities.invokeLater(run); } catch (SAXException ex) { JOptionPane.showMessageDialog(examplesComboBox, "Unable to parse dsdf: "+ ex.getMessage() ); logger.log(Level.SEVERE, ex.getMessage(), ex); } catch (ParserConfigurationException | IOException ex) { JOptionPane.showMessageDialog(examplesComboBox, "Unable to parse dsdf: "+ ex.getMessage() ); logger.log(Level.SEVERE, ex.getMessage(), ex); } finally { try { if ( in!=null ) in.close(); } catch (IOException ex) { logger.log(Level.SEVERE, ex.getMessage(), ex); } } } /** * return the dataset id (Juno/JED/ElectronSpectra) for the tree path. * @param p the tree path. * @return the dataset id like "http://jupiter.physics.uiowa.edu/das/server?Juno/JED/ElectronSpectra" */ private String getDataSetId( TreePath p ) { Object[] oo= p.getPath(); StringBuilder ds= new StringBuilder( String.valueOf( oo[0] ) ); ds.append("?").append(oo[1]); for ( int i=2; i? * @param url * @return "http://jupiter.physics.uiowa.edu/das/server?Juno/JED/ElectronSpectra" */ private String getDataSetId( URL url ) { Map p= URISplit.parseParams(url.getQuery()); return url.getProtocol()+"://"+url.getHost() + url.getPath() + "?" + p.get("dataset"); } private void jTree1ValueChanged(javax.swing.event.TreeSelectionEvent evt) {//GEN-FIRST:event_jTree1ValueChanged TreePath p= evt.getPath(); TreePath old= evt.getOldLeadSelectionPath(); TreeModel m= ((JTree)evt.getSource()).getModel(); if ( old!=null && m.isLeaf(old.getLastPathComponent()) ) { String osurl = getDataSetId( old ); readerParams.put( osurl, readerParamsTextArea.getText() ); } this.dsdfContent=null; if ( ! m.isLeaf( p.getLastPathComponent() ) ) { descriptionLabel.setText( "" ); this.validRangeLabel.setText("no dataset selected"); this.viewDsdfButton.setEnabled(false); } else { this.viewDsdfButton.setEnabled(true); this.validRangeLabel.setText("retrieving dataset info..."); String ds= getDataSetId( p ); int i= ds.indexOf('?'); String surl = p.getPath()[0] + "?server=dsdf&dataset=" + ds.substring(i+1); try { final URL url = new URL(surl); RequestProcessor.invokeLater( new Runnable() { @Override public void run() { updateDataSetSelected( url ); } }); } catch ( MalformedURLException ex ) { logger.log(Level.SEVERE, ex.getMessage(), ex); JOptionPane.showConfirmDialog( this, "Internal Error: "+ex.toString() ); // give a message } } }//GEN-LAST:event_jTree1ValueChanged private void updateDas2Servers() { Runnable runOffEvt= new Runnable() { public void run() { updateDas2ServersImmediately(); } }; new Thread(runOffEvt).start(); } private void updateDas2ServersImmediately() { d2ss= listDas2Servers(); Runnable run= new Runnable() { @Override public void run() { das2ServerComboBox.setModel( new DefaultComboBoxModel(d2ss.toArray()) ); if ( serverURL.length()==0 ) { serverURL= d2ss.get(0); RequestProcessor.invokeLater( getDataSetsRunnable() ); } das2ServerComboBox.setSelectedItem(serverURL); das2ServerComboBox.setRenderer(myListCellRenderer); } }; SwingUtilities.invokeLater(run); } private static final Map icons= Collections.synchronizedMap( new HashMap() ); private static Icon iconFor( Object o, boolean wait ) { //return new javax.swing.ImageIcon(Das2ServerDataSourceEditorPanel.class.getResource("/org/autoplot/datasource/fileMag.png")); //icons.clear(); // for debugging ImageIcon result= icons.get(o.toString()); if (result==null && wait ) { try { long t1= System.currentTimeMillis(); result= new ImageIcon( new URL( "" + o +"?server=logo" ) ); Image im= result.getImage(); int h= im.getWidth(null); int w= im.getHeight(null); int s= 20; int h1= Math.min(24,s*w/h); BufferedImage bi= new BufferedImage( s, h1, BufferedImage.TYPE_INT_ARGB); Graphics g= bi.createGraphics(); g.drawImage( im, 0, 0, s, h1, null, null ); result= new ImageIcon(bi); logger.log(Level.FINE, "time to load icon for {0}: {1} ms", new Object[]{ o, System.currentTimeMillis()-t1}); icons.put( o.toString(), result ); } catch (MalformedURLException ex) { Logger.getLogger(Das2ServerDataSourceEditorPanel.class.getName()).log(Level.SEVERE, null, ex); } } return result; } private static class IconCellRenderer implements ListCellRenderer { DefaultListCellRenderer r= new DefaultListCellRenderer(); @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { Component c= r.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); Icon icon= iconFor( value, false ); ((DefaultListCellRenderer)c).setIcon(icon); return c; } } private transient final ListCellRenderer myListCellRenderer= new IconCellRenderer(); private List listPeers( String suri ) { String uri= suri+"?server=peers"; List result= new ArrayList(); InputStream in=null; try { in = new URL(uri).openStream(); DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); InputSource source = new InputSource(in); Document initialDocument = builder.parse(source); XPathFactory factory = XPathFactory.newInstance(); XPath xpath = factory.newXPath(); NodeList urls = (NodeList) xpath.evaluate("//das2server/peers/server/url/text()", initialDocument, XPathConstants.NODESET ); for ( int i=0; i listDas2Servers() { List d2ss1= new ArrayList( ); d2ss1.add( "https://planet.physics.uiowa.edu/das/das2Server" ); if ( serverURL.length()==0 ) { d2ss1.addAll( listPeers("https://planet.physics.uiowa.edu/das/das2Server") ); } else { d2ss1.addAll( listPeers(serverURL) ); } File home = new File(AutoplotSettings.settings().resolveProperty(AutoplotSettings.PROP_AUTOPLOTDATA)); File book = new File(home, "bookmarks"); File hist = new File(book, "history.txt"); long t0= System.currentTimeMillis(); logger.log( Level.FINE, "reading recent datasources from {0}", hist.toString()); if ( hist.exists() ) { BufferedReader r=null; try { String seek="das2server:"; int ttaglen= 25; r = new BufferedReader(new FileReader(hist)); String s = r.readLine(); LinkedHashSet dss = new LinkedHashSet(); while (s != null) { if ( s.length()>ttaglen+15 && s.substring(ttaglen+4,ttaglen+15).equalsIgnoreCase(seek)) { int i= s.indexOf('?'); if ( i==-1 ) i= s.length(); String key= s.substring(ttaglen+4+seek.length(),i); if ( dss.contains(key) ) dss.remove( key ); // move to the end dss.add( key ); } s = r.readLine(); } d2ss1.removeAll(dss); // remove whatever we have already List d2ssDiscoveryList= new ArrayList(dss); Collections.reverse( d2ssDiscoveryList ); d2ssDiscoveryList.addAll(d2ss1); d2ss1= d2ssDiscoveryList; // put the most recently used ones at the front of the list logger.log( Level.FINE, "read extra das2servers in {0} millis\n", (System.currentTimeMillis()-t0) ); } catch ( IOException ex ) { logger.log( Level.FINE, "IOException when reading in {0}", hist ); JOptionPane.showConfirmDialog(examplesComboBox,"IOException when reading in "+hist ); } finally { try { if ( r!=null ) r.close(); } catch (IOException ex) { logger.log( Level.SEVERE, ex.getMessage(), ex ); } } } else { logger.log( Level.FINE, "no history file found: {0}", hist ); } final List fd2ss1= d2ss1; Runnable run= new Runnable() { @Override public void run() { for ( String s: fd2ss1 ) { Icon i= iconFor( s, true ); // force load of icon off the event thread. logger.log(Level.FINER, "iconHeight={0}", i.getIconHeight()); } }; }; new Thread(run,"loadDas2ServerIcons").start(); return d2ss1; } private String readDsdf( URL url ) throws IOException { try ( InputStream in = openConnection(url) ) { StringBuilder sb= new StringBuilder(); int by= in.read(); while ( by!=-1 ) { sb.append( (char)by ); by= in.read(); } String s= sb.toString(); int contentLength= Integer.parseInt( s.substring(4,10) ); String sxml= s.substring(10,10+contentLength); return sxml; } } private void showDsdf( URL url ) { try { String sxml= readDsdf( url ); Reader xin = new BufferedReader(new StringReader(sxml)); DocumentBuilder builder; builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); InputSource source = new InputSource(xin); Document document = builder.parse(source); XPathFactory factory= XPathFactory.newInstance(); XPath xpath= (XPath) factory.newXPath(); NodeList o= (NodeList)xpath.evaluate( "/stream/properties/@*", document, XPathConstants.NODESET ); StringBuilder result= new StringBuilder(""); for ( int ii=0; ii0 ) { try { URL url= new URL(String.valueOf(o)); setServerURL( url.toString() ); } catch (MalformedURLException ex) { if ( !String.valueOf(o).contains(":") ) { JOptionPane.showMessageDialog(this,"Invalid URL (no http):
"+o); } else { JOptionPane.showMessageDialog(this,"Invalid URL:
"+o); } } } }//GEN-LAST:event_das2ServerComboBoxActionPerformed private void discoveryCbActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_discoveryCbActionPerformed org.das2.util.LoggerManager.logGuiEvent(evt); jTree1.setModel( waitTreeModel() ); RequestProcessor.invokeLater( getDataSetsRunnable() ); }//GEN-LAST:event_discoveryCbActionPerformed private void examplesComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_examplesComboBoxActionPerformed org.das2.util.LoggerManager.logGuiEvent(evt); String item= (String) examplesComboBox.getSelectedItem(); if ( item.startsWith("example") ) { logger.log(Level.FINE, "example item: {0}", item); Example e= theExamples.get(item); if ( e==null ) { logger.warning("whoops, where is the label"); } else { recentComboBox1.setText( e.timeRange ); readerParamsTextArea.setText( e.params ); } } }//GEN-LAST:event_examplesComboBoxActionPerformed private void timeRangeToolActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_timeRangeToolActionPerformed org.das2.util.LoggerManager.logGuiEvent(evt); TimeRangeTool tt= new TimeRangeTool(); //JTextField tf= timeRangeTextField; RecentComboBox tf= recentComboBox1; tt.setSelectedRange(tf.getText()); int r= JOptionPane.showConfirmDialog( this, tt, "Select Time Range", JOptionPane.OK_CANCEL_OPTION ); if ( r==JOptionPane.OK_OPTION) { tf.setText(tt.getSelectedRange()); } }//GEN-LAST:event_timeRangeToolActionPerformed private void intrinsicCbActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_intrinsicCbActionPerformed // TODO add your handling code here: }//GEN-LAST:event_intrinsicCbActionPerformed private void recentComboBox1ItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_recentComboBox1ItemStateChanged logger.log(Level.FINEST, "changed {0}", evt.getItem()); }//GEN-LAST:event_recentComboBox1ItemStateChanged private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed org.das2.util.LoggerManager.logGuiEvent(evt); TreePath p= jTree1.getSelectionPath(); TreeModel m= jTree1.getModel(); if ( p==null ) { JOptionPane.showConfirmDialog( this, "No dataset selected" ); return; } if ( m.isLeaf( p.getLastPathComponent() ) ) { { try { Object[] oo = p.getPath(); StringBuilder ds = new StringBuilder( String.valueOf(oo[1]) ); for (int i = 2; i < oo.length; i++) { ds.append( "/" ).append( oo[i] ); } String surl = oo[0] + "?server=dsdf&dataset=" + ds.toString(); final URL url = new URL(surl); RequestProcessor.invokeLater( new Runnable() { @Override public void run() { if ( dsdfContent==null ) { try { dsdfContent= readDsdf( url ); } catch (IOException ex) { logger.log(Level.SEVERE, null, ex); } } if ( dsdfContent!=null ) { editDsdfContent(); } } } ); } catch ( MalformedURLException ex ) { logger.log(Level.SEVERE, ex.getMessage(), ex); JOptionPane.showConfirmDialog( this, "Internal Error: "+ex.toString() ); // give a message } } } }//GEN-LAST:event_jButton1ActionPerformed public void editDsdfContent() { Das2ServerGUI x = new Das2ServerGUI(); x.setSpecification( dsdfContent ); x.setParameters( readerParamsTextArea.getText() ); JScrollPane sp= new JScrollPane(x.getPanel()); sp.setMaximumSize( new Dimension(500,800) ); sp.setPreferredSize( new Dimension(300,500) ); sp.getVerticalScrollBar().setUnitIncrement(sp.getFont().getSize()); int response= JOptionPane.showConfirmDialog( this, sp, "Edit reader params", JOptionPane.OK_CANCEL_OPTION ); if ( response==JOptionPane.OK_OPTION ) { readerParamsTextArea.setText( x.getParameters() ); } } // Variables declaration - do not modify//GEN-BEGIN:variables public javax.swing.JComboBox das2ServerComboBox; public javax.swing.JLabel descriptionLabel; public javax.swing.JCheckBox discoveryCb; public javax.swing.JComboBox examplesComboBox; public javax.swing.JCheckBox intrinsicCb; public javax.swing.JComboBox itemsComboBox; public javax.swing.JButton jButton1; public javax.swing.JLabel jLabel1; public javax.swing.JLabel jLabel2; public javax.swing.JLabel jLabel3; public javax.swing.JLabel jLabel4; public javax.swing.JLabel jLabel5; public javax.swing.JLabel jLabel6; public javax.swing.JLabel jLabel7; public javax.swing.JScrollPane jScrollPane1; public javax.swing.JScrollPane jScrollPane2; public javax.swing.JTree jTree1; public javax.swing.JTextArea readerParamsTextArea; public org.autoplot.datasource.RecentComboBox recentComboBox1; public javax.swing.JTextField tcaTextField; public javax.swing.JButton timeRangeTool; public javax.swing.JLabel validRangeLabel; public javax.swing.JButton viewDsdfButton; // End of variables declaration//GEN-END:variables protected String serverURL = ""; public static final String PROP_SERVERURL = "serverURL"; public String getServerURL() { return serverURL; } public void setServerURL(String serverURL) { String oldServerURL = this.serverURL; this.serverURL = serverURL; if ( !this.serverURL.equals(oldServerURL) ) { //timeRangeTextField.setText( DEFAULT_TIMERANGE ); descriptionLabel.setText(""); jTree1.setModel( waitTreeModel() ); RequestProcessor.invokeLater( getDataSetsRunnable() ); } firePropertyChange(PROP_SERVERURL, oldServerURL, serverURL); } protected String dataSetId = null; public static final String PROP_DATASETID = "dataSetId"; public String getDataSetId() { return dataSetId; } public void setDataSetId(String dataSetId) { String oldDataSetId = this.dataSetId; this.dataSetId = dataSetId; firePropertyChange(PROP_DATASETID, oldDataSetId, dataSetId); } @Override public JPanel getPanel() { return this; } @Override public boolean reject(String uri) throws Exception { URISplit split = URISplit.parse(uri); if ( split.file==null || split.file.equals("file:///") ) { // use UIOWA's main one by default. split.file= "https://planet.physics.uiowa.edu/das/das2Server"; } String s= split.file; if ( s.equals("https://planet.physics.uiowa.edu/das/das2Server") ) { return false; } // there's really no way to tell if it really is a Das2Server on the event thread, so accept all URIs. // and graphically tell them if it is not a valid server. return false; } @Override public boolean prepare( String uri, java.awt.Window parent, ProgressMonitor mon) { return true; } @Override public void setURI(String uri) { URISplit split= URISplit.parse(uri); if ( split.resourceUri==null ) { serverURL= ""; } else { String uriServerUrl= DataSetURI.fromUri( split.resourceUri ); if ( uriServerUrl.length()>0 && !uriServerUrl.startsWith("file:/") ) { serverURL= uriServerUrl; } else { serverURL= ""; } } Map params= URISplit.parseParams(split.params); dataSetId= params.remove("dataset"); if ( dataSetId==null ) { dataSetId= params.remove("arg_0"); } if ( dataSetId!=null && dataSetId.startsWith("/") ) { dataSetId= dataSetId.substring(1); } String startTime= params.remove("start_time"); String endTime= params.remove("end_time"); String str= params.remove("timerange"); if ( str!=null ) { userTimeRange= str; DatumRange tr; try { tr = DatumRangeUtil.parseTimeRange( str ); startTime= tr.min().toString(); endTime= tr.max().toString(); } catch (ParseException ex) { logger.log(Level.SEVERE, ex.getMessage(), ex); } } if ( startTime!=null && endTime!=null ) { try { Datum t1= TimeUtil.create( startTime ); Datum t2= TimeUtil.create( endTime ); DatumRange dr = new DatumRange( t1, t2 ); if ( userTimeRange==null ) userTimeRange= dr.toString(); recentComboBox1.setText(dr.toString()); } catch ( ParseException ex ) { recentComboBox1.setText( DEFAULT_TIMERANGE ); } } else { recentComboBox1.setText( DEFAULT_TIMERANGE ); } String intrinsic = params.remove("intrinsic"); intrinsicCb.setSelected("true".equals(intrinsic)); String interval= params.remove("interval"); if ( interval!=null ) { tcaTextField.setText(interval); } String item= params.remove("item"); if ( item!=null ) { itemsComboBox.setSelectedItem(item); tcaItem.put( "" + serverURL + "?server=dsdf&dataset=" + dataSetId, item ); } otherParams.put( "qubeSubset", params.remove("qubeSubset") ); StringBuilder paramsStr= new StringBuilder(); for ( Entry e: params.entrySet() ) { if ( e.getKey().startsWith("arg_") ) { paramsStr.append(e.getValue()).append("\n"); } else { paramsStr.append(e.getKey()).append("=").append(e.getValue()).append("\n"); } } readerParamsTextArea.setText(paramsStr.toString()); String key= serverURL + "?" + dataSetId; readerParams.put( key, paramsStr.toString() ); das2ServerComboBox.setSelectedItem(serverURL); updateDas2Servers(); // this will set serverUrl to the last used server if nothing is specified. if ( serverURL.length()>0 ) { RequestProcessor.invokeLater( getDataSetsRunnable() ); } } TreeModel waitTreeModel() { DefaultMutableTreeNode treeNode1 = new DefaultMutableTreeNode("updating, please wait..." ); return new javax.swing.tree.DefaultTreeModel(treeNode1); } /** * Class to handle custom rendering of the dataset list. The DefaultTreeCellRenderer * is just a JLable derived object. So those are the functions being used to get the * display properly rendered */ private static class DataSetItemRenderer extends DefaultTreeCellRenderer { @Override public Component getTreeCellRendererComponent(JTree tree, Object value, boolean bSelected, boolean bExpanded, boolean bIsLeaf, int iRow, boolean bHasFocus) { super.getTreeCellRendererComponent(tree, value, bSelected, bExpanded, bIsLeaf, iRow, bHasFocus); DefaultMutableTreeNode tn = (DefaultMutableTreeNode) value; Object obj = tn.getUserObject(); if (obj instanceof DasServer.DataSrcListItem) { DasServer.DataSrcListItem li = (DasServer.DataSrcListItem) obj; if (li.description() == null) { setText(String.format("%s", li.name())); } else { setText(String.format("%s  %s", li.name(), li.description())); } } return this; } } private void updateTree( TreeModel model ) { jTree1.setModel(model); jTree1.setCellRenderer(new DataSetItemRenderer()); if ( dataSetId!=null ) selectDataSetId(); } Runnable getDataSetsRunnable() { Runnable run= new Runnable() { @Override public void run() { String ss1= serverURL; try { DasServer server= DasServer.create( new URL( ss1 ) ); final TreeModel model; if ( discoveryCb.isSelected() ) { model= server.getDataSetListWithDiscovery(); } else { model= server.getDataSetList(); } updateDas2ServersImmediately(); SwingUtilities.invokeLater( new Runnable() { @Override public void run() { updateTree(model); } }); } catch (DasException ex) { logger.log(Level.SEVERE, ex.getMessage(), ex); javax.swing.tree.DefaultMutableTreeNode treeNode1 = new javax.swing.tree.DefaultMutableTreeNode("Error connecting to " + ss1 + ", \n" + ex ); jTree1.setModel(new javax.swing.tree.DefaultTreeModel(treeNode1)); } catch (MalformedURLException ex) { javax.swing.tree.DefaultMutableTreeNode treeNode1 = new javax.swing.tree.DefaultMutableTreeNode("Error connecting to " + ss1 + ", \n" + ex ); jTree1.setModel(new javax.swing.tree.DefaultTreeModel(treeNode1)); } } }; return run; } private void selectDataSetId() { String[] ss= dataSetId.split("/"); TreeNode[] oo= new TreeNode[ss.length+1]; oo[0]= (TreeNode) jTree1.getModel().getRoot(); for ( int i=1; i 1) { DefaultMutableTreeNode tn = (DefaultMutableTreeNode) tp0[1]; DasServer.DataSrcListItem li = (DasServer.DataSrcListItem) tn.getUserObject(); ldataSetId = new StringBuilder(li.name()); for (int i = 2; i < tp0.length; i++) { tn = (DefaultMutableTreeNode) tp0[i]; li = (DasServer.DataSrcListItem) tn.getUserObject(); ldataSetId.append("/").append(li.name()); } } if ( folder ) ldataSetId.append("/"); StringBuilder params= new StringBuilder(); String lreaderParams= readerParamsTextArea.getText(); String[] ss= lreaderParams.split("\n"); for ( int i=0; i problems) { } //private boolean expert; /** * call this before prepare. * @param expert */ public void setExpertMode( boolean expert ) { //this.expert= expert; this.discoveryCb.setSelected(!expert); } }