package com.bizosys.hsearch.loader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import com.bizosys.hsearch.validator.DateValidator;
import com.bizosys.hsearch.validator.DecimalValidator;
import com.bizosys.hsearch.validator.EMailValidator;
import com.bizosys.hsearch.validator.PhoneValidator;
import com.bizosys.hsearch.validator.StringValidator;
import com.bizosys.oneline.ApplicationFault;
import com.bizosys.oneline.SystemFault;
import com.bizosys.oneline.util.StringUtils;
public class DataLoader {
public static final int NONE = 0;
public static final int NEUMERIC = 1;
public static final int DECIMAL = 2;
public static final int ALPHA = 3;
public static final int ALPHANEUMERIC = 4;
public static final int DATE = 5;
public static final int EMAIL = 6;
public static final int PHONE = 7;
public static final String [] DATA_TYPE_NAMES = new String[]{
"NONE","NEUMERIC","DECIMAL","ALPHA",
"ALPHANEUMERIC", "DATE","EMAIL","PHONE"};
public static void load(URL url, boolean isHeader,
RowEventProcessor handler, String separator,
int [] columnFormats, int [] nonEmptyCells,
int [] optionCheckCells, String optionCheckValues[],
int [] minCheckCells, double[] minCheckValues,
int [] maxCheckCells, double[] maxCheckValues)
throws ApplicationFault, SystemFault {
/**
* Populate cell choices
*/
Map<Integer, String[]> optionCheck = new HashMap<Integer, String[]>();
for (int i=0; i< optionCheckValues.length; i++) {
String[] choices = StringUtils.getStrings(optionCheckValues[i], ",");
optionCheck.put(optionCheckCells[i], choices);
}
/**
* Populate minimum values
*/
Map<Integer, Double> minChecks = new HashMap<Integer, Double>();
int minCheckCellsT = ( null == minCheckCells) ? 0 : minCheckCells.length;
for (int i=0; i<minCheckCellsT; i++) {
minChecks.put(minCheckCells[i], minCheckValues[i]);
}
/**
* Populate maximum values
*/
Map<Integer, Double> maxChecks = new HashMap<Integer, Double>();
int maxCheckCellsT = ( null == maxCheckCells) ? 0 : maxCheckCells.length;
for (int i=0; i<maxCheckCellsT; i++) {
maxChecks.put(maxCheckCells[i], maxCheckValues[i]);
}
load(url, isHeader, handler, separator, columnFormats,
nonEmptyCells, optionCheck,minChecks,maxChecks);
}
public static void load(URL url, boolean isHeader,
RowEventProcessor handler,String separator,
int [] columnFormats, int [] nonEmptyCells,
Map<Integer, String[]> optionCheck,
Map<Integer, Double> minChecks,
Map<Integer, Double> maxChecks)
throws ApplicationFault, SystemFault {
InputStream stream = null;
try {
stream = url.openStream();
} catch (IOException ex) {
throw new ApplicationFault(ex);
}
//Don't buffer as CsvReader already does it
Reader isReader = new InputStreamReader(stream);
RowReader reader = RowReaderFactory.getReader(separator, isReader);
String [] rowCells;
int rowNumber = 0;
try {
while ((rowCells = reader.readNext()) != null) {
rowNumber++;
if ( isHeader ) {
handler.onHeaderRow(rowCells);
isHeader = false;
continue;
}
validateNonEmpty(rowCells, nonEmptyCells, rowNumber);
validateFormats(columnFormats, rowCells, rowNumber);
validateAllowedValues(rowCells, optionCheck, rowNumber);
validateMinimumValues(rowCells, minChecks, rowNumber);
validateMaximumValues(rowCells, maxChecks, rowNumber);
handler.onDataRow(rowCells);
}
handler.onEnd();
} catch (IOException ex) {
throw new SystemFault(ex);
} finally {
if ( null != reader) try {reader.close();}
catch (Exception ex) {LoaderLog.l.warn(ex);}
}
}
private static void validateMaximumValues(String[] rowCells, Map<Integer,
Double> maxChecks, int rowNumber) throws ApplicationFault {
if ( null == maxChecks) return;
for (int cellIndex : maxChecks.keySet()) {
String cell = rowCells[cellIndex];
if ( StringUtils.isEmpty(cell)) continue;
boolean isValid = DecimalValidator.maxValue(
new Double(cell), maxChecks.get(cellIndex));
if ( !isValid) throw new ApplicationFault(
"Illegal Cell: [" + cell + "] at row=" + rowNumber + "\n" +
StringUtils.arrayToString(rowCells, '|'));
}
}
private static void validateMinimumValues(String[] rowCells, Map<Integer, Double> minChecks, int rowNumber) throws ApplicationFault {
if ( null == minChecks) return;
for (int cellIndex : minChecks.keySet()) {
String cell = rowCells[cellIndex];
if ( StringUtils.isEmpty(cell)) continue;
boolean isValid = DecimalValidator.minValue(
new Double(cell), minChecks.get(cellIndex));
if ( !isValid) throw new ApplicationFault(
"Illegal Cell: [" + cell + "] at row=" + rowNumber + "\n" +
StringUtils.arrayToString(rowCells, '|'));
}
}
private static void validateAllowedValues(String[] rowCells, Map<Integer, String[]> cellChoices, int rowNumber) throws ApplicationFault {
if ( null == cellChoices) return;
boolean isValid = false;
for (int cellNo : cellChoices.keySet()) {
String cell = rowCells[cellNo];
isValid = StringValidator.isValidSelect(cell, cellChoices.get(cellNo));
if ( !isValid) throw new ApplicationFault(
"Illegal Cell: [" + cell + "] at row=" + rowNumber + "\n" +
StringUtils.arrayToString(rowCells, '|'));
}
}
private static void validateNonEmpty(String[] rowCells, int[] nonEmptyCells, int rowNumber) throws ApplicationFault {
int cellsTotal = rowCells.length;
for (int cellIndex : nonEmptyCells) {
if ( cellIndex >= cellsTotal) {
throw new ApplicationFault("validateNonEmpty Failed : cellIndex/cellsTotal=" +
cellIndex + "/" + cellsTotal + "\n[[" +
StringUtils.arrayToString(rowCells, '\n') + "]]");
}
if ( StringUtils.isEmpty(rowCells[cellIndex]) )
throw new ApplicationFault(
"Illegal Empty Cell: [" + cellIndex + "] at row=" + rowNumber + "\n" +
StringUtils.arrayToString(rowCells, '\n'));
}
}
private static void validateFormats(int [] columnFormats, String [] rowCells, int rowNumber) throws ApplicationFault{
int columnFormatsT = columnFormats.length;
int cellsTotal = rowCells.length;
boolean isValid = false;
int format = -1;
String cell = null;
if ( null != columnFormats) {
for (int i=0; i< columnFormatsT; i++) {
if ( ! (i < cellsTotal) ) break;
format = columnFormats[i];
cell = rowCells[i];
if ( StringUtils.isEmpty(cell)) continue;
//if ( decode ) cell = StringUtils.decode(cell);
isValid = false;
switch ( format ) {
case NONE:
isValid = true;
break;
case NEUMERIC:
isValid = StringValidator.isValidNumberic(cell, false);
break;
case DECIMAL:
isValid = StringValidator.isValidDecimal(cell, false);
break;
case ALPHA:
isValid = StringValidator.isValidAlpha(cell, false);
break;
case ALPHANEUMERIC:
isValid = StringValidator.isValidAlphaNumberic(cell, false);
break;
case DATE:
isValid = DateValidator.isValid(cell, null);
break;
case EMAIL:
isValid = EMailValidator.isValid(cell);
break;
case PHONE:
isValid = PhoneValidator.isValid(cell);
break;
default:
isValid = true;
break;
}
if ( !isValid) throw new ApplicationFault(
"Illegal Cell: [" + cell + "] for format " + DATA_TYPE_NAMES[format] + " at row=" + rowNumber + "\n" +
StringUtils.arrayToString(rowCells, '|'));
}
}
}
}