com.haulmont.yarg.formatters.impl.AbstractFormatter.java Source code

Java tutorial

Introduction

Here is the source code for com.haulmont.yarg.formatters.impl.AbstractFormatter.java

Source

/*
 * Copyright 2013 Haulmont
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.haulmont.yarg.formatters.impl;

import com.google.common.base.Preconditions;
import com.haulmont.yarg.exception.ReportFormattingException;
import com.haulmont.yarg.formatters.ReportFormatter;
import com.haulmont.yarg.formatters.factory.FormatterFactoryInput;
import com.haulmont.yarg.formatters.impl.inline.BitmapContentInliner;
import com.haulmont.yarg.formatters.impl.inline.ContentInliner;
import com.haulmont.yarg.formatters.impl.inline.HtmlContentInliner;
import com.haulmont.yarg.formatters.impl.inline.ImageContentInliner;
import com.haulmont.yarg.structure.BandData;
import com.haulmont.yarg.structure.ReportFieldFormat;
import com.haulmont.yarg.structure.ReportOutputType;
import com.haulmont.yarg.structure.ReportTemplate;
import org.apache.commons.lang.StringUtils;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public abstract class AbstractFormatter implements ReportFormatter {
    public static final String SIMPLE_ALIAS_REGEXP = "\\$\\{([A-z0-9_]+?)\\}";

    public static final String ALIAS_GROUP = "([A-z0-9_\\.]+?)";
    public static final String STRING_FUNCTION_GROUP = "(\\[\\d+\\])";
    public static final String UNIVERSAL_ALIAS_REGEXP = "\\$\\{" + ALIAS_GROUP + " *" + STRING_FUNCTION_GROUP
            + "?\\}";
    public static final String ALIAS_WITH_BAND_NAME_REGEXP = UNIVERSAL_ALIAS_REGEXP;
    public static final String BAND_NAME_DECLARATION_REGEXP = "##band=([A-z_0-9]+) *";

    public static final Pattern UNIVERSAL_ALIAS_PATTERN = Pattern.compile(UNIVERSAL_ALIAS_REGEXP,
            Pattern.CASE_INSENSITIVE);
    public static final Pattern ALIAS_WITH_BAND_NAME_PATTERN = Pattern.compile(ALIAS_WITH_BAND_NAME_REGEXP);
    public static final Pattern BAND_NAME_DECLARATION_PATTERN = Pattern.compile(BAND_NAME_DECLARATION_REGEXP);

    protected BandData rootBand;
    protected ReportTemplate reportTemplate;
    protected OutputStream outputStream;
    protected Set<ReportOutputType> supportedOutputTypes = new HashSet<ReportOutputType>();
    protected DefaultFormatProvider defaultFormatProvider;

    /**
     * Chain of responsibility for content inliners
     */
    protected List<ContentInliner> contentInliners = new ArrayList<ContentInliner>();

    protected AbstractFormatter(FormatterFactoryInput formatterFactoryInput) {
        Preconditions.checkNotNull("\"rootBand\" parameter can not be null", formatterFactoryInput.getRootBand());
        Preconditions.checkNotNull("\"reportTemplate\" parameter can not be null",
                formatterFactoryInput.getReportTemplate());

        this.rootBand = formatterFactoryInput.getRootBand();
        this.reportTemplate = formatterFactoryInput.getReportTemplate();
        this.outputStream = formatterFactoryInput.getOutputStream();

        this.contentInliners.add(new BitmapContentInliner());
        this.contentInliners.add(new HtmlContentInliner());
        this.contentInliners.add(new ImageContentInliner());
    }

    @Override
    public byte[] createDocument() {
        Preconditions.checkArgument(supportedOutputTypes.contains(reportTemplate.getOutputType()), String
                .format("%s formatter doesn't support %s output type", getClass(), reportTemplate.getOutputType()));
        outputStream = new ByteArrayOutputStream();
        renderDocument();
        return ((ByteArrayOutputStream) outputStream).toByteArray();
    }

    public List<ContentInliner> getContentInliners() {
        return contentInliners;
    }

    public void setContentInliners(List<ContentInliner> contentInliners) {
        this.contentInliners = contentInliners;
    }

    public void setDefaultFormatProvider(DefaultFormatProvider defaultFormatProvider) {
        this.defaultFormatProvider = defaultFormatProvider;
    }

    protected String unwrapParameterName(String nameWithAlias) {
        Matcher matcher = UNIVERSAL_ALIAS_PATTERN.matcher(nameWithAlias);
        if (matcher.find()) {
            return matcher.group(1);
        }

        return null;
    }

    protected String formatValue(Object value, String parameterName, String fullParameterName) {
        return formatValue(value, parameterName, fullParameterName, null);
    }

    protected String formatValue(Object value, String parameterName, String fullParameterName,
            String stringFunction) {
        if (value == null) {
            return "";
        }

        String valueString;
        String formatString = getFormatString(parameterName, fullParameterName);
        if (formatString != null) {
            if (value instanceof Number) {
                DecimalFormat decimalFormat = new DecimalFormat(formatString);
                valueString = decimalFormat.format(value);
            } else if (value instanceof Date) {
                SimpleDateFormat dateFormat = new SimpleDateFormat(formatString);
                valueString = dateFormat.format(value);
            } else if (value instanceof String && !formatString.startsWith("${")) {//do not use inliner alias as format string
                valueString = String.format(formatString, value);
            } else {
                valueString = value.toString();
            }
        } else {
            valueString = defaultFormat(value);
        }

        if (stringFunction != null) {
            valueString = applyStringFunction(valueString, stringFunction);
        }

        return valueString;
    }

    protected String getFormatString(String parameterName, String fullParameterName) {
        Map<String, ReportFieldFormat> formats = rootBand.getReportFieldFormats();
        String formatString = null;
        if (formats != null) {
            if (formats.containsKey(fullParameterName)) {
                formatString = formats.get(fullParameterName).getFormat();
            } else if (formats.containsKey(parameterName)) {
                formatString = formats.get(parameterName).getFormat();
            }
        }
        return formatString;
    }

    protected String applyStringFunction(String valueString, String stringFunction) {
        if (stringFunction.matches(STRING_FUNCTION_GROUP)) {
            Integer index = Integer.valueOf(stringFunction.replaceAll("[^\\d]", ""));

            if (valueString.length() >= index) {
                return valueString.substring(index, index + 1);
            }
        }

        return valueString;
    }

    protected String defaultFormat(Object value) {
        if (defaultFormatProvider != null) {
            return defaultFormatProvider.format(value);
        } else {
            return value != null ? value.toString() : null;
        }
    }

    protected String insertBandDataToString(BandData bandData, String resultStr) {
        List<String> parametersToInsert = new ArrayList<String>();
        Matcher matcher = UNIVERSAL_ALIAS_PATTERN.matcher(resultStr);
        while (matcher.find()) {
            parametersToInsert.add(unwrapParameterName(matcher.group()));
        }
        for (String parameterName : parametersToInsert) {
            Object value = bandData.getData().get(parameterName);
            String fullParameterName = bandData.getName() + "." + parameterName;
            String valueStr = formatValue(value, parameterName, fullParameterName);
            resultStr = inlineParameterValue(resultStr, parameterName, valueStr);
        }
        return resultStr;
    }

    protected String inlineParameterValue(String template, String parameterName, String value) {
        String parameterRegex = UNIVERSAL_ALIAS_REGEXP.replace(ALIAS_GROUP, parameterName);
        return template.replaceAll(parameterRegex, Matcher.quoteReplacement(value));
    }

    protected boolean containsJustOneAlias(String value) {
        return !StringUtils.isBlank(value) && value.matches("\\$\\{[^\\$\\{\\}]*\\}");
    }

    protected BandData findBandByPath(String path) {
        if (rootBand.getName().equals(path))
            return rootBand;

        String[] pathParts = path.split("\\.");
        BandData currentBand = rootBand;
        for (String pathPart : pathParts) {
            if (currentBand == null)
                return null;
            currentBand = currentBand.findBandRecursively(pathPart);
        }

        return currentBand;
    }

    protected BandPathAndParameterName separateBandNameAndParameterName(String alias) {
        List<String> bandPathList = new ArrayList<String>();
        String[] pathParts = alias.split("\\.");
        BandData currentBand = rootBand;
        for (String pathPart : pathParts) {
            currentBand = currentBand.findBandRecursively(pathPart);
            if (currentBand != null) {
                bandPathList.add(pathPart);
            } else {
                break;
            }
        }

        if (bandPathList.isEmpty()) {
            return new BandPathAndParameterName("", alias);
        } else {
            String bandPathPart = StringUtils.join(bandPathList, ".");
            String paramNamePart = alias.replaceFirst(bandPathPart + ".", "");
            return new BandPathAndParameterName(bandPathPart, paramNamePart);
        }
    }

    protected ReportFormattingException wrapWithReportingException(String message, Exception e) {
        return new ReportFormattingException(message + ". Template name [" + reportTemplate.getDocumentName() + "]",
                e);
    }

    protected ReportFormattingException wrapWithReportingException(String message) {
        return new ReportFormattingException(
                message + ". Template name [" + reportTemplate.getDocumentName() + "]");
    }

    protected static class InlinerAndMatcher {
        final ContentInliner contentInliner;
        final Matcher matcher;

        public InlinerAndMatcher(ContentInliner contentInliner, Matcher matcher) {
            this.contentInliner = contentInliner;
            this.matcher = matcher;
        }
    }

    protected InlinerAndMatcher getContentInlinerForFormat(String formatString) {
        if (formatString != null) {
            for (ContentInliner contentInliner : contentInliners) {
                Matcher matcher = contentInliner.getTagPattern().matcher(formatString);
                if (matcher.find()) {
                    return new InlinerAndMatcher(contentInliner, matcher);
                }
            }
        }
        return null;
    }

    public static class BandPathAndParameterName {
        protected final String bandPath;
        protected final String parameterName;

        public BandPathAndParameterName(String bandPath, String parameterName) {
            this.bandPath = bandPath;
            this.parameterName = parameterName;
        }

        public String getBandPath() {
            return bandPath;
        }

        public String getParameterName() {
            return parameterName;
        }
    }
}