Hey Rob - thanks for your insight.
Yes, I was trying to avoid building that 200-record flat file schema.
The alternative of mapping out unparsed data from ‘undefdata’ using a tokenize service didn’t sit right either. I was considering ‘ps.util.string:parse’ (it has a more correct approach to missing fields, compared to ‘pub.string:tokenize’.) However, tokenizers don’t handle CSV parsing natively (e.g. parsing quoted CSV data with embedded ‘,’).
So I ended up ditching WmFlatFile altogether, and using this open-source SourceForge package:
‘CSV4180 - CSV parser based on RFC 4180’
[url]https://sourceforge.net/projects/csv4180/[/url]
I imported their JAR into my webMethods package and wrote the two Java services below. (Put the jar under /code/jars. Import ‘com.sunsetbrew.csv4180.*’)
My flow uses these services to process the CSV row by row, generating an order for each row.
[‘getCSVReader’ Java Service - create CSVReader object from inputStream]
IDataCursor cursor = pipeline.getCursor();
if (cursor.first("inputStream"))
{
InputStream inputStream = (InputStream) cursor.getValue();
// Create a BufferedReader from the input stream
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
CSVReader csvReader = new CSVReader( reader);
IDataUtil.put(cursor, "CSVReader", csvReader);
}
[ ‘parseRow’ Java service - takes ‘CSVReader’ input, returns a CSV row as string list ]
// Input pipeline
IDataCursor pipelineCursor = pipeline.getCursor();
CSVReader csvReader = (CSVReader)IDataUtil.get( pipelineCursor, "CSVReader" );
pipelineCursor.destroy();
//temporary ArrayList variable hold parsed row data
ArrayList<String> fieldsArrayList = new ArrayList<String> ();
try{
// Read current line's fields into the ArrayList variable
csvReader.readFields(fieldsArrayList);
if (csvReader.isEOF()) {
return; // Don't populate 'field' output when EOF reached
}
} catch (IOException e) {
// promote to webMethods ServiceException used by webMethods
throw new ServiceException(e);
}
// Build output string list
String[] field = new String[fieldsArrayList.size()];
for (int j = 0; j < field.length; j++) {
field[j] = (String) fieldsArrayList.get(j);
}
// Output pipeline
IDataCursor pipelineCursor_1 = pipeline.getCursor();
IDataUtil.put( pipelineCursor_1, "field", field);
pipelineCursor_1.destroy();
Another Java ‘Array-slicing’ utility service (using System.arraycopy) is used to extract out specific parts of the string list for mapping.