/*
* 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) 2001 - 2013 Object Refinery Ltd, Pentaho Corporation and Contributors.. All rights reserved.
*/
package org.pentaho.reporting.engine.classic.core.states.process;
import org.pentaho.reporting.engine.classic.core.ReportElement;
import org.pentaho.reporting.engine.classic.core.ReportProcessingException;
import org.pentaho.reporting.engine.classic.core.RootLevelBand;
import org.pentaho.reporting.engine.classic.core.Section;
import org.pentaho.reporting.engine.classic.core.SubReport;
import org.pentaho.reporting.engine.classic.core.layout.InlineSubreportMarker;
import org.pentaho.reporting.engine.classic.core.states.ReportStateKey;
import org.pentaho.reporting.engine.classic.core.util.InstanceID;
import java.util.LinkedHashMap;
import java.util.Map;
public class InlineSubreportProcessor {
private static InstanceID DUMMY_SUBREPORT_MARKER = new InstanceID();
private static InlineSubreportMarker[] EMPTY_MARKERS = new InlineSubreportMarker[0];
private InlineSubreportProcessor() {
}
private static InlineSubreportMarker[] collectMarkers( final ProcessState state, final RootLevelBand rootLevelBand )
throws ReportProcessingException {
final Map<InstanceID, InlineSubreportMarker> markers = collectSubReportMarkers( state, rootLevelBand );
if ( markers == null || markers.size() == 0 ) {
return EMPTY_MARKERS;
}
return markers.values().toArray( new InlineSubreportMarker[markers.size()] );
}
public static ProcessState processInline( ProcessState state, final RootLevelBand rootLevelBand )
throws ReportProcessingException {
final InlineSubreportMarker[] markers = collectMarkers( state, rootLevelBand );
if ( markers.length == 0 ) {
return state;
}
state.getLayoutProcess().getOutputFunction().clearInlineSubreports( SubReportProcessType.INLINE );
final int index = findNextIndex( markers, SubReportProcessType.INLINE, 0 );
if ( index == -1 ) {
return state;
}
try {
// this recreates the process key.
state = state.clone();
} catch ( CloneNotSupportedException e ) {
throw new IllegalStateException();
}
// we need to execute the state until it returns ..
final ReportStateKey processKey = state.getProcessKey();
ProcessState process = new ProcessState();
process.initializeForSubreport( markers, index, state );
while ( processKey.equals( process.getProcessKey() ) == false ) {
process = process.advance();
if ( processKey.equals( process.getProcessKey() ) ) {
throw new IllegalStateException( "You cannot switch contexts when not being commited!" );
}
process = process.commit();
}
return process;
}
public static boolean hasSubReports( final ProcessState state, final RootLevelBand rootLevelBand )
throws ReportProcessingException {
final Map<InstanceID, InlineSubreportMarker> markers = collectSubReportMarkers( state, rootLevelBand );
if ( markers == null || markers.size() == 0 ) {
return false;
}
return true;
}
public static ProcessState processBandedSubReports( final ProcessState state, final RootLevelBand rootLevelBand )
throws ReportProcessingException {
final InlineSubreportMarker[] markers = collectMarkers( state, rootLevelBand );
if ( markers.length == 0 ) {
return state;
}
state.getLayoutProcess().getOutputFunction().clearInlineSubreports( SubReportProcessType.BANDED );
final int index = findNextIndex( markers, SubReportProcessType.BANDED, 0 );
if ( index == -1 ) {
return state;
}
final ProcessState pstate = new ProcessState();
pstate.initializeForSubreport( markers, index, state );
return pstate;
}
private static Map<InstanceID, InlineSubreportMarker> collectSubReportMarkers( final ProcessState state,
final RootLevelBand rootLevelBand ) throws ReportProcessingException {
final Map<InstanceID, InlineSubreportMarker> list = collectSubReportMarkers( (Section) rootLevelBand, null );
if ( list == null ) {
final InlineSubreportMarker[] subreports = state.getLayoutProcess().getOutputFunction().getInlineSubreports();
if ( subreports.length == 0 ) {
return null;
}
final Map<InstanceID, InlineSubreportMarker> map = new LinkedHashMap<InstanceID, InlineSubreportMarker>();
for ( int i = 0; i < subreports.length; i++ ) {
final InlineSubreportMarker subreport = subreports[i];
map.put( subreport.getSubreport().getObjectID(), subreport );
}
return map;
}
final InlineSubreportMarker[] markers = state.getLayoutProcess().getOutputFunction().getInlineSubreports();
for ( int i = 0; i < markers.length; i++ ) {
final InlineSubreportMarker marker = markers[i];
list.put( marker.getSubreport().getObjectID(), marker );
}
return list;
}
private static Map collectBandedSubReportMarkers( final RootLevelBand rootLevelBand,
Map<InstanceID, InlineSubreportMarker> list ) throws ReportProcessingException {
final int count = rootLevelBand.getSubReportCount();
for ( int i = 0; i < count; i++ ) {
final SubReport element = rootLevelBand.getSubReport( i );
if ( list == null ) {
list = new LinkedHashMap<InstanceID, InlineSubreportMarker>();
}
list.put( element.getObjectID(), new InlineSubreportMarker( element, null, SubReportProcessType.BANDED ) );
}
return list;
}
private static Map<InstanceID, InlineSubreportMarker> collectSubReportMarkers( final Section rootLevelBand,
Map<InstanceID, InlineSubreportMarker> list ) throws ReportProcessingException {
if ( rootLevelBand instanceof RootLevelBand ) {
list = collectBandedSubReportMarkers( (RootLevelBand) rootLevelBand, list );
}
final int count = rootLevelBand.getElementCount();
for ( int i = 0; i < count; i++ ) {
final ReportElement element = rootLevelBand.getElement( i );
if ( element instanceof SubReport ) {
if ( list == null ) {
list = new LinkedHashMap<InstanceID, InlineSubreportMarker>();
}
list.put( element.getObjectID(), new InlineSubreportMarker( (SubReport) element, DUMMY_SUBREPORT_MARKER,
SubReportProcessType.INLINE ) );
} else if ( element instanceof Section ) {
list = collectSubReportMarkers( (Section) element, list );
}
}
return list;
}
public static int findNextIndex( final InlineSubreportMarker[] markers, final SubReportProcessType type,
final int startIndex ) {
for ( int i = startIndex; i < markers.length; i++ ) {
final InlineSubreportMarker marker = markers[i];
if ( marker.getProcessType() == type ) {
return i;
}
}
return -1;
}
}