net.sf.jasperreports.engine.fill.JRFillBand.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.jasperreports.engine.fill.JRFillBand.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.engine.fill;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

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

import net.sf.jasperreports.engine.CommonReturnValue;
import net.sf.jasperreports.engine.ExpressionReturnValue;
import net.sf.jasperreports.engine.JRBand;
import net.sf.jasperreports.engine.JRElement;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExpression;
import net.sf.jasperreports.engine.JRGroup;
import net.sf.jasperreports.engine.JROrigin;
import net.sf.jasperreports.engine.JRPropertiesHolder;
import net.sf.jasperreports.engine.JRPropertiesMap;
import net.sf.jasperreports.engine.JRRuntimeException;
import net.sf.jasperreports.engine.type.BandTypeEnum;
import net.sf.jasperreports.engine.type.PrintOrderEnum;
import net.sf.jasperreports.engine.type.SplitTypeEnum;

/**
 * @author Teodor Danciu (teodord@users.sourceforge.net)
 */
public class JRFillBand extends JRFillElementContainer implements JRBand, JROriginProvider {

    private static final Log log = LogFactory.getLog(JRFillBand.class);

    /**
     *
     */
    private JRBand parent;

    private boolean isPrintWhenTrue = true;

    /**
     *
     */
    private boolean isNewPageColumn;
    private boolean isFirstWholeOnPageColumn;
    private Map<JRGroup, Boolean> isNewGroupMap = new HashMap<JRGroup, Boolean>();

    private Set<JREvaluationTime> nowEvaluationTimes;

    // used by subreports to save values of variables used as return receptacles
    // so that the values can be restored when the bands gets rewound
    private Map<String, Object> savedVariableValues = new HashMap<String, Object>();

    protected JROrigin origin;

    private SplitTypeEnum splitType;
    private Integer breakHeight;

    private FillReturnValues returnValues;
    private FillReturnValues.SourceContext returnValuesContext = new FillReturnValues.SourceContext() {
        @Override
        public Object getValue(CommonReturnValue returnValue) {
            ExpressionReturnValue expressionReturnValue = (ExpressionReturnValue) returnValue;
            Object value = null;
            try {
                value = filler.evaluateExpression(expressionReturnValue.getExpression(),
                        JRExpression.EVALUATION_DEFAULT);
            } catch (JRException e) {
                throw new JRRuntimeException(e);
            }
            return value;
        }

        @Override
        public void check(CommonReturnValue returnValue) throws JRException {
            //FIXMERETURN check something
        }

        @Override
        public JRFillVariable getToVariable(String name) {
            return filler.getVariable(name);
        }
    };

    private Set<FillReturnValues> returnValuesSet;

    /**
     *
     */
    protected JRFillBand(JRBaseFiller filler, JRBand band, JRFillObjectFactory factory) {
        super(filler, band, factory);

        parent = band;

        // we need to do this before setBand()
        returnValuesSet = new LinkedHashSet<FillReturnValues>();

        if (deepElements.length > 0) {
            for (int i = 0; i < deepElements.length; i++) {
                deepElements[i].setBand(this);
            }
        }

        List<ExpressionReturnValue> expRetValues = getReturnValues();
        returnValues = new FillReturnValues(
                expRetValues == null ? null
                        : (ExpressionReturnValue[]) expRetValues
                                .toArray(new ExpressionReturnValue[expRetValues.size()]), //FIXMERETURN make special class for constructor differentiation
                factory, filler);
        registerReturnValues(returnValues);

        initElements();

        initConditionalStyles();

        nowEvaluationTimes = new HashSet<JREvaluationTime>();
    }

    @Override
    public JROrigin getOrigin() {
        return origin;
    }

    /**
     *
     */
    protected void setOrigin(JROrigin origin) {
        if (log.isDebugEnabled()) {
            log.debug("Origin " + origin + " for band " + getId());
        }

        this.origin = origin;
        this.filler.getJasperPrint().addOrigin(origin);
    }

    /**
     *
     */
    protected void setNewPageColumn(boolean isNew) {
        this.isNewPageColumn = isNew;
    }

    /**
     *
     */
    protected boolean isNewPageColumn() {
        return isNewPageColumn;
    }

    /**
     * Decides whether this band is the for whole band on the page/column.
     *
     * @return whether this band is the for whole band on the page/column
     */
    protected boolean isFirstWholeOnPageColumn() {
        return isFirstWholeOnPageColumn;
    }

    /**
     *
     */
    protected void setNewGroup(JRGroup group, boolean isNew) {
        isNewGroupMap.put(group, isNew);
    }

    /**
     *
     */
    protected boolean isNewGroup(JRGroup group) {
        Boolean value = isNewGroupMap.get(group);

        if (value == null) {
            value = Boolean.FALSE;
        }

        return value;
    }

    @Override
    public int getHeight() {
        return (parent == null ? 0 : parent.getHeight());
    }

    /**
     *
     */
    public int getBreakHeight() {
        // needs to be lazy calculated because it depends on splitType, which is itself lazy loaded
        if (breakHeight == null) {
            breakHeight = getHeight();
            if (SplitTypeEnum.IMMEDIATE == getSplitTypeValue() && elements != null && elements.length > 0) {
                for (int i = 0; i < elements.length; i++) {
                    JRElement element = elements[i];
                    int bottom = element.getY() + element.getHeight();
                    breakHeight = bottom < breakHeight ? bottom : breakHeight;
                }
            }
        }

        return breakHeight;
    }

    @Override
    public SplitTypeEnum getSplitTypeValue() {
        // needs to be lazy loaded because in JRFillBand constructor above, the filler.getMainDataset() is not yet set, 
        // when the band is a group band
        if (splitType == null) {
            splitType = (parent == null ? null : parent.getSplitTypeValue());
            if (splitType == null) {
                splitType = SplitTypeEnum.getByName(filler.getPropertiesUtil().getProperty(filler.getMainDataset(),
                        JRBand.PROPERTY_SPLIT_TYPE));
            }
        }

        return splitType;
    }

    @Override
    public void setSplitType(SplitTypeEnum splitType) {
        throw new UnsupportedOperationException();
    }

    @Override
    public JRExpression getPrintWhenExpression() {
        return (parent == null ? null : parent.getPrintWhenExpression());
    }

    /**
     *
     */
    protected boolean isSplitPrevented() {
        return SplitTypeEnum.PREVENT == getSplitTypeValue();
    }

    /**
     *
     */
    protected boolean isPrintWhenExpressionNull() {
        return (getPrintWhenExpression() == null);
    }

    /**
     *
     */
    protected boolean isPrintWhenTrue() {
        return isPrintWhenTrue;
    }

    /**
     *
     */
    protected void setPrintWhenTrue(boolean isPrintWhenTrue) {
        this.isPrintWhenTrue = isPrintWhenTrue;
    }

    /**
     *
     */
    protected boolean isToPrint() {
        return this != filler.missingFillBand
                && (isPrintWhenExpressionNull() || (!isPrintWhenExpressionNull() && isPrintWhenTrue()));
    }

    /**
     *
     */
    protected void evaluatePrintWhenExpression(byte evaluation) throws JRException {
        boolean isPrintTrue = false;

        JRExpression expression = getPrintWhenExpression();
        if (expression != null) {
            Boolean printWhenExpressionValue = (Boolean) filler.evaluateExpression(expression, evaluation);
            if (printWhenExpressionValue == null) {
                isPrintTrue = false;
            } else {
                isPrintTrue = printWhenExpressionValue;
            }
        }

        setPrintWhenTrue(isPrintTrue);
    }

    /**
     *
     */
    protected JRPrintBand refill(byte evaluation, int availableHeight) throws JRException {
        rewind();
        restoreSavedVariables();

        JRPrintBand printBand = null;

        @SuppressWarnings("deprecation")
        boolean isLegacyBandEvaluationEnabled = filler.getFillContext().isLegacyBandEvaluationEnabled();
        if (isLegacyBandEvaluationEnabled) {
            printBand = fill(availableHeight);
        } else {
            evaluatePrintWhenExpression(evaluation);

            if (isToPrint()) {
                evaluate(evaluation);

                printBand = fill(availableHeight);
            } else {
                printBand = new JRPrintBand();
            }
        }

        return printBand;
    }

    /**
     *
     */
    protected JRPrintBand fill() throws JRException {
        return fill(getHeight(), false);
    }

    /**
     *
     */
    protected JRPrintBand fill(int availableHeight) throws JRException {
        return fill(availableHeight, true);
    }

    /**
     *
     */
    protected JRPrintBand fill(int availableHeight, boolean isOverflowAllowed) throws JRException {
        filler.checkInterrupted();

        filler.setBandOverFlowAllowed(isOverflowAllowed);

        initFill();

        if (isNewPageColumn && !isOverflow) {
            isFirstWholeOnPageColumn = true;
        }

        resetElements();

        prepareElements(availableHeight, isOverflowAllowed);

        if (isLegacyElementStretchEnabled()) {
            stretchElements();

            moveBandBottomElements();

            removeBlankElements();
        }

        isFirstWholeOnPageColumn = isNewPageColumn && isOverflow;
        isNewPageColumn = false;
        isNewGroupMap = new HashMap<JRGroup, Boolean>();

        JRPrintBand printBand = new JRPrintBand();
        fillElements(printBand);

        if (!willOverflow()) {
            returnValues.copyValues(returnValuesContext);
        }

        return printBand;
    }

    protected boolean willOverflowWithElements() {
        return willOverflowWithElements;
    }

    @Override
    protected int getContainerHeight() {
        return getHeight();
    }

    @Override
    protected int getActualContainerHeight() {
        return getContainerHeight();
    }

    protected boolean isVariableUsedInReturns(String variableName) {
        boolean used = false;
        for (FillReturnValues returnValues : returnValuesSet) {
            if (returnValues.usesForReturnValue(variableName)) {
                used = true;
                break;
            }
        }
        return used;
    }

    protected void addNowEvaluationTime(JREvaluationTime evaluationTime) {
        nowEvaluationTimes.add(evaluationTime);
    }

    protected void addNowEvaluationTimes(JREvaluationTime[] evaluationTimes) {
        for (int i = 0; i < evaluationTimes.length; i++) {
            nowEvaluationTimes.add(evaluationTimes[i]);
        }
    }

    protected boolean isNowEvaluationTime(JREvaluationTime evaluationTime) {
        return nowEvaluationTimes.contains(evaluationTime);
    }

    protected int getId() {
        //FIXME this is not necessarily unique
        return System.identityHashCode(this);
    }

    @Override
    protected void evaluate(byte evaluation) throws JRException {
        resetSavedVariables();
        evaluateConditionalStyles(evaluation);
        super.evaluate(evaluation);
    }

    protected void resetSavedVariables() {
        savedVariableValues.clear();
    }

    protected void saveVariable(String variableName) {
        if (!savedVariableValues.containsKey(variableName)) {
            Object value = filler.getVariableValue(variableName);
            savedVariableValues.put(variableName, value);
        }
    }

    protected void restoreSavedVariables() {
        for (Iterator<Map.Entry<String, Object>> it = savedVariableValues.entrySet().iterator(); it.hasNext();) {
            Map.Entry<String, Object> entry = it.next();
            String variableName = entry.getKey();
            Object value = entry.getValue();
            JRFillVariable variable = filler.getVariable(variableName);
            variable.setOldValue(value);
            variable.setValue(value);
            variable.setIncrementedValue(value);
        }
    }

    protected boolean isEmpty() {
        return this == filler.missingFillBand || (getHeight() == 0
                && (getElements() == null || getElements().length == 0) && getPrintWhenExpression() == null);
    }

    protected boolean isColumnBand() {
        BandTypeEnum bandType = origin.getBandTypeValue();

        return bandType == BandTypeEnum.GROUP_HEADER || bandType == BandTypeEnum.GROUP_FOOTER
                || bandType == BandTypeEnum.DETAIL;
    }

    protected boolean isPageBreakInhibited() {
        boolean isPageBreakInhibited = filler.isFirstPageBand && !atLeastOneElementIsToPrint;

        if (isPageBreakInhibited && filler.isSubreport()) {
            isPageBreakInhibited = filler.bandReportParent.isPageBreakInhibited();
        }

        return isPageBreakInhibited;
    }

    protected boolean isSplitTypePreventInhibited() {
        return isSplitTypePreventInhibited(true);
    }

    @Override
    public boolean isSplitTypePreventInhibited(boolean isTopLevelCall) {
        boolean isSplitTypePreventInhibited = false;

        if (((filler.printOrder == PrintOrderEnum.VERTICAL && filler.isFirstColumnBand)
                || (filler.printOrder == PrintOrderEnum.HORIZONTAL && filler.isFirstPageBand))
                && (isTopLevelCall || !atLeastOneElementIsToPrint)) {
            if (isColumnBand() && filler.columnIndex < filler.columnCount - 1) {
                isSplitTypePreventInhibited = true;
            } else {
                if (filler.isSubreport()) {
                    isSplitTypePreventInhibited = filler.bandReportParent.isSplitTypePreventInhibited(false);
                } else {
                    isSplitTypePreventInhibited = true;
                }
            }
        }

        return isSplitTypePreventInhibited;
    }

    @Override
    public boolean hasProperties() {
        return parent.hasProperties();
    }

    // not doing anything with the properties at fill time
    @Override
    public JRPropertiesMap getPropertiesMap() {
        return parent.getPropertiesMap();
    }

    @Override
    public JRPropertiesHolder getParentProperties() {
        return null;
    }

    @Override
    public List<ExpressionReturnValue> getReturnValues() {
        return parent == null ? null : parent.getReturnValues();
    }

    public void registerReturnValues(FillReturnValues fillReturnValues) {
        returnValuesSet.add(fillReturnValues);
    }

}