/*!
* 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 java.awt.Color;
import java.util.ArrayList;
import java.util.Locale;
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;
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;
}
}