/* * 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) 2006 - 2013 Pentaho Corporation.. All rights reserved. */ package org.pentaho.reporting.engine.classic.core.modules.output.fast.template; import org.pentaho.reporting.engine.classic.core.ReportElement; import org.pentaho.reporting.engine.classic.core.Section; import org.pentaho.reporting.engine.classic.core.SubReport; import org.pentaho.reporting.engine.classic.core.filter.DataSource; import org.pentaho.reporting.engine.classic.core.filter.RawDataSource; import org.pentaho.reporting.engine.classic.core.function.ExpressionRuntime; import org.pentaho.reporting.engine.classic.core.layout.build.RichTextStyleResolver; import org.pentaho.reporting.engine.classic.core.layout.output.ContentProcessingException; import org.pentaho.reporting.engine.classic.core.style.BandStyleKeys; import org.pentaho.reporting.engine.classic.core.style.StyleSheet; public class FastTextExtractor { private final StringBuilder textBuffer; private ExpressionRuntime runtime; private Object rawResult; private int inlineLayout; public FastTextExtractor() { this.textBuffer = new StringBuilder(); } public Object compute( final ReportElement content, final ExpressionRuntime runtime ) throws ContentProcessingException { this.runtime = runtime; this.rawResult = null; this.textBuffer.delete( 0, this.textBuffer.length() ); this.inlineLayout = 0; try { if ( content instanceof Section ) { traverseSection( (Section) content ); } else { inspectElement( content, true ); } // A simple result. So there's no need to create a rich-text string. if ( rawResult != null ) { return rawResult; } return textBuffer.toString(); } finally { this.runtime = null; } } public void setRuntime( final ExpressionRuntime runtime ) { this.runtime = runtime; } protected void clearText() { textBuffer.delete( 0, textBuffer.length() ); } public Object getRawResult() { return rawResult; } public String getText() { return textBuffer.toString(); } protected void traverseSection( final Section section ) throws ContentProcessingException { boolean inlineSection; if ( inlineLayout == 0 ) { StyleSheet styleSheet = section.getComputedStyle(); if ( BandStyleKeys.LAYOUT_INLINE.equals( styleSheet.getStyleProperty( BandStyleKeys.LAYOUT ) ) ) { inlineLayout += 1; inlineSection = true; } else { inlineSection = false; } } else { inlineLayout += 1; inlineSection = true; } if ( inspectStartSection( section, inlineSection ) ) { final int count = section.getElementCount(); for ( int i = 0; i < count; i++ ) { final ReportElement element = section.getElement( i ); if ( element instanceof SubReport ) { inspectStartSection( element, inlineSection ); inspectElement( element, inlineSection ); inspectEndSection( element, inlineSection ); } else if ( element instanceof Section ) { traverseSection( (Section) element ); } else { inspectStartSection( element, inlineSection ); inspectElement( element, inlineSection ); inspectEndSection( element, inlineSection ); } } } inspectEndSection( section, inlineSection ); if ( inlineLayout > 0 ) { inlineLayout -= 1; } } protected void inspectEndSection( final ReportElement section, final boolean inlineSection ) { } protected boolean inspectStartSection( final ReportElement section, final boolean inlineSection ) { return false; } protected void inspectElement( final ReportElement element, final boolean inlineSection ) throws ContentProcessingException { if ( element instanceof Section ) { // subreports and so on .. return; } Object value = AbstractFormattedDataBuilder.filterRichText( element, element.getElementType().getValue( runtime, element ) ); if ( value == null ) { return; } if ( value instanceof Section ) { Section section = (Section) value; RichTextStyleResolver.resolveStyle( section ); traverseSection( section ); return; } handleValueContent( element, value, inlineSection ); } protected void handleValueContent( final ReportElement element, final Object value, final boolean inlineSection ) throws ContentProcessingException { if ( value instanceof String ) { textBuffer.append( value ); final DataSource dataSource = element.getElementType(); if ( dataSource instanceof RawDataSource ) { final RawDataSource rds = (RawDataSource) dataSource; rawResult = rds.getRawValue( runtime, element ); } else { rawResult = null; } return; } rawResult = value; } protected StringBuilder getTextBuffer() { return textBuffer; } protected void setRawResult( final Object rawResult ) { this.rawResult = rawResult; } protected int getTextLength() { return textBuffer.length(); } }