/*
* 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<>();
editParamsButton = 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[] { " ", " " }));
editParamsButton.setText("Edit Params");
editParamsButton.setToolTipText("The DSDF can be used to describe the parameters, and this experimental GUI will be generated.");
editParamsButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
editParamsButtonActionPerformed(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(editParamsButton)))
.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(editParamsButton))
.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 editParamsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editParamsButtonActionPerformed
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_editParamsButtonActionPerformed
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.JButton editParamsButton;
public javax.swing.JComboBox examplesComboBox;
public javax.swing.JCheckBox intrinsicCb;
public javax.swing.JComboBox itemsComboBox;
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; i0 ) result.append("&").append(params.toString());
if ( otherParams.get("qubeSubset")!=null ) {
result.append("&qubeSubset=").append(otherParams.get("qubeSubset"));
}
return result.toString();
}
@Override
public void markProblems(List problems) {
}
//private boolean expert;
/**
* call this before prepare.
* @param expert
*/
public void setExpertMode( boolean expert ) {
//this.expert= expert;
this.discoveryCb.setSelected(!expert);
}
}