package com.metaweb.gridworks.templating; import java.io.IOException; import java.io.Writer; import java.util.Collection; import java.util.List; import java.util.Properties; import com.metaweb.gridworks.browsing.RecordVisitor; import com.metaweb.gridworks.browsing.RowVisitor; import com.metaweb.gridworks.expr.ExpressionUtils; import com.metaweb.gridworks.model.Project; import com.metaweb.gridworks.model.Record; import com.metaweb.gridworks.model.Row; public class Template { protected String _prefix; protected String _suffix; protected String _separator; protected List _fragments; public Template(List fragments) { _fragments = fragments; } public void setPrefix(String prefix) { _prefix = prefix; } public void setSuffix(String suffix) { _suffix = suffix; } public void setSeparator(String separator) { _separator = separator; } public RowVisitor getRowVisitor(Writer writer, int limit) { return get(writer, limit); } public RecordVisitor getRecordVisitor(Writer writer, int limit) { return get(writer, limit); } protected RowWritingVisitor get(Writer writer, int limit) { return new RowWritingVisitor(writer, limit); } protected class RowWritingVisitor implements RowVisitor, RecordVisitor { final protected int limit; final protected Writer writer; protected Properties bindings; public int total; public RowWritingVisitor(Writer writer, int limit) { this.limit = limit; this.writer = writer; } @Override public void start(Project project) { bindings = ExpressionUtils.createBindings(project); try { if (_prefix != null) { writer.write(_prefix); } } catch (IOException e) { // ignore } } @Override public void end(Project project) { try { if (_suffix != null) { writer.write(_suffix); } } catch (IOException e) { // ignore } } public boolean visit(Project project, int rowIndex, Row row) { if (limit <= 0 || total < limit) { internalVisit(project, rowIndex, row); } total++; return limit > 0 && total >= limit; } @Override public boolean visit(Project project, Record record) { if (limit <= 0 || total < limit) { internalVisit(project, record); } total++; return limit > 0 && total >= limit; } protected void writeValue(Object v) throws IOException { if (v == null) { writer.write("null"); } else if (ExpressionUtils.isError(v)) { writer.write("null"); //writer.write("[Error: " + ((EvalError) v).message); } else if (v instanceof String) { writer.write((String) v); } else { writer.write(v.toString()); } } public boolean internalVisit(Project project, int rowIndex, Row row) { try { if (total > 0 && _separator != null) { writer.write(_separator); } ExpressionUtils.bind(bindings, row, rowIndex, null, null); for (Fragment f : _fragments) { if (f instanceof StaticFragment) { writer.write(((StaticFragment) f).text); } else { DynamicFragment df = (DynamicFragment) f; Object value = df.eval.evaluate(bindings); if (value != null && ExpressionUtils.isArrayOrCollection(value)) { if (ExpressionUtils.isArray(value)) { Object[] a = (Object[]) value; for (Object v : a) { writeValue(v); } } else { Collection a = ExpressionUtils.toObjectCollection(value); for (Object v : a) { writeValue(v); } } continue; } writeValue(value); } } } catch (IOException e) { // ignore } return false; } protected boolean internalVisit(Project project, Record record) { bindings.put("recordIndex", record.recordIndex); for (int r = record.fromRowIndex; r < record.toRowIndex; r++) { Row row = project.rows.get(r); bindings.put("rowIndex", r); internalVisit(project, r, row); bindings.remove("recordIndex"); } return false; } } }