package org.pentaho.platform.dataaccess.datasource.wizard.models;
import java.io.Serializable;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import org.pentaho.reporting.libraries.base.util.CSVTokenizer;
import org.pentaho.ui.xul.XulEventSourceAdapter;
import org.pentaho.ui.xul.stereotype.Bindable;
public class CsvFileInfo extends XulEventSourceAdapter implements Serializable {
public static final String HEADER_ROWS_ATTRIBUTE = "headerRows"; //$NON-NLS-1$
public static final String ENCLOSURE_ATTRIBUTE = "enclosure"; //$NON-NLS-1$
public static final String DELIMITER_ATTRIBUTE = "delimiter"; //$NON-NLS-1$
public static final String TMP_FILENAME_ATTRIBUTE = "tmpFilename"; //$NON-NLS-1$
public static final String ENCODING = "encoding"; //$NON-NLS-1$
public static final String DEFAULT_COLUMN_NAME_PREFIX = "Field_"; //$NON-NLS-1$
private static final long serialVersionUID = 2498165533158482382L;
private List<String> contents;
private String delimiter = ","; //$NON-NLS-1$
private String enclosure = "\""; //$NON-NLS-1$
private String encoding; //$NON-NLS-1$
private int headerRows = 1;
private String project;
private String tmpFilename;
private String filename;
private String currencySymbol = ""; //$NON-NLS-1$
private String decimalSymbol = "."; //$NON-NLS-1$
private String groupSymbol = ","; //$NON-NLS-1$
private String ifNull = "---"; //$NON-NLS-1$
private String nullStr = ""; //$NON-NLS-1$
public static final String FRIENDLY_FILENAME_ATTRIBUTE = "friendlyFilename"; //$NON-NLS-1$
private String friendlyFilename;
private String savedEncoding;
@Bindable
public String getIfNull() {
return ifNull;
}
@Bindable
public void setIfNull(String ifNull) {
this.ifNull = ifNull;
}
@Bindable
public String getNullStr() {
return nullStr;
}
@Bindable
public void setNullStr(String nullStr) {
this.nullStr = nullStr;
}
@Bindable
public List<String> getContents() {
return contents;
}
@Bindable
public void setContents(List<String> contents) {
this.contents = contents;
}
@Bindable
public String getDelimiter() {
return delimiter;
}
@Bindable
public void setDelimiter(String delimiter) {
String previousVal = this.delimiter;
this.delimiter = delimiter;
firePropertyChange(DELIMITER_ATTRIBUTE, previousVal, delimiter);
}
@Bindable
public String getEnclosure() {
return enclosure;
}
@Bindable
public void setEnclosure(String enclosure) {
String previousVal = this.enclosure;
this.enclosure = enclosure;
firePropertyChange(ENCLOSURE_ATTRIBUTE, previousVal, enclosure);
}
@Bindable
public int getHeaderRows() {
return headerRows;
}
@Bindable
public void setHeaderRows(int headerRows) {
int previousVal = this.headerRows;
this.headerRows = headerRows;
firePropertyChange(HEADER_ROWS_ATTRIBUTE, previousVal, this.headerRows);
}
@Bindable
public String getProject() {
return project;
}
@Bindable
public void setProject(String project) {
this.project = project;
}
@Bindable
public String getTmpFilename() {
return tmpFilename;
}
@Bindable
public void setTmpFilename(String filename) {
String previousVal = this.tmpFilename;
this.tmpFilename = filename;
firePropertyChange(TMP_FILENAME_ATTRIBUTE, previousVal, filename);
}
public String getFilename() {
return this.filename;
}
public void setFilename(String file) {
this.filename = file;
}
@Bindable
public String getCurrencySymbol() {
return currencySymbol;
}
@Bindable
public void setCurrencySymbol(String currencySymbol) {
this.currencySymbol = currencySymbol;
}
@Bindable
public String getDecimalSymbol() {
return decimalSymbol;
}
@Bindable
public void setDecimalSymbol(String decimalSymbol) {
this.decimalSymbol = decimalSymbol;
}
@Bindable
public String getGroupSymbol() {
return groupSymbol;
}
@Bindable
public void setGroupSymbol(String groupSymbol) {
this.groupSymbol = groupSymbol;
}
@Bindable
public String getEncoding() {
return encoding;
}
@Bindable
public void setEncoding(String encoding) {
String previousVal = this.encoding;
this.encoding = encoding;
firePropertyChange(ENCODING, previousVal, encoding);
}
public void setEncodingFromServer(String encoding){
if(this.savedEncoding != null && !this.savedEncoding.trim().equals("")){
setEncoding(this.savedEncoding);
this.savedEncoding = null;
} else {
setEncoding(encoding);
}
}
public void setSavedEncoding(String encoding) {
this.savedEncoding = encoding;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((currencySymbol == null) ? 0 : currencySymbol.hashCode());
result = prime * result + ((decimalSymbol == null) ? 0 : decimalSymbol.hashCode());
result = prime * result + ((delimiter == null) ? 0 : delimiter.hashCode());
result = prime * result + ((enclosure == null) ? 0 : enclosure.hashCode());
result = prime * result + ((encoding == null) ? 0 : encoding.hashCode());
result = prime * result + ((tmpFilename == null) ? 0 : tmpFilename.hashCode());
result = prime * result + ((groupSymbol == null) ? 0 : groupSymbol.hashCode());
result = prime * result + headerRows;
result = prime * result + ((ifNull == null) ? 0 : ifNull.hashCode());
result = prime * result + ((nullStr == null) ? 0 : nullStr.hashCode());
result = prime * result + ((project == null) ? 0 : project.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CsvFileInfo other = (CsvFileInfo) obj;
if (currencySymbol == null) {
if (other.currencySymbol != null)
return false;
} else if (!currencySymbol.equals(other.currencySymbol))
return false;
if (decimalSymbol == null) {
if (other.decimalSymbol != null)
return false;
} else if (!decimalSymbol.equals(other.decimalSymbol))
return false;
if (delimiter == null) {
if (other.delimiter != null)
return false;
} else if (!delimiter.equals(other.delimiter))
return false;
if (enclosure == null) {
if (other.enclosure != null)
return false;
} else if (!enclosure.equals(other.enclosure))
return false;
if (encoding == null) {
if (other.encoding != null)
return false;
} else if (!encoding.equals(other.encoding))
return false;
if (tmpFilename == null) {
if (other.tmpFilename != null)
return false;
} else if (!tmpFilename.equals(other.tmpFilename))
return false;
if (groupSymbol == null) {
if (other.groupSymbol != null)
return false;
} else if (!groupSymbol.equals(other.groupSymbol))
return false;
if (headerRows != other.headerRows)
return false;
if (ifNull == null) {
if (other.ifNull != null)
return false;
} else if (!ifNull.equals(other.ifNull))
return false;
if (nullStr == null) {
if (other.nullStr != null)
return false;
} else if (!nullStr.equals(other.nullStr))
return false;
if (project == null) {
if (other.project != null)
return false;
} else if (!project.equals(other.project))
return false;
return true;
}
public List<List<String>> parseSampleContents() {
String delim = getDelimiter();
if (contents == null) {
throw new IllegalStateException("Sample Contents is null, nothing to parse"); //$NON-NLS-1$
} else if (delim == null || "".equals(delim)) { //$NON-NLS-1$
// use a random delimiter that will result in an un-parsed list
delim = "~!@#$%";
}
List<List<String>> sample = new ArrayList<List<String>>();
CSVTokenizer csvTokenizer;
String enclosure = null;
if (!"".equals(getEnclosure())) {
enclosure = getEnclosure();
}
for ( String line : contents ) {
csvTokenizer = new CSVTokenizer(line, delim, enclosure);
List<String> rowData = new ArrayList<String>();
int count = 0;
while (csvTokenizer.hasMoreTokens()) {
// get next token and store it in the list
rowData.add(csvTokenizer.nextToken());
count++;
}
sample.add(rowData);
}
return sample;
}
public String formatSampleContents() {
StringBuilder sb = new StringBuilder();
String padding = " ";
List<List<String>> parsed;
try {
parsed = parseSampleContents();
} catch (IllegalStateException e) {
// nothing to parse, formatted value is "nothing"
return "";
}
int maxColumns = getMaxColumnCount(parsed);
// create a dummy row for the header
if (getHeaderRows() == 0) {
List<String> dummy = getDummyHeader(maxColumns);
parsed.add(0, dummy);
}
int[] widths = getMaxWidths(parsed, maxColumns);
int lineNumber = 0;
StringBuilder headerMarker = new StringBuilder();
int lineWidth = 0;
// find out how big the entire line will be, including the padding between fields
for (int w = 0; w < widths.length; w++) {
lineWidth += widths[w] + padding.length();
}
// create a string that will separate the header from the body of text
for (int x = 0; x < lineWidth; x++) {
headerMarker.append("-");
}
// format each field, padding as required
for (List<String> line : parsed) {
for (int i = 0; i < line.size(); i++) {
String field = line.get(i);
sb.append(padField(field, widths[i]));
sb.append(padding);
}
sb.append("\n");
if (lineNumber == 0) {
sb.append(headerMarker.toString());
sb.append("\n");
}
lineNumber++;
}
return sb.toString();
}
private List<String> getDummyHeader(int maxColumns) {
List<String> dummy = new ArrayList<String>(maxColumns);
DecimalFormat df = new DecimalFormat("000");
for(int i = 0; i < maxColumns; i++) {
dummy.add(DEFAULT_COLUMN_NAME_PREFIX + df.format(i + 1));
}
return dummy;
}
/**
* It would be nice just to use String.format here, but it is not available in GWT.
* @param field
* @param totalWidth
* @return
*/
private String padField(String field, int totalWidth) {
StringBuilder sb = new StringBuilder(field);
if (field.length() < totalWidth) {
for (int i = field.length(); i < totalWidth; i++) {
sb.append(" ");
}
}
return sb.toString();
}
private int[] getMaxWidths(List<List<String>> parsedContents, int columns) {
if (parsedContents != null && parsedContents.size() > 0) {
int[] widths = new int[columns];
for (List<String> lines: parsedContents) {
for (int i = 0; i < lines.size(); i++) {
String field = lines.get(i);
widths[i] = field.length() > widths[i] ? field.length() : widths[i];
}
}
return widths;
}
return null;
}
private int getMaxColumnCount(List<List<String>> parsedContents) {
int max = 0;
for (List<String> line : parsedContents) {
max = line.size() > max ? line.size() : max;
}
return max;
}
@Bindable
public String getFriendlyFilename() {
return friendlyFilename;
}
@Bindable
public void setFriendlyFilename(String friendlyFilename) {
String previousVal = this.friendlyFilename;
this.friendlyFilename = friendlyFilename;
firePropertyChange(FRIENDLY_FILENAME_ATTRIBUTE, previousVal, friendlyFilename);
}
public void clear() {
setDelimiter(",");
setContents(null);
setCurrencySymbol("");
setEnclosure("\"");
setEncoding("");
setTmpFilename(null);
setFilename(null);
setFriendlyFilename(null);
setGroupSymbol(",");
setCurrencySymbol("");
setDecimalSymbol(".");
setHeaderRows(1);
setIfNull("---");
setNullStr("");
setProject(null);
formatSampleContents();
}
}