org.betaconceptframework.astroboa.commons.excelbuilder.ExcelSheetBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.betaconceptframework.astroboa.commons.excelbuilder.ExcelSheetBuilder.java

Source

/**
 * Copyright (C) 2005-2012 BetaCONCEPT Limited
 *
 * This file is part of Astroboa.
 *
 * Astroboa is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Astroboa 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Astroboa.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.betaconceptframework.astroboa.commons.excelbuilder;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.RichTextString;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.betaconceptframework.astroboa.api.model.BinaryChannel;
import org.betaconceptframework.astroboa.api.model.CmsProperty;
import org.betaconceptframework.astroboa.api.model.ComplexCmsProperty;
import org.betaconceptframework.astroboa.api.model.ContentObject;
import org.betaconceptframework.astroboa.api.model.SimpleCmsProperty;
import org.betaconceptframework.astroboa.api.model.StringProperty;
import org.betaconceptframework.astroboa.api.model.Topic;
import org.betaconceptframework.astroboa.api.model.definition.CalendarPropertyDefinition;
import org.betaconceptframework.astroboa.api.model.definition.CmsPropertyDefinition;
import org.betaconceptframework.astroboa.api.model.definition.ContentObjectTypeDefinition;
import org.betaconceptframework.astroboa.api.model.definition.StringPropertyDefinition;
import org.betaconceptframework.astroboa.api.model.io.ResourceRepresentationType;
import org.betaconceptframework.astroboa.api.service.DefinitionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Class responsible to create an Excel sheet which
 * contains a list of one or more content objects of the same content type.
 * 
 * Each sheet contains one or more rows which represent the values of one or
 * more content objects of the same content type.
 *  
 * @author Gregory Chomatas (gchomatas@betaconcept.com)
 * @author Savvas Triantafyllou (striantafyllou@betaconcept.com)
 * 
 */
public class ExcelSheetBuilder {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    private CreationHelper creationHelper;

    private HSSFCellStyle propertyNameCellStyle;
    private HSSFCellStyle stringPropertyValueCellStyle;
    private HSSFCellStyle integerPropertyValueCellStyle;
    private HSSFCellStyle doublePropertyValueCellStyle;
    private HSSFCellStyle datePropertyValueCellStyle;
    private HSSFCellStyle dateTimePropertyValueCellStyle;

    private String locale;

    private List<HelperRow> rows = new ArrayList<HelperRow>();

    //Property Paths. Order is significant
    private List<String> propertyPaths = new ArrayList<String>();

    private Map<String, RichTextString> headersForProperty = new HashMap<String, RichTextString>();

    private int currentPropertyPathIndex;

    private String contentType;
    private DefinitionService definitionService;

    public ExcelSheetBuilder(DefinitionService definitionService, String contentType, String locale,
            CreationHelper creationHelper, HSSFCellStyle propertyNameCellStyle,
            HSSFCellStyle stringPropertyValueCellStyle, HSSFCellStyle integerPropertyValueCellStyle,
            HSSFCellStyle doublePropertyValueCellStyle, HSSFCellStyle datePropertyValueCellStyle,
            HSSFCellStyle dateTimePropertyValueCellStyle) {

        this.locale = locale;
        this.contentType = contentType;
        this.definitionService = definitionService;

        this.creationHelper = creationHelper;

        this.propertyNameCellStyle = propertyNameCellStyle;
        this.stringPropertyValueCellStyle = stringPropertyValueCellStyle;
        this.integerPropertyValueCellStyle = integerPropertyValueCellStyle;
        this.doublePropertyValueCellStyle = doublePropertyValueCellStyle;
        this.datePropertyValueCellStyle = datePropertyValueCellStyle;
        this.dateTimePropertyValueCellStyle = dateTimePropertyValueCellStyle;

    }

    public void clear() {
        locale = null;
        creationHelper = null;

        propertyNameCellStyle = null;
        stringPropertyValueCellStyle = null;
        integerPropertyValueCellStyle = null;
        doublePropertyValueCellStyle = null;
        datePropertyValueCellStyle = null;
        dateTimePropertyValueCellStyle = null;

    }

    public void addContentObject(ContentObject contentObject) {

        if (contentObject == null) {
            return;
        }

        if (!StringUtils.equals(contentType, contentObject.getContentObjectType())) {
            logger.warn(
                    "Try to add object {} of type {} in sheet which is responsible to contain objects of type {}",
                    new Object[] { contentObject.getSystemName(), contentObject.getContentObjectType(),
                            contentType });
            return;
        }

        //Create a new row with the values of all properties of the object
        HelperRow helperRow = new HelperRow();
        rows.add(helperRow);

        fillRowWithValues(contentObject.getComplexCmsRootProperty(), helperRow);

        currentPropertyPathIndex = -1;
    }

    public void createSheet(HSSFWorkbook workbook) {

        Sheet sheet = instantiateSheet(workbook);

        addRowWithHeaders(sheet);

        for (HelperRow helperRow : rows) {

            Row contentObjectRow = sheet.createRow(sheet.getLastRowNum() + 1);
            int cellIndex = 1;

            for (String propertyPath : propertyPaths) {

                Cell contentObjectPropertyCell = contentObjectRow.createCell(cellIndex++);

                helperRow.addValueToCellForPath(propertyPath, contentObjectPropertyCell);
            }
        }

        autoSizeColumns(sheet);

    }

    private Sheet instantiateSheet(HSSFWorkbook workbook) {

        ContentObjectTypeDefinition contentObjectTypeDefinition = (ContentObjectTypeDefinition) definitionService
                .getCmsDefinition(contentType, ResourceRepresentationType.DEFINITION_INSTANCE, false);

        //Reorder property paths
        DefinitionOrderHelper definitionOrderHelper = new DefinitionOrderHelper();
        contentObjectTypeDefinition.accept(definitionOrderHelper);

        Collections.sort(propertyPaths, definitionOrderHelper);

        // create a new sheet
        if (contentObjectTypeDefinition.getDisplayName() == null || StringUtils
                .isBlank(contentObjectTypeDefinition.getDisplayName().getAvailableLocalizedLabel(locale))) {
            return workbook.createSheet(contentType);
        } else {
            String sheetName = contentObjectTypeDefinition.getDisplayName().getAvailableLocalizedLabel(locale);

            //Remove invalid characters (according to POI)
            sheetName = StringUtils.replaceChars(sheetName, "/\\?*[]", "");

            //SheetName must be at most 31 chars
            if (sheetName.length() > 31) {
                sheetName = sheetName.substring(0, 30);
            }

            return workbook.createSheet(sheetName);
        }

    }

    private void addRowWithHeaders(Sheet sheet) {
        Row headerRow = sheet.createRow(1);

        int headerCellIndex = 1;

        for (String propertyPath : propertyPaths) {

            Cell headerCell = headerRow.createCell(headerCellIndex++);
            headerCell.setCellStyle(propertyNameCellStyle);

            if (headersForProperty.containsKey(propertyPath)) {
                headerCell.setCellValue(headersForProperty.get(propertyPath));
            } else {
                logger.warn("Coludn not find header for property {}. Will put Property path instead", propertyPath);
            }
        }
    }

    private void autoSizeColumns(Sheet sheet) {

        for (short columnIndex = 1; columnIndex <= propertyPaths.size(); ++columnIndex) {
            sheet.autoSizeColumn(columnIndex);
        }
    }

    private void fillRowWithValues(ComplexCmsProperty complexCmsProperty, HelperRow helperRow) {

        if (complexCmsProperty == null) {
            return;
        }

        if (StringUtils.equals(complexCmsProperty.getPath(), "accessibility")) {
            return;
        }

        Collection<List<CmsProperty<?, ?>>> childProperties = complexCmsProperty.getChildProperties().values();

        for (List<CmsProperty<?, ?>> childPropertyList : childProperties) {

            for (CmsProperty<?, ?> childProperty : childPropertyList) {

                if (childProperty instanceof ComplexCmsProperty) {
                    fillRowWithValues((ComplexCmsProperty) childProperty, helperRow);
                } else {
                    fillRowWithValues((SimpleCmsProperty) childProperty, helperRow);
                }

            }
        }
    }

    private void fillRowWithValues(SimpleCmsProperty simpleProperty, HelperRow helperRow) {

        if (simpleProperty == null || simpleProperty.getPropertyDefinition() == null) {
            return;
        }

        CmsPropertyDefinition propertyDefinition = simpleProperty.getPropertyDefinition();

        //Property of type password in not exported
        if (propertyDefinition instanceof StringPropertyDefinition
                && ((StringPropertyDefinition) propertyDefinition).isPasswordType()) {
            return;
        }

        if (simpleProperty.hasNoValues()) {
            return;
        }

        boolean multiple = propertyDefinition.isMultiple();
        String path = simpleProperty.getPath();

        if (multiple) {

            int index = 0;

            for (Object value : simpleProperty.getSimpleTypeValues()) {
                setPropertyCellStyleAndValue(path + "[" + index++ + "]", propertyDefinition, value, helperRow,
                        creationHelper, locale);
            }

        } else {
            setPropertyCellStyleAndValue(path, propertyDefinition, simpleProperty.getSimpleTypeValue(), helperRow,
                    creationHelper, locale);
        }

    }

    private void setPropertyCellStyleAndValue(String propertyPath, CmsPropertyDefinition propertyDefinition,
            Object value, HelperRow row, CreationHelper creationHelper, String locale) {

        appendPropertyPathList(propertyPath);

        appendHeaderPropertyList(propertyPath, propertyDefinition);

        switch (propertyDefinition.getValueType()) {
        case String: {

            row.addValueAndStyleForPath(propertyPath, creationHelper.createRichTextString(((String) value)),
                    stringPropertyValueCellStyle);

            break;
        }
        case Date: {

            if (((CalendarPropertyDefinition) propertyDefinition).isDateTime()) {
                row.addValueAndStyleForPath(propertyPath, (Calendar) value, dateTimePropertyValueCellStyle);
            } else {
                row.addValueAndStyleForPath(propertyPath, (Calendar) value, datePropertyValueCellStyle);
            }
            break;
        }
        case TopicReference: {

            String cellValue = getTopicPath((Topic) value, locale);
            row.addValueAndStyleForPath(propertyPath, creationHelper.createRichTextString(cellValue),
                    stringPropertyValueCellStyle);

            break;
        }
        case Double: {

            row.addValueAndStyleForPath(propertyPath, (Double) value, doublePropertyValueCellStyle);
            break;
        }
        case Long: {

            row.addValueAndStyleForPath(propertyPath, (Long) value, integerPropertyValueCellStyle);
            break;
        }
        case ObjectReference: {

            String cellValue = getContentObjectTitle((ContentObject) value, locale);

            row.addValueAndStyleForPath(propertyPath, creationHelper.createRichTextString(cellValue),
                    stringPropertyValueCellStyle);
            break;
        }
        case Binary: {

            String cellValue = ((BinaryChannel) value).buildResourceApiURL(null, null, null, null, null, true,
                    false);

            row.addValueAndStyleForPath(propertyPath, creationHelper.createRichTextString(cellValue),
                    stringPropertyValueCellStyle);

            break;
        }

        default:
            break;
        }

    }

    private void appendHeaderPropertyList(String propertyPath, CmsPropertyDefinition propertyDefinition) {

        if (!headersForProperty.containsKey(propertyPath)) {
            headersForProperty.put(propertyPath, creationHelper
                    .createRichTextString(propertyDefinition.getDisplayName().getLocalizedLabelForLocale(locale)));
        }

    }

    private void appendPropertyPathList(String propertyPath) {

        if (!propertyPaths.contains(propertyPath)) {
            if (currentPropertyPathIndex == -1) {
                propertyPaths.add(propertyPath);
            } else {
                propertyPaths.add(currentPropertyPathIndex, propertyPath);
            }
        }

        currentPropertyPathIndex = propertyPaths.indexOf(propertyPath);

    }

    private String getTopicPath(Topic topic, String locale) {

        if (topic != null) {
            return topic.getAvailableLocalizedLabel(locale);
        }

        return "";

        /*List<Topic> topicPath = new ArrayList<Topic>();
        createTopicPath(topicPath, topic);
            
        String topicPathAsString = topicPath.get(0).getLocalizedLabelForLocale(locale);
        for(Topic topicInPath : topicPath.subList(1, topicPath.size())) {
           topicPathAsString = topicPathAsString + "/" + topicInPath.getLocalizedLabelForLocale(locale);
        }
            
        return topicPathAsString;*/
    }

    private String getContentObjectTitle(ContentObject object, String locale) {

        if (object == null) {
            return "";
        }

        String label = object.getLabel(locale);
        if (StringUtils.isNotBlank(label)) {
            return label;
        }

        StringProperty titleProperty = (StringProperty) object.getCmsProperty("profile.title");

        if (titleProperty == null || titleProperty.hasNoValues()) {
            //this should never happen 
            return object.getSystemName();
        }

        return titleProperty.getFirstValue();
    }
}