blob: ed698e4b962411817e87d5e0de124d01327027a6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012, 2020 Original authors and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Original authors and others - initial API and implementation
******************************************************************************/
package org.eclipse.nebula.widgets.nattable.dataset.generator;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import org.eclipse.nebula.widgets.nattable.dataset.valuegenerator.UppercaseStringValueGenerator;
public class NatTableDataGenerator {
private int numRows = 0;
private int numCols = 0;
private List<ColumnDataType> columnDataTypes;
private static DataGenerator<DoubleColumnValueBean> doubleGenerator = new DataGenerator<DoubleColumnValueBean>();
private static DataGenerator<StringColumnValueBean> stringGenerator = new DataGenerator<StringColumnValueBean>();
enum ColumnDataType {
STRING_DATA, DOUBLE_DATA
};
public NatTableDataGenerator(int numCols, final int numRows) {
this.numRows = numRows;
this.numCols = numCols;
initColumnDataTypes();
}
public NatTableDataGenerator() {
}
private void initColumnDataTypes() {
this.columnDataTypes = new ArrayList<ColumnDataType>();
for (int i = 0; i < this.numCols; i++) {
ColumnDataType dataType = ColumnDataType.values()[(int) (Math.random() * ColumnDataType.values().length)];
this.columnDataTypes.add(dataType);
}
}
public void persistData(final String fileName) throws IOException, GeneratorException {
try (BufferedWriter out = new BufferedWriter(new FileWriter(fileName))) {
// first write the data types
for (int i = 0; i < this.columnDataTypes.size(); i++) {
ColumnDataType dataType = this.columnDataTypes.get(i);
out.write(dataType.toString());
out.write(i == this.columnDataTypes.size() - 1 ? "" : ",");
}
out.newLine();
String text = "Writing to " + fileName;
int charsWritten = text.length();
System.out.print(text);
for (int i = 0; i < this.numRows; i++) {
for (int j = 0; j < this.numCols; j++) {
ColumnDataType dataType = this.columnDataTypes.get(j);
ColumnValueBean<?> value = null;
switch (dataType) {
case STRING_DATA:
value = stringGenerator.generate(StringColumnValueBean.class);
break;
case DOUBLE_DATA:
value = doubleGenerator.generate(DoubleColumnValueBean.class);
break;
}
String stringValue = (value == null || value.getValue() == null) ? " "
: value.getValue().toString();
stringValue = "".equals(stringValue) ? " " : stringValue;
out.write(stringValue);
out.write(j == this.numCols - 1 ? "" : ",");
}
if (i % this.numCols == 0) {
System.out.print(".");
charsWritten++;
}
if (charsWritten > 80) {
System.out.println();
charsWritten = 0;
}
out.newLine();
}
System.out.println("done");
}
}
// TODO: file dimensions should be embedded in the file
public void getNumRows(String fileName) throws IOException {
try (BufferedReader bro = new BufferedReader(new FileReader(fileName))) {
String stringFromFile = bro.readLine();
while (stringFromFile != null) // end of the file
{
this.numRows++;
stringFromFile = bro.readLine(); // read next line
}
}
this.numRows--; // first row contains the data types of the columns
}
public TableDataProvider loadData(final String fileName) throws FileNotFoundException, IOException {
// need to pass through file first to get matrix dimensions
getNumRows(fileName);
Object[][] tableData = null;
try (BufferedReader bro = new BufferedReader(new FileReader(fileName))) {
// declare String variable and prime the read
String stringFromFile = bro.readLine();
boolean columnDataTypesRead = false;
List<ColumnDataType> dataTypes = null;
int curRow = 0;
System.out.print("Loading data");
while (stringFromFile != null) // end of the file
{
if (!columnDataTypesRead) {
columnDataTypesRead = true;
dataTypes = parseDataTypes(stringFromFile);
this.numCols = dataTypes.size();
tableData = new Object[this.numCols][this.numRows];
} else {
if (dataTypes == null || dataTypes.size() == 0)
throw new IllegalStateException(
"Data description line missing");
addRow(tableData, curRow++, dataTypes, stringFromFile);
}
stringFromFile = bro.readLine(); // read next line
if (curRow % 1000 == 0)
System.out.print(".");
}
System.out.println("done");
}
return new TableDataProvider(tableData, this.numCols, this.numRows);
}
private void addRow(Object[][] tableData, int curRow,
List<ColumnDataType> dataTypes, String stringFromFile) {
StringTokenizer tokenizer = new StringTokenizer(stringFromFile, ",");
String token;
for (int i = 0; i < dataTypes.size(); i++) {
ColumnDataType dataType = dataTypes.get(i);
token = tokenizer.nextToken().trim();
switch (dataType) {
case STRING_DATA:
tableData[i][curRow] = token;
break;
case DOUBLE_DATA:
tableData[i][curRow] = Double.valueOf(token);
break;
}
}
}
private List<ColumnDataType> parseDataTypes(String stringFromFile) {
List<ColumnDataType> dataTypes = new ArrayList<ColumnDataType>();
StringTokenizer tokenizer = new StringTokenizer(stringFromFile, ",");
int numDataTypes = tokenizer.countTokens();
String token;
for (int i = 0; i < numDataTypes; i++) {
token = tokenizer.nextToken().trim();
ColumnDataType dataType = ColumnDataType.valueOf(token);
dataTypes.add(dataType);
}
return dataTypes;
}
public static class ColumnValueBean<T> {
private T value;
public T getValue() {
return this.value;
}
public void setValue(T value) {
this.value = value;
}
}
public static class DoubleColumnValueBean extends ColumnValueBean<Double> {
@GenerateDouble(range = 1000)
private Double value;
@Override
public Double getValue() {
return this.value;
}
@Override
public void setValue(Double value) {
this.value = value;
}
};
public static class StringColumnValueBean extends ColumnValueBean<String> {
@DataValueGenerator(UppercaseStringValueGenerator.class)
private String value;
@Override
public String getValue() {
return this.value;
}
@Override
public void setValue(String value) {
this.value = value;
}
};
public static void main(String[] args) throws GeneratorException, IOException {
NatTableDataGenerator dataGenerator;
String fileName;
dataGenerator = new NatTableDataGenerator(100, 10000);
fileName = "c:/temp/100x10K_tableData.txt";
dataGenerator.persistData(fileName);
dataGenerator = new NatTableDataGenerator(100, 100000);
fileName = "c:/temp/100x100K_tableData.txt";
dataGenerator.persistData(fileName);
dataGenerator = new NatTableDataGenerator(100, 1000000);
fileName = "c:/temp/100x1mil_tableData.txt";
dataGenerator.persistData(fileName);
}
}