package org.autoplot.cdf;
import gov.nasa.gsfc.spdf.cdfj.CDFException;
import gov.nasa.gsfc.spdf.cdfj.CDFException.ReaderError;
import gov.nasa.gsfc.spdf.cdfj.CDFReader;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Array;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import org.autoplot.cdf.CdfUtil.CdfVariableDescription;
import org.autoplot.help.AutoplotHelpSystem;
import org.das2.util.DasExceptionHandler;
import org.das2.util.filesystem.FileSystem;
import org.das2.util.monitor.NullProgressMonitor;
import org.das2.util.monitor.ProgressMonitor;
import org.das2.qds.QDataSet;
import org.autoplot.datasource.DataSetSelector;
import org.autoplot.datasource.DataSetURI;
import org.autoplot.datasource.DataSourceEditorPanel;
import org.autoplot.datasource.URISplit;
/**
* Editor panel for CDF files. The "Java" part of the name comes from this is a
* second implementation of the CDF reader, where the first was a native reader
* interfaced to Autoplot via Java Native Interface.
* @author jbf
*/
public final class CdfJavaDataSourceEditorPanel extends javax.swing.JPanel implements DataSourceEditorPanel {
public static final String NO_PLOTTABLE_PARAMETERS_MSG = "No plottable parameters";
/** the maximum number of DEPEND_1 channels where we should show option for depend_1. */
private static final int MAX_SLICE1_OFFER = 32;
private final static Logger logger= Logger.getLogger( "apdss.cdf" );
private boolean isValidCDF= false;
private boolean listening = true;
/** Creates new form AggregatingDataSourceEditorPanel */
public CdfJavaDataSourceEditorPanel() {
initComponents();
parameterTree.getSelectionModel().setSelectionMode( TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION );
xParameterTree.getSelectionModel().setSelectionMode( TreeSelectionModel.SINGLE_TREE_SELECTION );
yParameterTree.getSelectionModel().setSelectionMode( TreeSelectionModel.SINGLE_TREE_SELECTION );
jPanel3.setVisible(false);
if ( AutoplotHelpSystem.getHelpSystem()!=null ) { // to help with debugging, check for null so we needn't initialize all of Autoplot to debug.
AutoplotHelpSystem.getHelpSystem().registerHelpID(this, "cdf_main");
}
}
/** 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() {
bindingGroup = new org.jdesktop.beansbinding.BindingGroup();
jPanel1 = new javax.swing.JPanel();
jSplitPane2 = new javax.swing.JSplitPane();
jSplitPane1 = new javax.swing.JSplitPane();
jPanel3 = new javax.swing.JPanel();
jLabel4 = new javax.swing.JLabel();
subsetComboBox = new javax.swing.JComboBox();
interpretMetadataLabel = new javax.swing.JLabel();
noInterpMeta = new javax.swing.JCheckBox();
noDep = new javax.swing.JCheckBox();
showAllVarTypeCB = new javax.swing.JCheckBox();
whereCB = new javax.swing.JCheckBox();
whereParamList = new javax.swing.JComboBox();
whereOp = new javax.swing.JComboBox();
whereTF = new javax.swing.JTextField();
filterComboBox = new org.autoplot.datasource.RecentComboBox();
sortAlphaCheckBox = new javax.swing.JCheckBox();
emptyVariablesCB = new javax.swing.JCheckBox();
jTabbedPane1 = new javax.swing.JTabbedPane();
jScrollPane3 = new javax.swing.JScrollPane();
parameterTree = new javax.swing.JTree();
jPanel2 = new javax.swing.JPanel();
jScrollPane4 = new javax.swing.JScrollPane();
xParameterTree = new javax.swing.JTree();
xCheckBox = new javax.swing.JCheckBox();
jPanel4 = new javax.swing.JPanel();
jScrollPane5 = new javax.swing.JScrollPane();
yParameterTree = new javax.swing.JTree();
yCheckBox = new javax.swing.JCheckBox();
jScrollPane2 = new javax.swing.JScrollPane();
paramInfo = new javax.swing.JLabel();
setName("cdfDataSourceEditorPanel"); // NOI18N
setPreferredSize(new java.awt.Dimension(615, 452));
jPanel1.setBorder(javax.swing.BorderFactory.createEtchedBorder());
jPanel1.setPreferredSize(new java.awt.Dimension(615, 452));
jSplitPane2.setDividerLocation(230);
jSplitPane2.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
jSplitPane1.setDividerLocation(320);
jSplitPane1.setResizeWeight(1.0);
jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder("Advanced"));
jPanel3.setMaximumSize(new java.awt.Dimension(285, 32767));
jLabel4.setText("Load subset of the data:");
jLabel4.setToolTipText("Load a subset of the data records, for example:
[0:100] first 100 records
[-100:] last 100 records
[::10] every tenth record
");
subsetComboBox.setEditable(true);
subsetComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "", "::10", "0:100", "-100:", "0:10000:5" }));
subsetComboBox.setToolTipText("Load a subset of the data records, for example:
[0:100] first 100 records
[-100:] last 100 records
[::10] every tenth record
");
interpretMetadataLabel.setText("Interpret Metadata:");
noInterpMeta.setText("no ISTP");
noInterpMeta.setToolTipText("Don't interpret metadata to get titles and units.");
noDep.setText("no dependencies");
noDep.setToolTipText("Ignore connections between variables like \"DEPEND_0\"\n");
showAllVarTypeCB.setText("show all");
showAllVarTypeCB.setToolTipText("show all parameters, even if ISTP VAR_TYPE is not \"data\"");
showAllVarTypeCB.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
showAllVarTypeCBActionPerformed(evt);
}
});
whereCB.setText("Only load data where:");
whereCB.setToolTipText("return only the records where the condition is true");
whereParamList.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
org.jdesktop.beansbinding.Binding binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, whereCB, org.jdesktop.beansbinding.ELProperty.create("${selected}"), whereParamList, org.jdesktop.beansbinding.BeanProperty.create("enabled"));
bindingGroup.addBinding(binding);
whereOp.setModel(new javax.swing.DefaultComboBoxModel(new String[] { ".eq", ".gt", ".lt", ".ne", ".within" }));
binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, whereCB, org.jdesktop.beansbinding.ELProperty.create("${selected}"), whereOp, org.jdesktop.beansbinding.BeanProperty.create("enabled"));
bindingGroup.addBinding(binding);
whereTF.setText("0");
whereTF.setToolTipText("enter the value, or \"mode\" for the most frequently occuring value.");
binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, whereCB, org.jdesktop.beansbinding.ELProperty.create("${selected}"), whereTF, org.jdesktop.beansbinding.BeanProperty.create("enabled"));
bindingGroup.addBinding(binding);
filterComboBox.setToolTipText("Pattern to match in variables names. If this is a valid regular expression, it will be used as such, otherwise the variables containing the string are used.");
filterComboBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
filterComboBoxActionPerformed(evt);
}
});
sortAlphaCheckBox.setText("sort alpha");
sortAlphaCheckBox.setToolTipText("Sort the names alphabetically.");
sortAlphaCheckBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
sortAlphaCheckBoxActionPerformed(evt);
}
});
emptyVariablesCB.setSelected(true);
emptyVariablesCB.setText("empty variables");
emptyVariablesCB.setToolTipText("show variables which have no records");
emptyVariablesCB.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
emptyVariablesCBActionPerformed(evt);
}
});
org.jdesktop.layout.GroupLayout jPanel3Layout = new org.jdesktop.layout.GroupLayout(jPanel3);
jPanel3.setLayout(jPanel3Layout);
jPanel3Layout.setHorizontalGroup(
jPanel3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(jPanel3Layout.createSequentialGroup()
.addContainerGap()
.add(whereParamList, 0, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(whereOp, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 84, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(whereTF, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 53, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
.add(jPanel3Layout.createSequentialGroup()
.add(jPanel3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(jLabel4)
.add(whereCB)
.add(interpretMetadataLabel)
.add(jPanel3Layout.createSequentialGroup()
.add(12, 12, 12)
.add(jPanel3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(jPanel3Layout.createSequentialGroup()
.add(jPanel3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(noInterpMeta)
.add(showAllVarTypeCB)
.add(sortAlphaCheckBox))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
.add(jPanel3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(filterComboBox, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.add(noDep)
.add(emptyVariablesCB)))
.add(subsetComboBox, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 160, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))))
.add(0, 0, Short.MAX_VALUE))
);
jPanel3Layout.setVerticalGroup(
jPanel3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(jPanel3Layout.createSequentialGroup()
.add(jLabel4)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(subsetComboBox, 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(whereCB)
.add(8, 8, 8)
.add(jPanel3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(whereParamList, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.add(whereOp, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.add(whereTF, 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(interpretMetadataLabel)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(jPanel3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(noInterpMeta)
.add(noDep))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(jPanel3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(showAllVarTypeCB)
.add(filterComboBox, 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(jPanel3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(sortAlphaCheckBox)
.add(emptyVariablesCB)))
);
jSplitPane1.setRightComponent(jPanel3);
jTabbedPane1.addChangeListener(new javax.swing.event.ChangeListener() {
public void stateChanged(javax.swing.event.ChangeEvent evt) {
jTabbedPane1StateChanged(evt);
}
});
parameterTree.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() {
public void valueChanged(javax.swing.event.TreeSelectionEvent evt) {
parameterTreeValueChanged(evt);
}
});
jScrollPane3.setViewportView(parameterTree);
jTabbedPane1.addTab("Data", jScrollPane3);
xParameterTree.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() {
public void valueChanged(javax.swing.event.TreeSelectionEvent evt) {
xParameterTreeValueChanged(evt);
}
});
jScrollPane4.setViewportView(xParameterTree);
xCheckBox.setText("Set Variable for X");
xCheckBox.setToolTipText("Specify the parameter to use for the X tags, overriding any settings found in the file.");
xCheckBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
xCheckBoxActionPerformed(evt);
}
});
org.jdesktop.layout.GroupLayout jPanel2Layout = new org.jdesktop.layout.GroupLayout(jPanel2);
jPanel2.setLayout(jPanel2Layout);
jPanel2Layout.setHorizontalGroup(
jPanel2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(xCheckBox, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 401, Short.MAX_VALUE)
.add(jScrollPane4)
);
jPanel2Layout.setVerticalGroup(
jPanel2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(jPanel2Layout.createSequentialGroup()
.add(xCheckBox)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(jScrollPane4, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 169, Short.MAX_VALUE))
);
jTabbedPane1.addTab("X", jPanel2);
yParameterTree.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() {
public void valueChanged(javax.swing.event.TreeSelectionEvent evt) {
yParameterTreeValueChanged(evt);
}
});
jScrollPane5.setViewportView(yParameterTree);
yCheckBox.setText("Set Variable for Y");
yCheckBox.setToolTipText("Specify the parameter to use for the Y tags, overriding any settings found in the file.");
org.jdesktop.layout.GroupLayout jPanel4Layout = new org.jdesktop.layout.GroupLayout(jPanel4);
jPanel4.setLayout(jPanel4Layout);
jPanel4Layout.setHorizontalGroup(
jPanel4Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(yCheckBox, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 401, Short.MAX_VALUE)
.add(jScrollPane5)
);
jPanel4Layout.setVerticalGroup(
jPanel4Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(jPanel4Layout.createSequentialGroup()
.add(yCheckBox)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(jScrollPane5, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 169, Short.MAX_VALUE))
);
jTabbedPane1.addTab("Y", jPanel4);
jSplitPane1.setLeftComponent(jTabbedPane1);
jSplitPane2.setTopComponent(jSplitPane1);
jScrollPane2.setMaximumSize(new java.awt.Dimension(1000, 600));
paramInfo.setText("Variable");
paramInfo.setVerticalAlignment(javax.swing.SwingConstants.TOP);
paramInfo.setMaximumSize(new java.awt.Dimension(1000, 4000));
paramInfo.setPreferredSize(new java.awt.Dimension(600, 100));
paramInfo.setVerticalTextPosition(javax.swing.SwingConstants.TOP);
jScrollPane2.setViewportView(paramInfo);
jSplitPane2.setRightComponent(jScrollPane2);
org.jdesktop.layout.GroupLayout jPanel1Layout = new org.jdesktop.layout.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(org.jdesktop.layout.GroupLayout.TRAILING, jPanel1Layout.createSequentialGroup()
.addContainerGap()
.add(jSplitPane2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 675, Short.MAX_VALUE)
.addContainerGap())
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.add(jSplitPane2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 425, Short.MAX_VALUE)
.addContainerGap())
);
org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(jPanel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(org.jdesktop.layout.GroupLayout.TRAILING, jPanel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
bindingGroup.bind();
}// //GEN-END:initComponents
private void showAllVarTypeCBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showAllVarTypeCBActionPerformed
org.das2.util.LoggerManager.logGuiEvent(evt);
setURI( getURI() );
}//GEN-LAST:event_showAllVarTypeCBActionPerformed
private void jTabbedPane1StateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_jTabbedPane1StateChanged
int tab= jTabbedPane1.getSelectedIndex();
updateMetadata(tab);
}//GEN-LAST:event_jTabbedPane1StateChanged
private void yParameterTreeValueChanged(javax.swing.event.TreeSelectionEvent evt) {//GEN-FIRST:event_yParameterTreeValueChanged
yCheckBox.setSelected(true);
TreePath tp= evt.getPath();
if ( isValidCDF ) {
yparameter= String.valueOf(tp.getPathComponent(1));
String longName= yparameterInfo.get(yparameter);
paramInfo.setText( longName );
}
}//GEN-LAST:event_yParameterTreeValueChanged
private void xCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_xCheckBoxActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_xCheckBoxActionPerformed
private void xParameterTreeValueChanged(javax.swing.event.TreeSelectionEvent evt) {//GEN-FIRST:event_xParameterTreeValueChanged
xCheckBox.setSelected(true);
TreePath tp= evt.getPath();
if ( isValidCDF ) {
xparameter= String.valueOf(tp.getPathComponent(1));
String longName= xparameterInfo.get(xparameter);
paramInfo.setText( longName );
}
}//GEN-LAST:event_xParameterTreeValueChanged
private void parameterTreeValueChanged(javax.swing.event.TreeSelectionEvent evt) {//GEN-FIRST:event_parameterTreeValueChanged
TreePath tp= evt.getPath();
if ( isValidCDF && listening ) {
parameter= String.valueOf(tp.getPathComponent(1));
String s;
String slice1;
slice1= "";
s= getParamAndSubset(xParameterTree,"");
if ( xparameter!=null && xparameter.length()<=s.length() ) {
slice1= s.substring(xparameter.length());
}
LinkedHashMap xx= getCompatible( cdfParameterInfo, parameter, X_PARAMETER );
fillTree( xParameterTree, toDescriptions(xx), cdf, xparameter, slice1 );
s= getParamAndSubset(yParameterTree,"");
slice1= "";
if ( yparameter!=null && yparameter.length()<=s.length() ) {
slice1= s.substring(yparameter.length());
}
LinkedHashMap yy= getCompatible( cdfParameterInfo, parameter, Y_PARAMETER );
fillTree( yParameterTree, toDescriptions(yy), cdf, yparameter, slice1 );
updateMetadata();
}
}//GEN-LAST:event_parameterTreeValueChanged
/**
* convert the CdfVariableDescription blocks into an html page describing the variables.
* @param xx
* @return
*/
private Map toDescriptions( LinkedHashMap xx ) {
LinkedHashMap result= new LinkedHashMap<>();
for ( Entry e: xx.entrySet() ) {
CdfVariableDescription desc=e.getValue();
result.put( e.getKey(), desc.htmlDescription );
}
return result;
}
/**
* return the list of variables which are compatible with this parameter, having the same number
* of records, etc.
* @param parameter
* @param whichIndependentParameter X_PARAMETER, Y_PARAMETER
* @return a linked hash map of name to descriptions.
*/
public static LinkedHashMap getCompatible(
LinkedHashMap cdfParameterInfo, String parameter, Object whichIndependentParameter ) {
CdfVariableDescription dependent= cdfParameterInfo.get(parameter);
LinkedHashMap result= new LinkedHashMap<>();
for ( Entry cvds : cdfParameterInfo.entrySet() ) {
CdfVariableDescription cvd = cvds.getValue();
if ( dependent!=null && whichIndependentParameter==X_PARAMETER ) {
if ( cvd.numberOfRecords==dependent.numberOfRecords ) {
if ( cvd.dimensions.length==0 || ( cvd.dimensions.length==1 && cvd.dimensions[0]==2 ) ) {
result.put( cvd.name, cvd );
}
}
} else if ( dependent!=null && whichIndependentParameter==Y_PARAMETER) {
if ( cvd.dimensions.length==1 && dependent.dimensions.length==1
&& cvd.dimensions[0]==dependent.dimensions[0] ) {
if ( cvd.numberOfRecords==1 ) {
result.put( cvd.name, cvd );
} else if ( cvd.numberOfRecords==dependent.numberOfRecords ) {
result.put( cvd.name, cvd );
}
} else if ( cvd.dimensions.length==0 && dependent.dimensions.length==0
&& cvd.numberOfRecords==dependent.numberOfRecords ) {
result.put( cvd.name, cvd );
}
} else {
result.put( cvd.name, cvd );
}
}
return result;
}
private void filterComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_filterComboBoxActionPerformed
updateTree();
}//GEN-LAST:event_filterComboBoxActionPerformed
private void sortAlphaCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sortAlphaCheckBoxActionPerformed
updateTree();
}//GEN-LAST:event_sortAlphaCheckBoxActionPerformed
private void emptyVariablesCBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_emptyVariablesCBActionPerformed
setURI( getURI() );
}//GEN-LAST:event_emptyVariablesCBActionPerformed
private void updateTree() {
String param = getParam();
fillTree( this.parameterTree, parameterInfo, cdf, param, "" );
}
private void updateMetadata() {
updateMetadata(0);
}
private void updateMetadata( int tab ) {
switch (tab) {
case 0:
if ( parameter!=null ) {
String longName= parameterInfo.get(parameter);
paramInfo.setText( longName );
break;
}
case 1:
if ( xparameter!=null ) {
String longName= xparameterInfo.get(xparameter);
paramInfo.setText( longName );
break;
}
case 2:
if ( yparameter!=null ) {
String longName= yparameterInfo.get(yparameter);
paramInfo.setText( longName );
break;
}
default:
break;
}
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JCheckBox emptyVariablesCB;
private org.autoplot.datasource.RecentComboBox filterComboBox;
private javax.swing.JLabel interpretMetadataLabel;
private javax.swing.JLabel jLabel4;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel2;
private javax.swing.JPanel jPanel3;
private javax.swing.JPanel jPanel4;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JScrollPane jScrollPane3;
private javax.swing.JScrollPane jScrollPane4;
private javax.swing.JScrollPane jScrollPane5;
private javax.swing.JSplitPane jSplitPane1;
private javax.swing.JSplitPane jSplitPane2;
private javax.swing.JTabbedPane jTabbedPane1;
private javax.swing.JCheckBox noDep;
private javax.swing.JCheckBox noInterpMeta;
private javax.swing.JLabel paramInfo;
private javax.swing.JTree parameterTree;
private javax.swing.JCheckBox showAllVarTypeCB;
private javax.swing.JCheckBox sortAlphaCheckBox;
private javax.swing.JComboBox subsetComboBox;
private javax.swing.JCheckBox whereCB;
private javax.swing.JComboBox whereOp;
private javax.swing.JComboBox whereParamList;
private javax.swing.JTextField whereTF;
private javax.swing.JCheckBox xCheckBox;
private javax.swing.JTree xParameterTree;
private javax.swing.JCheckBox yCheckBox;
private javax.swing.JTree yParameterTree;
private org.jdesktop.beansbinding.BindingGroup bindingGroup;
// End of variables declaration//GEN-END:variables
@Override
public JPanel getPanel() {
if (showAllInitially) {
SwingUtilities.invokeLater( new Runnable() {
@Override
public void run() {
showAllVarTypeCB.setSelected(true);
setURI( getURI() );
}
});
}
return this;
}
JComponent delegateComponent = null;
DataSetSelector delegateDataSetSelector=null;
DataSourceEditorPanel delegateEditorPanel= null;
/**
* extra URI parameters that are not supported in the dialog.
*/
Map params;
String vapScheme;
/**
* the location of the CDF file.
*/
URI resourceUri;
/**
* short descriptions of the parameters
*/
Map parameterDescriptions;
/**
* long descriptions html formatted metadata about each parameter.
*/
Map parameterInfo;
/**
* long descriptions html formatted metadata about each parameter.
*/
Map xparameterInfo;
/**
* long descriptions html formatted metadata about each parameter.
*/
Map yparameterInfo;
/**
* new descriptions of variables with size and lengths
*/
LinkedHashMap cdfParameterInfo;
String parameter;
String xparameter;
String yparameter;
public static final String X_PARAMETER = "X_PARAMETER";
public static final String Y_PARAMETER = "Y_PARAMETER";
boolean showAllInitially= false;
/**
* can I reuse the slice? Only if the maxRec doesn't change.
*/
long subsetMaxRec=-1;
File cdfFile;
CDFReader cdf;
Throwable cdfException;
/**
* allow more abstract sources, namely cdaweb, to turn off these controls.
* @param v
*/
public void setShowAdvancedSubpanel( boolean v ) {
noDep.setVisible(v);
noInterpMeta.setVisible(v);
//showAllVarTypeCB.setVisible(v);
}
@Override
public boolean reject( String url ) throws IOException, URISyntaxException {
URISplit split = URISplit.parse(url);
if ( split.resourceUri==null ) {
return true;
}
FileSystem fs = FileSystem.create( DataSetURI.getWebURL( DataSetURI.toUri(split.path) ).toURI() );
return fs.isDirectory( split.file.substring(split.path.length()) );
}
@Override
public boolean prepare( String url, java.awt.Window parent, ProgressMonitor mon) throws Exception {
URISplit split= URISplit.parse(url);
cdfFile= DataSetURI.getFile( split.resourceUri, mon );
DataSetURI.checkLength(cdfFile);
logger.log(Level.FINE, "opening cdf file {0}", cdfFile.toString());
try {
CdfDataSource.checkCdf(cdfFile);
cdf = CdfDataSource.getCdfFile(cdfFile.toString());
if ( cdf==null ) {
throw new IllegalArgumentException("file is not a CDF file");
}
cdfException= null;
} catch ( IOException | IllegalArgumentException ex ) {
cdfException= ex;
}
return true;
}
public static String getKeyForFile( String filename ) {
int j=filename.indexOf("19");
if ( j==-1 ) j= filename.indexOf("20");
if ( j==-1 ) j= filename.length();
while ( j>0 && filename.charAt(j-1)=='_' ) j=j-1;
String key= filename.substring(0,j);
return key;
}
@Override
public void setURI(String url) {
URISplit split= URISplit.parse(url);
vapScheme= split.vapScheme;
Map lparams= URISplit.parseParams(split.params);
try {
resourceUri= split.resourceUri;
cdfFile= DataSetURI.getFile( split.resourceUri, new NullProgressMonitor() );
DataSetURI.checkLength(cdfFile);
String fileName= cdfFile.toString();
String key= getKeyForFile( split.file.substring(split.path.length()) );
filterComboBox.setPreferenceNode("cdf_"+key);
filterComboBox.setToolTipText("Filter parameters");
logger.log(Level.FINE, "opening cdf file {0}", fileName);
if ( cdf==null && cdfException==null ) {
try {
cdf = CdfDataSource.getCdfFile(fileName);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
if ( cdfException!=null ) {
this.parameterTree.setModel( new DefaultTreeModel( new DefaultMutableTreeNode("") ) );
this.paramInfo.setText( "Unable to read CDF file:
"+cdfException.getMessage() );
return;
}
logger.finest("inspect cdf for plottable parameters");
boolean isMaster= fileName.contains("MASTERS");
Map options= new HashMap<>();
options.put( org.autoplot.cdf.CdfUtil.OPTION_INCLUDE_EMPTY_RECORDS, String.valueOf(this.emptyVariablesCB.isSelected()) );
options.put( org.autoplot.cdf.CdfUtil.OPTION_IS_MASTER, String.valueOf(isMaster) );
options.put( org.autoplot.cdf.CdfUtil.OPTION_DEEP, String.valueOf(true) );
try {
parameterDescriptions= org.autoplot.cdf.CdfUtil.getPlottable(cdf, !this.showAllVarTypeCB.isSelected(),
QDataSet.MAX_RANK);
} catch ( Exception ex ) {
this.parameterTree.setModel( new DefaultTreeModel( new DefaultMutableTreeNode("") ) );
this.paramInfo.setText( "Unable to work with metadata in CDF file:
"+ex );
throw ex;
}
Map allParameterInfo= org.autoplot.cdf.CdfUtil.getPlottable(cdf, false, QDataSet.MAX_RANK, options );
Map dataParameterInfo= org.autoplot.cdf.CdfUtil.getPlottable(cdf, true, QDataSet.MAX_RANK, options );
options.put( org.autoplot.cdf.CdfUtil.OPTION_DEEP, String.valueOf( false ) );
Map whereParameterInfo= org.autoplot.cdf.CdfUtil.getPlottable(cdf, false, 2, options);
cdfParameterInfo= org.autoplot.cdf.CdfUtil.getPlottable(cdf, options);
String param= lparams.remove("arg_0");
String[] params= null;
if ( param!=null ) {
params= param.split(";",-2);
for ( String p : params ) {
if ( !dataParameterInfo.containsKey(p) ) {
this.showAllVarTypeCB.setSelected(true);
parameterDescriptions= org.autoplot.cdf.CdfUtil.getPlottable(cdf,
!this.showAllVarTypeCB.isSelected(), QDataSet.MAX_RANK, new HashMap());
this.showAllVarTypeCB.setEnabled(false);
}
}
}
if ( dataParameterInfo.isEmpty() && !cdfParameterInfo.isEmpty() ) {
this.showAllVarTypeCB.setSelected(true);
}
String label;
if ( this.showAllVarTypeCB.isSelected() ) {
parameterInfo= allParameterInfo;
label= "Select CDF Variable (%d data, %d support):";
} else {
parameterInfo= dataParameterInfo;
label= "Select CDF Variable (%d data, %d support not shown):";
}
xparameterInfo= allParameterInfo;
yparameterInfo= allParameterInfo;
this.isValidCDF= true;
jPanel3.setVisible(true);
int numData= dataParameterInfo.size();
int numSupport= allParameterInfo.size() - numData;
//this.selectVariableLabel.setText( String.format( label, numData, numSupport ) );
if ( this.showAllVarTypeCB.isSelected() ) {
this.jTabbedPane1.setTitleAt( 0, String.format( "Select CDF Variable (of %d)", numData+numSupport ) );
} else {
this.jTabbedPane1.setTitleAt( 0, String.format( "Select CDF Variable (of %d)", numData ) );
}
this.jTabbedPane1.setToolTipText( String.format( label, numData, numSupport ) );
if ( this.showAllVarTypeCB.isSelected() ) {
this.showAllVarTypeCB.setText("show all ("+numSupport+" support shown)");
} else {
this.showAllVarTypeCB.setText("show all ("+numSupport+" support not shown)");
}
Pattern slice1pattern= Pattern.compile("\\[\\:\\,(\\d+)\\]");
String slice= lparams.remove("slice1"); // legacy
Pattern slice2pattern= Pattern.compile("\\[\\:\\,\\:\\,(\\d+)\\]");
String subset= null;
if ( param!=null ) {
int i= param.indexOf("[");
if ( i!=-1 ) {
subset= param.substring(i);
param= param.substring(0,i);
Matcher m= slice1pattern.matcher(subset);
if ( m.matches() ) {
slice= m.group(1);
subset= null;
}
if ( subset!=null ) {
m= slice2pattern.matcher(subset);
if ( m.matches() ) {
slice= m.group(1);
subset= null;
}
}
}
}
if ( allParameterInfo.containsKey(param) ) {
if ( !dataParameterInfo.containsKey(param) ) {
showAllInitially= true;
}
}
listening= false;
if ( params!=null && params.length>1 ) {
fillTree( this.parameterTree, parameterInfo, cdf, param, slice );
} else {
fillTree( this.parameterTree, parameterInfo, cdf, param, slice );
}
listening= true;
Map parameterDescriptions2= org.autoplot.cdf.CdfUtil.getPlottable(cdf, false, 2 );
String xparam= lparams.remove("depend0");
String xslice1= null;
if ( xparam==null ) xparam= lparams.remove("X");
if ( xparam==null ) xparam= lparams.remove("x");
if ( xparam!=null ) {
int i= xparam.indexOf("[");
if ( i!=-1 ) {
String xsubset= xparam.substring(i);
xparam= xparam.substring(0,i);
Matcher m= slice1pattern.matcher(xsubset);
if ( m.matches() ) {
xslice1= m.group(1);
}
}
}
fillTree(this.xParameterTree, parameterDescriptions2, cdf, xparam, xslice1 );
String yslice1= null;
String yparam= lparams.remove("Y");
if ( yparam==null ) yparam= lparams.remove("y");
if ( yparam!=null ) {
int i= yparam.indexOf("[");
if ( i!=-1 ) {
String ysubset= yparam.substring(i);
yparam= yparam.substring(0,i);
Matcher m= slice1pattern.matcher(ysubset);
if ( m.matches() ) {
yslice1= m.group(1);
}
}
}
fillTree(this.yParameterTree, parameterDescriptions2, cdf, yparam, yslice1 );
logger.finest("close cdf");
DefaultComboBoxModel cbmodel= new DefaultComboBoxModel();
for ( String p: parameterDescriptions.keySet() ) {
cbmodel.addElement(p);
}
if ( param!=null ) {
if ( subset!=null ) {
if ( subset.startsWith("[") ) subset= subset.substring(1);
if ( subset.endsWith("]") ) subset= subset.substring(0,subset.length()-1);
subsetComboBox.setSelectedItem( subset );
} else {
subsetComboBox.setSelectedItem("");
}
} else {
if ( !parameterDescriptions.isEmpty() ) {
parameter= parameterDescriptions.entrySet().iterator().next().getKey();
subsetComboBox.setSelectedItem("");
param= parameter;
paramInfo.setText("");
} else {
param= "";
if ( this.parameterTree.getRowCount()==0 && numSupport>0 && numData==0 && !this.showAllVarTypeCB.isSelected() ) {
paramInfo.setText("(all parameters are marked as support data, select \"show all\" above)");
} else {
paramInfo.setText("(no plottable parameters)");
}
}
}
parameter= param.replaceAll("%3D", "=");
if ( "no".equals( lparams.remove("interpMeta")) ) {
noInterpMeta.setSelected(true);
}
if ( "no".equals( lparams.remove("doDep" ) ) ) {
noDep.setSelected(true);
}
whereParamList.setModel( new DefaultComboBoxModel( whereParameterInfo.keySet().toArray() ) );
String where= lparams.remove("where");
if ( where!=null && where.length()>0 ) {
whereCB.setSelected(true);
int i= where.indexOf(".");
if ( i>-1 ) {
whereParamList.setSelectedItem(where.substring(0,i));
int i0= where.indexOf("(");
int i1= where.indexOf(")",i0);
whereOp.setSelectedItem(where.substring(i,i0));
whereTF.setText( where.substring(i0+1,i1).replaceAll("\\+"," "));
}
} else {
whereCB.setSelected(false);
}
updateMetadata();
} catch (IOException ex) {
DasExceptionHandler.handle( ex );
logger.log(Level.SEVERE, ex.getMessage(), ex);
} catch (IllegalArgumentException ex) {
DasExceptionHandler.handle( ex );
logger.log(Level.SEVERE, ex.getMessage(), ex);
} catch (Exception ex) {
DasExceptionHandler.handle( ex );
logger.log(Level.SEVERE, ex.getMessage(), ex);
}
this.params= lparams;
}
/**
* return the name of the selected parameter, or null.
* @return
*/
private String getParam() {
TreePath treePath= parameterTree.getSelectionPath();
String p;
if ( treePath==null ) {
return null;
} else {
p= String.valueOf( treePath.getPathComponent(1) );
p= p.replaceAll("=", "%3D");
}
return p;
}
/**
* return the parameter, if something is selected, possibly with [:,n] to indicate a slice should be done.
* @param jtree the tree showing the selection
* @param subset subset by index, like [::2] for every other element.
* @return empty string if no selection, or the path.
*/
private String getParamAndSubset( JTree jtree, String subset ) {
StringBuilder ps= new StringBuilder();
TreePath[] tps= jtree.getSelectionPaths(); // typically this will be a one-element array.
if ( tps==null ) tps= new TreePath[] { jtree.getSelectionPath() };
for ( TreePath treePath : tps ) {
if ( ps.length()>0 ) ps.append(";");
if ( treePath==null ) {
logger.fine("param was null");
} else if ( treePath.getPathCount()==3 ) {
String p= String.valueOf( treePath.getPathComponent(1) );
p= p.replaceAll("=", "%3D");
String val= String.valueOf( treePath.getPathComponent(2) );
int dims= 1;
try {
dims= cdf.getDimensions(p).length;
} catch ( ReaderError e ) {
e.printStackTrace();
}
if ( dims==2 ) {
int idx= val.indexOf(":");
ps.append(p).append("[:,:,").append(val.substring(0,idx).trim()).append("]");
} else {
int idx= val.indexOf(":");
ps.append(p).append("[:,").append(val.substring(0,idx).trim()).append("]");
}
} else {
String p= String.valueOf( treePath.getPathComponent(1) );
p= p.replaceAll("=", "%3D");
ps.append(p).append(subset);
}
}
return ps.toString();
}
@Override
public String getURI() {
URISplit split= URISplit.parse(resourceUri);
split.vapScheme= this.vapScheme;
String subset= subsetComboBox.getSelectedItem().toString().trim();
if ( subset.length()>0 && subset.charAt(0)!='[' ) {
subset= "["+subset+"]";
}
Map lparams= this.params;
if ( lparams!=null ) {
lparams= new HashMap(lparams);
} else {
lparams= new HashMap();
}
if ( isValidCDF ) {
TreePath[] tps= parameterTree.getSelectionPaths();
if ( tps!=null ) {
String p= getParamAndSubset(parameterTree,subset);
if ( p.length()>0 ) lparams.put( "arg_0", p );
}
if ( xCheckBox.isSelected() ) {
String p = getParamAndSubset(xParameterTree,"");
if ( p.length()>0 ) lparams.put( "X", p );
}
if ( yCheckBox.isSelected() ) {
String p= getParamAndSubset(yParameterTree,"");
if ( p.length()>0 ) lparams.put( "Y", p );
}
if ( noDep.isSelected() ) {
lparams.put("doDep","no");
}
if ( noInterpMeta.isSelected() ) {
lparams.put("interpMeta", "no");
}
if ( whereCB.isSelected() ) {
if ( whereParamList.getSelectedItem()!=null ) {
lparams.put( "where", String.format( "%s%s(%s)", whereParamList.getSelectedItem(), whereOp.getSelectedItem(), whereTF.getText().replaceAll(" ","+") ) );
} else {
lparams.remove("where");
}
} else {
lparams.remove("where");
}
}
split.params= URISplit.formatParams(lparams);
if ( split.params!=null && split.params.length()==0 ) split.params= null;
return URISplit.format(split);
}
@Override
public void markProblems(List problems) {
}
/**
* fill the parameter tree using metadata.
* @param parameterTree the tree which will contain the parameter list.
* @param mm the metadata map from parameter names to html descriptions.
* @param cdf the cdf file.
* @param param null or the name of the parameter which should be selected.
* @param slice1 null or the slice selection (X,Y,Z of BGSM, for example).
*/
private void fillTree( JTree parameterTree, Map mm, gov.nasa.gsfc.spdf.cdfj.CDFReader cdf, String param, String slice1 ) {
logger.entering( "CdfJavaDataSourceEditorPanel", "fillTree" );
DefaultMutableTreeNode root= new DefaultMutableTreeNode("");
List expand=new ArrayList(mm.size());
String filter= filterComboBox.getText().trim();
Pattern filterPattern= null;
if ( filter.length()>0 ) {
try {
filterPattern= Pattern.compile(filter,Pattern.CASE_INSENSITIVE);
} catch ( PatternSyntaxException ex ) {
filterPattern= Pattern.compile( Pattern.quote(filter), Pattern.CASE_INSENSITIVE );
}
}
boolean sortAlpha= sortAlphaCheckBox.isSelected();
if ( sortAlpha ) {
Map sortedMM= new TreeMap<>();
sortedMM.putAll(mm);
mm= sortedMM;
}
List selections= new ArrayList<>();
List params;
if ( param!=null ) {
params = Arrays.asList(param.split(";"));
} else {
params= new ArrayList<>();
}
TreePath selection=null;
for ( Entry e: mm.entrySet() ) {
String varname = e.getKey();
if ( filterPattern!=null ) {
if ( filterPattern.matcher( varname ).find() ||
filterPattern.matcher( e.getValue() ).find() ) {
logger.log(Level.FINER, "found pattern for {0}", varname );
} else {
continue;
}
}
try {
Object oattr= cdf.getAttribute( varname, "LABL_PTR_2");
String lablPtr=null;
if ( oattr!=null && oattr instanceof List ) {
List voattr= (List)oattr;
if ( voattr.size()>0 ) {
lablPtr= (String)((List)oattr).get(0);
} else {
oattr= Collections.emptyList();
}
}
if ( oattr!=null && oattr instanceof List && ((List)oattr).size()==0 ) {
oattr= cdf.getAttribute( varname, "LABL_PTR_1");
if ( oattr!=null && oattr instanceof List ) {
List voattr= (List)oattr;
if ( voattr.size()>0 ) {
lablPtr= (String)((List)oattr).get(0);
} else {
oattr= null;
}
}
}
int[] dimensions= cdf.getDimensions( varname );
boolean doComponents= oattr!=null && ( dimensions.length==1 || dimensions.length==2 ) && dimensions[dimensions.length-1]<=MAX_SLICE1_OFFER;
if ( doComponents ) {
String s= lablPtr;
DefaultMutableTreeNode node= new DefaultMutableTreeNode( varname );
try {
Object o = cdf.get(s);
String[] rec;
if ( o.getClass().isArray() && String.class.isAssignableFrom( o.getClass().getComponentType() ) ) {
rec= (String[])o;
} else {
Object oo= Array.get(o,0);
if ( !oo.getClass().isArray() || !( String.class.isAssignableFrom( oo.getClass().getComponentType() ) ) ) {
logger.log(Level.FINE, "Expected string array in element: {0}", s);
continue;
}
rec= (String[])Array.get(o,0);
}
for ( int i=0; i0 ) {
parameterTree.setSelectionPaths( selections.toArray(new TreePath[selections.size()]) );
}
for ( TreePath tp: expand ) {
parameterTree.expandPath(tp);
}
logger.exiting("CdfJavaDataSourceEditorPanel", "fillTree" );
}
private static boolean isSupportParameter(Map dataParameterInfo, String param) {
if ( param==null || param.trim().length()==0 ) {
return false;
}
String[] params;
if ( param.contains(";") ) {
params= param.split(";");
} else {
params= new String[] { param };
}
for ( String p: params ) {
CdfVariableDescription cdfvd= dataParameterInfo.get(p);
if ( cdfvd!=null ) { // sure hope so
if ( cdfvd.isSupport ) return true;
}
}
return false;
}
}