Java tutorial
/*! * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software * Foundation. * * You should have received a copy of the GNU Lesser General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * 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 Lesser General Public License for more details. * * Copyright (c) 2002-2017 Hitachi Vantara.. All rights reserved. */ package org.pentaho.reporting.engine.classic.wizard; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.pentaho.reporting.engine.classic.core.AbstractReportDefinition; import org.pentaho.reporting.engine.classic.core.AbstractReportPreProcessor; import org.pentaho.reporting.engine.classic.core.AttributeNames; import org.pentaho.reporting.engine.classic.core.Band; import org.pentaho.reporting.engine.classic.core.CrosstabColumnGroup; import org.pentaho.reporting.engine.classic.core.CrosstabColumnGroupBody; import org.pentaho.reporting.engine.classic.core.CrosstabGroup; import org.pentaho.reporting.engine.classic.core.CrosstabOtherGroup; import org.pentaho.reporting.engine.classic.core.CrosstabOtherGroupBody; import org.pentaho.reporting.engine.classic.core.CrosstabRowGroup; import org.pentaho.reporting.engine.classic.core.CrosstabRowGroupBody; import org.pentaho.reporting.engine.classic.core.Element; import org.pentaho.reporting.engine.classic.core.Group; import org.pentaho.reporting.engine.classic.core.GroupBody; import org.pentaho.reporting.engine.classic.core.GroupFooter; import org.pentaho.reporting.engine.classic.core.GroupHeader; import org.pentaho.reporting.engine.classic.core.MasterReport; import org.pentaho.reporting.engine.classic.core.MetaAttributeNames; import org.pentaho.reporting.engine.classic.core.RelationalGroup; import org.pentaho.reporting.engine.classic.core.ReportElement; import org.pentaho.reporting.engine.classic.core.ReportProcessingException; import org.pentaho.reporting.engine.classic.core.Section; import org.pentaho.reporting.engine.classic.core.SubGroupBody; import org.pentaho.reporting.engine.classic.core.SubReport; import org.pentaho.reporting.engine.classic.core.Watermark; import org.pentaho.reporting.engine.classic.core.filter.types.ContentType; import org.pentaho.reporting.engine.classic.core.filter.types.LabelType; import org.pentaho.reporting.engine.classic.core.filter.types.TextFieldType; import org.pentaho.reporting.engine.classic.core.function.ProcessingContext; import org.pentaho.reporting.engine.classic.core.function.StructureFunction; import org.pentaho.reporting.engine.classic.core.metadata.ElementType; import org.pentaho.reporting.engine.classic.core.states.datarow.DefaultFlowController; import org.pentaho.reporting.engine.classic.core.style.BandStyleKeys; import org.pentaho.reporting.engine.classic.core.style.BorderStyle; import org.pentaho.reporting.engine.classic.core.style.ElementStyleKeys; import org.pentaho.reporting.engine.classic.core.style.ElementStyleSheet; import org.pentaho.reporting.engine.classic.core.style.TextStyleKeys; import org.pentaho.reporting.engine.classic.core.wizard.AutoGeneratorUtility; import org.pentaho.reporting.engine.classic.core.wizard.DataAttributes; import org.pentaho.reporting.engine.classic.core.wizard.DefaultDataAttributeContext; import org.pentaho.reporting.engine.classic.core.wizard.RelationalAutoGeneratorPreProcessor; import org.pentaho.reporting.engine.classic.wizard.model.DetailFieldDefinition; import org.pentaho.reporting.engine.classic.wizard.model.FieldDefinition; import org.pentaho.reporting.engine.classic.wizard.model.GroupDefinition; import org.pentaho.reporting.engine.classic.wizard.model.GroupType; import org.pentaho.reporting.engine.classic.wizard.model.Length; import org.pentaho.reporting.engine.classic.wizard.model.RootBandDefinition; import org.pentaho.reporting.engine.classic.wizard.model.WatermarkDefinition; import org.pentaho.reporting.engine.classic.wizard.model.WizardSpecification; import org.pentaho.reporting.libraries.base.util.ObjectUtilities; import org.pentaho.reporting.libraries.base.util.StringUtils; import org.pentaho.reporting.libraries.resourceloader.ResourceManager; import java.awt.*; import java.util.ArrayList; /** * @author Thomas Morgner * @noinspection UnnecessaryBoxing, UnnecessaryUnboxing, UnusedDeclaration */ public class WizardProcessor extends AbstractReportPreProcessor { private static final Log logger = LogFactory.getLog(WizardProcessor.class); protected DefaultDataAttributeContext attributeContext; protected AbstractReportDefinition definition; protected DefaultFlowController flowController; protected WizardSpecification wizardSpecification; public WizardProcessor() { } public MasterReport performPreProcessing(final MasterReport definition, final DefaultFlowController flowController) throws ReportProcessingException { return (MasterReport) performCommonPreProcessing(definition, flowController, definition.getResourceManager()); } public SubReport performPreProcessing(final SubReport definition, final DefaultFlowController flowController) throws ReportProcessingException { return (SubReport) performCommonPreProcessing(definition, flowController, definition.getResourceManager()); } protected AbstractReportDefinition performCommonPreProcessing(final AbstractReportDefinition definition, final DefaultFlowController flowController, final ResourceManager resourceManager) throws ReportProcessingException { try { this.wizardSpecification = WizardProcessorUtil.loadWizardSpecification(definition, resourceManager); if (wizardSpecification == null) { return definition; } final StructureFunction[] functions = definition.getStructureFunctions(); boolean hasOverrideFunction = false; for (int i = 0; i < functions.length; i++) { final StructureFunction function = functions[i]; if (function instanceof WizardOverrideFormattingFunction) { hasOverrideFunction = true; break; } } if (hasOverrideFunction == false) { definition.addStructureFunction(new WizardOverrideFormattingFunction()); } final ProcessingContext reportContext = flowController.getReportContext(); this.definition = definition; this.flowController = flowController; this.attributeContext = new DefaultDataAttributeContext(reportContext.getOutputProcessorMetaData(), reportContext.getResourceBundleFactory().getLocale()); final Object o = definition.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ENABLE); if (Boolean.TRUE.equals(o) == false) { return performRefreshPreProcessing(); } else { return performGenerationPreProcessing(); } } finally { this.wizardSpecification = null; this.definition = null; this.flowController = null; this.attributeContext = null; } } private AbstractReportDefinition performRefreshPreProcessing() throws ReportProcessingException { final GroupDefinition[] groupDefinitions = wizardSpecification.getGroupDefinitions(); final int wizardCount = groupDefinitions.length; // 1 5 5 final int groupCount = definition.getGroupCount(); // 5 1 5 final int count = Math.min(groupCount, wizardCount); for (int i = 0; i < count; i++) { final int groupIdx = groupCount - i - 1; final int wizGroupIdx = wizardCount - i - 1; final GroupDefinition gd = groupDefinitions[wizGroupIdx]; final RelationalGroup g = definition.getRelationalGroup(groupIdx); if (g == null) { break; } final Band groupHeader = g.getHeader(); final Band groupFooter = g.getFooter(); iterateSection(groupHeader, new UpdateHeaderTask(gd)); iterateSection(groupFooter, new UpdateFooterTask(gd)); } final Band itemband = definition.getItemBand(); final Band detailsHeader = definition.getDetailsHeader(); final Band detailsFooter = definition.getDetailsFooter(); final DetailFieldDefinition[] detailFieldDefinitions = wizardSpecification.getDetailFieldDefinitions(); for (int i = 0; i < detailFieldDefinitions.length; i++) { final DetailFieldDefinition fieldDefinition = detailFieldDefinitions[i]; final UpdateDetailsTask updateTask = new UpdateDetailsTask(fieldDefinition); iterateSection(itemband, updateTask); iterateSection(detailsHeader, updateTask); iterateSection(detailsFooter, updateTask); } return definition; } protected static interface UpdateTask { public void processElement(ReportElement e); } private static class UpdateHeaderTask implements UpdateTask { private GroupDefinition groupDefinition; private UpdateHeaderTask(final GroupDefinition groupDefinition) { this.groupDefinition = groupDefinition; } public void processElement(final ReportElement e) { if (Boolean.TRUE.equals(e.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ALLOW_METADATA_STYLING))) { e.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.CACHED_WIZARD_FORMAT_DATA, groupDefinition.getHeader()); } if (Boolean.TRUE.equals(e.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ALLOW_METADATA_ATTRIBUTES))) { e.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.CACHED_WIZARD_FIELD_DATA, groupDefinition); } } } private static class UpdateFooterTask implements UpdateTask { private GroupDefinition groupDefinition; private UpdateFooterTask(final GroupDefinition groupDefinition) { this.groupDefinition = groupDefinition; } public void processElement(final ReportElement e) { if (Boolean.TRUE.equals(e.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ALLOW_METADATA_STYLING))) { e.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.CACHED_WIZARD_FORMAT_DATA, groupDefinition.getFooter()); } if (Boolean.TRUE.equals(e.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ALLOW_METADATA_ATTRIBUTES))) { e.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.CACHED_WIZARD_FIELD_DATA, groupDefinition); } } } private static class UpdateDetailsTask implements UpdateTask { private FieldDefinition fieldDefinition; private UpdateDetailsTask(final FieldDefinition groupDefinition) { this.fieldDefinition = groupDefinition; } public void processElement(final ReportElement e) { final String field = fieldDefinition.getField(); final Object labelFor = e.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.LABEL_FOR); if (labelFor != null) { if (ObjectUtilities.equal(field, labelFor) == false) { return; } } else { final Object fieldName = e.getAttribute(AttributeNames.Core.NAMESPACE, AttributeNames.Core.FIELD); if (ObjectUtilities.equal(field, fieldName) == false) { return; } } if (Boolean.TRUE.equals(e.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ALLOW_METADATA_STYLING))) { e.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.CACHED_WIZARD_FORMAT_DATA, fieldDefinition); if (Boolean.TRUE.equals(e.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.PRESERVE_USER_STYLING))) { final ElementStyleSheet styleSheet = e.getStyle(); if (styleSheet.isLocalKey(TextStyleKeys.BOLD)) { if (e.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ENABLE_STYLE_BOLD) != null) { e.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ENABLE_STYLE_BOLD, Boolean.FALSE); } } if (styleSheet.isLocalKey(TextStyleKeys.ITALIC)) { if (e.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ENABLE_STYLE_ITALICS) != null) { e.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ENABLE_STYLE_ITALICS, Boolean.FALSE); } } if (styleSheet.isLocalKey(TextStyleKeys.UNDERLINED)) { if (e.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ENABLE_STYLE_UNDERLINE) != null) { e.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ENABLE_STYLE_UNDERLINE, Boolean.FALSE); } } if (styleSheet.isLocalKey(TextStyleKeys.STRIKETHROUGH)) { if (e.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ENABLE_STYLE_STRIKETHROUGH) != null) { e.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ENABLE_STYLE_STRIKETHROUGH, Boolean.FALSE); } } if (styleSheet.isLocalKey(TextStyleKeys.FONT)) { if (e.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ENABLE_STYLE_FONTFAMILY) != null) { e.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ENABLE_STYLE_FONTFAMILY, Boolean.FALSE); } } if (styleSheet.isLocalKey(TextStyleKeys.FONTSIZE)) { if (e.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ENABLE_STYLE_FONTSIZE) != null) { e.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ENABLE_STYLE_FONTSIZE, Boolean.FALSE); } } if (styleSheet.isLocalKey(ElementStyleKeys.PAINT)) { if (e.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ENABLE_STYLE_COLOR) != null) { e.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ENABLE_STYLE_COLOR, Boolean.FALSE); } } if (styleSheet.isLocalKey(ElementStyleKeys.BACKGROUND_COLOR)) { if (e.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ENABLE_STYLE_BACKGROUND_COLOR) != null) { e.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ENABLE_STYLE_BACKGROUND_COLOR, Boolean.FALSE); } } if (styleSheet.isLocalKey(ElementStyleKeys.VALIGNMENT)) { if (e.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ENABLE_STYLE_VALIGNMENT) != null) { e.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ENABLE_STYLE_VALIGNMENT, Boolean.FALSE); } } if (styleSheet.isLocalKey(ElementStyleKeys.ALIGNMENT)) { if (e.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ENABLE_STYLE_ALIGNMENT) != null) { e.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ENABLE_STYLE_ALIGNMENT, Boolean.FALSE); } } } } if (Boolean.TRUE.equals(e.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ALLOW_METADATA_ATTRIBUTES))) { e.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.CACHED_WIZARD_FIELD_DATA, fieldDefinition); } } } protected void iterateSection(final Section s, final UpdateTask task) { final int count = s.getElementCount(); for (int i = 0; i < count; i++) { final ReportElement element = s.getElement(i); task.processElement(element); if (element instanceof SubReport) { continue; } if (element instanceof Section) { iterateSection((Section) element, task); } } } protected AbstractReportDefinition performGenerationPreProcessing() throws ReportProcessingException { setupWatermark(); setupRelationalGroups(); /** remove check on data source to display to use cross-tab if (isCrosstab()) { setupCrosstab(); } else { clearCrosstab(); } */ setupDetails(); return definition; } private void clearCrosstab() { final CrosstabGroup crosstabGroup = lookupCrosstab(); if (crosstabGroup != null) { if (definition.getRootGroup() == crosstabGroup) { definition.setRootGroup(new RelationalGroup()); } else { final Section parentSection = crosstabGroup.getParentSection(); if (parentSection instanceof SubGroupBody) { final SubGroupBody sgb = (SubGroupBody) parentSection; sgb.setGroup(new RelationalGroup()); } } } } /** * Creating a crosstab report deletes all sub-definitions and the itemband. * * @throws ReportProcessingException if an error occurs. */ private void setupCrosstab() throws ReportProcessingException { CrosstabGroup crosstab = lookupCrosstab(); if (crosstab == null) { crosstab = new CrosstabGroup(); insertCrosstab(crosstab); } Group insertGroup = crosstab; final GroupDefinition[] groupDefinitions = wizardSpecification.getGroupDefinitions(); for (int i = 0; i < groupDefinitions.length; i++) { final GroupDefinition groupDefinition = groupDefinitions[i]; if (GroupType.CT_OTHER.equals(groupDefinition.getGroupType()) == false) { continue; } // create a new group and insert it at the end final CrosstabOtherGroup relationalGroup = new CrosstabOtherGroup(); if (groupDefinition.getGroupName() != null) { relationalGroup.setName(groupDefinition.getGroupName()); } configureCrosstabOtherGroup(relationalGroup, groupDefinition); insertGroup.setBody(new CrosstabOtherGroupBody(relationalGroup)); insertGroup = relationalGroup; } for (int i = 0; i < groupDefinitions.length; i++) { final GroupDefinition groupDefinition = groupDefinitions[i]; if (GroupType.CT_ROW.equals(groupDefinition.getGroupType()) == false) { continue; } // create a new group and insert it at the end final CrosstabRowGroup relationalGroup = new CrosstabRowGroup(); if (groupDefinition.getGroupName() != null) { relationalGroup.setName(groupDefinition.getGroupName()); } configureCrosstabRowGroup(relationalGroup, groupDefinition); insertGroup.setBody(new CrosstabRowGroupBody(relationalGroup)); insertGroup = relationalGroup; } for (int i = 0; i < groupDefinitions.length; i++) { final GroupDefinition groupDefinition = groupDefinitions[i]; if (GroupType.CT_COLUMN.equals(groupDefinition.getGroupType()) == false) { continue; } // create a new group and insert it at the end final CrosstabColumnGroup relationalGroup = new CrosstabColumnGroup(); if (groupDefinition.getGroupName() != null) { relationalGroup.setName(groupDefinition.getGroupName()); } configureCrosstabColumnGroup(relationalGroup, groupDefinition); insertGroup.setBody(new CrosstabColumnGroupBody(relationalGroup)); insertGroup = relationalGroup; } final Band itemBand = AutoGeneratorUtility.findGeneratedContent(definition.getItemBand()); if (itemBand == null) { return; } final DetailFieldDefinition[] detailFieldDefinitions = wizardSpecification.getDetailFieldDefinitions(); if (detailFieldDefinitions.length == 0) { return; } final Float[] widthSpecs = new Float[detailFieldDefinitions.length]; for (int i = 0; i < detailFieldDefinitions.length; i++) { final DetailFieldDefinition fieldDefinition = detailFieldDefinitions[i]; final Length length = fieldDefinition.getWidth(); if (length == null) { continue; } widthSpecs[i] = length.getNormalizedValue(); } final float[] computedWidth = AutoGeneratorUtility.computeFieldWidths(widthSpecs, definition.getPageDefinition().getWidth()); itemBand.getStyle().setStyleProperty(BandStyleKeys.LAYOUT, "row"); for (int i = 0; i < detailFieldDefinitions.length; i++) { final DetailFieldDefinition detailFieldDefinition = detailFieldDefinitions[i]; setupField(null, null, itemBand, detailFieldDefinition, computedWidth[i], i); } } protected void setupDetails() throws ReportProcessingException { final DetailFieldDefinition[] detailFieldDefinitions = wizardSpecification.getDetailFieldDefinitions(); if (detailFieldDefinitions.length == 0) { if (wizardSpecification.isAutoGenerateDetails()) { final RelationalAutoGeneratorPreProcessor generatorPreProcessor = new RelationalAutoGeneratorPreProcessor(); if (definition instanceof MasterReport) { generatorPreProcessor.performPreProcessing((MasterReport) definition, flowController); } else if (definition instanceof SubReport) { generatorPreProcessor.performPreProcessing((SubReport) definition, flowController); } } return; } definition.getDetailsHeader().setRepeat(true); definition.getDetailsFooter().setRepeat(true); final Band detailsHeader = AutoGeneratorUtility.findGeneratedContent(definition.getDetailsHeader()); final Band detailsFooter = AutoGeneratorUtility.findGeneratedContent(definition.getDetailsFooter()); final Band itemBand = AutoGeneratorUtility.findGeneratedContent(definition.getItemBand()); if (itemBand == null) { return; } final Float[] widthSpecs = new Float[detailFieldDefinitions.length]; for (int i = 0; i < detailFieldDefinitions.length; i++) { final DetailFieldDefinition fieldDefinition = detailFieldDefinitions[i]; final Length length = fieldDefinition.getWidth(); if (length == null) { continue; } widthSpecs[i] = length.getNormalizedValue(); } final float[] computedWidth = AutoGeneratorUtility.computeFieldWidths(widthSpecs, definition.getPageDefinition().getWidth()); itemBand.getStyle().setStyleProperty(BandStyleKeys.LAYOUT, "row"); if (detailsHeader != null) { detailsHeader.getStyle().setStyleProperty(BandStyleKeys.LAYOUT, "row"); } if (detailsFooter != null) { detailsFooter.getStyle().setStyleProperty(BandStyleKeys.LAYOUT, "row"); } for (int i = 0; i < detailFieldDefinitions.length; i++) { final DetailFieldDefinition detailFieldDefinition = detailFieldDefinitions[i]; setupField(detailsHeader, detailsFooter, itemBand, detailFieldDefinition, computedWidth[i], i); } if (detailsFooter != null) { final Element[] elements = detailsFooter.getElementArray(); boolean footerEmpty = true; for (int i = 0; i < elements.length; i++) { final Element element = elements[i]; if (LabelType.class.isInstance(element.getElementType()) == false) { footerEmpty = false; break; } } if (footerEmpty) { detailsFooter.clear(); } } } protected void setupDefaultPadding(final Band band, final Element detailElement) { final Object maybePaddingTop = band.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.PADDING_TOP); final Object maybePaddingLeft = band.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.PADDING_LEFT); final Object maybePaddingBottom = band.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.PADDING_BOTTOM); final Object maybePaddingRight = band.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.PADDING_RIGHT); if (maybePaddingTop instanceof Number == false || maybePaddingLeft instanceof Number == false || maybePaddingBottom instanceof Number == false || maybePaddingRight instanceof Number == false) { return; } final Number paddingTop = (Number) maybePaddingTop; final Number paddingLeft = (Number) maybePaddingLeft; final Number paddingBottom = (Number) maybePaddingBottom; final Number paddingRight = (Number) maybePaddingRight; final ElementStyleSheet styleSheet = detailElement.getStyle(); styleSheet.setStyleProperty(ElementStyleKeys.PADDING_TOP, new Float(paddingTop.floatValue())); styleSheet.setStyleProperty(ElementStyleKeys.PADDING_LEFT, new Float(paddingLeft.floatValue())); styleSheet.setStyleProperty(ElementStyleKeys.PADDING_BOTTOM, new Float(paddingBottom.floatValue())); styleSheet.setStyleProperty(ElementStyleKeys.PADDING_RIGHT, new Float(paddingRight.floatValue())); } protected void setupDefaultGrid(final Band band, final Element detailElement) { setupDefaultPadding(band, detailElement); final ElementStyleSheet styleSheet = detailElement.getStyle(); // Always make the height of the detailElement dynamic to the band // According to thomas negative numbers equate to percentages styleSheet.setStyleProperty(ElementStyleKeys.MIN_HEIGHT, new Float(-100)); final Object maybeBorderStyle = band.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.GRID_STYLE); final Object maybeBorderWidth = band.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.GRID_WIDTH); final Object maybeBorderColor = band.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.GRID_COLOR); if (maybeBorderColor instanceof Color == false || maybeBorderStyle instanceof BorderStyle == false || maybeBorderWidth instanceof Number == false) { return; } final BorderStyle style = (BorderStyle) maybeBorderStyle; final Color color = (Color) maybeBorderColor; final Number number = (Number) maybeBorderWidth; final Float width = new Float(number.floatValue()); styleSheet.setStyleProperty(ElementStyleKeys.BORDER_TOP_WIDTH, width); styleSheet.setStyleProperty(ElementStyleKeys.BORDER_TOP_COLOR, color); styleSheet.setStyleProperty(ElementStyleKeys.BORDER_TOP_STYLE, style); styleSheet.setStyleProperty(ElementStyleKeys.BORDER_LEFT_WIDTH, width); styleSheet.setStyleProperty(ElementStyleKeys.BORDER_LEFT_COLOR, color); styleSheet.setStyleProperty(ElementStyleKeys.BORDER_LEFT_STYLE, style); styleSheet.setStyleProperty(ElementStyleKeys.BORDER_BOTTOM_WIDTH, width); styleSheet.setStyleProperty(ElementStyleKeys.BORDER_BOTTOM_COLOR, color); styleSheet.setStyleProperty(ElementStyleKeys.BORDER_BOTTOM_STYLE, style); styleSheet.setStyleProperty(ElementStyleKeys.BORDER_RIGHT_WIDTH, width); styleSheet.setStyleProperty(ElementStyleKeys.BORDER_RIGHT_COLOR, color); styleSheet.setStyleProperty(ElementStyleKeys.BORDER_RIGHT_STYLE, style); } protected void setupField(final Band detailsHeader, final Band detailsFooter, final Band itemBand, final DetailFieldDefinition field, final float width, final int fieldIdx) throws ReportProcessingException { if (StringUtils.isEmpty(field.getField())) { return; } final Element detailElement = AutoGeneratorUtility.generateDetailsElement(field.getField(), computeElementType(field)); setupDefaultGrid(itemBand, detailElement); final String id = "wizard::details-" + field.getField(); detailElement.setName(id); detailElement.getStyle().setStyleProperty(ElementStyleKeys.MIN_WIDTH, new Float(width)); if (Boolean.TRUE.equals(detailElement.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ALLOW_METADATA_STYLING))) { detailElement.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.CACHED_WIZARD_FORMAT_DATA, field); } if (Boolean.TRUE.equals(detailElement.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ALLOW_METADATA_ATTRIBUTES))) { detailElement.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.CACHED_WIZARD_FIELD_DATA, field); } itemBand.addElement(detailElement); if (Boolean.TRUE.equals(field.getOnlyShowChangingValues())) { detailElement.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ONLY_SHOW_CHANGING_VALUES, Boolean.TRUE); } if (detailsHeader != null) { final Element headerElement = AutoGeneratorUtility.generateHeaderElement(field.getField()); setupDefaultGrid(detailsHeader, headerElement); headerElement.getStyle().setStyleProperty(ElementStyleKeys.MIN_WIDTH, new Float(width)); if (Boolean.TRUE.equals(headerElement.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ALLOW_METADATA_STYLING))) { headerElement.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.CACHED_WIZARD_FORMAT_DATA, field); } if (Boolean.TRUE.equals(headerElement.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ALLOW_METADATA_ATTRIBUTES))) { headerElement.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.CACHED_WIZARD_FIELD_DATA, field); } headerElement.setAttribute(AttributeNames.Wizard.NAMESPACE, MetaAttributeNames.Style.HORIZONTAL_ALIGNMENT, field.getHorizontalAlignment()); detailsHeader.addElement(headerElement); } if (detailsFooter != null) { final Class aggFunctionClass = field.getAggregationFunction(); final Element footerElement = AutoGeneratorUtility.generateFooterElement(aggFunctionClass, computeElementType(field), null, field.getField()); setupDefaultGrid(detailsFooter, footerElement); footerElement.getStyle().setStyleProperty(ElementStyleKeys.MIN_WIDTH, new Float(width)); if (Boolean.TRUE.equals(footerElement.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ALLOW_METADATA_STYLING))) { footerElement.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.CACHED_WIZARD_FORMAT_DATA, field); } if (Boolean.TRUE.equals(footerElement.getAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ALLOW_METADATA_ATTRIBUTES))) { footerElement.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.CACHED_WIZARD_FIELD_DATA, field); } detailsFooter.addElement(footerElement); } } /* * Removes the unusedTemplateGroups based on the assumption that if a group doesn't have any * fields assigned to it that it is empty. */ private void removedUnusedTemplateGroups(final int groupsDefined) { final RelationalGroup[] templateRelationalGroups = getTemplateRelationalGroups(); final int templateRelationalGroupCount = templateRelationalGroups.length; for (int i = groupsDefined; i < templateRelationalGroupCount; i++) { final RelationalGroup templateRelationalGroup = templateRelationalGroups[i]; definition.removeGroup(templateRelationalGroup); } } /** * @return the relational groups in the templates in a flattened array. */ private RelationalGroup[] getTemplateRelationalGroups() { final ArrayList<RelationalGroup> relationalGroups = new ArrayList<RelationalGroup>(); Group group = definition.getRootGroup(); while (group != null && group instanceof RelationalGroup) { relationalGroups.add((RelationalGroup) group); final GroupBody body = group.getBody(); if (body instanceof SubGroupBody) { final SubGroupBody sgBody = (SubGroupBody) body; if (sgBody.getGroup() instanceof RelationalGroup) { group = sgBody.getGroup(); } else { group = null; } } else { group = null; } } return relationalGroups.toArray(new RelationalGroup[relationalGroups.size()]); } private void setupRelationalGroups() throws ReportProcessingException { final Group rootgroup = definition.getRootGroup(); RelationalGroup group; if (rootgroup instanceof RelationalGroup == false) { group = null; } else { group = (RelationalGroup) rootgroup; } final RelationalGroup template = findInnermostRelationalGroup(definition); final GroupDefinition[] groupDefinitions = wizardSpecification.getGroupDefinitions(); for (int i = 0; i < groupDefinitions.length; i++) { final GroupDefinition groupDefinition = groupDefinitions[i]; final GroupType type = groupDefinition.getGroupType(); if (type != null && GroupType.RELATIONAL.equals(type) == false) { continue; } if (group == null) { // create a new group and insert it at the end final RelationalGroup relationalGroup; if (template != null) { relationalGroup = (RelationalGroup) template.derive(); } else { relationalGroup = new RelationalGroup(); } if (groupDefinition.getGroupName() != null) { relationalGroup.setName(groupDefinition.getGroupName()); } configureRelationalGroup(relationalGroup, groupDefinition, i); insertGroup(relationalGroup); } else { // modify the existing group configureRelationalGroup(group, groupDefinition, i); final GroupBody body = group.getBody(); if (body instanceof SubGroupBody) { final SubGroupBody sgBody = (SubGroupBody) body; if (sgBody.getGroup() instanceof RelationalGroup) { group = (RelationalGroup) sgBody.getGroup(); } else { group = null; } } else { group = null; } } } // Remove any group bands are not being used ie. groups with no fields removedUnusedTemplateGroups(groupDefinitions.length); } private RelationalGroup findInnermostRelationalGroup(final AbstractReportDefinition definition) { RelationalGroup retval = null; Group existingGroup = definition.getRootGroup(); while (existingGroup instanceof RelationalGroup) { retval = (RelationalGroup) existingGroup; final GroupBody body = existingGroup.getBody(); if (body instanceof SubGroupBody == false) { return retval; } final SubGroupBody sgb = (SubGroupBody) body; existingGroup = sgb.getGroup(); } return retval; } /** * Inserts the crosstab into the report as innermost group. This method will fail if there is already a crosstab * active. * * @param crosstabGroup */ private void insertCrosstab(final CrosstabGroup crosstabGroup) { Group existingGroup = definition.getRootGroup(); GroupBody gb = existingGroup.getBody(); while (gb instanceof SubGroupBody) { final SubGroupBody sgb = (SubGroupBody) gb; existingGroup = sgb.getGroup(); gb = existingGroup.getBody(); } existingGroup.setBody(new SubGroupBody(crosstabGroup)); } private CrosstabGroup lookupCrosstab() { Group existingGroup = definition.getRootGroup(); if (existingGroup instanceof CrosstabGroup) { return (CrosstabGroup) existingGroup; } GroupBody gb = existingGroup.getBody(); while (gb instanceof SubGroupBody) { final SubGroupBody sgb = (SubGroupBody) gb; existingGroup = sgb.getGroup(); if (existingGroup instanceof CrosstabGroup) { return (CrosstabGroup) existingGroup; } gb = existingGroup.getBody(); } return null; } private void insertGroup(final RelationalGroup group) { Group lastGroup = null; Group insertGroup = definition.getRootGroup(); while (true) { if (insertGroup instanceof RelationalGroup == false) { if (lastGroup == null) { definition.setRootGroup(group); group.setBody(new SubGroupBody(insertGroup)); return; } final GroupBody body = lastGroup.getBody(); final SubGroupBody sgb = new SubGroupBody(group); lastGroup.setBody(sgb); group.setBody(body); return; } final GroupBody body = insertGroup.getBody(); if (body instanceof SubGroupBody == false) { final SubGroupBody sgb = new SubGroupBody(group); insertGroup.setBody(sgb); group.setBody(body); return; } lastGroup = insertGroup; final SubGroupBody sgb = (SubGroupBody) body; insertGroup = sgb.getGroup(); } } private void configureCrosstabOtherGroup(final CrosstabOtherGroup group, final GroupDefinition groupDefinition) throws ReportProcessingException { final String groupField = groupDefinition.getField(); group.setField(groupField); configureCrosstabGroupHeader(group, groupDefinition); configureCrosstabGroupFooter(group, groupDefinition); } private void configureCrosstabRowGroup(final CrosstabRowGroup group, final GroupDefinition groupDefinition) throws ReportProcessingException { final String groupField = groupDefinition.getField(); group.setField(groupField); configureCrosstabGroupHeader(group, groupDefinition); configureCrosstabGroupFooter(group, groupDefinition); } private void configureCrosstabColumnGroup(final CrosstabColumnGroup group, final GroupDefinition groupDefinition) throws ReportProcessingException { final String groupField = groupDefinition.getField(); group.setField(groupField); configureCrosstabGroupHeader(group, groupDefinition); configureCrosstabGroupFooter(group, groupDefinition); } protected void configureRelationalGroup(final RelationalGroup group, final GroupDefinition groupDefinition, final int index) throws ReportProcessingException { final String groupField = groupDefinition.getField(); if (groupField != null) { group.setFieldsArray(new String[] { groupField }); } configureRelationalGroupFooter(group, groupDefinition, index); configureRelationalGroupHeader(group, groupDefinition, index); } private void configureCrosstabGroupHeader(final Group group, final GroupDefinition groupDefinition) { /* final RootBandDefinition headerDefinition = groupDefinition.getHeader(); if (headerDefinition.isVisible()) { final GroupHeader header = group.getHeader(); final Boolean repeat = headerDefinition.getRepeat(); if (repeat != null) { header.setRepeat(repeat.booleanValue()); } final Band content = AutoGeneratorUtility.findGeneratedContent(header); if (content == null) { return; } final Element headerElement = AutoGeneratorUtility.generateDetailsElement (groupDefinition.getField(), computeElementType(groupDefinition)); final Length length = groupDefinition.getWidth(); if (length != null) { headerElement.getStyle().setStyleProperty(ElementStyleKeys.MIN_WIDTH, length.getNormalizedValue()); } headerElement.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.CACHED_WIZARD_FORMAT_DATA, headerDefinition); headerElement.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.CACHED_WIZARD_FIELD_DATA, groupDefinition); content.clear(); content.addElement(headerElement); } */ } protected void configureRelationalGroupHeader(final RelationalGroup group, final GroupDefinition groupDefinition, final int index) { final RootBandDefinition headerDefinition = groupDefinition.getHeader(); if (headerDefinition.isVisible()) { final GroupHeader header = group.getHeader(); final Boolean repeat = headerDefinition.getRepeat(); if (repeat != null) { header.setRepeat(repeat.booleanValue()); } final Band content = AutoGeneratorUtility.findGeneratedContent(header); if (content == null) { return; } final Element headerLabelElement = new Element(); headerLabelElement.setElementType(new LabelType()); if (groupDefinition.getDisplayName() != null) { headerLabelElement.setAttribute(AttributeNames.Core.NAMESPACE, AttributeNames.Core.VALUE, groupDefinition.getDisplayName()); } else { headerLabelElement.setAttribute(AttributeNames.Core.NAMESPACE, AttributeNames.Core.VALUE, groupDefinition.getField()); headerLabelElement.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.LABEL_FOR, groupDefinition.getField()); headerLabelElement.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ALLOW_METADATA_ATTRIBUTES, Boolean.TRUE); } final Element headerValueElement = AutoGeneratorUtility .generateDetailsElement(groupDefinition.getField(), computeElementType(groupDefinition)); headerValueElement.setAttribute(AttributeNames.Core.NAMESPACE, AttributeNames.Core.NULL_VALUE, "-"); final Band headerElement = new Band(); headerElement.getStyle().setStyleProperty(BandStyleKeys.LAYOUT, BandStyleKeys.LAYOUT_INLINE); headerElement.getStyle().setStyleProperty(ElementStyleKeys.MIN_WIDTH, new Float(-100)); headerElement.getStyle().setStyleProperty(ElementStyleKeys.DYNAMIC_HEIGHT, Boolean.TRUE); headerElement.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ALLOW_METADATA_STYLING, Boolean.TRUE); headerElement.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.LABEL_FOR, groupDefinition.getField()); headerElement.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.CACHED_WIZARD_FORMAT_DATA, headerDefinition); headerElement.addElement(headerLabelElement); headerElement.addElement(headerValueElement); content.clear(); content.addElement(headerElement); } } protected void configureRelationalGroupFooter(final RelationalGroup group, final GroupDefinition groupDefinition, final int index) throws ReportProcessingException { final RootBandDefinition footerDefinition = groupDefinition.getFooter(); if (footerDefinition.isVisible() == false) { return; } if (groupDefinition.getAggregationFunction() == null && (groupDefinition.getGroupTotalsLabel() == null || groupDefinition.getGroupTotalsLabel().length() == 0)) { return; } final GroupFooter footer = group.getFooter(); final Boolean repeat = footerDefinition.getRepeat(); if (repeat != null) { footer.setRepeat(repeat.booleanValue()); } final Band content = AutoGeneratorUtility.findGeneratedContent(footer); if (content == null) { return; } final Class aggFunctionClass = groupDefinition.getAggregationFunction(); final Element footerValueElement = AutoGeneratorUtility.generateFooterElement(aggFunctionClass, computeElementType(groupDefinition), groupDefinition.getGroupName(), groupDefinition.getField()); final Element footerLabelElement = new Element(); footerLabelElement.setElementType(new LabelType()); if (groupDefinition.getGroupTotalsLabel() != null) { footerLabelElement.setAttribute(AttributeNames.Core.NAMESPACE, AttributeNames.Core.VALUE, groupDefinition.getGroupTotalsLabel()); } else { footerLabelElement.setAttribute(AttributeNames.Core.NAMESPACE, AttributeNames.Core.VALUE, groupDefinition.getField()); footerLabelElement.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.LABEL_FOR, groupDefinition.getField()); footerLabelElement.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ALLOW_METADATA_ATTRIBUTES, Boolean.TRUE); } final Band footerElement = new Band(); footerElement.getStyle().setStyleProperty(BandStyleKeys.LAYOUT, BandStyleKeys.LAYOUT_INLINE); footerElement.getStyle().setStyleProperty(ElementStyleKeys.MIN_WIDTH, new Float(-100)); footerElement.getStyle().setStyleProperty(ElementStyleKeys.DYNAMIC_HEIGHT, Boolean.TRUE); footerElement.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ALLOW_METADATA_STYLING, Boolean.TRUE); footerElement.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.LABEL_FOR, groupDefinition.getField()); footerElement.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.CACHED_WIZARD_FORMAT_DATA, footerDefinition); footerElement.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.CACHED_WIZARD_FIELD_DATA, groupDefinition); footerElement.addElement(footerLabelElement); footerElement.addElement(footerValueElement); content.clear(); content.addElement(footerElement); } private void configureCrosstabGroupFooter(final Group group, final GroupDefinition groupDefinition) throws ReportProcessingException { /* final RootBandDefinition footerDefinition = groupDefinition.getFooter(); if (footerDefinition.isVisible() == false) { return; } if (groupDefinition.getAggregationFunction() == null) { return; } final GroupFooter footer = group.getFooter(); final Boolean repeat = footerDefinition.getRepeat(); if (repeat != null) { footer.setRepeat(repeat.booleanValue()); } final Band content = AutoGeneratorUtility.findGeneratedContent(footer); if (content == null) { return; } final Class aggFunctionClass = groupDefinition.getAggregationFunction(); final Element footerValueElement = AutoGeneratorUtility.generateFooterElement (aggFunctionClass, computeElementType(groupDefinition), groupDefinition.getGroupName(), groupDefinition.getField()); footerValueElement.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.CACHED_WIZARD_FORMAT_DATA, footer); footerValueElement.setAttribute(AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.CACHED_WIZARD_FIELD_DATA, groupDefinition); content.clear(); content.addElement(footerValueElement); */ } protected ElementType computeElementType(final FieldDefinition fieldDefinition) { final String field = fieldDefinition.getField(); final DataAttributes attributes = flowController.getDataSchema().getAttributes(field); if (attributes == null) { logger.warn("Field '" + field + "' is declared in the wizard-specification, " + "but not present in the data. Assuming defaults."); return new TextFieldType(); } final Class fieldType = (Class) attributes.getMetaAttribute(MetaAttributeNames.Core.NAMESPACE, MetaAttributeNames.Core.TYPE, Class.class, attributeContext); if (fieldType == null) { return new TextFieldType(); } return AutoGeneratorUtility.createFieldType(fieldType); } private boolean isCrosstab() { final GroupDefinition[] groupDefinitions = wizardSpecification.getGroupDefinitions(); for (int i = 0; i < groupDefinitions.length; i++) { final GroupDefinition groupDefinition = groupDefinitions[i]; final GroupType groupType = groupDefinition.getGroupType(); if (GroupType.CT_COLUMN.equals(groupType) || GroupType.CT_ROW.equals(groupType)) { return true; } } final DataAttributes tableAttributes = flowController.getDataSchema().getTableAttributes(); final Object crosstabMode = tableAttributes.getMetaAttribute(MetaAttributeNames.Core.NAMESPACE, MetaAttributeNames.Core.CROSSTAB_MODE, String.class, attributeContext); if (MetaAttributeNames.Core.CROSSTAB_VALUE_NORMALIZED.equals(crosstabMode)) { // the data-source indicates a high probability that a crosstab is requested. return true; } return false; } private void setupWatermark() { final WatermarkDefinition watermarkDefinition = wizardSpecification.getWatermarkDefinition(); if (watermarkDefinition.isVisible() == false) { return; } if (watermarkDefinition.getSource() == null) { return; } final Watermark watermark = definition.getWatermark(); final Band content = AutoGeneratorUtility.findGeneratedContent(watermark); if (content == null) { // there is already some content, and we are not allowed to override it. return; } content.clear(); final Element watermarkImage = new Element(); watermarkImage.setElementType(new ContentType()); watermarkImage.setAttribute(AttributeNames.Core.NAMESPACE, AttributeNames.Core.VALUE, watermarkDefinition.getSource()); final ElementStyleSheet watermarkStyle = watermarkImage.getStyle(); watermarkStyle.setStyleProperty(ElementStyleKeys.POS_X, convertLength(watermarkDefinition.getX())); watermarkStyle.setStyleProperty(ElementStyleKeys.POS_Y, convertLength(watermarkDefinition.getY())); watermarkStyle.setStyleProperty(ElementStyleKeys.MIN_WIDTH, convertLength(watermarkDefinition.getWidth())); watermarkStyle.setStyleProperty(ElementStyleKeys.MIN_HEIGHT, convertLength(watermarkDefinition.getHeight())); watermarkStyle.setStyleProperty(ElementStyleKeys.KEEP_ASPECT_RATIO, watermarkDefinition.getKeepAspectRatio()); watermarkStyle.setStyleProperty(ElementStyleKeys.SCALE, watermarkDefinition.getScale()); content.addElement(watermarkImage); } private Float convertLength(final Length length) { if (length == null) { return null; } return length.getNormalizedValue(); } }