All Downloads are FREE. Search and download functionalities are using the official Maven repository.

xdev.tableexport.export.ReportBuilder Maven / Gradle / Ivy

There is a newer version: 6.0.1
Show newest version
package xdev.tableexport.export;

/*-
 * #%L
 * XDEV BI Suite
 * %%
 * Copyright (C) 2011 - 2020 XDEV Software
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * 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 General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */


import java.awt.Color;
import java.awt.Font;
import java.util.HashSet;
import java.util.Set;

import javax.swing.JLabel;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRLineBox;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.design.JRDesignBand;
import net.sf.jasperreports.engine.design.JRDesignExpression;
import net.sf.jasperreports.engine.design.JRDesignField;
import net.sf.jasperreports.engine.design.JRDesignSection;
import net.sf.jasperreports.engine.design.JRDesignStaticText;
import net.sf.jasperreports.engine.design.JRDesignTextElement;
import net.sf.jasperreports.engine.design.JRDesignTextField;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.type.ModeEnum;
import net.sf.jasperreports.engine.type.PositionTypeEnum;
import net.sf.jasperreports.engine.type.SplitTypeEnum;
import xdev.tableexport.config.ColumnBorder;
import xdev.tableexport.config.ColumnPadding;
import xdev.tableexport.config.ColumnStyle;
import xdev.tableexport.config.ContentColumn;
import xdev.tableexport.config.HeaderColumn;
import xdev.tableexport.config.PageProperties;
import xdev.tableexport.config.TemplateColumn;
import xdev.tableexport.config.TemplateConfig;
import xdev.vt.XdevBlob;
import xdev.vt.XdevClob;


/**
 * The {@link ReportBuilder} generates a {@link JasperReport} based on the
 * information of the {@link TemplateConfig}.
 * 
 * @author XDEV Software (FHAE)
 * 
 * @see TemplateConfig
 * @see ReportExporter
 * 
 */
public class ReportBuilder
{
	private TemplateConfig			config;
	private Set		fieldSet	= new HashSet<>();
	
	
	public ReportBuilder(TemplateConfig tempConfig)
	{
		this.config = tempConfig;
	}
	
	
	private JRDesignBand initDetailBand()
	{
		final JRDesignBand detailBand = new JRDesignBand();
		detailBand.setHeight(TemplateConfig.DEFAULT_DETAIL_BAND_HEIGHT);
		detailBand.setSplitType(SplitTypeEnum.STRETCH);
		
		return detailBand;
	}
	
	
	private JRDesignBand initHeaderBand()
	{
		// Header
		final JRDesignBand headerBand = new JRDesignBand();
		headerBand.setHeight(TemplateConfig.DEFAULT_HEADER_BAND_HEIGHT);
		
		return headerBand;
	}
	
	
	private JasperDesign createDefaultDesign()
	{
		JasperDesign jasperDesign = new JasperDesign();
		jasperDesign.setName("DefaultDesign");
		PageProperties properties = this.config.getPageProperties();
		
		jasperDesign.setPageWidth(calcPageWidth(properties));
		jasperDesign.setColumnWidth(calcColumnsWidth());
		
		jasperDesign.setPageHeight(properties.getPageHeight());
		jasperDesign.setColumnSpacing(properties.getColumnSpacing());
		jasperDesign.setLeftMargin(properties.getLeftMargin());
		jasperDesign.setRightMargin(properties.getRightMargin());
		jasperDesign.setTopMargin(properties.getTopMargin());
		jasperDesign.setBottomMargin(properties.getBottomMargin());
		
		return jasperDesign;
	}
	
	
	private int calcColumnsWidth()
	{
		int width = 0;
		
		for(TemplateColumn col : this.config.getColumns())
		{
			width += col.getWidth();
		}
		
		return width;
	}

	/***
	 * Calculated the page width including the margins.
	 * 
	 * @param properties
	 * 
	 * @return
	 */
	private int calcPageWidth(final PageProperties properties)
	{
		int width = 0;
		
		for(TemplateColumn col : this.config.getColumns())
		{
			width += col.getWidth();
		}
		
		width += properties.getLeftMargin() + properties.getRightMargin();
		
		return width;
	}
	
	
	/**
	 * 
	 * @return
	 */
	private int calcMaxHeaderHeight()
	{
		
		final JLabel lbl = new JLabel("a");
		int maxHeight = 0;
		
		for(TemplateColumn col : this.config.getColumns())
		{
			final ColumnStyle style = col.getHeaderColumn().getStyle();
			final Font font = style.getFont();
			lbl.setFont(font);
			//get the normal height of the label
			int lblHeigh = (int)lbl.getPreferredSize().getHeight();
			//add the column border width
			lblHeigh+= style.getColBorder().getLineWidth()*2;
			//Add padding
			lblHeigh+= style.getColumnPadding().getTopWidth() + style.getColumnPadding().getBottomWidth();
			
			if(lblHeigh > maxHeight) maxHeight = lblHeigh;
		}
		
		return maxHeight;
	}
	
	private int calcMaxContentHeight()
	{
		
		final JLabel lbl = new JLabel("a");
		int maxHeight = 0;
		
		for(TemplateColumn col : this.config.getColumns())
		{
			final ColumnStyle style = col.getContentColumn().getStyle();
			final Font font = style.getFont();
			lbl.setFont(font);
			int lblHeigh = (int)lbl.getPreferredSize().getHeight();
			//Add border width
			lblHeigh+= style.getColBorder().getLineWidth()*2;
			//Add padding
			lblHeigh+= style.getColumnPadding().getTopWidth() + style.getColumnPadding().getBottomWidth();
			
			if(lblHeigh > maxHeight) maxHeight = lblHeigh;
		}
		
		return maxHeight;
	}
	
	
	private void createTemplateFields(final JasperDesign jasperDesign) throws ExportException
	{
		JRDesignField field;
		
		for(TemplateColumn col : this.config.getColumns())
		{
			field = new JRDesignField();
			field.setName(col.getContentColumn().getFieldName());
			chooseValueClass(col,field);
			
			try
			{
				jasperDesign.addField(field);
				this.fieldSet.add(field);
			}
			catch(JRException e)
			{
				throw new ExportException("error during add the field "
						+ col.getContentColumn().getFieldName(),e);
			}
		}
		
	}

	
	private JRDesignField chooseValueClass(final TemplateColumn col, final JRDesignField field)
	{
		final Class valueClass = col.getContentColumn().getColumnValueClass();
		
		if(valueClass.isAssignableFrom(byte[].class) || valueClass.isAssignableFrom(XdevBlob.class) || valueClass.isAssignableFrom(XdevClob.class))
		{
			field.setValueClass(String.class);
		}
		else
		{
			field.setValueClass(valueClass);
		}
		
		return field;
	}
	
	
	private void createHeaderAndContent(JRDesignBand headerBand, JRDesignBand detailBand)
	{
		JRDesignStaticText headerLabel;
		JRDesignStaticText emptyHeaderLabel;
		JRDesignTextField textField;
				
		final int headerLabelHeight = calcMaxHeaderHeight();
		headerBand.setHeight(headerLabelHeight);
		
		final int contentLabelHeight = calcMaxContentHeight();
		detailBand.setHeight(contentLabelHeight);
				
		final boolean createHeader = this.config.hasAnyHeader();
		
		int x = 0;
		
		for(TemplateColumn col : this.config.getColumns())
		{
			// Header is created
			if(createHeader)
			{
				// If this column has a header the JRDesignStaticText get the
				// propertys of the Column
				if(col.hasHeaderColumn())
				{
					HeaderColumn headerColumn = col.getHeaderColumn();
					// Build label and set x / y
					headerLabel = new JRDesignStaticText();
					headerLabel.setX(x);
					headerLabel.setWidth(col.getWidth());
					headerLabel.setY(TemplateConfig.DEFAULT_COMPONENT_Y_POSITION);
					
					headerLabel.setHeight(headerLabelHeight);
					setStlyeForTextField(headerLabel,headerColumn.getStyle());
					prepareTextfieldWithBorder(headerLabel,headerColumn.getStyle());
					prepareTextfieldPadding(headerLabel,headerColumn.getStyle());
					
					headerLabel.setPositionType(PositionTypeEnum.FLOAT);

					
					// Get the Property
					headerLabel.setText(headerColumn.getProperty());
					headerBand.addElement(headerLabel);
				}
				else
				{
					// an empty label must be added to complete the layout
					// Build label and set x / y
					emptyHeaderLabel = new JRDesignStaticText();
					emptyHeaderLabel.setX(x);
					emptyHeaderLabel.setWidth(col.getWidth());
					headerBand.addElement(emptyHeaderLabel);
				}
			}
			
			final ContentColumn contentColumn = col.getContentColumn();
			
			textField = new JRDesignTextField();
			textField.setX(x);
			textField.setWidth(col.getWidth());
			textField.setY(TemplateConfig.DEFAULT_COMPONENT_Y_POSITION);
			textField.setHeight(contentLabelHeight);
			
			setStlyeForTextField(textField,contentColumn.getStyle());
			textField.setPattern(contentColumn.getProperty());
			
			// box tag properties
			prepareTextfieldWithBorder(textField,contentColumn.getStyle());
			prepareTextfieldPadding(textField,contentColumn.getStyle());
			
			textField.setExpression(buildExpression(contentColumn));
			
			textField.setPositionType(PositionTypeEnum.FLOAT);
			
			if(config.isBlankWhenNullValue())
				textField.setBlankWhenNull(true);
			detailBand.addElement(textField);
			
			x += col.getWidth();
		}
		
	}
	
	private void setStlyeForTextField(final JRDesignTextElement txtField, final ColumnStyle style)
	{
		txtField.setBackcolor(style.getBackground());
		txtField.setForecolor(style.getForeground());
		// Font
		final Font f = style.getFont();
		txtField.setFontName(f.getName());
		txtField.setFontSize(f.getSize());
		txtField.setBold(f.isBold());
		txtField.setItalic(f.isItalic());
		txtField.setHorizontalAlignment(style.getHorizontalAlignment().getHorizontalAlignEnum());
		
		
		if(!style.getBackground().equals(Color.WHITE))
		{
			txtField.setMode(ModeEnum.OPAQUE);
		}
	}
	
	
	private void prepareTextfieldWithBorder(final JRDesignTextElement textField, final ColumnStyle style)
	{
		final ColumnBorder border = style.getColBorder();
		if(border == null)
			return;
		
		textField.getLineBox().getPen().setLineWidth(border.getLineWidth());
		textField.getLineBox().getPen().setLineColor(border.getLineColor());
		textField.getLineBox().getPen().setLineStyle(border.getLineStyle().getLineStyleEnum());
	}
	
	private void prepareTextfieldPadding(final JRDesignTextElement textField, final ColumnStyle style)
	{
		final ColumnPadding colPadding = style.getColumnPadding();
		final JRLineBox lineBox = textField.getLineBox();
		
		
		lineBox.setTopPadding(colPadding.getTopWidth());
		lineBox.setRightPadding(colPadding.getRightWidth());
		lineBox.setLeftPadding(colPadding.getLeftWidth());
		lineBox.setBottomPadding(colPadding.getBottomWidth());
	}
	
	
	private JRDesignExpression buildExpression(ContentColumn column)
	{
		JRDesignExpression expression = new JRDesignExpression();
		expression.setText("$F{" + column.getFieldName() + "}");
		return expression;
	}
	
	
	/**
	 * 
	 * Assemble and compile a {@link JasperReport} based on the information of
	 * the {@link TemplateConfig} object.
	 * 
	 * @return the compiled {@link JasperReport}
	 * @throws ExportException
	 */
	public JasperReport assembleReport() throws ExportException
	{
		try
		{
			final JasperDesign jasperDesign = createDefaultDesign();
			createTemplateFields(jasperDesign);
			
			final JRDesignBand headerBand = initHeaderBand();
			final JRDesignBand detailBand = initDetailBand();
			
			createHeaderAndContent(headerBand,detailBand);
			
			((JRDesignSection)jasperDesign.getDetailSection()).addBand(detailBand);
			if(this.config.hasAnyHeader())
			{
				jasperDesign.setTitle(headerBand);
			}
						
			return JasperCompileManager.compileReport(jasperDesign);
		}
		catch(Exception e)
		{
			throw new ExportException(e);
		}
	}
	
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy