/*
* NCSA Data To Knowledge (D2K) Project
* Automated Learning Group
* National Center for Supercomputing Applications
* University of Illinois at Urbana-Champaign
* 605 E. Springfield, Champaign, IL 61820
*
* d2k@ncsa.uiuc.edu
*
* Copyright 2003, Board of Trustees of the University of Illinois,
* All Rights Reserved
*
* NCSA Data To Knowledge (D2K) software, source code, binary code, and Java-byte
* code including D2K modules and D2K itineraries (hereafter, Software) is
* copyrighted by the Board of Trustees of the University of Illinois (UI),
* and ownership remains with the UI.
*
* Prior to receiving this Software Source Code, You must have agreed to a
* non-exclusive, non-transferable, restricted License of Software with UI for
* limited Research Use and/or Internal Business Use. The terms of that License
* control the use of this Software Source Code. For the sake of convenience,
* certain provisions of that License are stated here. However, in the event
* of any real or perceived differences between the terms of the License and the
* statements made herein, the License controls.
*
* You may not distribute the Software including the Binary Code and this Source
* Code to third parties.
*
* You may make Derivative Works. You are encouraged to provide information to
* UI regarding Derivative Works and your experience with Software. However, if
* You make any Derivative Work based on or derived from the Software, then You
* will: (1) clearly notify users that such Derivative Work is a modified version
* and uses or is derived from the original NCSA Data To Knowledge (D2K)
* developed at UI, and include specific language in that notice as provided for
* in the License, and (2) acknowledge via citation and provide UI with a copy of
* any report or publication using the Software or Derivative Work.
*
* If You wish to make Commercial Use of the Software or Derivative Works, then
* You should contact the UI, c/o NCSA, to negotiate an appropriate license for
* such Commercial Use. Commercial Use includes sale, lease, license,
* distribution or otherwise making the Software or Derivative Works available to
* third parties, which includes, but is not limited to, integration of all or
* part of the Software or Derivative Work into a product for sale or license by
* or on behalf of You to third parties.
*
* UI MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY
* PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. THE UI
* SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY THE USERS OF THIS SOFTWARE.
*
* By using or copying this Software, You agree to abide by the copyright law
* and all other applicable laws of the U.S. including, but not limited to,
* export control laws, and the terms of the License. UI shall have the right
* to terminate its license with You immediately upon Your breach of, or
* non-compliance with, any of its terms. You may be held legally responsible
* for any copyright infringement that is caused or encouraged by Your failure
* to abide by the terms of the License.
*/
package ncsa.d2k.modules.core.io.file.output;
import ncsa.d2k.core.modules.*;
import ncsa.d2k.modules.core.datatype.table.*;
import java.io.*;
import java.beans.PropertyVetoException;
/**
* This module writes the contents of a <code>Table</code> to a flat file.
*
* @author David Clutter
*/
public class WriteTableToFile extends OutputModule {
transient String delimiter;
String delimChar = "C";
boolean useDataTypes = true;
boolean useColumnLabels = true;
public void setDelimChar(String c) throws PropertyVetoException {
// here we check for valid entries and save as upper case
if (c.equalsIgnoreCase("C")) {
delimChar = "C";
} else if (c.equalsIgnoreCase("S")) {
delimChar = "S";
} else if (c.equalsIgnoreCase("T")) {
delimChar = "T";
} else {
throw new PropertyVetoException(
"An invalid Delimiter Character was entered. "+
"Enter C for comma, S for space, or T for tab.",
null);
}
}
public String getDelimChar() {
return delimChar;
}
public void setUseDataTypes(boolean b) {
useDataTypes = b;
}
public boolean getUseDataTypes() {
return useDataTypes;
}
public void setUseColumnLabels(boolean b) {
useColumnLabels = b;
}
public boolean getUseColumnLabels() {
return useColumnLabels;
}
/**
Return a description of the function of this module.
@return A description of this module.
*/
public String getModuleInfo() {
StringBuffer sb = new StringBuffer("<p>Overview: ");
sb.append("<p>This module writes the contents of a Table to a file. ");
sb.append("</p><p>Detailed Description: ");
sb.append("This module writes the contents of the input ");
sb.append("<i>Table</i> to the file specified by the input <i>File Name</i> ");
sb.append("The user can select a space, a common, or a tab as the ");
sb.append("column delimiter using the properties editor. ");
sb.append("If the <i>useColumnLabels</i> property is set, ");
sb.append("the first row of the file will be the column labels. ");
sb.append("If the <i>useDataTypes</i> property is set, the data type of ");
sb.append("each column will be written to the file.");
sb.append("</p><p>Data Handling: ");
sb.append("This module does not destroy or modify its input data.");
sb.append("</p>");
return sb.toString();
}
public PropertyDescription[] getPropertiesDescriptions() {
PropertyDescription[] descriptions = new PropertyDescription [3];
descriptions[0] = new PropertyDescription("delimChar",
"Delimiter Character (C=comma, S=space, T=tab)",
"Selects the delimiter character used to separate columns in the file. "+
"Enter C for comma, S for space, or T for tab.");
descriptions[1] = new PropertyDescription("useColumnLabels",
"Write Column Labels",
"Controls whether the table's column labels are written to the file.");
descriptions[2] = new PropertyDescription("useDataTypes",
"Write Data Types",
"Controls whether the table's column data types are written to the file.");
return descriptions;
}
/**
Return the name of this module.
@return The name of this module.
*/
public String getModuleName() {
return "Write Table to File";
}
/**
Return a String array containing the datatypes the inputs to this
module.
@return The datatypes of the inputs.
*/
public String[] getInputTypes() {
String[] types = {"java.lang.String","ncsa.d2k.modules.core.datatype.table.Table"};
return types;
}
/**
Return a String array containing the datatypes of the outputs of this
module.
@return The datatypes of the outputs.
*/
public String[] getOutputTypes() {
String[] types = { };
return types;
}
/**
Return a description of a specific input.
@param i The index of the input
@return The description of the input
*/
public String getInputInfo(int i) {
switch (i) {
case 0: return "The name of the file to be written.";
case 1: return "The Table to write.";
default: return "No such input";
}
}
/**
Return the name of a specific input.
@param i The index of the input.
@return The name of the input
*/
public String getInputName(int i) {
switch(i) {
case 0:
return "File Name";
case 1:
return "Table";
default: return "No such input";
}
}
/**
Return the description of a specific output.
@param i The index of the output.
@return The description of the output.
*/
public String getOutputInfo(int i) {
switch (i) {
default: return "No such output";
}
}
/**
Return the name of a specific output.
@param i The index of the output.
@return The name of the output
*/
public String getOutputName(int i) {
switch(i) {
default: return "No such output";
}
}
/**
Write the table to the file.
*/
public void doit() throws Exception {
String fileName = (String)pullInput(0);
Table vt = (Table)pullInput(1);
FileWriter fw;
String newLine = "\n";
delimiter = ","; // default to comma
if (delimChar.equals("S")) {
delimiter = " ";
} else if (delimChar.equals("T")) {
delimiter = "\t";
}
try {
// write the actual data
writeTable(vt, delimiter, fileName, useColumnLabels, useDataTypes);
}
catch (IOException e) {
throw new IOException( getAlias() +
": Could not open file: " + fileName +
"\n" + e );
}
}
/**
Get the datatype of a column.
*/
public static final String getDataType(int i) {
switch(i) {
case 0:
return "int";
case 1:
return "float";
case 2:
return "double";
case 3:
return "short";
case 4:
return "long";
case 5:
return "String";
case 6:
return "char[]";
case 7:
return "byte[]";
case 8:
return "boolean";
case 9:
return "Object";
case 10:
return "byte";
case 11:
return "char";
default:
return "String";
}
}
public static void writeTable(Table vt, String delimiter, String fileName,
boolean writeColumnLabels, boolean writeColumnTypes) throws IOException {
FileWriter fw = new FileWriter(fileName);
String newLine = "\n";
// write the column labels
if(writeColumnLabels) {
for(int i = 0; i < vt.getNumColumns(); i++) {
String s = vt.getColumnLabel(i);
if (s == null || s.length() == 0)
s = "column_" + i;
fw.write(s, 0, s.length());
if(i != (vt.getNumColumns() - 1))
fw.write(delimiter.toCharArray(), 0, delimiter.length());
}
fw.write(newLine.toCharArray(), 0, newLine.length());
}
// write the datatypes.
if(writeColumnTypes) {
for(int i = 0; i < vt.getNumColumns(); i++) {
String s = getDataType(vt.getColumnType(i));
fw.write(s, 0, s.length());
if(i != (vt.getNumColumns() - 1))
fw.write(delimiter.toCharArray(), 0, delimiter.length());
}
fw.write(newLine.toCharArray(), 0, newLine.length());
}
// write the actual data
for(int i = 0; i < vt.getNumRows(); i++) {
for(int j = 0; j < vt.getNumColumns(); j++) {
String s;
if (vt.isValueMissing(i, j) || vt.isValueEmpty(i, j))
s = "";
else
s = vt.getString(i, j);
//System.out.println("s: "+s);
fw.write(s, 0, s.length());
if(j != (vt.getNumColumns() - 1) )
fw.write(delimiter.toCharArray(), 0, delimiter.length());
}
fw.write(newLine.toCharArray(), 0, newLine.length());
}
fw.flush();
fw.close();
}
}
// Start QA Comments
// 3/6/03 - Received from David C and Greg & QA started by Ruth
// - Added code to allow for selection of delimiter character and
// updated description accordingly. Removed lots of commented-out
// code. Added exception handler for IO exceptions instead of just
// message to stderr. Committing to Basic.
// End QA Comments