/*
* 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();
}
}