oms3.io.DataIO Maven / Gradle / Ivy
/*
* $Id:$
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
package oms3.io;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.lang.reflect.Array;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
import oms3.Conversions;
/** Data Input/Output management.
*
* @author Olaf David
*/
public class DataIO {
private static final String P = "@";
public static final String TABLE = P + "T";
public static final String HEADER = P + "H";
public static final String PROPERTIES = P + "S";
public static final String PROPERTY = P + "P";
public static final String TABLE1 = P + "Table";
public static final String HEADER1 = P + "Header";
public static final String PROPERTIES1 = P + "Properties";
public static final String PROPERTY1 = P + "Property";
//
//
public static final String CSPROPERTIES_EXT = "csp";
public static final String CSTABLE_EXT = "cst";
//
private static final String ROOT_ANN = "___root___";
private static final String COMMENT = "#";
private static final Map NOINFO = Collections.unmodifiableMap(new HashMap());
private static final Pattern varPattern = Pattern.compile("\\$\\{([^$}]+)\\}");
/* some static helpers, might have to go somewhere else */
private static final String ISO8601 = "yyyy-MM-dd'T'hh:mm:ss";
//
// all meta data keys
public static final String KEY_CONVERTED_FROM = "converted_from";
public static final String DATE_FORMAT = "date_format";
public static final String DATE_START = "date_start";
public static final String DATE_END = "date_end";
public static final String KEY_CREATED_AT = "created_at";
public static final String KEY_CREATED_BY = "created_by";
public static final String KEY_UNIT = "unit";
public static final String KEY_FORMAT = "format";
public static final String KEY_TYPE = "type";
public static final String KEY_NAME = "name";
public static final String KEY_MISSING_VAL = "missing_value";
public static final String KEY_FC_START = "forecast_start";
public static final String KEY_FC_DAYS = "forecast_days";
public static final String KEY_HIST_YEAR = "historical_year";
public static final String KEY_DIGEST = "digest";
public static final String VAL_DATE = "Date";
//
public static double[] getColumnDoubleValuesInterval(Date start, Date end, CSTable t, String columnName) {
int col = findColumnByName(t, columnName);
if (col == -1) {
throw new IllegalArgumentException("No such column: " + columnName);
}
DateFormat fmt = lookupDateFormat(t, 1);
List l = new ArrayList();
for (String[] row : t.rows()) {
try {
Date d = fmt.parse(row[1]);
if ((d.equals(start) || d.after(start)) && (d.equals(end) || d.before(end))) {
l.add(new Double(row[col]));
}
} catch (ParseException ex) {
throw new RuntimeException(ex);
}
}
double[] arr = new double[l.size()];
for (int i = 0; i < arr.length; i++) {
arr[i] = l.get(i);
}
return arr;
}
public static SimpleDateFormat lookupDateFormat(CSTable table, int col) {
if (col < 0 || col > table.getColumnCount()) {
throw new IllegalArgumentException("invalid column: " + col);
}
String format = table.getColumnInfo(col).get(KEY_FORMAT);
if (format == null) {
format = table.getInfo().get(DATE_FORMAT);
}
if (format == null) {
format = Conversions.ISO().toPattern();
}
return new SimpleDateFormat(format);
}
public static int findRowByDate(Date date, int dateColumn, CSTable table) {
String type = table.getColumnInfo(dateColumn).get(KEY_TYPE);
if ((type == null) || !type.equalsIgnoreCase(VAL_DATE)) {
throw new IllegalArgumentException();
}
DateFormat fmt = lookupDateFormat(table, dateColumn);
int rowNo = 0;
for (String[] row : table.rows()) {
try {
// System.out.println("Date : " + row[dateColumn]);
Date d = fmt.parse(row[dateColumn]);
if (d.equals(date)) {
return rowNo;
}
rowNo++;
} catch (ParseException ex) {
throw new RuntimeException(ex);
}
}
throw new IllegalArgumentException(date.toString());
}
public static CSTable synthESPInput(CSTable table, Date iniStart, Date iniEnd, int fcDays, int year) {
int dateColumn = 1;
DateFormat hfmt = lookupDateFormat(table, dateColumn);
// Forecast start = end of initialzation + 1 day
Calendar fcStartCal = new GregorianCalendar();
fcStartCal.setTime(iniEnd);
fcStartCal.add(Calendar.DATE, 1);
Date fcStart = fcStartCal.getTime();
// get the initialization period
MemoryTable t = new MemoryTable(table);
int iniStartRow = findRowByDate(iniStart, dateColumn, t);
int iniEndRow = findRowByDate(iniEnd, dateColumn, t);
List iniRows = t.getRows(iniStartRow, iniEndRow);
// set the historical date to the forcast date, but use the
// historical year.
Calendar histStart = new GregorianCalendar();
histStart.setTime(fcStart);
histStart.set(Calendar.YEAR, year);
// get the historical data
int histStartRow = findRowByDate(histStart.getTime(), dateColumn, t);
int histEndRow = histStartRow + (fcDays - 1);
List histRows = t.getRows(histStartRow, histEndRow);
// create the new Table.
MemoryTable espTable = new MemoryTable(table);
espTable.getInfo().put(DATE_START, hfmt.format(iniStart));
espTable.getInfo().put(KEY_FC_START, hfmt.format(fcStart));
espTable.getInfo().put(KEY_FC_DAYS, Integer.toString(fcDays));
espTable.getInfo().put(KEY_HIST_YEAR, Integer.toString(year));
espTable.clearRows();
espTable.addRows(iniRows);
espTable.addRows(histRows);
// historical date -> forecast date.
Calendar fcCurrent = new GregorianCalendar();
fcCurrent.setTime(fcStart);
List espRows = espTable.getRows();
int start = iniRows.size();
for (int i = start; i <= start + (fcDays - 1); i++) {
espRows.get(i)[1] = hfmt.format(fcCurrent.getTime());
fcCurrent.add(Calendar.DATE, 1);
}
fcCurrent.add(Calendar.DATE, -1);
espTable.getInfo().put(DATE_END, hfmt.format(fcCurrent.getTime()));
return espTable;
}
/** Get a slice of rows out of the table matching the time window
*
* @param table
* @param timeCol
* @param start
* @param end
* @return the first and last row that matches the time window start->end
*/
public static int[] sliceByTime(CSTable table, int timeCol, Date start, Date end) {
if (end.before(start)) {
throw new IllegalArgumentException("end rows = new ArrayList();
for (String[] row : src.rows()) {
rows.add(row);
}
return new TableModel() {
@Override
public int getColumnCount() {
return src.getColumnCount();
}
@Override
public String getColumnName(int column) {
return src.getColumnName(column);
}
@Override
public int getRowCount() {
return rows.size();
}
@Override
public Class> getColumnClass(int columnIndex) {
return String.class;
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
return rows.get(rowIndex)[columnIndex];
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
// rows.get(rowIndex)[columnIndex] = (String) aValue;
}
@Override
public void addTableModelListener(TableModelListener l) {
}
@Override
public void removeTableModelListener(TableModelListener l) {
}
};
}
/**
* Get the KVP as table.
* @param p
* @return an AbstractTableModel for properties (KVP)
*/
public static AbstractTableModel getProperties(final CSProperties p) {
return new AbstractTableModel() {
@Override
public int getRowCount() {
return p.keySet().size();
}
@Override
public int getColumnCount() {
return 2;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
if (columnIndex == 0) {
return " " + p.keySet().toArray()[rowIndex];
} else {
return p.values().toArray()[rowIndex];
}
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == 1;
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (columnIndex == 1) {
String[] keys = p.keySet().toArray(new String[0]);
p.put(keys[rowIndex], aValue.toString());
}
}
@Override
public String getColumnName(int column) {
return column == 0 ? "Name" : "Value";
}
@Override
public Class> getColumnClass(int columnIndex) {
return String.class;
}
};
}
public static AbstractTableModel get2DBounded(final CSProperties p, final String pname) throws ParseException {
String m = p.getInfo(pname).get("bound");
String[] dims = m.split(",");
final int rows = DataIO.getInt(p, dims[0].trim());
final int cols = DataIO.getInt(p, dims[1].trim());
return new AbstractTableModel() {
@Override
public int getRowCount() {
return rows;
}
@Override
public int getColumnCount() {
return cols;
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
@Override
public Object getValueAt(int row, int col) {
String[][] d = Conversions.convert(p.get(pname), String[][].class);
return d[row][col].trim();
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
String[][] d = Conversions.convert(p.get(pname), String[][].class);
d[rowIndex][columnIndex] = aValue.toString().trim();
String s = toArrayString(d);
// System.out.println(s);
p.put(pname, s);
}
@Override
public String getColumnName(int column) {
return Integer.toString(column);
}
@Override
public Class> getColumnClass(int columnIndex) {
return String.class;
}
};
}
static public boolean playsRole(final CSProperties p, String key, String role) {
String r = p.getInfo(key).get("role");
if (r == null) {
return false;
}
return r.contains(role);
}
static public boolean isBound(final CSProperties p, String key, int dim) {
String bound = p.getInfo(key).get("bound");
if (bound == null) {
return false;
}
StringTokenizer t = new StringTokenizer(bound, ",");
if (t.countTokens() == dim) {
return true;
}
return false;
}
// 1D arrays
public static AbstractTableModel getBoundProperties(final CSProperties p, String boundName) throws ParseException {
final int rows = DataIO.getInt(p, boundName);
final List arr = keysByMeta(p, "bound", boundName);
return new AbstractTableModel() {
@Override
public int getRowCount() {
return rows;
}
@Override
public int getColumnCount() {
return arr.size();
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
String colname = arr.get(columnIndex);
String[] d = Conversions.convert(p.get(colname), String[].class);
return d[rowIndex].trim();
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
String colname = arr.get(columnIndex);
String[] d = Conversions.convert(p.get(colname), String[].class);
d[rowIndex] = aValue.toString().trim();
String s = toArrayString(d);
// System.out.println(s);
p.put(colname, s);
}
@Override
public String getColumnName(int column) {
return arr.get(column);
}
@Override
public Class> getColumnClass(int columnIndex) {
return String.class;
}
};
}
// unbound
public static AbstractTableModel getUnBoundProperties(final CSProperties p) throws ParseException {
final List arr = keysByNotMeta(p, "bound");
return new AbstractTableModel() {
@Override
public int getRowCount() {
return arr.size();
}
@Override
public int getColumnCount() {
return 2;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
if (columnIndex == 0) {
return arr.get(rowIndex);
} else {
return p.get(arr.get(rowIndex));
}
// String colname = arr.get(columnIndex);
// String[] d = Conversions.convert(p.get(colname), String[].class);
// return d[rowIndex].trim();
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
// String colname = arr.get(columnIndex);
// String[] d = Conversions.convert(p.get(colname), String[].class);
// d[rowIndex] = aValue.toString().trim();
// String s = toArrayString(d);
// System.out.println(s);
// p.put(colname, s);
}
@Override
public String getColumnName(int column) {
return (column == 0) ? "Key" : "Value";
}
@Override
public Class> getColumnClass(int columnIndex) {
return String.class;
}
};
}
/**
* Create array string.
*
* @param arr
* @return an array String.
*/
public static String toArrayString(String[] arr) {
StringBuffer b = new StringBuffer();
b.append('{');
for (int i = 0; i < arr.length; i++) {
b.append(arr[i]);
if (i < arr.length - 1) {
b.append(',');
}
}
b.append('}');
return b.toString();
}
public static String toArrayString(String[][] arr) {
StringBuffer b = new StringBuffer();
b.append('{');
for (int i = 0; i < arr.length; i++) {
b.append('{');
for (int j = 0; j < arr[i].length; j++) {
b.append(arr[i][j]);
if (j < arr[i].length - 1) {
b.append(',');
}
}
b.append('}');
if (i < arr.length - 1) {
b.append(',');
}
}
b.append('}');
return b.toString();
}
/** Returns a r/o table from a CSP file
*
* @param p
* @param dim
* @return a table model for properties with dimension.
*/
public static TableModel fromCSP(CSProperties p, final int dim) {
List dims = keysByMeta(p, "role", "dimension");
if (dims.size() == 0) {
return null;
}
for (String d : dims) {
if (Integer.parseInt(p.get(d).toString()) == dim) {
final List bounds = keysByMeta(p, "bound", d);
final List
© 2015 - 2024 Weber Informatics LLC | Privacy Policy