net.sf.jasperreports.components.headertoolbar.json.HeaderToolbarElementJsonHandler.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.jasperreports.components.headertoolbar.json.HeaderToolbarElementJsonHandler.java

Source

/*
 * JasperReports - Free Java Reporting Library.
 * Copyright (C) 2001 - 2019 TIBCO Software Inc. All rights reserved.
 * http://www.jaspersoft.com
 *
 * Unless you have purchased a commercial license agreement from Jaspersoft,
 * the following license terms apply:
 *
 * This program is part of JasperReports.
 *
 * JasperReports 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.
 *
 * JasperReports 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 JasperReports. If not, see <http://www.gnu.org/licenses/>.
 */
package net.sf.jasperreports.components.headertoolbar.json;

import java.awt.GraphicsEnvironment;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.TreeSet;
import java.util.UUID;

import net.sf.jasperreports.components.headertoolbar.HeaderToolbarElement;
import net.sf.jasperreports.components.headertoolbar.HeaderToolbarElementUtils;
import net.sf.jasperreports.components.headertoolbar.actions.ConditionalFormattingData;
import net.sf.jasperreports.components.headertoolbar.actions.EditTextElementData;
import net.sf.jasperreports.components.headertoolbar.actions.FilterAction;
import net.sf.jasperreports.components.headertoolbar.actions.SortAction;
import net.sf.jasperreports.components.sort.FieldFilter;
import net.sf.jasperreports.components.sort.FilterTypeBooleanOperatorsEnum;
import net.sf.jasperreports.components.sort.FilterTypeDateOperatorsEnum;
import net.sf.jasperreports.components.sort.FilterTypeNumericOperatorsEnum;
import net.sf.jasperreports.components.sort.FilterTypeTextOperatorsEnum;
import net.sf.jasperreports.components.sort.FilterTypesEnum;
import net.sf.jasperreports.components.sort.actions.FilterCommand;
import net.sf.jasperreports.components.sort.actions.FilterData;
import net.sf.jasperreports.components.sort.actions.SortData;
import net.sf.jasperreports.components.table.BaseColumn;
import net.sf.jasperreports.components.table.Column;
import net.sf.jasperreports.components.table.ColumnGroup;
import net.sf.jasperreports.components.table.GroupCell;
import net.sf.jasperreports.components.table.StandardColumn;
import net.sf.jasperreports.components.table.StandardTable;
import net.sf.jasperreports.components.table.util.TableUtil;
import net.sf.jasperreports.engine.DatasetFilter;
import net.sf.jasperreports.engine.JRExpression;
import net.sf.jasperreports.engine.JRExpressionChunk;
import net.sf.jasperreports.engine.JRField;
import net.sf.jasperreports.engine.JRGenericPrintElement;
import net.sf.jasperreports.engine.JRIdentifiable;
import net.sf.jasperreports.engine.JRPropertiesMap;
import net.sf.jasperreports.engine.JRSortField;
import net.sf.jasperreports.engine.JRStyle;
import net.sf.jasperreports.engine.JRStyleContainer;
import net.sf.jasperreports.engine.JRVariable;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReportsContext;
import net.sf.jasperreports.engine.ReportContext;
import net.sf.jasperreports.engine.base.JRBasePrintHyperlink;
import net.sf.jasperreports.engine.design.JRDesignComponentElement;
import net.sf.jasperreports.engine.design.JRDesignDataset;
import net.sf.jasperreports.engine.design.JRDesignDatasetRun;
import net.sf.jasperreports.engine.design.JRDesignTextElement;
import net.sf.jasperreports.engine.design.JRDesignTextField;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.export.GenericElementJsonHandler;
import net.sf.jasperreports.engine.export.JsonExporterContext;
import net.sf.jasperreports.engine.fonts.FontUtil;
import net.sf.jasperreports.engine.type.ModeEnum;
import net.sf.jasperreports.engine.type.NamedEnum;
import net.sf.jasperreports.engine.type.SortFieldTypeEnum;
import net.sf.jasperreports.engine.util.JRColorUtil;
import net.sf.jasperreports.engine.util.JRDataUtils;
import net.sf.jasperreports.engine.util.JRStringUtil;
import net.sf.jasperreports.engine.util.MessageProvider;
import net.sf.jasperreports.engine.util.MessageUtil;
import net.sf.jasperreports.repo.JasperDesignCache;
import net.sf.jasperreports.web.commands.CommandTarget;
import net.sf.jasperreports.web.util.JacksonUtil;
import net.sf.jasperreports.web.util.ReportInteractionHyperlinkProducer;
import net.sf.jasperreports.web.util.VelocityUtil;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @author Teodor Danciu (teodord@users.sourceforge.net)
 */
public class HeaderToolbarElementJsonHandler implements GenericElementJsonHandler {
    private static final Log log = LogFactory.getLog(HeaderToolbarElementJsonHandler.class);

    private static final String HEADER_TOOLBAR_ELEMENT_JSON_TEMPLATE = "net/sf/jasperreports/components/headertoolbar/json/resources/HeaderToolbarElementJsonTemplate.vm";
    private static final String PARAM_GENERATED_TEMPLATE_PREFIX = "net.sf.jasperreports.headertoolbar.";

    private static final List<String> datePatterns = new ArrayList<String>();
    private static final List<String> timePatterns = new ArrayList<String>();
    private static final Map<String, String> numberPatternsMap = new LinkedHashMap<String, String>();

    private static final String DURATION_PATTERN = "[h]:mm:ss";

    static {
        // date patterns
        datePatterns.add("dd/MM/yyyy");
        datePatterns.add("MM/dd/yyyy");
        datePatterns.add("yyyy/MM/dd");
        datePatterns.add("EEEEE dd MMMMM yyyy");
        datePatterns.add("MMMMM dd. yyyy");
        datePatterns.add("dd/MM");
        datePatterns.add("dd/MM/yy");
        datePatterns.add("dd-MMM");
        datePatterns.add("dd-MMM-yy");
        datePatterns.add("MMM-yy");
        datePatterns.add("MMMMM-yy");
        datePatterns.add("dd/MM/yyyy h.mm a");
        datePatterns.add("dd/MM/yyyy HH.mm.ss");
        datePatterns.add("MMM");
        datePatterns.add("d/M/yyyy");
        datePatterns.add("dd-MMM-yyyy");
        datePatterns.add("yyyy.MM.dd G 'at' HH:mm:ss z");
        datePatterns.add("EEE. MMM d. ''yy");
        datePatterns.add("yyyy.MMMMM.dd GGG hh:mm aaa");
        datePatterns.add("EEE. d MMM yyyy HH:mm:ss Z");
        datePatterns.add("yyMMddHHmmssZ");

        timePatterns.add("hh:mm aaa");
        timePatterns.add("hh:mm:ss aaa");
        timePatterns.add("HH:mm");
        timePatterns.add("HH:mm:ss");

        numberPatternsMap.put("###0;-###0", "-1234");
        numberPatternsMap.put("###0;###0-", "1234-");
        numberPatternsMap.put("###0;(###0)", "(1234)");
        numberPatternsMap.put("###0;(-###0)", "(-1234)");
        numberPatternsMap.put("###0;(###0-)", "(1234-)");
        numberPatternsMap.put(DURATION_PATTERN, "[h]:mm:ss");
    }

    private static final String TABLE_UUID = "exporter_first_attempt";

    @Override
    public String getJsonFragment(JsonExporterContext context, JRGenericPrintElement element) {
        boolean templateAlreadyLoaded = false;

        String htmlFragment = null;
        String tableUUID = element.getPropertiesMap().getProperty(HeaderToolbarElement.PROPERTY_TABLE_UUID);
        ReportContext reportContext = context.getExporterRef().getReportContext();
        if (reportContext != null && tableUUID != null)//FIXMEJIVE
        {
            String columnUuid = element.getPropertiesMap().getProperty(HeaderToolbarElement.PROPERTY_COLUMN_UUID);
            String columnLabel = (String) element.getParameterValue(HeaderToolbarElement.PARAMETER_COLUMN_LABEL);
            if (columnLabel == null) {
                columnLabel = "";
            }
            int columnIndex = Integer
                    .parseInt(element.getPropertiesMap().getProperty(HeaderToolbarElement.PROPERTY_COLUMN_INDEX));

            Map<String, Object> contextMap = new HashMap<String, Object>();
            contextMap.put("JRStringUtil", JRStringUtil.class);
            contextMap.put("tableUUID", tableUUID);

            JasperReportsContext jrContext = context.getJasperReportsContext();

            JasperPrint jasperPrint = context.getExportedReport();
            Locale locale = jasperPrint.getLocaleCode() == null ? Locale.getDefault()
                    : JRDataUtils.getLocale(jasperPrint.getLocaleCode());
            TimeZone timeZone = getFilterTimeZone(jasperPrint, element);

            if (log.isDebugEnabled()) {
                log.debug("column " + columnUuid + " has locale " + locale + ", timezone " + timeZone);
            }

            Boolean isClearCache = (Boolean) reportContext.getParameterValue(PARAMETER_CLEAR_CONTEXT_CACHE);

            if (reportContext.getParameterValue(PARAM_GENERATED_TEMPLATE_PREFIX) != null
                    && !(isClearCache != null && isClearCache)) {
                templateAlreadyLoaded = true;
            } else {
                reportContext.setParameterValue(PARAM_GENERATED_TEMPLATE_PREFIX, true);
            }

            ColumnFormatting.store(reportContext, tableUUID, columnIndex, locale, timeZone);

            /*** begin: FILTER PATTERNS ***/
            // numeric filter pattern
            String numericFilterPattern = HeaderToolbarElementUtils.getNumberPattern(jrContext, locale);

            // date filter pattern
            String dateFilterPattern = HeaderToolbarElementUtils.getDatePattern(jrContext, locale);

            // time filter pattern
            String timeFilterPattern = HeaderToolbarElementUtils.getTimePattern(jrContext, locale);
            /*** end: FILTER PATTERNS ***/

            FilterAction action = new FilterAction();
            action.init(jrContext, reportContext);
            CommandTarget target = action.getCommandTarget(UUID.fromString(tableUUID));

            JasperDesign jasperDesign = null;
            JRDesignDataset dataset = null;
            StandardTable table = null;

            if (target != null) {
                JRIdentifiable identifiable = target.getIdentifiable();
                JRDesignComponentElement componentElement = identifiable instanceof JRDesignComponentElement
                        ? (JRDesignComponentElement) identifiable
                        : null;
                table = componentElement == null ? null : (StandardTable) componentElement.getComponent();
                JasperDesignCache cache = JasperDesignCache.getInstance(jrContext, reportContext);
                jasperDesign = cache.getJasperDesign(target.getUri());
                JRDesignDatasetRun datasetRun = (JRDesignDatasetRun) table.getDatasetRun();
                String datasetName = datasetRun.getDatasetName();
                dataset = (JRDesignDataset) jasperDesign.getDatasetMap().get(datasetName);
            }

            if (!tableUUID.equals(context.getValue(TABLE_UUID))) {
                Map<String, ColumnInfo> columnNames = getAllColumnNames(element, jrContext, contextMap);
                List<Map<String, Object>> columnGroupsData = getColumnGroupsData(jrContext, reportContext, target,
                        jasperDesign, dataset, table, tableUUID, locale, timeZone);
                // column names are normally set on the first column, but check if we got them
                if (!columnNames.isEmpty()) {
                    context.setValue(TABLE_UUID, tableUUID);

                    // column info
                    contextMap.put("allColumnNames", JacksonUtil.getInstance(jrContext).getJsonString(columnNames));
                    contextMap.put("allColumnGroupsData",
                            JacksonUtil.getInstance(jrContext).getJsonString(columnGroupsData));
                    contextMap.put("tableName",
                            element.getPropertiesMap().getProperty(HeaderToolbarElement.PROPERTY_TABLE_NAME));

                    // floating header
                    contextMap.put("hasFloatingHeader", Boolean.parseBoolean(
                            element.getPropertiesMap().getProperty(HeaderToolbarElement.PROPERTY_FLOATING_HEADER)));

                    // patterns
                    contextMap.put("numericPatterns",
                            JacksonUtil.getInstance(jrContext).getJsonString(getNumberPatterns(numberPatternsMap)));
                    contextMap.put("datePatterns", JacksonUtil.getInstance(jrContext)
                            .getJsonString(getDatePatterns(datePatterns, locale)));
                    contextMap.put("timePatterns", JacksonUtil.getInstance(jrContext)
                            .getJsonString(getDatePatterns(timePatterns, locale)));

                    // operators
                    contextMap.put("numericOperators",
                            JacksonUtil.getInstance(jrContext)
                                    .getJsonString(getTranslatedOperators(jrContext,
                                            FilterTypeNumericOperatorsEnum.class.getName(),
                                            FilterTypeNumericOperatorsEnum.values(), locale)));
                    contextMap.put("dateOperators",
                            JacksonUtil.getInstance(jrContext)
                                    .getJsonString(getTranslatedOperators(jrContext,
                                            FilterTypeDateOperatorsEnum.class.getName(),
                                            FilterTypeDateOperatorsEnum.values(), locale)));
                    contextMap.put("timeOperators",
                            JacksonUtil.getInstance(jrContext)
                                    .getJsonString(getTranslatedOperators(jrContext,
                                            FilterTypeDateOperatorsEnum.class.getName(),
                                            FilterTypeDateOperatorsEnum.values(), locale)));
                    contextMap.put("textOperators",
                            JacksonUtil.getInstance(jrContext)
                                    .getJsonString(getTranslatedOperators(jrContext,
                                            FilterTypeTextOperatorsEnum.class.getName(),
                                            FilterTypeTextOperatorsEnum.values(), locale)));
                    contextMap.put("booleanOperators",
                            JacksonUtil.getInstance(jrContext)
                                    .getJsonString(getTranslatedOperators(jrContext,
                                            FilterTypeBooleanOperatorsEnum.class.getName(),
                                            FilterTypeBooleanOperatorsEnum.values(), locale)));

                    /*** begin: FILTER PATTERNS ***/
                    // numeric filter pattern
                    contextMap.put("numericFilterPattern", numericFilterPattern);

                    // date filter pattern
                    contextMap.put("dateFilterPattern", dateFilterPattern);

                    // time filter pattern
                    contextMap.put("timeFilterPattern", timeFilterPattern);
                    /*** end: FILTER PATTERNS ***/

                    /*** begin: CALENDAR PATTERNS ***/
                    // date pattern
                    contextMap.put("calendarDatePattern",
                            HeaderToolbarElementUtils.getCalendarDatePattern(jrContext, locale));

                    // time pattern
                    contextMap.put("calendarTimePattern",
                            HeaderToolbarElementUtils.getCalendarTimePattern(jrContext, locale));
                    /*** end: CALENDAR PATTERNS ***/

                    contextMap.put("exporterFirstAttempt", true);
                }
            }

            contextMap.put("templateAlreadyLoaded", templateAlreadyLoaded);

            Boolean canSort = Boolean
                    .parseBoolean(element.getPropertiesMap().getProperty(HeaderToolbarElement.PROPERTY_CAN_SORT));
            Boolean canFilter = Boolean
                    .parseBoolean(element.getPropertiesMap().getProperty(HeaderToolbarElement.PROPERTY_CAN_FILTER));

            if (element.getModeValue() == ModeEnum.OPAQUE) {
                contextMap.put("backgroundColor", JRColorUtil.getColorHexa(element.getBackcolor()));
            }

            contextMap.put("columnUuid", columnUuid);
            //FIXME conceptually it would be better not to encode for html here 
            //but produce a pure json and encode for html on the client where necessary
            contextMap.put("columnLabel", JRStringUtil.htmlEncode(columnLabel));
            contextMap.put("columnIndex", columnIndex);
            contextMap.put("dataType", FilterTypesEnum.TEXT.getName()); // use Text as default
            contextMap.put("canSort", canSort);
            contextMap.put("canFilter", canFilter);

            contextMap.put("fontExtensionsFontNames", getFontExtensionsFontNames(jrContext));
            contextMap.put("systemFontNames", getSystemFontNames(jrContext));

            setColumnHeaderData(columnLabel, columnIndex, target, contextMap, jrContext, reportContext, locale);
            EditTextElementData columnValueData = setColumnValueData(columnIndex, target, contextMap, jrContext,
                    reportContext, locale);

            String columnName = element.getPropertiesMap().getProperty(HeaderToolbarElement.PROPERTY_COLUMN_NAME);
            String columnComponentName = element.getPropertiesMap()
                    .getProperty(HeaderToolbarElement.PROPERTY_COLUMN_COMPONENT_NAME);
            String columnType = element.getPropertiesMap().getProperty(HeaderToolbarElement.PROPERTY_COLUMN_TYPE);
            FilterTypesEnum filterType = FilterTypesEnum
                    .getByName(element.getPropertiesMap().getProperty(HeaderToolbarElement.PROPERTY_FILTER_TYPE));

            if (columnComponentName == null) {
                columnComponentName = columnName;
            }
            contextMap.put("columnName", columnComponentName);

            if (canFilter) {
                FilterData filterData = getFilterData(jrContext, dataset, columnName, columnType, filterType,
                        columnValueData.getFormatPattern(), locale, timeZone);

                contextMap.put("dataType", filterType.getName());
                contextMap.put("filterData", JacksonUtil.getInstance(jrContext).getJsonString(filterData));
                contextMap.put("filterTableUuid", filterData.getTableUuid());
            }

            if (canSort) {
                SortData sortAscData = new SortData(tableUUID, columnName, columnType,
                        HeaderToolbarElement.SORT_ORDER_ASC);
                SortData sortDescData = new SortData(tableUUID, columnName, columnType,
                        HeaderToolbarElement.SORT_ORDER_DESC);
                String sortField = getCurrentSortField(jrContext, reportContext, tableUUID, columnName, columnType);
                if (sortField != null) {
                    String[] sortActionData = HeaderToolbarElementUtils.extractColumnInfo(sortField);

                    boolean isAscending = HeaderToolbarElement.SORT_ORDER_ASC.equals(sortActionData[2]);
                    if (isAscending) {
                        sortAscData.setSortOrder(HeaderToolbarElement.SORT_ORDER_NONE);
                    } else {
                        sortDescData.setSortOrder(HeaderToolbarElement.SORT_ORDER_NONE);
                    }
                }
                contextMap.put("sortAscData", JacksonUtil.getInstance(jrContext).getJsonString(sortAscData));
                contextMap.put("sortDescData", JacksonUtil.getInstance(jrContext).getJsonString(sortDescData));
            }

            List<BaseColumn> tableColumns = TableUtil.getAllColumns(table);
            Column column = (Column) tableColumns.get(columnIndex);

            JRDesignTextField detailTextField = TableUtil.getCellElement(JRDesignTextField.class,
                    column.getDetailCell(), true);
            if (detailTextField != null) {
                ConditionalFormattingData detailCfd = getConditionalFormattingData(element, jrContext, dataset,
                        detailTextField, null, locale, timeZone);
                if (detailCfd != null) {
                    contextMap.put("conditionalFormattingData",
                            JacksonUtil.getInstance(jrContext).getJsonString(detailCfd));
                }
            }

            htmlFragment = VelocityUtil.processTemplate(
                    HeaderToolbarElementJsonHandler.HEADER_TOOLBAR_ELEMENT_JSON_TEMPLATE, contextMap);
        }

        return htmlFragment;
    }

    protected TimeZone getFilterTimeZone(JasperPrint jasperPrint, JRGenericPrintElement element) {
        String formatTimeZone = element.getPropertiesMap()
                .getProperty(HeaderToolbarElement.PROPERTY_FORMAT_TIME_ZONE);
        TimeZone timeZone;
        if (formatTimeZone != null) {
            timeZone = JRDataUtils.getTimeZone(formatTimeZone);
        } else if (jasperPrint.getTimeZoneId() != null) {
            timeZone = JRDataUtils.getTimeZone(jasperPrint.getTimeZoneId());
        } else {
            timeZone = TimeZone.getDefault();
        }
        return timeZone;
    }

    private List<HashMap<String, String>> getDatePatterns(List<String> datePatterns, Locale locale) {
        List<HashMap<String, String>> formatPatterns = new ArrayList<HashMap<String, String>>();

        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy", locale);
        Date today = new Date();
        HashMap<String, String> keys;

        for (String datePattern : datePatterns) {
            keys = new HashMap<String, String>();
            sdf.applyPattern(datePattern);
            keys.put("key", datePattern);
            keys.put("val", sdf.format(today));
            formatPatterns.add(keys);
        }

        return formatPatterns;
    }

    private List<HashMap<String, String>> getNumberPatterns(Map<String, String> numberPatternsMap) {
        List<HashMap<String, String>> formatPatterns = new ArrayList<HashMap<String, String>>();
        HashMap<String, String> keys;

        for (Map.Entry<String, String> entry : numberPatternsMap.entrySet()) {
            keys = new HashMap<String, String>();
            keys.put("key", entry.getKey());
            keys.put("val", entry.getValue());
            formatPatterns.add(keys);
        }

        return formatPatterns;
    }

    private String getActionBaseUrl(JsonExporterContext context) {
        JRBasePrintHyperlink hyperlink = new JRBasePrintHyperlink();
        hyperlink.setLinkType(ReportInteractionHyperlinkProducer.HYPERLINK_TYPE_REPORT_INTERACTION);
        //      return context.getHyperlinkURL(hyperlink);
        return "FIXME HeaderToolbarElementJsonHandler.getActionBaseUrl";
    }

    private String getCurrentSortField(JasperReportsContext jasperReportsContext, ReportContext reportContext,
            String uuid, String sortColumnName, String sortColumnType) {
        JasperDesignCache cache = JasperDesignCache.getInstance(jasperReportsContext, reportContext);
        SortAction action = new SortAction();
        action.init(jasperReportsContext, reportContext);
        CommandTarget target = action.getCommandTarget(UUID.fromString(uuid));
        if (target != null) {
            JRIdentifiable identifiable = target.getIdentifiable();
            JRDesignComponentElement componentElement = identifiable instanceof JRDesignComponentElement
                    ? (JRDesignComponentElement) identifiable
                    : null;
            StandardTable table = componentElement == null ? null : (StandardTable) componentElement.getComponent();

            JRDesignDatasetRun datasetRun = (JRDesignDatasetRun) table.getDatasetRun();

            String datasetName = datasetRun.getDatasetName();

            JasperDesign jasperDesign = cache.getJasperDesign(target.getUri());//FIXMEJIVE getJasperReport not design
            JRDesignDataset dataset = (JRDesignDataset) jasperDesign.getDatasetMap().get(datasetName);

            List<JRSortField> existingFields = dataset.getSortFieldsList();
            String sortField = null;

            if (existingFields != null && existingFields.size() > 0) {
                for (JRSortField field : existingFields) {
                    if (field.getName().equals(sortColumnName)
                            && field.getType().getName().equals(sortColumnType)) {
                        sortField = sortColumnName + HeaderToolbarElement.SORT_COLUMN_TOKEN_SEPARATOR
                                + sortColumnType + HeaderToolbarElement.SORT_COLUMN_TOKEN_SEPARATOR;
                        switch (field.getOrderValue()) {
                        case ASCENDING:
                            sortField += HeaderToolbarElement.SORT_ORDER_ASC;
                            break;
                        case DESCENDING:
                            sortField += HeaderToolbarElement.SORT_ORDER_DESC;
                            break;
                        }
                        break;
                    }
                }
            }

            return sortField;
        }

        return null;
    }

    @Override
    public boolean toExport(JRGenericPrintElement element) {
        return true;
    }

    private List<LinkedHashMap<String, String>> getTranslatedOperators(JasperReportsContext jasperReportsContext,
            String bundleName, NamedEnum[] operators, Locale locale) //FIXMEJIVE make utility method for translating enums
    {
        List<LinkedHashMap<String, String>> result = new ArrayList<LinkedHashMap<String, String>>();
        MessageProvider messageProvider = MessageUtil.getInstance(jasperReportsContext)
                .getMessageProvider(bundleName);
        LinkedHashMap<String, String> keys;

        for (NamedEnum operator : operators) {
            keys = new LinkedHashMap<String, String>();
            String key = bundleName + "." + ((Enum<?>) operator).name();
            keys.put("key", ((Enum<?>) operator).name());
            keys.put("val", messageProvider.getMessage(key, null, locale));
            result.add(keys);
        }

        return result;
    }

    private static FilterData getFilterData(JasperReportsContext jasperReportsContext, JRDesignDataset dataset,
            String columnName, String columnType, FilterTypesEnum filterType, String columnValuePattern,
            Locale locale, TimeZone timeZone) {
        // get existing filter as JSON string
        String serializedFilters = "[]";
        JRPropertiesMap propertiesMap = dataset.getPropertiesMap();
        if (propertiesMap.getProperty(FilterCommand.DATASET_FILTER_PROPERTY) != null) {
            serializedFilters = propertiesMap.getProperty(FilterCommand.DATASET_FILTER_PROPERTY);
        }

        List<DatasetFilter> filters = new ArrayList<DatasetFilter>();

        List<? extends DatasetFilter> existingFilters = JacksonUtil.getInstance(jasperReportsContext)
                .loadList(serializedFilters, FieldFilter.class);
        if (existingFilters.size() > 0) {
            for (DatasetFilter filter : existingFilters) {
                if (((FieldFilter) filter).getField().equals(columnName)) {
                    filters.add(filter);
                    break;
                }
            }
        }

        FilterData filterData = new FilterData();
        filterData.setFieldName(columnName);
        filterData.setFilterType(filterType.getName());
        filterData.setIsField(SortFieldTypeEnum.FIELD.equals(SortFieldTypeEnum.getByName(columnType)));

        if (filters.size() > 0) {
            FieldFilter ff = (FieldFilter) filters.get(0);
            filterData.setFieldValueStart(ff.getFilterValueStart());
            filterData.setFieldValueEnd(ff.getFilterValueEnd());
            filterData.setFilterTypeOperator(ff.getFilterTypeOperator());
            filterData.setFilterType(ff.getFilterType());
            filterData.setFilterPattern(ff.getFilterPattern());
            filterData.setLocaleCode(ff.getLocaleCode());
            filterData.setTimeZoneId(ff.getTimeZoneId());
        }

        if (filterType.getName().equals(filterData.getFilterType())) {
            String filterPattern = HeaderToolbarElementUtils.getFilterPattern(jasperReportsContext, locale,
                    filterType);

            if (FilterTypesEnum.NUMERIC.equals(filterType) && DURATION_PATTERN.equals(columnValuePattern)) {
                filterPattern = DURATION_PATTERN;
            }

            HeaderToolbarElementUtils.updateFilterData(filterData, filterPattern, locale, timeZone);
        } else {
            //FIXMEJIVE should we raise error?
        }

        return filterData;
    }

    private void setColumnHeaderData(String sortColumnLabel, Integer columnIndex, CommandTarget target,
            Map<String, Object> contextMap, JasperReportsContext jasperReportsContext, ReportContext reportContext,
            Locale locale) {
        if (target != null) {
            JRIdentifiable identifiable = target.getIdentifiable();
            JRDesignComponentElement componentElement = identifiable instanceof JRDesignComponentElement
                    ? (JRDesignComponentElement) identifiable
                    : null;
            StandardTable table = componentElement == null ? null : (StandardTable) componentElement.getComponent();

            List<BaseColumn> tableColumns = TableUtil.getAllColumns(table);

            if (columnIndex != null) {
                StandardColumn column = (StandardColumn) tableColumns.get(columnIndex);

                JRDesignTextElement textElement = TableUtil.getCellElement(JRDesignTextElement.class,
                        column.getColumnHeader(), true);

                if (textElement != null) {
                    EditTextElementData textElementData = new EditTextElementData();

                    textElementData.setHeadingName(JRStringUtil.htmlEncode(sortColumnLabel));
                    textElementData.setColumnIndex(columnIndex);
                    JRDesignTextElement styledElement = resolveElementStyle(textElement, reportContext, target);
                    HeaderToolbarElementUtils.copyTextElementStyle(textElementData, styledElement, locale);

                    contextMap.put("colHeaderData",
                            JacksonUtil.getInstance(jasperReportsContext).getJsonString(textElementData));
                }
            }
        }
    }

    private JRDesignTextElement resolveElementStyle(JRDesignTextElement element, ReportContext context,
            CommandTarget target) {
        JRStyle defaultStyle = element.getDefaultStyleProvider() == null ? null
                : element.getDefaultStyleProvider().getDefaultStyle();
        boolean hasExternalStyle = hasExternalStyle(element)
                || (defaultStyle != null && hasExternalStyle(defaultStyle));
        if (!hasExternalStyle && defaultStyle != null) {
            //we have everything
            return element;
        }

        JasperDesignCache designCache = JasperDesignCache.getExistingInstance(context);
        List<JRStyle> reportStyles = designCache == null ? null
                : designCache.getStyles(target.getUri(),
                        target.getIdentifiable() == null ? null : target.getIdentifiable().getUUID());
        if (reportStyles == null || reportStyles.isEmpty()) {
            return element;
        }

        JRStyle externalDefault = null;
        if (defaultStyle == null) {
            for (JRStyle style : reportStyles) {
                if (style.isDefault()) {
                    externalDefault = style;
                }
            }

            if (!hasExternalStyle && externalDefault == null) {
                //nothing to change
                return element;
            }
        }

        JRStyle elementStyle;
        if (element.getStyle() == null && element.getStyleNameReference() == null) {
            elementStyle = externalDefault;
        } else {
            String elementStyleName = element.getStyleNameReference() == null ? element.getStyle().getName()
                    : element.getStyleNameReference();

            elementStyle = null;
            for (JRStyle style : reportStyles) {
                if (style.getName().equals(elementStyleName)) {
                    elementStyle = style;
                }
            }
        }

        if (elementStyle == null) {
            //didn't find a style for the element
            return element;
        }

        JRDesignTextElement elementClone = (JRDesignTextElement) element.clone();
        elementClone.setStyle(elementStyle);
        return elementClone;
    }

    private boolean hasExternalStyle(JRStyleContainer styleContainer) {
        if (styleContainer.getStyle() == null && styleContainer.getStyleNameReference() != null) {
            return true;
        }

        JRStyle style = styleContainer.getStyle();
        while (style != null) {
            if (style.getStyle() == null && style.getStyleNameReference() != null) {
                return true;
            }

            style = style.getStyle();
        }
        return false;
    }

    private EditTextElementData setColumnValueData(Integer columnIndex, CommandTarget target,
            Map<String, Object> contextMap, JasperReportsContext jasperReportsContext, ReportContext reportContext,
            Locale locale) {
        EditTextElementData textElementData = new EditTextElementData();

        if (target != null) {
            JRIdentifiable identifiable = target.getIdentifiable();
            JRDesignComponentElement componentElement = identifiable instanceof JRDesignComponentElement
                    ? (JRDesignComponentElement) identifiable
                    : null;
            StandardTable table = componentElement == null ? null : (StandardTable) componentElement.getComponent();

            List<BaseColumn> tableColumns = TableUtil.getAllColumns(table);

            if (columnIndex != null) {
                StandardColumn column = (StandardColumn) tableColumns.get(columnIndex);

                JRDesignTextField textElement = TableUtil.getCellElement(JRDesignTextField.class,
                        column.getDetailCell(), true);

                if (textElement != null) {
                    textElementData.setColumnIndex(columnIndex);
                    JRDesignTextElement styledElement = resolveElementStyle(textElement, reportContext, target);
                    HeaderToolbarElementUtils.copyTextElementStyle(textElementData, styledElement, locale);
                }
            }
        }
        contextMap.put("colValueData",
                JacksonUtil.getInstance(jasperReportsContext).getJsonString(textElementData));

        return textElementData;
    }

    public static class ColumnInfo {
        private String index;
        private String label;
        private String uuid;
        private boolean visible;
        private boolean interactive;

        private ColumnInfo(String index, String label, String uuid, boolean visible, boolean interactive) {
            this.index = index;
            this.label = label;
            this.uuid = uuid;
            this.visible = visible;
            this.interactive = interactive;
        }

        public String getIndex() {
            return index;
        }

        public String getLabel() {
            return label;
        }

        public String getUuid() {
            return uuid;
        }

        public boolean getVisible() {
            return visible;
        }

        public boolean getInteractive() {
            return interactive;
        }
    }

    private Map<String, ColumnInfo> getAllColumnNames(JRGenericPrintElement element,
            JasperReportsContext jasperReportsContext, Map<String, Object> contextMap) {
        int prefixLength = HeaderToolbarElement.PARAM_COLUMN_LABEL_PREFIX.length();
        Map<String, ColumnInfo> columnNames = new HashMap<String, ColumnInfo>();
        for (String paramName : element.getParameterNames()) {
            if (paramName.startsWith(HeaderToolbarElement.PARAM_COLUMN_LABEL_PREFIX)) {
                String columnName = (String) element.getParameterValue(paramName);
                String[] tokens = paramName.substring(prefixLength).split("\\|");
                if (columnName == null || columnName.trim().length() == 0) {
                    columnName = "Column_" + tokens[0];
                }
                columnNames.put(tokens[0], new ColumnInfo(tokens[0], JRStringUtil.htmlEncode(columnName), tokens[1],
                        false, Boolean.valueOf(tokens[2])));
            }
        }
        return columnNames;
    }

    public static class GroupInfo {
        public static final String TYPE_GROUP_HEADING = "groupheading";
        public static final String TYPE_GROUP_SUBTOTAL = "groupsubtotal";
        public static final String TYPE_TABLE_TOTAL = "tabletotal";

        private String name;
        private String type;
        private List<Integer> forColumns;

        public GroupInfo(String name, String type) {
            this.name = name;
            this.type = type;
            this.forColumns = new ArrayList<Integer>();
        }

        public String getName() {
            return name;
        }

        public String getType() {
            return type;
        }

        public void addForColumn(Integer index) {
            forColumns.add(index);
        }

        public List<Integer> getForColumns() {
            return this.forColumns;
        }
    }

    private boolean setTextElements(List<GroupCell> groupCells, Map<JRDesignTextElement, GroupInfo> groups,
            String groupType, Integer columnIndex) {
        boolean result = false;
        if (groupCells != null) {
            for (GroupCell gc : groupCells) {
                JRDesignTextElement textElement = TableUtil.getCellElement(JRDesignTextElement.class, gc.getCell(),
                        false);

                if (textElement != null) {
                    result = true;
                    if (groups.containsKey(textElement)) {
                        groups.get(textElement).addForColumn(columnIndex);
                    } else {
                        GroupInfo gi = new GroupInfo(
                                gc.getGroupName() != null ? gc.getGroupName() : groupType + "_" + columnIndex,
                                groupType);
                        gi.addForColumn(columnIndex);
                        groups.put(textElement, gi);
                    }
                }
            }
        }
        return result;
    }

    private List<Map<String, Object>> getColumnGroupsData(JasperReportsContext jasperReportsContext,
            ReportContext reportContext, CommandTarget target, JasperDesign jasperDesign, JRDesignDataset dataset,
            StandardTable table, String tableUuid, Locale locale, TimeZone timeZone) {
        List<BaseColumn> allColumns = TableUtil.getAllColumns(table);

        int i = 0;
        Map<JRDesignTextElement, GroupInfo> groups = new HashMap<JRDesignTextElement, GroupInfo>();
        boolean found;

        // build the groups map
        for (BaseColumn bc : allColumns) {
            List<ColumnGroup> colGroups = TableUtil.getHierarchicalColumnGroupsForColumn(bc, table.getColumns(),
                    table);

            // group headers
            found = setTextElements(bc.getGroupHeaders(), groups, GroupInfo.TYPE_GROUP_HEADING, i);
            if (!found) {
                for (ColumnGroup cg : colGroups) {
                    if (cg.getGroupHeaders() == null) {
                        continue;
                    }
                    found = setTextElements(cg.getGroupHeaders(), groups, GroupInfo.TYPE_GROUP_HEADING, i);
                    if (found)
                        break;
                }
            }

            // group footers
            found = setTextElements(bc.getGroupFooters(), groups, GroupInfo.TYPE_GROUP_SUBTOTAL, i);
            if (!found) {
                for (ColumnGroup cg : colGroups) {
                    if (cg.getGroupFooters() == null) {
                        continue;
                    }
                    found = setTextElements(cg.getGroupFooters(), groups, GroupInfo.TYPE_GROUP_SUBTOTAL, i);
                    if (found)
                        break;
                }
            }

            // table footers
            found = false;
            if (bc.getTableFooter() != null) {
                JRDesignTextElement textElement = TableUtil.getCellElement(JRDesignTextElement.class,
                        bc.getTableFooter(), false);

                if (textElement != null) {
                    found = true;
                    if (groups.containsKey(textElement)) {
                        groups.get(textElement).addForColumn(i);
                    } else {
                        GroupInfo gi = new GroupInfo("Tabletotal" + "_" + i, GroupInfo.TYPE_TABLE_TOTAL);
                        gi.addForColumn(i);
                        groups.put(textElement, gi);
                    }
                }
            }
            if (!found) {
                for (ColumnGroup cg : colGroups) {
                    if (cg.getTableFooter() == null) {
                        continue;
                    }
                    JRDesignTextElement textElement = TableUtil.getCellElement(JRDesignTextElement.class,
                            cg.getTableFooter(), false);

                    if (textElement != null) {
                        found = true;
                        if (groups.containsKey(textElement)) {
                            groups.get(textElement).addForColumn(i);
                        } else {
                            GroupInfo gi = new GroupInfo("Tabletotal" + "_" + i, GroupInfo.TYPE_TABLE_TOTAL);
                            gi.addForColumn(i);
                            groups.put(textElement, gi);
                        }
                    }

                    if (found)
                        break;
                }
            }
            i++;
        }

        List<Map<String, Object>> groupsData = new ArrayList<Map<String, Object>>();

        // populate groupsData
        i = 0;
        for (Map.Entry<JRDesignTextElement, GroupInfo> entry : groups.entrySet()) {
            JRDesignTextElement textElement = entry.getKey();
            GroupInfo groupInfo = entry.getValue();

            EditTextElementData textElementData;
            textElementData = new EditTextElementData();
            textElementData.setGroupName(groupInfo.getName());
            JRDesignTextElement styledElement = resolveElementStyle(textElement, reportContext, target);
            HeaderToolbarElementUtils.copyTextElementStyle(textElementData, styledElement, locale);

            Map<String, Object> groupData = new HashMap<String, Object>();
            groupData.put("groupType", groupInfo.getType());
            groupData.put("id", groupInfo.getType() + "_" + i);
            groupData.put("groupData", textElementData);
            groupData.put("groupName", groupInfo.getName());
            groupData.put("forColumns", groupInfo.getForColumns());

            JRDesignTextField textField = textElement instanceof JRDesignTextField ? (JRDesignTextField) textElement
                    : null;
            ConditionalFormattingData cfData = textField == null ? null
                    : getConditionalFormattingData(null, jasperReportsContext, dataset, textField,
                            groupInfo.getName(), locale, timeZone);

            if (cfData != null) {
                groupData.put("dataType", cfData.getConditionType());
                groupData.put("conditionalFormattingData", cfData);
            } else {
                groupData.put("dataType", FilterTypesEnum.TEXT.getName());
            }

            groupsData.add(groupData);

            i++;
        }

        return groupsData;
    }

    private static ConditionalFormattingData getConditionalFormattingData(JRGenericPrintElement element,
            JasperReportsContext jasperReportsContext, JRDesignDataset dataset, JRDesignTextField textField,
            String groupName, Locale locale, TimeZone timeZone) {
        FilterTypesEnum conditionType = null;
        String conditionTypeProp;

        // only for the detail values the element will not be null
        if (element != null) {
            conditionTypeProp = element.getPropertiesMap().getProperty(HeaderToolbarElement.PROPERTY_FILTER_TYPE);

            if (element.getPropertiesMap().containsProperty(HeaderToolbarElement.PROPERTY_COLUMN_FIELD)) {
                textField.getPropertiesMap().setProperty(HeaderToolbarElement.PROPERTY_COLUMN_FIELD,
                        element.getPropertiesMap().getProperty(HeaderToolbarElement.PROPERTY_COLUMN_FIELD));
            } else if (element.getPropertiesMap().containsProperty(HeaderToolbarElement.PROPERTY_COLUMN_VARIABLE)) {
                textField.getPropertiesMap().setProperty(HeaderToolbarElement.PROPERTY_COLUMN_VARIABLE,
                        element.getPropertiesMap().getProperty(HeaderToolbarElement.PROPERTY_COLUMN_VARIABLE));
            }

        } else {
            conditionTypeProp = textField.getPropertiesMap()
                    .getProperty(HeaderToolbarElement.PROPERTY_CONDTION_TYPE);
        }

        if (conditionTypeProp == null) {
            JRExpression expression = textField.getExpression();
            if (expression != null) {
                JRExpressionChunk[] chunks = expression.getChunks();
                if (chunks != null && chunks.length == 1) {
                    JRExpressionChunk expressionChunk = expression.getChunks()[0];
                    String fieldOrVariableName = expressionChunk.getText();

                    switch (expressionChunk.getType()) {
                    case JRExpressionChunk.TYPE_FIELD:
                        JRField field = HeaderToolbarElementUtils.getField(fieldOrVariableName, dataset);
                        conditionType = HeaderToolbarElementUtils.getFilterType(field.getValueClass());
                        break;

                    case JRExpressionChunk.TYPE_VARIABLE:
                        JRVariable variable = HeaderToolbarElementUtils.getVariable(fieldOrVariableName, dataset);
                        conditionType = HeaderToolbarElementUtils.getFilterType(variable.getValueClass());
                        break;

                    case JRExpressionChunk.TYPE_TEXT:
                    default:
                    }
                }
            }
        } else {
            conditionType = FilterTypesEnum.getByName(conditionTypeProp);
        }

        ConditionalFormattingData cfd = null;
        if (conditionType != null) {
            cfd = HeaderToolbarElementUtils.getConditionalFormattingData(textField, jasperReportsContext);
            if (cfd == null) {
                cfd = new ConditionalFormattingData();
                if (groupName != null) {
                    cfd.setGroupName(groupName);
                }
                cfd.setConditionType(conditionType.getName());
            }

            if (conditionType.getName().equals(cfd.getConditionType())) {
                String conditionPattern = HeaderToolbarElementUtils.getFilterPattern(jasperReportsContext, locale,
                        conditionType);

                if (FilterTypesEnum.NUMERIC.equals(conditionType)
                        && DURATION_PATTERN.equals(textField.getPattern())) {
                    conditionPattern = DURATION_PATTERN;
                }

                HeaderToolbarElementUtils.updateConditionalFormattingData(cfd, conditionPattern, locale, timeZone);
            } else {
                //FIXMEJIVE should we raise error?
            }
        }

        return cfd;
    }

    private Set<String> getFontExtensionsFontNames(JasperReportsContext jasperReportsContext) {
        Set<String> classes = new TreeSet<String>();

        Collection<String> extensionFonts = FontUtil.getInstance(jasperReportsContext).getFontNames();
        for (Iterator<String> it = extensionFonts.iterator(); it.hasNext();) {
            String fname = it.next();
            classes.add(fname);
        }

        return classes;
    }

    private Set<String> getSystemFontNames(JasperReportsContext jasperReportsContext) {
        Set<String> fontExtensionsFontNames = getFontExtensionsFontNames(jasperReportsContext);
        Set<String> classes = new TreeSet<String>();

        String[] names = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
        for (int i = 0; i < names.length; i++) {
            String name = names[i];
            if (fontExtensionsFontNames.add(name)) {
                classes.add(name);
            }
        }

        return classes;
    }

}