package com.metaweb.gridworks.operations; import java.util.List; import java.util.Properties; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; import com.metaweb.gridworks.browsing.RowVisitor; import com.metaweb.gridworks.expr.Evaluable; import com.metaweb.gridworks.expr.ExpressionUtils; import com.metaweb.gridworks.expr.MetaParser; import com.metaweb.gridworks.model.AbstractOperation; import com.metaweb.gridworks.model.Cell; import com.metaweb.gridworks.model.Column; import com.metaweb.gridworks.model.Project; import com.metaweb.gridworks.model.Row; import com.metaweb.gridworks.model.changes.CellChange; public class TextTransformOperation extends EngineDependentMassCellOperation { private static final long serialVersionUID = -7698202759999537298L; static public enum OnError { KeepOriginal, SetToBlank, StoreError } final protected String _expression; final protected OnError _onError; static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { JSONObject engineConfig = obj.getJSONObject("engineConfig"); return new TextTransformOperation( engineConfig, obj.getString("columnName"), obj.getString("expression"), stringToOnError(obj.getString("onError")) ); } static public OnError stringToOnError(String s) { if ("set-to-blank".equalsIgnoreCase(s)) { return OnError.SetToBlank; } else if ("store-error".equalsIgnoreCase(s)) { return OnError.StoreError; } else { return OnError.KeepOriginal; } } static public String onErrorToString(OnError onError) { if (onError == OnError.SetToBlank) { return "set-to-blank"; } else if (onError == OnError.StoreError) { return "store-error"; } else { return "keep-original"; } } public TextTransformOperation(JSONObject engineConfig, String columnName, String expression, OnError onError) { super(engineConfig, columnName, true); _expression = expression; _onError = onError; } public void write(JSONWriter writer, Properties options) throws JSONException { writer.object(); writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); writer.key("description"); writer.value(getBriefDescription(null)); writer.key("engineConfig"); writer.value(getEngineConfig()); writer.key("columnName"); writer.value(_columnName); writer.key("expression"); writer.value(_expression); writer.key("onError"); writer.value(onErrorToString(_onError)); writer.endObject(); } protected String getBriefDescription(Project project) { return "Text transform on cells in column " + _columnName + " using expression " + _expression; } protected String createDescription(Column column, List cellChanges) { return "Text transform on " + cellChanges.size() + " cells in column " + column.getHeaderLabel() + ": " + _expression; } protected RowVisitor createRowVisitor(Project project, List cellChanges) throws Exception { Column column = project.columnModel.getColumnByName(_columnName); Evaluable eval = MetaParser.parse(_expression); Properties bindings = ExpressionUtils.createBindings(project); return new RowVisitor() { int cellIndex; Properties bindings; List cellChanges; Evaluable eval; public RowVisitor init(int cellIndex, Properties bindings, List cellChanges, Evaluable eval) { this.cellIndex = cellIndex; this.bindings = bindings; this.cellChanges = cellChanges; this.eval = eval; return this; } public boolean visit(Project project, int rowIndex, Row row, boolean contextual) { Cell cell = row.getCell(cellIndex); Object oldValue = cell != null ? cell.value : null; ExpressionUtils.bind(bindings, row, rowIndex, cell); Object newValue = eval.evaluate(bindings); if (ExpressionUtils.isError(newValue)) { if (_onError == OnError.KeepOriginal) { return false; } else if (_onError == OnError.SetToBlank) { newValue = null; } } if (!ExpressionUtils.sameValue(oldValue, newValue)) { Cell newCell = new Cell(newValue, (cell != null) ? cell.recon : null); CellChange cellChange = new CellChange(rowIndex, cellIndex, cell, newCell); cellChanges.add(cellChange); } return false; } }.init(column.getCellIndex(), bindings, cellChanges, eval); } }