Search in sources :

Example 1 with FormattingProvider

use of org.jooq.FormattingProvider in project jOOQ by jOOQ.

the class AbstractResult method format.

// -------------------------------------------------------------------------
// XXX: Formattable API
// -------------------------------------------------------------------------
@Override
public final void format(Writer writer, TXTFormat format) {
    try {
        final FormattingProvider fp = Tools.configuration(this).formattingProvider();
        // Numeric columns have greater max width because values are aligned
        final int NUM_COL_MAX_WIDTH = format.maxColWidth() == Integer.MAX_VALUE ? Integer.MAX_VALUE : 2 * format.maxColWidth();
        // The max number of records that will be considered for formatting purposes
        final int MAX_RECORDS = min(50, format.maxRows());
        final Deque<R> buffer = new ArrayDeque<>();
        final Iterator<R> it = iterator();
        // Buffer some rows for formatting purposes
        for (int i = 0; i < MAX_RECORDS && it.hasNext(); i++) buffer.offer(it.next());
        // Get max decimal places for numeric type columns
        int size = fields.size();
        final int[] decimalPlaces = new int[size];
        final int[] widths = new int[size];
        for (int index = 0; index < size; index++) {
            if (Number.class.isAssignableFrom(fields.field(index).getType())) {
                List<Integer> decimalPlacesList = new ArrayList<>(1 + buffer.size());
                // Initialize
                decimalPlacesList.add(0);
                // Collect all decimal places for the column values
                for (R record : buffer) decimalPlacesList.add(decimalPlaces(format0(record.get(index), record.changed(index), true)));
                // Find max
                decimalPlaces[index] = Collections.max(decimalPlacesList);
            }
        }
        // Get max column widths
        int colMaxWidth;
        for (int index = 0; index < size; index++) {
            // Is number column?
            boolean isNumCol = Number.class.isAssignableFrom(fields.field(index).getType());
            colMaxWidth = isNumCol ? NUM_COL_MAX_WIDTH : format.maxColWidth();
            // Collect all widths for the column
            List<Integer> widthList = new ArrayList<>(1 + buffer.size());
            // Add column name width first
            widthList.add(min(colMaxWidth, max(format.minColWidth(), fp.width(fields.field(index).getName()))));
            // Add column values width
            for (R record : buffer) {
                String value = format0(record.get(index), record.changed(index), true);
                // Align number values before width is calculated
                if (isNumCol)
                    value = alignNumberValue(decimalPlaces[index], value);
                widthList.add(min(colMaxWidth, fp.width(value)));
            }
            // Find max
            widths[index] = Collections.max(widthList);
        }
        // Write top line
        if (format.horizontalTableBorder())
            formatHorizontalLine(writer, format, widths);
        // Write headers
        if (format.verticalTableBorder())
            writer.append('|');
        for (int index = 0; index < size; index++) {
            if (index > 0)
                if (format.verticalCellBorder())
                    writer.append('|');
                else
                    writer.append(' ');
            String padded;
            String name = fields.field(index).getName();
            int width = fp.width(name);
            if (Number.class.isAssignableFrom(fields.field(index).getType()))
                padded = leftPad(name, width, widths[index]);
            else
                padded = rightPad(name, width, widths[index]);
            if (widths[index] < 4)
                writer.append(padded);
            else
                writer.append(abbreviate(padded, widths[index]));
        }
        if (format.verticalTableBorder())
            writer.append('|');
        writer.append('\n');
        // Write separator
        if (format.horizontalHeaderBorder())
            formatHorizontalLine(writer, format, widths);
        // Write records
        int i;
        recordLoop: for (i = 0; i < format.maxRows(); i++) {
            R record = buffer.pollFirst();
            if (record == null)
                if (it.hasNext())
                    record = it.next();
                else
                    break recordLoop;
            // Write separator
            if (i > 0 && format.horizontalCellBorder())
                formatHorizontalLine(writer, format, widths);
            if (format.verticalTableBorder())
                writer.append('|');
            for (int index = 0; index < size; index++) {
                if (index > 0)
                    if (format.verticalCellBorder())
                        writer.append('|');
                    else
                        writer.append(' ');
                String value = StringUtils.replace(StringUtils.replace(StringUtils.replace(format0(record.get(index), record.changed(index), true), "\n", "{lf}"), "\r", "{cr}"), "\t", "{tab}");
                String padded;
                if (Number.class.isAssignableFrom(fields.field(index).getType()))
                    padded = leftPad(alignNumberValue(decimalPlaces[index], value), widths[index]);
                else
                    padded = rightPad(value, fp.width(value), widths[index]);
                if (widths[index] < 4)
                    writer.append(padded);
                else
                    writer.append(abbreviate(padded, widths[index]));
            }
            if (format.verticalTableBorder())
                writer.append('|');
            writer.append('\n');
        }
        // Write bottom line
        if (format.horizontalTableBorder() && i > 0)
            formatHorizontalLine(writer, format, widths);
        // Write truncation message, if applicable
        if (it.hasNext()) {
            if (format.verticalTableBorder())
                writer.append('|');
            writer.append("...record(s) truncated...\n");
        }
        writer.flush();
    } catch (java.io.IOException e) {
        throw new IOException("Exception while writing TEXT", e);
    }
}
Also used : FormattingProvider(org.jooq.FormattingProvider) ArrayList(java.util.ArrayList) IOException(org.jooq.exception.IOException) ArrayDeque(java.util.ArrayDeque)

Example 2 with FormattingProvider

use of org.jooq.FormattingProvider in project jOOQ by jOOQ.

the class AbstractResult method formatChart.

@SuppressWarnings("unchecked")
@Override
public final void formatChart(Writer writer, ChartFormat format) {
    Result<R> result;
    if (this instanceof Result)
        result = (Result<R>) this;
    else if (this instanceof Cursor)
        result = ((Cursor<R>) this).fetch();
    else
        throw new IllegalStateException();
    try {
        if (result.isEmpty()) {
            writer.append("No data available");
            return;
        }
        DSLContext ctx = configuration.dsl();
        FormattingProvider fp = configuration.formattingProvider();
        Field<?> category = fields.field(format.category());
        TreeMap<Object, Result<R>> groups = new TreeMap<>(result.intoGroups(format.category()));
        if (!format.categoryAsText()) {
            if (Date.class.isAssignableFrom(category.getType())) {
                Date categoryMin = (Date) groups.firstKey();
                Date categoryMax = (Date) groups.lastKey();
                for (Date i = categoryMin; i.before(categoryMax); i = new Date(i.getYear(), i.getMonth(), i.getDate() + 1)) if (!groups.containsKey(i))
                    groups.put(i, (Result<R>) ctx.newResult(fields.fields.fields));
            }
        }
        List<?> categories = new ArrayList<>(groups.keySet());
        int categoryPadding = 1;
        int categoryWidth = 0;
        for (Object o : categories) categoryWidth = Math.max(categoryWidth, fp.width("" + o));
        double axisMin = Double.POSITIVE_INFINITY;
        double axisMax = Double.NEGATIVE_INFINITY;
        for (Result<R> values : groups.values()) {
            double sum = 0;
            for (int i = 0; i < format.values().length; i++) {
                if (format.display() == Display.DEFAULT)
                    sum = 0;
                for (Record r : values) sum = sum + r.get(format.values()[i], double.class);
                if (sum < axisMin)
                    axisMin = sum;
                if (sum > axisMax)
                    axisMax = sum;
            }
        }
        int verticalLegendWidth = format.showVerticalLegend() ? (format.display() == Display.HUNDRED_PERCENT_STACKED) ? fp.width(format.percentFormat().format(100.0)) : Math.max(format.numericFormat().format(axisMin).length(), format.numericFormat().format(axisMax).length()) : 0;
        int horizontalLegendHeight = format.showHorizontalLegend() ? 1 : 0;
        int verticalBorderWidth = format.showVerticalLegend() ? 1 : 0;
        int horizontalBorderHeight = format.showHorizontalLegend() ? 1 : 0;
        int chartHeight = format.height() - horizontalLegendHeight - horizontalBorderHeight;
        int chartWidth = format.width() - verticalLegendWidth - verticalBorderWidth;
        double barWidth = (double) chartWidth / groups.size();
        double axisStep = (axisMax - axisMin) / (chartHeight - 1);
        for (int y = chartHeight - 1; y >= 0; y--) {
            double axisLegend = axisMax - (axisStep * (chartHeight - 1 - y));
            double axisLegendPercent = (axisLegend - axisMin) / (axisMax - axisMin);
            if (format.showVerticalLegend()) {
                String axisLegendString = (format.display() == Display.HUNDRED_PERCENT_STACKED) ? format.percentFormat().format(axisLegendPercent * 100.0) : format.numericFormat().format(axisLegend);
                for (int x = fp.width(axisLegendString); x < verticalLegendWidth; x++) writer.write(' ');
                writer.write(axisLegendString);
                for (int x = 0; x < verticalBorderWidth; x++) writer.write('|');
            }
            for (int x = 0; x < chartWidth; x++) {
                int index = (int) (x / barWidth);
                Result<R> group = groups.get(categories.get(index));
                double[] values = new double[format.values().length];
                for (Record record : group) for (int i = 0; i < values.length; i++) values[i] = values[i] + record.get(format.values()[i], double.class);
                if (format.display() == Display.STACKED || format.display() == Display.HUNDRED_PERCENT_STACKED)
                    for (int i = 1; i < values.length; i++) values[i] = values[i] + values[i - 1];
                if (format.display() == Display.HUNDRED_PERCENT_STACKED)
                    for (int i = 0; i < values.length; i++) values[i] = values[i] / values[values.length - 1];
                int shadeIndex = -1;
                for (int i = values.length - 1; i >= 0; i--) if ((format.display() == Display.HUNDRED_PERCENT_STACKED ? axisLegendPercent : axisLegend) > values[i])
                    break;
                else
                    shadeIndex = i;
                if (shadeIndex == -1)
                    writer.write(' ');
                else
                    writer.write(format.shades()[shadeIndex % format.shades().length]);
            }
            writer.write(format.newline());
        }
        if (format.showHorizontalLegend()) {
            for (int y = 0; y < horizontalBorderHeight; y++) {
                if (format.showVerticalLegend()) {
                    for (int x = 0; x < verticalLegendWidth; x++) writer.write('-');
                    for (int x = 0; x < verticalBorderWidth; x++) writer.write('+');
                }
                for (int x = 0; x < chartWidth; x++) writer.write('-');
                writer.write(format.newline());
            }
            for (int y = 0; y < horizontalLegendHeight; y++) {
                if (format.showVerticalLegend()) {
                    for (int x = 0; x < verticalLegendWidth; x++) writer.write(' ');
                    for (int x = 0; x < verticalBorderWidth; x++) writer.write('|');
                }
                double rounding = 0.0;
                for (double x = 0.0; x < chartWidth; ) {
                    String label = "" + categories.get((int) (x / barWidth));
                    int width = fp.width(label);
                    double padding = Math.max(categoryPadding, (barWidth - width) / 2);
                    rounding = (rounding + padding - Math.floor(padding)) % 1;
                    x = x + (padding + rounding);
                    for (int i = 0; i < (int) (padding + rounding); i++) writer.write(' ');
                    x = x + width;
                    if (x >= chartWidth)
                        break;
                    writer.write(label);
                    rounding = (rounding + padding - Math.floor(padding)) % 1;
                    x = x + (padding + rounding);
                    for (int i = 0; i < (int) (padding + rounding); i++) writer.write(' ');
                }
                writer.write(format.newline());
            }
        }
    } catch (java.io.IOException e) {
        throw new IOException("Exception while writing Chart", e);
    }
}
Also used : FormattingProvider(org.jooq.FormattingProvider) ArrayList(java.util.ArrayList) DSLContext(org.jooq.DSLContext) IOException(org.jooq.exception.IOException) Cursor(org.jooq.Cursor) TreeMap(java.util.TreeMap) Date(java.sql.Date) Result(org.jooq.Result) TableRecord(org.jooq.TableRecord) Record(org.jooq.Record)

Aggregations

ArrayList (java.util.ArrayList)2 FormattingProvider (org.jooq.FormattingProvider)2 IOException (org.jooq.exception.IOException)2 Date (java.sql.Date)1 ArrayDeque (java.util.ArrayDeque)1 TreeMap (java.util.TreeMap)1 Cursor (org.jooq.Cursor)1 DSLContext (org.jooq.DSLContext)1 Record (org.jooq.Record)1 Result (org.jooq.Result)1 TableRecord (org.jooq.TableRecord)1