package nl.helixsoft.recordstream;
import java.util.Map;
import nl.helixsoft.util.StringUtils;
/**
* Adjuster can apply operations to individual fields of a RecordStream on the fly.
* <p>
* Pass one or more AdjustFunc implementations to the constructor. Unadjusted fields are
* left unharmed.
*/
public class Adjuster extends AbstractRecordStream
{
private final Map<String, AdjustFunc> adjust;
private final RecordStream parent;
private final RecordMetaData rmd;
/**
* Wraps a recordstream, modifies it on the fly by applying one or more adjustment functions.
* <p>
* @param parent the RecordStream to adjust
* @param adjust a map of fieldname / AdjustFunc pairs. The given field will be adjusted by the AdjustFunc.
* Any field not in this map will be passed through unharmed.
*/
public Adjuster (RecordStream parent, Map<String, AdjustFunc> adjust)
{
this.parent = parent;
this.adjust = adjust; //TODO: really should make a defensive copy here.
String[] colNames = new String[parent.getMetaData().getNumCols()];
for (int i = 0; i < parent.getMetaData().getNumCols(); ++i)
{
colNames[i] = parent.getMetaData().getColumnName(i);
}
rmd = new DefaultRecordMetaData(colNames);
}
@Override
/**
* Pull the next record from this record stream.
* Adjustment functions are applied just before returning.
*/
public Record getNext() throws StreamException
{
int colNum = rmd.getNumCols();
Object[] fields = new Object[colNum];
Record r = parent.getNext();
if (r == null) return null;
for (int col = 0; col < colNum; ++col)
{
String colName = rmd.getColumnName(col);
if (adjust.containsKey(colName))
fields[col] = adjust.get(colName).apply(r.get(col));
else
fields[col] = r.get(col);
}
return new DefaultRecord(rmd, fields);
}
public interface AdjustFunc extends Function<Object, Object> {}
/**
* Adjuster func to remove html tags, and replace html entities with the corresponding characters.
**/
public static class HtmlStrip implements AdjustFunc
{
public Object apply (Object val) {
return StringUtils.stripHtml("" + val);
}
}
/**
* The number of columns in this record stream is always the
* same as the number of columns in the parent record stream.
* Column names are always the same as the parent record stream.
*/
@Override
public RecordMetaData getMetaData()
{
return rmd;
}
@Override
public void close() { parent.close(); }
}