Package org.librebiz.pureport.reportfile

Source Code of org.librebiz.pureport.reportfile.ReportReader

/*
    Pureport, a report generator for Java
    Copyright (C) 2011  Maurice Perry <maurice@perry.ch>

    Project Web Site: http://code.google.com/p/pureport/

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.librebiz.pureport.reportfile;

import java.awt.Color;
import java.awt.font.TextAttribute;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.librebiz.pureport.definition.Band;
import org.librebiz.pureport.definition.Block;
import org.librebiz.pureport.definition.Box;
import org.librebiz.pureport.definition.Cell;
import org.librebiz.pureport.definition.Choose;
import org.librebiz.pureport.definition.Column;
import org.librebiz.pureport.definition.Expression;
import org.librebiz.pureport.definition.ImageElement;
import org.librebiz.pureport.definition.Iteration;
import org.librebiz.pureport.definition.MacroCall;
import org.librebiz.pureport.definition.MacroDefinition;
import org.librebiz.pureport.definition.PageLayout;
import org.librebiz.pureport.definition.Report;
import org.librebiz.pureport.definition.Row;
import org.librebiz.pureport.definition.Script;
import org.librebiz.pureport.definition.SectionContainer;
import org.librebiz.pureport.definition.StrokeInfo;
import org.librebiz.pureport.definition.TextContainer;
import org.librebiz.pureport.definition.TextString;
import org.librebiz.pureport.definition.TextWrapper;
import org.librebiz.pureport.definition.TileExpression;
import org.librebiz.pureport.definition.When;
import org.librebiz.pureport.quantity.Quantity;
import org.librebiz.pureport.quantity.Unit;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.helpers.DefaultHandler;

public class ReportReader extends DefaultHandler {
    private static final Logger LOG
            = Logger.getLogger(ReportReader.class.getName());

    private static final Map<String,Color> COLOR_MAP
            = new HashMap<String,Color>();
    private static final Map<String,Integer> IMAGE_ALIGNMENT_MAP
            = new HashMap<String,Integer>();
    private Unit defaultUnits = Unit.DEFAULT_UNIT;
    private Report report;
    private Band band;
    private int row;
    private int column;
    private Cell cell;
    private TextContainer container;
    private List containerStack = new LinkedList();
    private int imageAlignment;
    private Quantity imageOriginX;
    private Quantity imageOriginY;
    private Quantity imageWidth;
    private Quantity imageHeight;
    private boolean pass2;
    private TileExpression tileExpr;
    private Box box;
    private TextHandler textHandler;
    private SectionContainer sectionContainer;
    private List<SectionContainer> sectionContainerStack
            = new ArrayList<SectionContainer>();
    private MacroCall call;
    private String argName;
    private String argValue;
    private Choose choose;

    static {
        COLOR_MAP.put("white", Color.WHITE);
        COLOR_MAP.put("light-gray", Color.LIGHT_GRAY);
        COLOR_MAP.put("gray", Color.GRAY);
        COLOR_MAP.put("dark-gray", Color.DARK_GRAY);
        COLOR_MAP.put("black", Color.BLACK);
        COLOR_MAP.put("red", Color.RED);
        COLOR_MAP.put("pink", Color.PINK);
        COLOR_MAP.put("orange", Color.ORANGE);
        COLOR_MAP.put("yellow", Color.YELLOW);
        COLOR_MAP.put("green", Color.GREEN);
        COLOR_MAP.put("magenta", Color.MAGENTA);
        COLOR_MAP.put("cyan", Color.CYAN);
        COLOR_MAP.put("blue", Color.BLUE);
    }

    static {
        IMAGE_ALIGNMENT_MAP.put("top", ImageElement.TOP_ALIGNMENT);
        IMAGE_ALIGNMENT_MAP.put("bottom", ImageElement.BOTTOM_ALIGNMENT);
        IMAGE_ALIGNMENT_MAP.put("hanging", ImageElement.HANGING_BASELINE);
        IMAGE_ALIGNMENT_MAP.put("center", ImageElement.CENTER_BASELINE);
        IMAGE_ALIGNMENT_MAP.put("roman", ImageElement.ROMAN_BASELINE);
    }

    private ReportReader() {
    }

    public static Report load(InputStream in)
            throws IOException {
        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            factory.setFeature("http://xml.org/sax/features/validation", true);
            SAXParser parser = factory.newSAXParser();
            ReportReader handler = new ReportReader();
            parser.parse(new InputSource(in), handler);
            return handler.report;
        } catch (ParserConfigurationException ex) {
            throw new IOException(ex.getMessage());
        } catch (SAXNotSupportedException ex) {
            throw new IOException(ex.getMessage());
        } catch (SAXException ex) {
            throw new IOException(ex.getMessage());
        }
    }

    public static Report load(File file) throws IOException {
        InputStream in = new FileInputStream(file);
        try {
            return load(in);
        } finally {
            in.close();
        }
    }

    public static Report load(String fileName) throws IOException {
        return load(new File(fileName));
    }

    public static Report load(URL url) throws IOException {
        InputStream in = url.openStream();
        try {
            return load(in);
        } finally {
            in.close();
        }
    }

    @Override
    public InputSource resolveEntity(String publicId, String systemId)
            throws IOException, SAXException {
        if ("-//librebiz//DTD pureport 1.0//EN".equals(publicId)
                || "report.dtd".equals(systemId)) {
            return new InputSource(
                    getClass().getResourceAsStream("report.dtd"));
        }
        return null;
    }

    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attrs) {
        if (LOG.isLoggable(Level.FINE)) {
            dumpStart(qName, attrs);
        }
        if (qName.equals("report")) {
            startReport(attrs);
        } else if (qName.equals("script")) {
            startScript();
        } else if (qName.equals("before")) {
            startBefore();
        } else if (qName.equals("after")) {
            startAfter();
        } else if (qName.equals("condition")) {
            startCondition(attrs);
        } else if (qName.equals("page-layout")) {
            startPageLayout(attrs);
        } else if (qName.equals("report-header")) {
            startBand(attrs);
            report.setReportHeader(band);
        } else if (qName.equals("report-footer")) {
            startBand(attrs);
            report.setReportFooter(band);
        } else if (qName.equals("page-header")) {
            startBand(attrs);
            report.setPageHeader(band);
        } else if (qName.equals("page-footer")) {
            startBand(attrs);
            report.setPageFooter(band);
        } else if (qName.equals("band")) {
            startBand(attrs);
            sectionContainer.addContent(band);
        } else if (qName.equals("iterate")) {
            startIterate(attrs);
        } else if (qName.equals("row")) {
            startRow(attrs);
        } else if (qName.equals("column")) {
            startColumn(attrs);
        } else if (qName.equals("cell")) {
            startCell(attrs);
        } else if (qName.equals("block")) {
            startBlock(attrs);
        } else if (qName.equals("tile")) {
            startTile(attrs);
        } else if (qName.equals("wrapper")) {
            startWrapper(attrs);
        } else if (qName.equals("expression")) {
            startExpression(attrs);
        } else if (qName.equals("image")) {
            startImage(attrs);
        } else if (qName.equals("macro")) {
            startMacroDefinition(attrs);
        } else if (qName.equals("call")) {
            startMacroCall(attrs);
        } else if (qName.equals("argument")) {
            startArgument(attrs);
        } else if (qName.equals("choose")) {
            startChoose(attrs);
        } else if (qName.equals("when")) {
            startWhen(attrs);
        } else if (qName.equals("otherwise")) {
            startOtherwise(attrs);
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) {
        if (LOG.isLoggable(Level.FINE)) {
            dumpEnd(qName);
        }
        if (qName.equals("report")) {
            endReport();
        } else if (qName.equals("script")) {
            endScript();
        } else if (qName.equals("before")) {
            endBefore();
        } else if (qName.equals("after")) {
            endAfter();
        } else if (qName.equals("condition")) {
            endCondition();
        } else if (qName.equals("page-layout")) {
            endPageLayout();
        } else if (qName.equals("report-header")) {
            endBand();
        } else if (qName.equals("report-footer")) {
            endBand();
        } else if (qName.equals("page-header")) {
            endBand();
        } else if (qName.equals("page-footer")) {
            endBand();
        } else if (qName.equals("band")) {
            endBand();
        } else if (qName.equals("iterate")) {
            endIterate();
        } else if (qName.equals("row")) {
            endRow();
        } else if (qName.equals("column")) {
            endColumn();
        } else if (qName.equals("cell")) {
            endCell();
        } else if (qName.equals("block")) {
            endBlock();
        } else if (qName.equals("tile")) {
            endTile();
        } else if (qName.equals("wrapper")) {
            endWrapper();
        } else if (qName.equals("expression")) {
            endExpression();
        } else if (qName.equals("image")) {
            endImage();
        } else if (qName.equals("macro")) {
            endMacroDefinition();
        } else if (qName.equals("call")) {
            endMacroCall();
        } else if (qName.equals("argument")) {
            endArgument();
        } else if (qName.equals("choose")) {
            endChoose();
        } else if (qName.equals("when")) {
            endWhen();
        } else if (qName.equals("otherwise")) {
            endOtherwise();
        }
    }

    private void dumpStart(String element, Attributes attrs) {
        StringBuilder sb = new StringBuilder();
        sb.append('<');
        sb.append(element);
        int n = attrs.getLength();
        for (int i = 0; i < n; ++i) {
            sb.append(' ');
            sb.append(attrs.getLocalName(i));
            sb.append("=\"");
            sb.append(attrs.getValue(i));
            sb.append('"');
        }
        sb.append('>');
        LOG.fine(sb.toString());
    }

    private void dumpEnd(String element) {
        LOG.log(Level.FINE, "<{0}/>", element);
    }

    @Override
    public void characters(char chars[], int start, int length) {
        if (textHandler != null) {
            int end = start+length;
            for (int i = start; i < end; ++i) {
                textHandler.handleChar(chars[i]);
            }
        }
    }

    private Quantity zero() {
        return new Quantity(0, defaultUnits);
    }

    private Quantity toQuantity(String value) {
        return toQuantity(value, null);
    }

    private Quantity toQuantity(String value, Quantity defValue) {
        return value == null ? defValue : Quantity.parse(value, defaultUnits);
    }

    private int toInt(String value, int defValue) {
        return value == null ? defValue : Integer.parseInt(value);
    }

    private Color toColor(String s) {
        if (s == null) {
            return null;
        } else {
            Color col = (Color)COLOR_MAP.get(s.toLowerCase());
            if (col != null) {
                return col;
            } else {
                int rgb = (int)Long.parseLong(s, 16);
                return new Color(rgb, s.length() == 8);
            }
        }
    }

    private StrokeInfo toStrokeInfo(String s) {
        if (s == null) {
            return null;
        } else {
            StringTokenizer tokenizer = new StringTokenizer(s, " \t");
            if (tokenizer.countTokens() != 3) {
                throw new ReportReaderException("Invalid border info " + s);
            }
            StrokeInfo si = new StrokeInfo();
            si.setWidth(toQuantity(tokenizer.nextToken()));
            tokenizer.nextToken();
            si.setColor(toColor(tokenizer.nextToken()));
            return si;
        }
    }

    private void setBoxAttributes(Box box, Attributes attrs) {
        box.setCondition(attrs.getValue("condition"));
        box.setTopMargin(toQuantity(attrs.getValue("top-margin")));
        box.setBottomMargin(toQuantity(attrs.getValue("bottom-margin")));
        box.setLeftMargin(toQuantity(attrs.getValue("left-margin")));
        box.setRightMargin(toQuantity(attrs.getValue("right-margin")));

        box.setTopPadding(toQuantity(attrs.getValue("top-padding")));
        box.setBottomPadding(toQuantity(attrs.getValue("bottom-padding")));
        box.setLeftPadding(toQuantity(attrs.getValue("left-padding")));
        box.setRightPadding(toQuantity(attrs.getValue("right-padding")));

        box.setBackground(toColor(attrs.getValue("background")));

        String s = attrs.getValue("vertical-align");
        if ("bottom".equals(s)) {
            box.setVerticalAlignment(Cell.ALIGN_BOTTOM);
        } else if ("center".equals(s)) {
            box.setVerticalAlignment(Cell.ALIGN_CENTER);
        } else {
            box.setVerticalAlignment(Cell.ALIGN_TOP);
        }

        s = attrs.getValue("align");
        if ("right".equals(s)) {
            box.setAlignment(Block.ALIGN_RIGHT);
        } else if ("center".equals(s)) {
            box.setAlignment(Block.ALIGN_CENTER);
        } else if ("justify".equals(s)) {
            box.setAlignment(Block.ALIGN_JUSTIFY);
        } else {
            box.setAlignment(Block.ALIGN_LEFT);
        }

        StrokeInfo si = toStrokeInfo(attrs.getValue("border"));
        if (si != null) {
            box.setLeftBorder(si);
            box.setRightBorder(si);
            box.setTopBorder(si);
            box.setBottomBorder(si);
        } else {
            box.setLeftBorder(toStrokeInfo(attrs.getValue("border-left")));
            box.setRightBorder(toStrokeInfo(attrs.getValue("border-right")));
            box.setTopBorder(toStrokeInfo(attrs.getValue("border-top")));
            box.setBottomBorder(toStrokeInfo(attrs.getValue("border-bottom")));
        }
        this.box = box;
    }

    private void setTextAttributes(TextWrapper at, Attributes attrs) {
        at.setAttribute(TextAttribute.FAMILY, attrs.getValue("font-family"));
        String s = attrs.getValue("font-style");
        if (s != null) {
            StringTokenizer tokenizer = new StringTokenizer(s, " \t,;");
            while (tokenizer.hasMoreTokens()) {
                String token = tokenizer.nextToken();
                if (token.equals("italic")) {
                    at.setAttribute(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
                }
            }
        }
        Quantity q = toQuantity(attrs.getValue("font-size"));
        if (q != null) {
            float size = (float)q.getValue(Unit.PT);
            at.setAttribute(TextAttribute.SIZE, new Float(size));
        }
        Color col = toColor(attrs.getValue("foreground"));
        if (col != null) {
            at.setAttribute(TextAttribute.FOREGROUND, col);
        }
        col = toColor(attrs.getValue("background"));
        if (col != null) {
            at.setAttribute(TextAttribute.BACKGROUND, col);
        }
    }

    private void startReport(Attributes attrs) {
        report = new Report();
        String s = attrs.getValue("default-units");
        if (s != null) {
            Unit u = Unit.get(s);
            if (u != null) {
                defaultUnits = u;
            }
        }
        sectionContainer = report;
    }

    private void endReport() {
       
    }

    public void startBefore() {
        new ExpressionTextHandler().start();
    }

    public void endBefore() {
        String s = textHandler.end();
        if (s != null && s.length() > 0) {
            if (band == null) {
                report.setBefore(s);
            } else {
                band.setBefore(s);
            }
        }
    }

    public void startAfter() {
        new ExpressionTextHandler().start();
    }

    public void endAfter() {
        String s = textHandler.end();
        if (s != null && s.length() > 0) {
            if (band == null) {
                report.setAfter(s);
            } else {
                band.setAfter(s);
            }
        }
    }

    private void startCondition(Attributes attrs) {
        new ExpressionTextHandler().start();
    }

    private void endCondition() {
        String s = textHandler.end();
        if (s != null && s.length() > 0) {
            if (box != null) {
                box.setCondition(s);
            }
        }
    }

    private void startPageLayout(Attributes attrs) {
        PageLayout layout = new PageLayout();
        layout.setPaperWidth(toQuantity(attrs.getValue("paper-width"), new Quantity(21, Unit.CM)));
        layout.setPaperHeight(toQuantity(attrs.getValue("paper-height"), new Quantity(29.7, Unit.CM)));
        layout.setTopMargin(toQuantity(attrs.getValue("top-margin")));
        layout.setBottomMargin(toQuantity(attrs.getValue("bottom-margin")));
        layout.setLeftMargin(toQuantity(attrs.getValue("left-margin")));
        layout.setRightMargin(toQuantity(attrs.getValue("right-margin")));
        String orientation = attrs.getValue("orientation");
        if ("portrait".equals(orientation)) {
            layout.setOrientation(PageLayout.PORTRAIT);
        } else if ("landscape".equals(orientation)) {
            layout.setOrientation(PageLayout.LANDSCAPE);
        } else if ("reverse-landscape".equals(orientation)) {
            layout.setOrientation(PageLayout.REVERSE_LANDSCAPE);
        }
        report.setPageLayout(layout);
    }

    private void endPageLayout() {
       
    }

    private void startBand(Attributes attrs) {
        band = new Band();
        setBoxAttributes(band, attrs);
        row = 0;
        column = 0;
    }

    private void endBand() {
        band = null;
    }

    private void startRow(Attributes attrs) {
        Row r = new Row();
        r.setHeight(toQuantity(attrs.getValue("height")));
        r.setTopMargin(toQuantity(attrs.getValue("top-margin"), zero()));
        r.setBottomMargin(toQuantity(attrs.getValue("bottom-margin"), zero()));
        band.addRow(r);
    }

    private void endRow() {
       
    }

    private void startColumn(Attributes attrs) {
        Column c = new Column();
        c.setWidth(toQuantity(attrs.getValue("width")));
        c.setLeftMargin(toQuantity(attrs.getValue("left-margin"), zero()));
        c.setRightMargin(toQuantity(attrs.getValue("right-margin"), zero()));
        band.addColumn(c);
    }

    private void endColumn() {
       
    }

    private void startCell(Attributes attrs) {
        cell = new Cell();
        setBoxAttributes(cell, attrs);
        cell.setRow(row);
        cell.setColumn(column);
        cell.setRowSpan(toInt(attrs.getValue("row-span"), 1));
        cell.setColumnSpan(toInt(attrs.getValue("column-span"), 1));
        band.addCell(cell);
    }

    private void endCell() {
        while (true) {
            ++column;
            if (column >= band.getColumnCount()) {
                column = 0;
                ++row;
            }
            if (band.getCellAt(row, column) == null) {
                break;
            }
        }
        cell = null;
    }

    private void startBlock(Attributes attrs) {
        Block block = new Block();
        container = block.getContent();
        setBoxAttributes(block, attrs);
        setTextAttributes(block.getContent(), attrs);
        cell.addBox(block);
        new ContentTextHandler().start();
    }

    private void endBlock() {
        String s = textHandler.end();
        if (s.length() > 0) {
            container.add(new TextString(s));
        }
        container = null;
    }

    private void startTile(Attributes attrs) {
        tileExpr = new TileExpression();
        setBoxAttributes(tileExpr, attrs);
        tileExpr.setExpression(attrs.getValue("value"));
        cell.addBox(tileExpr);
        new ContentTextHandler().start();
    }

    private void endTile() {
        String s = textHandler.end();
        if (s.length() > 0) {
            tileExpr.setExpression(s);
        }
        tileExpr = null;
    }

    private void startWrapper(Attributes attrs) {
        String s = textHandler.text();
        if (s.length() > 0) {
            container.add(new TextString(s));
        }
        TextWrapper at = new TextWrapper();
        setTextAttributes(at, attrs);
        container.add(at);
        containerStack.add(0, container);
        container = at;
        new ContentTextHandler().start();
    }

    private void endWrapper() {
        String s = textHandler.end();
        if (s.length() > 0) {
            container.add(new TextString(s));
        }
        container = (TextContainer)containerStack.remove(0);
    }

    private void startExpression(Attributes attrs) {
        String s = textHandler.text();
        if (s.length() > 0) {
            container.add(new TextString(s));
        }
        s = attrs.getValue("pass2");
        pass2 = s == null ? false : "true".equalsIgnoreCase(s);
        s = attrs.getValue("value");
        if (s != null && s.length() > 0) {
            container.add(new Expression(s, pass2));
        }
        new ContentTextHandler().start();
    }

    private void endExpression() {
        String s = textHandler.end();
        if (s.length() > 0) {
            container.add(new Expression(s, pass2));
        }
    }

    private void startImage(Attributes attrs) {
        String s = textHandler.text();
        if (s.length() > 0) {
            container.add(new TextString(s));
        }
        s = attrs.getValue("alignment");
        Integer a = (Integer)IMAGE_ALIGNMENT_MAP.get(s);
        imageAlignment = a == null ? ImageElement.TOP_ALIGNMENT : a.intValue();
        imageWidth = toQuantity(attrs.getValue("width"));
        imageHeight = toQuantity(attrs.getValue("height"));
        imageOriginX = toQuantity(attrs.getValue("origin-x"), Quantity.ZERO);
        imageOriginY = toQuantity(attrs.getValue("origin-y"), Quantity.ZERO);
        s = attrs.getValue("value");
        if (s != null && s.length() > 0) {
            container.add(new ImageElement(s, imageAlignment,
                    imageWidth, imageHeight, imageOriginX, imageOriginY));
        }
        new ExpressionTextHandler().start();
    }

    private void endImage() {
        String s = textHandler.end();
        if (s.length() > 0) {
            container.add(new ImageElement(s, imageAlignment,
                    imageWidth, imageHeight, imageOriginX, imageOriginY));
        }
    }

    private void startSectionContainer(SectionContainer sc) {
        sectionContainerStack.add(0, sectionContainer);
        sectionContainer = sc;
    }

    private void endSectionContainer() {
        sectionContainer = sectionContainerStack.remove(0);
    }

    private void startIterate(Attributes attrs) {
        Iteration iteration = new Iteration();
        iteration.setId(attrs.getValue("id"));
        iteration.setIndexId(attrs.getValue("index-id"));
        iteration.setCollection(attrs.getValue("collection"));
        sectionContainer.addContent(iteration);
        startSectionContainer(iteration);
    }

    private void endIterate() {
        endSectionContainer();
    }

    private void startMacroDefinition(Attributes attrs) {
        MacroDefinition macro = new MacroDefinition();
        report.addMacro(attrs.getValue("name"), macro);
        String attrList = attrs.getValue("arguments");
        if (attrList != null) {
            String names[] = attrList.split("[,; ]");
            for (String name: names) {
                macro.addArgument(name.trim());
            }
        }
        startSectionContainer(macro);
    }

    private void endMacroDefinition() {
        endSectionContainer();
    }

    private void startMacroCall(Attributes attrs) {
        call = new MacroCall();
        call.setName(attrs.getValue("name"));
        sectionContainer.addContent(call);
    }

    private void endMacroCall() {
        call = null;
    }

    private void startArgument(Attributes attrs) {
        argName = attrs.getValue("name");
        argValue = attrs.getValue("value");
        new ExpressionTextHandler().start();
    }

    private void endArgument() {
        String s = textHandler.end();
        if (s.length() > 0) {
            call.addArgument(argName, s);
        } else {
            call.addArgument(argName, argValue);
        }
    }

    public void startScript() {
        new ExpressionTextHandler().start();
    }

    public void endScript() {
        String s = textHandler.end();
        if (s != null && s.length() > 0) {
            sectionContainer.addContent(new Script(s));
        }
    }

    private void startChoose(Attributes attrs) {
        choose = new Choose();
        sectionContainer.addContent(choose);
    }

    private void endChoose() {
        choose = null;
    }

    private void startWhen(Attributes attrs) {
        When branch = new When();
        choose.addBranch(branch);
        branch.setCondition(attrs.getValue("test"));
        startSectionContainer(branch);
    }

    private void endWhen() {
        endSectionContainer();
    }

    private void startOtherwise(Attributes attrs) {
        When branch = new When();
        choose.addBranch(branch);
        startSectionContainer(branch);
    }

    private void endOtherwise() {
        endSectionContainer();
    }

    private abstract class TextHandler {
        private TextHandler link;
        private StringBuffer buf = new StringBuffer();

        void start() {
            link = textHandler;
            textHandler = this;
        }

        String text() {
            String result = buf.toString();
            buf.setLength(0);
            return result;
        }

        String end() {
            textHandler = link;
            return buf.toString();
        }

        void putChar(char c) {
            buf.append(c);
        }

        boolean hasChars() {
            return buf.length() > 0;
        }

        void handleChar(char c) {
            putChar(c);
        }
    }

    private class ExpressionTextHandler extends TextHandler {
       
    }

    private class ContentTextHandler extends TextHandler {
        boolean wasBlank;
        boolean keepBlanks;

        ContentTextHandler() {
        }

        @Override
        String text() {
            if (wasBlank) {
                putChar(' ');
                wasBlank = false;
            }
            keepBlanks = true;
            return super.text();
        }

        @Override
        void handleChar(char c) {
            if (Character.isWhitespace(c)) {
                wasBlank = keepBlanks;
            } else {
                if (wasBlank) {
                    putChar(' ');
                    wasBlank = false;
                }
                keepBlanks = true;
                putChar(c);
            }
        }
    }
}
TOP

Related Classes of org.librebiz.pureport.reportfile.ReportReader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.