/*! * 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-2013 Pentaho Corporation.. All rights reserved. */ package org.pentaho.reporting.engine.classic.core.layout.output.crosstab; import org.pentaho.reporting.engine.classic.core.AttributeNames; import org.pentaho.reporting.engine.classic.core.CrosstabColumnGroup; import org.pentaho.reporting.engine.classic.core.CrosstabColumnGroupBody; import org.pentaho.reporting.engine.classic.core.CrosstabDetailMode; 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.GroupBody; import org.pentaho.reporting.engine.classic.core.InvalidReportStateException; import org.pentaho.reporting.engine.classic.core.states.crosstab.CrosstabSpecification; import org.pentaho.reporting.engine.classic.core.style.BandStyleKeys; import org.pentaho.reporting.engine.classic.core.style.TableLayout; import org.pentaho.reporting.engine.classic.core.util.InstanceID; import java.util.ArrayList; public class RenderedCrosstabLayout implements Cloneable { private boolean crosstabTableOpen; private boolean crosstabRowOpen; private boolean processingCrosstabHeader; private boolean crosstabHeaderOpen; private boolean detailsRendered; private boolean generateMeasureHeaders; private boolean generateColumnTitleHeaders; private boolean summaryRowPrintable; private int summaryRowGroupIndex; private String summaryRowField; private CrosstabSpecification crosstabSpecification; private int columnGroups; private int rowGroups; private int otherGroups; private String[] sortedKeys; private int crosstabGroupIndex; private InstanceID[] columnHeaderSubflows; private InstanceID[] rowHeaders; private InstanceID[] columnHeaders; private InstanceID[] columnTitleHeaders; private InstanceID crosstabId; private int firstRowGroupIndex; private int firstColGroupIndex; private CrosstabDetailMode detailMode; private TableLayout tableLayout; public RenderedCrosstabLayout() { firstRowGroupIndex = -1; firstColGroupIndex = -1; } public int getFirstRowGroupIndex() { return firstRowGroupIndex; } public void setFirstRowGroupIndex( final int firstRowGroupIndex ) { this.firstRowGroupIndex = firstRowGroupIndex; } public boolean isGenerateMeasureHeaders() { return generateMeasureHeaders; } public boolean isGenerateColumnTitleHeaders() { return generateColumnTitleHeaders; } public boolean isDetailsRendered() { return detailsRendered; } public void setDetailsRendered( final boolean detailsRendered ) { this.detailsRendered = detailsRendered; } public boolean isCrosstabRowOpen() { return crosstabRowOpen; } public void setCrosstabRowOpen( final boolean crosstabRowOpen ) { this.crosstabRowOpen = crosstabRowOpen; } public boolean isCrosstabTableOpen() { return crosstabTableOpen; } public boolean isCrosstabHeaderOpen() { return crosstabHeaderOpen; } public void setCrosstabHeaderOpen( final boolean crosstabHeaderOpen ) { this.crosstabHeaderOpen = crosstabHeaderOpen; } public void setCrosstabTableOpen( final boolean crosstabTableOpen ) { this.crosstabTableOpen = crosstabTableOpen; } public boolean isProcessingCrosstabHeader() { return processingCrosstabHeader; } public void setProcessingCrosstabHeader( final boolean processingCrosstabHeader ) { this.processingCrosstabHeader = processingCrosstabHeader; } public CrosstabSpecification getCrosstabSpecification() { return crosstabSpecification; } public int getColumnGroups() { return columnGroups; } public int getRowGroups() { return rowGroups; } public int getOtherGroups() { return otherGroups; } public String[] getSortedKeys() { return sortedKeys; } public int getCrosstabGroupIndex() { return crosstabGroupIndex; } public Object clone() { try { final RenderedCrosstabLayout layout = (RenderedCrosstabLayout) super.clone(); if ( columnHeaderSubflows != null ) { layout.columnHeaderSubflows = columnHeaderSubflows.clone(); } if ( rowHeaders != null ) { layout.rowHeaders = rowHeaders.clone(); } if ( columnHeaders != null ) { layout.columnHeaders = columnHeaders.clone(); } if ( columnTitleHeaders != null ) { layout.columnTitleHeaders = columnTitleHeaders.clone(); } return layout; } catch ( CloneNotSupportedException cne ) { throw new IllegalStateException( cne ); } } public RenderedCrosstabLayout derive() { return (RenderedCrosstabLayout) clone(); } public void initialize( final CrosstabSpecification crosstabSpecification, final CrosstabGroup group, final int crosstabGroupIndex ) { this.crosstabSpecification = crosstabSpecification; this.crosstabGroupIndex = crosstabGroupIndex; computeGroupCounts( group ); CrosstabDetailMode detailMode = group.getDetailsMode(); if ( detailMode == null ) { detailMode = CrosstabDetailMode.last; } this.detailMode = detailMode; this.generateMeasureHeaders = !( Boolean.FALSE.equals( group.getAttribute( AttributeNames.Crosstab.NAMESPACE, AttributeNames.Crosstab.PRINT_DETAIL_HEADER ) ) ); this.generateColumnTitleHeaders = !( Boolean.FALSE.equals( group.getAttribute( AttributeNames.Crosstab.NAMESPACE, AttributeNames.Crosstab.PRINT_COLUMN_TITLE_HEADER ) ) ); this.tableLayout = (TableLayout) group.getStyle().getStyleProperty( BandStyleKeys.TABLE_LAYOUT, TableLayout.fixed ); } private void computeGroupCounts( final CrosstabGroup crosstabGroup ) { final ArrayList<String> list = new ArrayList<String>(); GroupBody body = crosstabGroup.getBody(); while ( body != null ) { if ( body instanceof CrosstabOtherGroupBody ) { otherGroups += 1; final CrosstabOtherGroupBody cogb = (CrosstabOtherGroupBody) body; final CrosstabOtherGroup otherGroup = cogb.getGroup(); list.add( otherGroup.getField() ); body = otherGroup.getBody(); continue; } if ( body instanceof CrosstabRowGroupBody ) { rowGroups += 1; final CrosstabRowGroupBody cogb = (CrosstabRowGroupBody) body; final CrosstabRowGroup otherGroup = cogb.getGroup(); list.add( otherGroup.getField() ); body = otherGroup.getBody(); continue; } if ( body instanceof CrosstabColumnGroupBody ) { columnGroups += 1; final CrosstabColumnGroupBody cogb = (CrosstabColumnGroupBody) body; final CrosstabColumnGroup otherGroup = cogb.getGroup(); list.add( otherGroup.getField() ); body = otherGroup.getBody(); continue; } break; } rowHeaders = new InstanceID[rowGroups]; columnHeaders = new InstanceID[columnGroups]; columnTitleHeaders = new InstanceID[columnGroups]; sortedKeys = list.toArray( new String[list.size()] ); } public void setColumnHeaderRowIds( final InstanceID[] columnHeaders ) { if ( columnHeaders == null ) { throw new NullPointerException(); } if ( columnHeaders.length < 1 ) { throw new IllegalStateException(); } this.columnHeaderSubflows = columnHeaders; } public InstanceID[] getColumnHeaderSubFlows() { return columnHeaderSubflows; } public InstanceID getRowTitleHeaderId() { if ( columnHeaderSubflows == null ) { throw new IllegalStateException(); } return columnHeaderSubflows[columnHeaderSubflows.length - 1]; } public InstanceID getColumnTitleHeaderSubflowId( final int gidx ) { if ( generateColumnTitleHeaders == false ) { throw new InvalidReportStateException(); } final int offset = gidx - crosstabGroupIndex - otherGroups - rowGroups - 1; return columnHeaderSubflows[offset * 2]; } public InstanceID getColumnHeaderSubflowId( final int gidx ) { final int offset = gidx - crosstabGroupIndex - otherGroups - rowGroups - 1; if ( generateColumnTitleHeaders ) { return columnHeaderSubflows[offset * 2 + 1]; } else { return columnHeaderSubflows[offset]; } } public InstanceID getMeasureHeaderSubflowId() { if ( generateMeasureHeaders == false ) { throw new InvalidReportStateException(); } return columnHeaderSubflows[columnHeaderSubflows.length - 1]; } public void setRowHeader( final int index, final InstanceID instanceId ) { rowHeaders[index] = instanceId; } public InstanceID getRowHeader( final int index ) { return rowHeaders[index]; } public void setColumnHeaderCellId( final int index, final InstanceID instanceId ) { columnHeaders[index] = instanceId; } public InstanceID getColumnHeaderCellId( final int index ) { return columnHeaders[index]; } public void setColumnTitleHeaderCellId( final int index, final InstanceID instanceId ) { columnTitleHeaders[index] = instanceId; } public InstanceID getColumnTitleHeaderCellId( final int index ) { return columnTitleHeaders[index]; } public int getFirstColGroupIndex() { return firstColGroupIndex; } public void setFirstColGroupIndex( final int firstColGroupIndex ) { this.firstColGroupIndex = firstColGroupIndex; } public CrosstabDetailMode getDetailMode() { return detailMode; } public void startSummaryRowProcessing( final boolean summaryRowPrintable, final int summaryRowGroupIndex, final String summaryRowField ) { this.summaryRowPrintable = summaryRowPrintable; this.summaryRowGroupIndex = summaryRowGroupIndex; this.summaryRowField = summaryRowField; } public void endSummaryRowProcessing() { this.summaryRowPrintable = false; this.summaryRowGroupIndex = -1; this.summaryRowField = null; } public String getSummaryRowField() { return summaryRowField; } public int getSummaryRowGroupIndex() { return summaryRowGroupIndex; } public boolean isSummaryRowPrintable() { return summaryRowPrintable; } public TableLayout getTableLayout() { return tableLayout; } public InstanceID getCrosstabId() { return crosstabId; } public void setCrosstabId( final InstanceID crosstabId ) { this.crosstabId = crosstabId; } }