/*
* Copyright 1998-2014 University Corporation for Atmospheric Research/Unidata
*
* Portions of this software were developed by the Unidata Program at the
* University Corporation for Atmospheric Research.
*
* Access and use of this software shall impose the following obligations
* and understandings on the user. The user is granted the right, without
* any fee or cost, to use, copy, modify, alter, enhance and distribute
* this software, and any derivative works thereof, and its supporting
* documentation for any purpose whatsoever, provided that this entire
* notice appears in all copies of the software, derivative works and
* supporting documentation. Further, UCAR requests that the user credit
* UCAR/Unidata in any publications that result from the use of this
* software or in any product that includes this software. The names UCAR
* and/or Unidata, however, may not be used in any advertising or publicity
* to endorse or promote any products or commercial entity unless specific
* written permission is obtained from UCAR/Unidata. The user also
* understands that UCAR/Unidata is not obligated to provide the user with
* any support, consulting, training or assistance of any kind with regard
* to the use, operation and performance of this software nor to provide
* the user with any updates, revisions, new versions or "bug fixes."
*
* THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package ucar.nc2.ui;
import java.awt.BorderLayout;
import java.io.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableModel;
import ucar.ma2.Array;
import ucar.ma2.InvalidRangeException;
import ucar.nc2.Attribute;
import ucar.nc2.Dimension;
import ucar.nc2.NetcdfFile;
import ucar.nc2.Variable;
import ucar.nc2.constants.CDM;
import ucar.nc2.dataset.CoordinateAxis1DTime;
import ucar.nc2.dataset.NetcdfDataset;
import ucar.nc2.dataset.VariableDS;
import ucar.nc2.time.CalendarDate;
import ucar.nc2.time.CalendarDateFormatter;
import ucar.nc2.time.CalendarPeriod;
import ucar.nc2.time.CalendarTimeZone;
import ucar.nc2.ui.widget.FileManager;
import ucar.util.prefs.PreferencesExt;
public class VariableTable extends JPanel {
final private org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(this.getClass());
private PreferencesExt prefs;
private FileManager fileChooser; // for exporting
List col0 = null;
Array[] data = null;
public VariableTable(PreferencesExt prefs) {
this.prefs = prefs;
PreferencesExt fcPrefs = (prefs == null) ? null : (PreferencesExt) prefs.node("FileManager");
fileChooser = new FileManager(null, null, "csv", "comma seperated values", fcPrefs);
}
// clear the table
public void clear() {
if (dataModel != null)
dataModel.clear();
col0 = null;
}
// save state
public void saveState() {
fileChooser.save();
}
int col0Dim = -1;
private boolean col0isDate = false;
public void setVariableList(List<Variable> vl) {
int length = 1;
int i = 0;
// find the number of columns, get shape for each variable after the first DIMENSON
for(Variable v : vl) {
int[] shape = v.getShape();
length = 1;
for(int j=1;j<shape.length;j++) {
length *= shape[j];
}
i += length;
log.info("Length " + length + " i = " + i + " var " + v.getDimensionsString());
}
length = i;
columnNames = new String[length + 1];
data = new Array[length];
// Add each variable to the list of data, and also create column names
i = 0;
for(Variable v : vl)
{
log.info("Variable " + v.getShortName());
List<Dimension> vd = v.getDimensions();
int dimNo = 0;
for(Dimension d : vd) {
//System.out.println("Dimensions " + d + " " + d.getLength());
Variable dimVar = file.findVariable(d.getShortName());
if (dimVar != null) {
Attribute axis = dimVar.findAttribute("axis");
if ((axis != null) && axis.isString() && (axis.getStringValue().compareTo("T") == 0)) {
//System.out.println("Time AXIS");
CoordinateAxis1DTime tm;
try {
tm = CoordinateAxis1DTime.factory(fds, new VariableDS(null, dimVar, true), null);
col0 = tm.getCalendarDates();
col0Dim = dimNo;
col0isDate = true;
} catch (IOException e) {
e.printStackTrace();
}
}
}
dimNo++;
//System.out.println("Dimension Variable " + dimVar);
}
int[] shape = v.getShape();
if (col0Dim < 0) {
col0 = new ArrayList();
for(int j=0;j<shape[0];j++) {
col0.add(j);
}
col0Dim = 0;
}
columnNames[0] = vd.get(col0Dim).getShortName();
try {
if ((shape.length > 1) && (shape[1] > 1)) {
Variable dimVar = file.findVariable(v.getDimension(1).getShortName());
Array dimArray = null;
if (dimVar != null)
dimArray = dimVar.read();
for (int j=0;j<shape[1];j++) {
data[i] = v.slice(1, j).read();
if (dimVar != null) {
columnNames[i+1] = v.getShortName() + "[" + dimArray.getDouble(j) + "]";
}
else {
columnNames[i+1] = v.getShortName() + "[" + j + "]";
}
Attribute unit = v.findAttribute("units");
if ((unit != null) && unit.isString()) {
columnNames[i+1] += " (" + unit.getStringValue() + ")";
}
i++;
}
}
else
{
data[i] = v.read();
columnNames[i+1] = v.getShortName();
Attribute unit = v.findAttribute("units");
if ((unit != null) && unit.isString()) {
columnNames[i+1] += " (" + unit.getStringValue() + ")";
}
i++;
}
} catch (IOException e) {
e.printStackTrace();
} catch (InvalidRangeException e) {
e.printStackTrace();
}
}
}
NetcdfFile file;
NetcdfDataset fds;
public void setDataset(NetcdfFile ds) {
file = ds;
try {
fds = new NetcdfDataset(file);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
String[] columnNames;
class VariableTableModel extends AbstractTableModel {
@Override
public int getColumnCount() {
return data.length+1;
}
public void clear() {
// TODO Auto-generated method stub
}
public String getColumnName(int col) {
return columnNames[col];
}
public Class getColoumClass(int col) {
return String.class;
}
@Override
public int getRowCount() {
return col0.size();
}
@Override
public Object getValueAt(int row, int col) {
if (col == 0) {
return col0.get(row);
}
return data[col-1].getObject(row);
}
}
VariableTableModel dataModel = new VariableTableModel();
public void createTable() {
this.setLayout(new BorderLayout());
JTable table = new JTable(dataModel);
table.setPreferredScrollableViewportSize(new java.awt.Dimension(500, 70));
if (col0isDate) {
table.getColumnModel().getColumn(0).setCellRenderer(new DateRenderer());
}
table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
//Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(table);
//Add the scroll pane to this panel.
this.removeAll();
table.setFillsViewportHeight(true);
add(scrollPane);
includeGlobals = new JCheckBox("Export Attributes");
JButton export = new JButton("Export");
export.addActionListener(new AbstractAction() {
public void actionPerformed(java.awt.event.ActionEvent e) {
export();
}
});
JPanel holderPanel = new JPanel(new BorderLayout());
holderPanel.add(export, BorderLayout.EAST);
holderPanel.add(includeGlobals, BorderLayout.CENTER);
add(holderPanel, BorderLayout.PAGE_END);
}
JCheckBox includeGlobals;
private void export() {
String filename = fileChooser.chooseFilename();
CalendarDateFormatter printForm = new CalendarDateFormatter("yyyy-MM-dd HH:mm:ss", CalendarTimeZone.UTC);
if (filename == null) return;
try {
PrintWriter pw = new PrintWriter( new OutputStreamWriter(new FileOutputStream(filename), CDM.utf8Charset));
pw.println("; file name : " + fds.getLocation());
if (includeGlobals.isSelected()) {
List<Attribute> gAtts = fds.getGlobalAttributes();
for(Attribute a : gAtts) {
pw.println("; " + a.toString(false));
}
}
pw.println("; this file written : " + new Date());
TableModel model = dataModel;
for (int col = 0; col < model.getColumnCount(); col++) {
if (col > 0) pw.print(",");
pw.print(model.getColumnName(col));
}
pw.println();
for (int row = 0; row < model.getRowCount(); row++) {
for (int col = 0; col < model.getColumnCount(); col++) {
if (col > 0) pw.print(",");
Object o = model.getValueAt(row, col);
if (o instanceof CalendarDate) {
CalendarDate d = (CalendarDate)o;
pw.print(printForm.toString(d));
}
else {
pw.print(o.toString());
}
}
pw.println();
}
pw.close();
JOptionPane.showMessageDialog(this, "File successfully written");
} catch (IOException ioe) {
JOptionPane.showMessageDialog(this, "ERROR: " + ioe.getMessage());
ioe.printStackTrace();
}
fileChooser.save();
}
static class DateRenderer extends DefaultTableCellRenderer {
private CalendarDateFormatter newForm, oldForm;
private CalendarDate cutoff;
DateRenderer() {
super();
oldForm = new CalendarDateFormatter("yyyy-MM-dd HH:mm:ss", CalendarTimeZone.UTC);
newForm = new CalendarDateFormatter("dd MMM HH:mm:ss", CalendarTimeZone.UTC);
CalendarDate now = CalendarDate.present();
cutoff = now.add(-1, CalendarPeriod.Field.Year); // "now" time format within a year
}
public void setValue(Object value) {
if (value == null)
setText("");
else {
CalendarDate date = (CalendarDate) value;
if (date.isBefore(cutoff))
setText(oldForm.toString(date));
else
setText(newForm.toString(date));
}
}
}
}