/*!
* 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.testsupport;
import org.pentaho.reporting.engine.classic.core.AttributeNames;
import org.pentaho.reporting.engine.classic.core.Element;
import org.pentaho.reporting.engine.classic.core.GroupDataBody;
import org.pentaho.reporting.engine.classic.core.GroupFooter;
import org.pentaho.reporting.engine.classic.core.GroupHeader;
import org.pentaho.reporting.engine.classic.core.ItemBand;
import org.pentaho.reporting.engine.classic.core.MasterReport;
import org.pentaho.reporting.engine.classic.core.RelationalGroup;
import org.pentaho.reporting.engine.classic.core.SubGroupBody;
import org.pentaho.reporting.engine.classic.core.designtime.DesignTimeDataSchemaModel;
import org.pentaho.reporting.engine.classic.core.filter.types.LabelType;
import org.pentaho.reporting.engine.classic.core.filter.types.NumberFieldType;
import org.pentaho.reporting.engine.classic.core.filter.types.TextFieldType;
import org.pentaho.reporting.engine.classic.core.function.AbstractExpression;
import org.pentaho.reporting.engine.classic.core.metadata.ElementType;
import org.pentaho.reporting.engine.classic.core.style.ElementStyleKeys;
import org.pentaho.reporting.engine.classic.core.wizard.AutoGeneratorUtility;
import org.pentaho.reporting.engine.classic.core.wizard.DataAttributeContext;
import org.pentaho.reporting.engine.classic.core.wizard.DataAttributes;
import org.pentaho.reporting.libraries.base.util.ArgumentNullException;
import org.pentaho.reporting.libraries.base.util.StringUtils;
import java.awt.*;
import java.util.ArrayList;
import java.util.Locale;
public class RelationalReportBuilder {
public static class GroupDefinition {
private String groupField;
private boolean header;
private boolean headerAggregation;
private boolean footerAggregation;
public GroupDefinition( final String groupField, final boolean header, final boolean headerAggregation,
final boolean footerAggregation ) {
this.groupField = groupField;
this.header = header;
this.headerAggregation = headerAggregation;
this.footerAggregation = footerAggregation;
}
public String getGroupField() {
return groupField;
}
public boolean isHeader() {
return header;
}
public boolean isHeaderAggregation() {
return headerAggregation;
}
public boolean isFooterAggregation() {
return footerAggregation;
}
}
public static class RelationalDetail {
private String field;
private Class aggregation;
private Color background;
public RelationalDetail( final String field, final Class aggregation ) {
this( field, aggregation, null );
}
public RelationalDetail( final String field, final Class aggregation, final Color background ) {
this.field = field;
this.aggregation = aggregation;
this.background = background;
}
public String getField() {
return field;
}
public void setField( final String field ) {
this.field = field;
}
public Class getAggregation() {
return aggregation;
}
public void setAggregation( final Class aggregation ) {
this.aggregation = aggregation;
}
public Color getBackground() {
return background;
}
public void setBackground( final Color background ) {
this.background = background;
}
}
private ArrayList<GroupDefinition> groups;
private ArrayList<RelationalDetail> details;
private DesignTimeDataSchemaModel dataSchemaModel;
private String groupNamePrefix;
public RelationalReportBuilder( final DesignTimeDataSchemaModel dataSchemaModel ) {
ArgumentNullException.validate( "dataSchemaModel", dataSchemaModel );
groups = new ArrayList<GroupDefinition>();
details = new ArrayList<RelationalDetail>();
this.dataSchemaModel = dataSchemaModel;
this.groupNamePrefix = "";
}
public String getGroupNamePrefix() {
return groupNamePrefix;
}
public void setGroupNamePrefix( final String groupNamePrefix ) {
ArgumentNullException.validate( "groupNamePrefix", groupNamePrefix );
this.groupNamePrefix = groupNamePrefix;
}
public void addGroup( final GroupDefinition g ) {
ArgumentNullException.validate( "g", g );
groups.add( g );
}
public void addGroup( final String field ) {
addGroup( field, true, true, true );
}
public void addGroup( final String field, final boolean printHeader, final boolean printHeaderAgg,
final boolean printFooterAgg ) {
groups.add( new GroupDefinition( field, printHeader, printHeaderAgg, printFooterAgg ) );
}
public void addDetails( final RelationalDetail detail ) {
details.add( detail );
}
public void addDetails( final String field, final Class aggregation, final Color background ) {
details.add( new RelationalDetail( field, aggregation, background ) );
}
public MasterReport createReport() {
final MasterReport report = new MasterReport();
report.setRootGroup( create() );
return report;
}
public RelationalGroup create() {
RelationalGroup rootGroup = null;
RelationalGroup innerGroup = null;
boolean headerPrinted = false;
if ( groups.size() <= 0 ) {
rootGroup = new RelationalGroup();
innerGroup = rootGroup;
headerPrinted = false;
} else {
for ( int i = 0; i < groups.size(); i += 1 ) {
headerPrinted |= groups.get( i ).isHeader();
}
for ( int i = 0; i < groups.size(); i += 1 ) {
final GroupDefinition groupDefinition = groups.get( i );
final RelationalGroup g = new RelationalGroup();
g.addField( groupDefinition.getGroupField() );
g.setName( computeGroupName( groupDefinition ) );
configureGroupHeader( groupDefinition, g, headerPrinted );
configureGroupFooter( groupDefinition, g, headerPrinted );
if ( rootGroup == null ) {
rootGroup = g;
}
if ( innerGroup != null ) {
innerGroup.setBody( new SubGroupBody( g ) );
}
innerGroup = g;
}
}
// noinspection ConstantConditions
final GroupDataBody body = (GroupDataBody) innerGroup.getBody();
final ItemBand band = body.getItemBand();
band.setLayout( "row" );
band.getStyle().setStyleProperty( ElementStyleKeys.INVISIBLE_CONSUMES_SPACE, true );
band.addElement( createLabel( "D: ", 120 ) );
if ( headerPrinted ) {
band.addElement( createLabel( "Details" ) );
}
for ( int d = 0; d < details.size(); d += 1 ) {
final RelationalDetail relationalDetail = details.get( d );
band.addElement( createFieldItem( relationalDetail.getField(), null, relationalDetail.getBackground() ) );
}
return rootGroup;
}
protected String computeGroupName( final GroupDefinition g ) {
if ( StringUtils.isEmpty( getGroupNamePrefix() ) ) {
return g.getGroupField();
}
return getGroupNamePrefix() + g.getGroupField();
}
private void configureGroupFooter( final GroupDefinition groupDefinition, final RelationalGroup g,
final boolean headerPrinted ) {
final GroupFooter footer = g.getFooter();
footer.setLayout( "row" );
footer.getStyle().setStyleProperty( ElementStyleKeys.INVISIBLE_CONSUMES_SPACE, true );
footer.setRepeat( true );
footer.addElement( createLabel( "F: " + groupDefinition.getGroupField(), 120 ) );
if ( groupDefinition.isHeader() ) {
footer.addElement( createFieldItem( groupDefinition.getGroupField() ) );
} else if ( headerPrinted ) {
footer.addElement( createLabel( "Footer" ) );
}
if ( groupDefinition.isFooterAggregation() ) {
for ( int d = 0; d < details.size(); d += 1 ) {
final RelationalDetail relationalDetail = details.get( d );
footer.addElement( createFieldItem( relationalDetail.getField(), relationalDetail.getAggregation(),
relationalDetail.getBackground() ) );
}
}
}
private void configureGroupHeader( final GroupDefinition groupDefinition, final RelationalGroup g,
final boolean anyHeaderPrinted ) {
final GroupHeader header = g.getHeader();
header.setLayout( "row" );
header.getStyle().setStyleProperty( ElementStyleKeys.INVISIBLE_CONSUMES_SPACE, true );
header.setRepeat( true );
header.addElement( createLabel( "H: " + groupDefinition.getGroupField(), 120 ) );
if ( groupDefinition.isHeader() ) {
header.addElement( createFieldItem( groupDefinition.getGroupField() ) );
} else if ( anyHeaderPrinted ) {
header.addElement( createLabel( " " ) );
}
if ( groupDefinition.isHeaderAggregation() ) {
for ( int d = 0; d < details.size(); d += 1 ) {
final RelationalDetail relationalDetail = details.get( d );
header.addElement( createFieldItem( relationalDetail.getField(), relationalDetail.getAggregation(),
relationalDetail.getBackground() ) );
}
}
}
private Element createFieldItem( final String text ) {
return createFieldItem( text, null, null );
}
private static class CopyValueAsTextExpression extends AbstractExpression {
private String field;
private CopyValueAsTextExpression( final String field ) {
this.field = field;
}
public Object getValue() {
return String.valueOf( getDataRow().get( field ) );
}
}
private Element createFieldItem( final String fieldName, final Class aggregationType, final Color background ) {
final ElementType targetType;
if ( dataSchemaModel != null ) {
final DataAttributeContext context = dataSchemaModel.getDataAttributeContext();
final DataAttributes attributes = dataSchemaModel.getDataSchema().getAttributes( fieldName );
targetType = AutoGeneratorUtility.createFieldType( attributes, context );
} else {
targetType = TextFieldType.INSTANCE;
}
final Element element = new Element();
element.setAttributeExpression( "test-run", "test-value", new CopyValueAsTextExpression( fieldName ) );
element.setElementType( targetType );
element.getElementType().configureDesignTimeDefaults( element, Locale.getDefault() );
element.getStyle().setStyleProperty( ElementStyleKeys.BACKGROUND_COLOR, background );
if ( targetType instanceof NumberFieldType ) {
element.setAttribute( AttributeNames.Core.NAMESPACE, AttributeNames.Core.FORMAT_STRING, "0.00;-0.00" );
}
element.setAttribute( AttributeNames.Core.NAMESPACE, AttributeNames.Core.FIELD, fieldName );
element.getStyle().setStyleProperty( ElementStyleKeys.MIN_WIDTH, 80f );
element.getStyle().setStyleProperty( ElementStyleKeys.MIN_HEIGHT, 20f );
element.setAttribute( AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.AGGREGATION_TYPE, aggregationType );
element.setAttribute( AttributeNames.Wizard.NAMESPACE, AttributeNames.Wizard.ALLOW_METADATA_STYLING, Boolean.FALSE );
return element;
}
private Element createLabel( final String text ) {
return createLabel( text, 80 );
}
private Element createLabel( final String text, float width ) {
final Element element = new Element();
element.setElementType( LabelType.INSTANCE );
element.getElementType().configureDesignTimeDefaults( element, Locale.getDefault() );
element.setAttribute( AttributeNames.Core.NAMESPACE, AttributeNames.Core.VALUE, text );
element.getStyle().setStyleProperty( ElementStyleKeys.MIN_WIDTH, width );
element.getStyle().setStyleProperty( ElementStyleKeys.MIN_HEIGHT, 20f );
return element;
}
}