uk.co.spudsoft.birt.emitters.excel.StyleManager.java Source code

Java tutorial

Introduction

Here is the source code for uk.co.spudsoft.birt.emitters.excel.StyleManager.java

Source

/*************************************************************************************
 * Copyright (c) 2011, 2012, 2013 James Talbut.
 *  jim-emitters@spudsoft.co.uk
 *  
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     James Talbut - Initial implementation.
 ************************************************************************************/

package uk.co.spudsoft.birt.emitters.excel;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.extensions.XSSFCellBorder.BorderSide;
import org.eclipse.birt.report.engine.content.IStyle;
import org.eclipse.birt.report.engine.css.engine.CSSEngine;
import org.eclipse.birt.report.engine.css.engine.StyleConstants;
import org.eclipse.birt.report.engine.css.engine.value.DataFormatValue;
import org.eclipse.birt.report.engine.css.engine.value.FloatValue;
import org.eclipse.birt.report.engine.css.engine.value.css.CSSConstants;
import org.w3c.dom.css.CSSValue;

import uk.co.spudsoft.birt.emitters.excel.framework.Logger;

/**
 * StyleManager is a cache of POI CellStyles to enable POI CellStyles to be reused based upon their BIRT styles.
 * @author Jim Talbut
 *
 */
public class StyleManager {

    /**
     * StylePair maintains the relationship between a BIRT style and a POI style.
     * @author Jim Talbut
     *
     */
    private class StylePair {
        public BirtStyle birtStyle;
        public CellStyle poiStyle;

        public StylePair(BirtStyle birtStyle, CellStyle poiStyle) {
            this.birtStyle = birtStyle;
            this.poiStyle = poiStyle;
        }
    }

    private Workbook workbook;
    private FontManager fm;
    private List<StylePair> styles = new ArrayList<StylePair>();
    private StyleManagerUtils smu;
    private CSSEngine cssEngine;
    private Logger log;
    private Locale locale;

    /**
     * @param workbook
     * The workbook for which styles are being tracked.
     * @param styleStack
     * A style stack, to allow cells to inherit properties from container elements.
     * @param log
     * Logger to be used during processing.
     * @param smu
     * Set of functions for carrying out conversions between BIRT and POI. 
     * @param cssEngine
     * BIRT CSS Engine for creating BIRT styles. 
     */
    public StyleManager(Workbook workbook, Logger log, StyleManagerUtils smu, CSSEngine cssEngine, Locale locale) {
        this.workbook = workbook;
        this.fm = new FontManager(cssEngine, workbook, smu);
        this.log = log;
        this.smu = smu;
        this.cssEngine = cssEngine;
        this.locale = locale;
    }

    public FontManager getFontManager() {
        return fm;
    }

    public CSSEngine getCssEngine() {
        return cssEngine;
    }

    static int COMPARE_CSS_PROPERTIES[] = { StyleConstants.STYLE_TEXT_ALIGN, StyleConstants.STYLE_BACKGROUND_COLOR,
            StyleConstants.STYLE_BORDER_TOP_STYLE, StyleConstants.STYLE_BORDER_TOP_WIDTH,
            StyleConstants.STYLE_BORDER_TOP_COLOR, StyleConstants.STYLE_BORDER_LEFT_STYLE,
            StyleConstants.STYLE_BORDER_LEFT_WIDTH, StyleConstants.STYLE_BORDER_LEFT_COLOR,
            StyleConstants.STYLE_BORDER_RIGHT_STYLE, StyleConstants.STYLE_BORDER_RIGHT_WIDTH,
            StyleConstants.STYLE_BORDER_RIGHT_COLOR, StyleConstants.STYLE_BORDER_BOTTOM_STYLE,
            StyleConstants.STYLE_BORDER_BOTTOM_WIDTH, StyleConstants.STYLE_BORDER_BOTTOM_COLOR,
            StyleConstants.STYLE_WHITE_SPACE, StyleConstants.STYLE_VERTICAL_ALIGN, };

    /**
     * Test whether two BIRT styles are equivalent, as far as the attributes understood by POI are concerned.
     * <br/>
     * Every attribute tested in this method must be used in the construction of the CellStyle in createStyle.
     * @param style1
     * The first BIRT style to be compared.
     * @param style2
     * The second BIRT style to be compared.
     * @return
     * true if style1 and style2 would produce identical CellStyles if passed to createStyle.
     */
    private boolean stylesEquivalent(BirtStyle style1, BirtStyle style2) {

        // System.out.println( "style1: " + style1 );
        // System.out.println( "style2: " + style2 );

        for (int i = 0; i < COMPARE_CSS_PROPERTIES.length; ++i) {
            int prop = COMPARE_CSS_PROPERTIES[i];
            CSSValue value1 = style1.getProperty(prop);
            CSSValue value2 = style2.getProperty(prop);
            if (!StyleManagerUtils.objectsEqual(value1, value2)) {
                // System.out.println( "Differ on " + i + " because " + value1 + " != " + value2 );
                return false;
            }
        }
        if (!StyleManagerUtils.objectsEqual(style1.getProperty(BirtStyle.TEXT_ROTATION),
                style2.getProperty(BirtStyle.TEXT_ROTATION))) {
            // System.out.println( "Differ on " + i + " because " + value1 + " != " + value2 );
            return false;
        }

        // Number format
        if (!StyleManagerUtils.dataFormatsEquivalent(
                (DataFormatValue) style1.getProperty(StyleConstants.STYLE_DATA_FORMAT),
                (DataFormatValue) style2.getProperty(StyleConstants.STYLE_DATA_FORMAT))) {
            // System.out.println( "Differ on DataFormat" );
            return false;
        }

        // Font
        if (!FontManager.fontsEquivalent(style1, style2)) {
            // System.out.println( "Differ on font" );
            return false;
        }
        return true;
    }

    /**
     * Create a new POI CellStyle based upon a BIRT style.
     * @param birtStyle
     * The BIRT style to base the CellStyle upon.
     * @return
     * The CellStyle whose attributes are described by the BIRT style. 
     */
    private CellStyle createStyle(BirtStyle birtStyle) {
        CellStyle poiStyle = workbook.createCellStyle();
        // Font
        Font font = fm.getFont(birtStyle);
        if (font != null) {
            poiStyle.setFont(font);
        }
        // Alignment
        poiStyle.setAlignment(
                smu.poiAlignmentFromBirtAlignment(birtStyle.getString(StyleConstants.STYLE_TEXT_ALIGN)));
        // Background colour
        smu.addBackgroundColourToStyle(workbook, poiStyle,
                birtStyle.getString(StyleConstants.STYLE_BACKGROUND_COLOR));
        // Top border 
        smu.applyBorderStyle(workbook, poiStyle, BorderSide.TOP,
                birtStyle.getProperty(StyleConstants.STYLE_BORDER_TOP_COLOR),
                birtStyle.getProperty(StyleConstants.STYLE_BORDER_TOP_STYLE),
                birtStyle.getProperty(StyleConstants.STYLE_BORDER_TOP_WIDTH));
        // Left border 
        smu.applyBorderStyle(workbook, poiStyle, BorderSide.LEFT,
                birtStyle.getProperty(StyleConstants.STYLE_BORDER_LEFT_COLOR),
                birtStyle.getProperty(StyleConstants.STYLE_BORDER_LEFT_STYLE),
                birtStyle.getProperty(StyleConstants.STYLE_BORDER_LEFT_WIDTH));
        // Right border 
        smu.applyBorderStyle(workbook, poiStyle, BorderSide.RIGHT,
                birtStyle.getProperty(StyleConstants.STYLE_BORDER_RIGHT_COLOR),
                birtStyle.getProperty(StyleConstants.STYLE_BORDER_RIGHT_STYLE),
                birtStyle.getProperty(StyleConstants.STYLE_BORDER_RIGHT_WIDTH));
        // Bottom border 
        smu.applyBorderStyle(workbook, poiStyle, BorderSide.BOTTOM,
                birtStyle.getProperty(StyleConstants.STYLE_BORDER_BOTTOM_COLOR),
                birtStyle.getProperty(StyleConstants.STYLE_BORDER_BOTTOM_STYLE),
                birtStyle.getProperty(StyleConstants.STYLE_BORDER_BOTTOM_WIDTH));
        // Number format
        smu.applyNumberFormat(workbook, birtStyle, poiStyle, locale);
        // Whitespace/wrap
        if (CSSConstants.CSS_PRE_VALUE.equals(birtStyle.getString(StyleConstants.STYLE_WHITE_SPACE))) {
            poiStyle.setWrapText(true);
        }
        // Vertical alignment
        if (CSSConstants.CSS_TOP_VALUE.equals(birtStyle.getString(StyleConstants.STYLE_VERTICAL_ALIGN))) {
            poiStyle.setVerticalAlignment(CellStyle.VERTICAL_TOP);
        } else if (CSSConstants.CSS_MIDDLE_VALUE.equals(birtStyle.getString(StyleConstants.STYLE_VERTICAL_ALIGN))) {
            poiStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
        } else if (CSSConstants.CSS_BOTTOM_VALUE.equals(birtStyle.getString(StyleConstants.STYLE_VERTICAL_ALIGN))) {
            poiStyle.setVerticalAlignment(CellStyle.VERTICAL_BOTTOM);
        }
        // Rotation
        CSSValue rotation = birtStyle.getProperty(BirtStyle.TEXT_ROTATION);
        if (rotation instanceof FloatValue) {
            poiStyle.setRotation((short) ((FloatValue) rotation).getFloatValue());
        }

        styles.add(new StylePair(birtStyle.clone(), poiStyle));
        return poiStyle;
    }

    public CellStyle getStyle(BirtStyle birtStyle) {
        for (StylePair stylePair : styles) {
            if (stylesEquivalent(birtStyle, stylePair.birtStyle)) {
                // System.err.println( "Equivalent :\n\t" + birtStyle + "\n\t" + stylePair.birtStyle );
                return stylePair.poiStyle;
            }
        }

        return createStyle(birtStyle);
    }

    private BirtStyle birtStyleFromCellStyle(CellStyle source) {
        for (StylePair stylePair : styles) {
            if (source.equals(stylePair.poiStyle)) {
                return stylePair.birtStyle.clone();
            }
        }

        return new BirtStyle(cssEngine);
    }

    /**
     * Given a POI CellStyle, add border definitions to it and obtain a CellStyle (from the cache or newly created) based upon that.
     * @param source
     * The POI CellStyle to form the base style.
     * @param borderStyleBottom
     * The BIRT style of the bottom border.
     * @param borderWidthBottom
     * The BIRT with of the bottom border.
     * @param borderColourBottom
     * The BIRT colour of the bottom border.
     * @param borderStyleLeft
     * The BIRT style of the left border.
     * @param borderWidthLeft
     * The BIRT width of the left border.
     * @param borderColourLeft
     * The BIRT colour of the left border.
     * @param borderStyleRight
     * The BIRT width of the right border.
     * @param borderWidthRight
     * The BIRT colour of the right border.
     * @param borderColourRight
     * The BIRT style of the right border.
     * @param borderStyleTop
     * The BIRT style of the top border.
     * @param borderWidthTop
     * The BIRT width of the top border.
     * @param borderColourTop
     * The BIRT colour of the top border.
     * @return
     * A POI CellStyle equivalent to the source CellStyle with all the defined borders added to it.
     */
    public CellStyle getStyleWithBorders(CellStyle source, CSSValue borderStyleBottom, CSSValue borderWidthBottom,
            CSSValue borderColourBottom, CSSValue borderStyleLeft, CSSValue borderWidthLeft,
            CSSValue borderColourLeft, CSSValue borderStyleRight, CSSValue borderWidthRight,
            CSSValue borderColourRight, CSSValue borderStyleTop, CSSValue borderWidthTop,
            CSSValue borderColourTop) {

        BirtStyle birtStyle = birtStyleFromCellStyle(source);
        if ((borderStyleBottom != null) && (borderWidthBottom != null) && (borderColourBottom != null)) {
            birtStyle.setProperty(StyleConstants.STYLE_BORDER_BOTTOM_STYLE, borderStyleBottom);
            birtStyle.setProperty(StyleConstants.STYLE_BORDER_BOTTOM_WIDTH, borderWidthBottom);
            birtStyle.setProperty(StyleConstants.STYLE_BORDER_BOTTOM_COLOR, borderColourBottom);
        }
        if ((borderStyleLeft != null) && (borderWidthLeft != null) && (borderColourLeft != null)) {
            birtStyle.setProperty(StyleConstants.STYLE_BORDER_LEFT_STYLE, borderStyleLeft);
            birtStyle.setProperty(StyleConstants.STYLE_BORDER_LEFT_WIDTH, borderWidthLeft);
            birtStyle.setProperty(StyleConstants.STYLE_BORDER_LEFT_COLOR, borderColourLeft);
        }
        if ((borderStyleRight != null) && (borderWidthRight != null) && (borderColourRight != null)) {
            birtStyle.setProperty(StyleConstants.STYLE_BORDER_RIGHT_STYLE, borderStyleRight);
            birtStyle.setProperty(StyleConstants.STYLE_BORDER_RIGHT_WIDTH, borderWidthRight);
            birtStyle.setProperty(StyleConstants.STYLE_BORDER_RIGHT_COLOR, borderColourRight);
        }
        if ((borderStyleTop != null) && (borderWidthTop != null) && (borderColourTop != null)) {
            birtStyle.setProperty(StyleConstants.STYLE_BORDER_TOP_STYLE, borderStyleTop);
            birtStyle.setProperty(StyleConstants.STYLE_BORDER_TOP_WIDTH, borderWidthTop);
            birtStyle.setProperty(StyleConstants.STYLE_BORDER_TOP_COLOR, borderColourTop);
        }

        CellStyle newStyle = getStyle(birtStyle);
        return newStyle;
    }

    /**
     * Return a POI style created by combining a POI style with a BIRT style, where the BIRT style overrides the values in the POI style.
     * @param source
     * The POI style that represents the base style.
     * @param birtExtraStyle
     * The BIRT style to overlay on top of the POI style.
     * @return
     * A POI style representing the combination of source and birtExtraStyle.
     */
    public CellStyle getStyleWithExtraStyle(CellStyle source, IStyle birtExtraStyle) {

        BirtStyle birtStyle = birtStyleFromCellStyle(source);

        for (int i = 0; i < BirtStyle.NUMBER_OF_STYLES; ++i) {
            CSSValue value = birtExtraStyle.getProperty(i);
            if (value != null) {
                birtStyle.setProperty(i, value);
            }
        }

        CellStyle newStyle = getStyle(birtStyle);
        return newStyle;
    }

}