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

ar.com.fdvs.dj.core.DynamicJasperHelper Maven / Gradle / Ivy

/*
 * DynamicJasper: A library for creating reports dynamically by specifying
 * columns, groups, styles, etc. at runtime. It also saves a lot of development
 * time in many cases! (http://sourceforge.net/projects/dynamicjasper)
 *
 * Copyright (C) 2008  FDV Solutions (http://www.fdvsolutions.com)
 *
 * This library 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 2.1 of the License, or (at your option) any later version.
 *
 * This library 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.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 *
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *
 */

package ar.com.fdvs.dj.core;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.sql.Connection;
import java.sql.ResultSet;
import java.util.*;

import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRResultSetDataSource;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.design.JRCompiler;
import net.sf.jasperreports.engine.design.JRDesignField;
import net.sf.jasperreports.engine.design.JRDesignGroup;
import net.sf.jasperreports.engine.design.JRDesignParameter;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.util.JRProperties;
import net.sf.jasperreports.engine.xml.JRXmlLoader;
import net.sf.jasperreports.engine.xml.JRXmlWriter;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import ar.com.fdvs.dj.core.layout.LayoutManager;
import ar.com.fdvs.dj.core.registration.ColumnRegistrationManager;
import ar.com.fdvs.dj.core.registration.DJGroupRegistrationManager;
import ar.com.fdvs.dj.core.registration.DJGroupVariableDefRegistrationManager;
import ar.com.fdvs.dj.core.registration.VariableRegistrationManager;
import ar.com.fdvs.dj.domain.ColumnProperty;
import ar.com.fdvs.dj.domain.DJCalculation;
import ar.com.fdvs.dj.domain.DynamicJasperDesign;
import ar.com.fdvs.dj.domain.DynamicReport;
import ar.com.fdvs.dj.domain.entities.DJGroup;
import ar.com.fdvs.dj.domain.entities.DJGroupVariableDef;
import ar.com.fdvs.dj.domain.entities.Parameter;
import ar.com.fdvs.dj.domain.entities.Subreport;
import ar.com.fdvs.dj.domain.entities.columns.AbstractColumn;
import ar.com.fdvs.dj.domain.entities.columns.PercentageColumn;
import ar.com.fdvs.dj.util.DJCompilerFactory;
import ar.com.fdvs.dj.util.LayoutUtils;

/**
 * Helper class for running a report and some other DJ related stuff
 */
public class DynamicJasperHelper {

	private static final Log log = LogFactory.getLog(DynamicJasperHelper.class);
	public static final String DEFAULT_XML_ENCODING = "UTF-8";
	private static final String DJ_RESOURCE_BUNDLE ="dj-messages";

    private static final Random random = new Random(System.currentTimeMillis());

	private final static void registerEntities(DynamicJasperDesign jd, DynamicReport dr, LayoutManager layoutManager) {
		ColumnRegistrationManager columnRegistrationManager = new ColumnRegistrationManager(jd,dr,layoutManager);
		columnRegistrationManager.registerEntities(dr.getColumns());
		
		DJGroupRegistrationManager djGroupRegistrationManager = new DJGroupRegistrationManager(jd,dr,layoutManager);
		djGroupRegistrationManager.registerEntities(dr.getColumnsGroups());
		
		VariableRegistrationManager variableRegistrationManager = new VariableRegistrationManager(jd, dr, layoutManager);
		variableRegistrationManager.registerEntities(dr.getVariables());
		
		registerPercentageColumnsVariables(jd,dr,layoutManager);
		registerOtherFields(jd,dr.getFields());
		Locale locale = dr.getReportLocale() == null ? Locale.getDefault() : dr.getReportLocale();
		if (log.isDebugEnabled()){
			log.debug("Requested Locale = " + dr.getReportLocale() + ", Locale to use: "+ locale);
		}
		ResourceBundle messages = null;
		if (dr.getResourceBundle() != null ){
			try {
				messages =  ResourceBundle.getBundle(dr.getResourceBundle(), locale);
			} catch (MissingResourceException e){ log.warn(e.getMessage() + ", usign default (dj-messages)");}
		}

		if (messages == null) {
			try {
				messages =  ResourceBundle.getBundle(DJ_RESOURCE_BUNDLE, locale);
			} catch (MissingResourceException e){ 
				log.warn(e.getMessage() + ", usign default (dj-messages)");
				try {
					messages = ResourceBundle.getBundle(DJ_RESOURCE_BUNDLE, Locale.ENGLISH); //this cannot fail because is included in the DJ jar
				} catch (MissingResourceException e2) {
					log.error("Default messajes not found: " + DJ_RESOURCE_BUNDLE + ", " + e2.getMessage(), e2);
					throw new DJException("Default messajes file not found: "+ DJ_RESOURCE_BUNDLE + "en.properties",e2);
				}
			}
		}
		jd.getParametersWithValues().put(JRDesignParameter.REPORT_RESOURCE_BUNDLE, messages);
		jd.getParametersWithValues().put(JRDesignParameter.REPORT_LOCALE, locale);
//		JRDesignParameter.REPORT_RESOURCE_BUNDLE
//		report.
	}

	private static void registerPercentageColumnsVariables(DynamicJasperDesign jd, DynamicReport dr, LayoutManager layoutManager) {
		for (Iterator iterator = dr.getColumns().iterator(); iterator.hasNext();) {
			AbstractColumn column = (AbstractColumn) iterator.next();
//			if (column instanceof PercentageColumn) {
//				PercentageColumn percentageColumn = ((PercentageColumn) column);				
//				JRDesignGroup jrGroup = LayoutUtils.getJRDesignGroup(jd, layoutManager, percentageColumn.getGroup());
//				ColumnsGroupTemporalVariablesRegistrationManager variablesRM = new ColumnsGroupTemporalVariablesRegistrationManager(jd,dr,layoutManager, jrGroup);
//				DJGroupTemporalVariable variable = new DJGroupTemporalVariable(percentageColumn.getGroupVariableName(), percentageColumn.getPercentageColumn(), DJCalculation.SUM);
//				Collection entities = new ArrayList();
//				entities.add(variable);
//				variablesRM.registerEntities(entities);
//			}
			
			/**
			 * Group should not be needed in the percentage column. There should be a variable for each group, using
			 * parent group as "rest group"
			 */
			if (column instanceof PercentageColumn) {
				PercentageColumn percentageColumn = ((PercentageColumn) column);				
				for (Iterator iterator2 = dr.getColumnsGroups().iterator(); iterator2.hasNext();) {
					DJGroup djGroup = (DJGroup) iterator2.next();
					JRDesignGroup jrGroup = LayoutUtils.getJRDesignGroup(jd, layoutManager, djGroup);
					DJGroupVariableDefRegistrationManager variablesRM = new DJGroupVariableDefRegistrationManager(jd,dr,layoutManager, jrGroup);
					DJGroupVariableDef variable = new DJGroupVariableDef(percentageColumn.getGroupVariableName(djGroup), percentageColumn.getPercentageColumn(), DJCalculation.SUM);
					Collection entities = new ArrayList();
					entities.add(variable);
					variablesRM.registerEntities(entities);
				}
			}			
		}
	}
	
	
	private static void registerOtherFields(DynamicJasperDesign jd, List fields) {
		for (Iterator iter = fields.iterator(); iter.hasNext();) {
			ColumnProperty element = (ColumnProperty) iter.next();
			JRDesignField field = new JRDesignField();
			field.setValueClassName(element.getValueClassName());
			field.setName(element.getProperty());
			try {
				jd.addField(field);
			} catch (JRException e) {
//				e.printStackTrace();
				//if the field is already registered, it's not a problem
				log.warn(e.getMessage());
			}
		}

	}


	protected static DynamicJasperDesign generateJasperDesign(DynamicReport dr) throws CoreException {
		DynamicJasperDesign jd = null;
		try {
			if (dr.getTemplateFileName() != null) {
				log.info("about to load template file: "+dr.getTemplateFileName() + ", Attemping to find the file directly in the file system.");
				File file = new File(dr.getTemplateFileName());
				if (file.exists()){
					JasperDesign jdesign = JRXmlLoader.load(file);
					jd = DJJRDesignHelper.downCast(jdesign,dr);
				} else {
					log.info("Not found: Attemping to find the file in the classpath...");
					URL url = DynamicJasperHelper.class.getClassLoader().getResource(dr.getTemplateFileName());
					JasperDesign jdesign = JRXmlLoader.load(url.openStream());
					jd = DJJRDesignHelper.downCast(jdesign,dr);
				}
				DJJRDesignHelper.populateReportOptionsFromDesign(jd,dr);

			} else {
				//Create new JasperDesign from the scratch
				jd = DJJRDesignHelper.getNewDesign(dr);
			}

            //Force a unique name to the report
            jd.setName("" + jd.getName() + "_" + random.nextInt(10000));

            log.debug("The name for this report will be: " + jd.getName());

			jd.setScriptletClass(DJDefaultScriptlet.class.getName()); //Set up scripttlet so that custom expressions can do their magic
			registerParameters(jd,dr);
		} catch (JRException e) {
			throw new CoreException(e.getMessage(),e);
		} catch (IOException e) {
			throw new CoreException(e.getMessage(),e);
		}
		return jd;
	}

	protected static void registerParameters(DynamicJasperDesign jd, DynamicReport dr) {
		for (Iterator iterator = dr.getParameters().iterator(); iterator.hasNext();) {
			Parameter param= (Parameter) iterator.next();
			JRDesignParameter jrparam = new JRDesignParameter();
			jrparam.setName(param.getName());
			jrparam.setValueClassName(param.getClassName());

			try {
				jd.addParameter(jrparam);
			} catch (JRException e) {
				throw new CoreException(e.getMessage(),e);
			}
		}

	}

	public static JasperPrint generateJasperPrint(DynamicReport dr, LayoutManager layoutManager, JRDataSource ds) throws JRException {
        return generateJasperPrint(dr, layoutManager, ds, new HashMap());
    }

	public static JasperPrint generateJasperPrint(DynamicReport dr, LayoutManager layoutManager, Collection collection) throws JRException {
		JRDataSource ds = new JRBeanCollectionDataSource(collection);
		return generateJasperPrint(dr, layoutManager, ds, new HashMap());
	}

	public static JasperPrint generateJasperPrint(DynamicReport dr, LayoutManager layoutManager, ResultSet resultSet) throws JRException {
		JRDataSource ds = new JRResultSetDataSource(resultSet);
		return generateJasperPrint(dr, layoutManager, ds, new HashMap());
	}

	/**
	 * Compiles and fills the reports design.
	 *
	 * @param dr the DynamicReport
	 * @param layoutManager the object in charge of doing the layout
	 * @param ds The datasource
	 * @param _parameters Map with parameters that the report may need
	 * @return
	 * @throws JRException
	 */
    public static JasperPrint generateJasperPrint(DynamicReport dr, LayoutManager layoutManager, JRDataSource ds, Map _parameters) throws JRException {
		log.info("generating JasperPrint");
		JasperPrint jp = null;

//			if (_parameters == null)
//				_parameters = new HashMap();
//
//			visitSubreports(dr, _parameters);
//			compileOrLoadSubreports(dr, _parameters);
//
//			DynamicJasperDesign jd = generateJasperDesign(dr);
//			Map params = new HashMap();
//			if (!_parameters.isEmpty()){
//				registerParams(jd,_parameters);
//				params.putAll(_parameters);
//			}
//
//			registerEntities(jd, dr);
//			layoutManager.applyLayout(jd, dr);
//            JRProperties.setProperty(JRProperties.COMPILER_CLASS, DJCompilerFactory.getCompilerClassName());
//
//            JasperReport jr = JasperCompileManager.compileReport(jd);
//            params.putAll(jd.getParametersWithValues());

            JasperReport jr = DynamicJasperHelper.generateJasperReport(dr, layoutManager, _parameters);
            jp = JasperFillManager.fillReport(jr, _parameters, ds);

            return jp;
	}

    /**
     * For running queries embebed in the report design
     * @param dr
     * @param layoutManager
     * @param con
     * @param _parameters
     * @return
     * @throws JRException
     */
    public static JasperPrint generateJasperPrint(DynamicReport dr, LayoutManager layoutManager, Connection con, Map _parameters) throws JRException {
    	log.info("generating JasperPrint");
    	JasperPrint jp = null;

    	if (_parameters == null)
    		_parameters = new HashMap();

    	visitSubreports(dr, _parameters);
    	compileOrLoadSubreports(dr, _parameters, "r");

    	DynamicJasperDesign jd = generateJasperDesign(dr);
    	Map params = new HashMap();
    	if (!_parameters.isEmpty()){
    		registerParams(jd,_parameters);
    		params.putAll(_parameters);
    	}
    	registerEntities(jd, dr, layoutManager);
    	layoutManager.applyLayout(jd, dr);
    	JRProperties.setProperty(JRCompiler.COMPILER_PREFIX, DJCompilerFactory.getCompilerClassName());
    	JasperReport jr = JasperCompileManager.compileReport(jd);
    	params.putAll(jd.getParametersWithValues());
    	jp = JasperFillManager.fillReport(jr, params, con);

    	return jp;
    }


    /**
     * For compiling and filling reports whose datasource is passed as parameter (e.g. Hibernate, Mondrean, etc.)
     * @param dr
     * @param layoutManager
     * @param _parameters
     * @return
     * @throws JRException
     */
    public static JasperPrint generateJasperPrint(DynamicReport dr, LayoutManager layoutManager, Map _parameters) throws JRException {
    	log.info("generating JasperPrint");
    	JasperPrint jp = null;

    	if (_parameters == null)
    		_parameters = new HashMap();

    	visitSubreports(dr, _parameters);
    	compileOrLoadSubreports(dr, _parameters, "r");

    	DynamicJasperDesign jd = generateJasperDesign(dr);
    	Map params = new HashMap();
    	if (!_parameters.isEmpty()){
    		registerParams(jd,_parameters);
    		params.putAll(_parameters);
    	}
    	registerEntities(jd, dr, layoutManager);
    	layoutManager.applyLayout(jd, dr);
//    	JRProperties.setProperty(JRProperties.COMPILER_CLASS, DJCompilerFactory.getCompilerClassName());
    	JRProperties.setProperty(JRCompiler.COMPILER_PREFIX, DJCompilerFactory.getCompilerClassName());
    	JasperReport jr = JasperCompileManager.compileReport(jd);
    	params.putAll(jd.getParametersWithValues());
    	jp = JasperFillManager.fillReport(jr, params);

    	return jp;
    }

	/**
	 * Creates a jrxml file
	 * @param dr
	 * @param layoutManager
	 * @param _parameters
	 * @param xmlEncoding (default is UTF-8 )
	 * @return
	 * @throws JRException
	 */
    public static String generateJRXML(DynamicReport dr, LayoutManager layoutManager, Map _parameters, String xmlEncoding) throws JRException {
    	JasperReport jr = generateJasperReport(dr, layoutManager, _parameters);
    	if (xmlEncoding == null)
    		xmlEncoding = DEFAULT_XML_ENCODING;
    	log.debug("generating JRXML");
    	return JRXmlWriter.writeReport(jr, xmlEncoding);
    }

    /**
     * Creates a jrxml file
     * @param dr
     * @param layoutManager
     * @param _parameters
     * @param xmlEncoding  (default is UTF-8 )
     * @param outputStream
     * @throws JRException
     */
    public static void generateJRXML(DynamicReport dr, LayoutManager layoutManager, Map _parameters, String xmlEncoding, OutputStream outputStream) throws JRException {
    	JasperReport jr = generateJasperReport(dr, layoutManager, _parameters);
    	if (xmlEncoding == null)
    		xmlEncoding = DEFAULT_XML_ENCODING;
    	 JRXmlWriter.writeReport(jr, outputStream, xmlEncoding);
    }

    /**
     * Creates a jrxml file
     * @param dr
     * @param layoutManager
     * @param _parameters
     * @param xmlEncoding  (default is UTF-8 )
     * @param filename the path to the destination file
     * @throws JRException
     */
    public static void generateJRXML(DynamicReport dr, LayoutManager layoutManager, Map _parameters, String xmlEncoding, String filename) throws JRException {
    	JasperReport jr = generateJasperReport(dr, layoutManager, _parameters);
    	if (xmlEncoding == null)
    		xmlEncoding = DEFAULT_XML_ENCODING;
    	
    	ensurePath(filename);
    	log.debug("generating JRXML to " + filename);
    	JRXmlWriter.writeReport(jr, filename, xmlEncoding);
    }

    public static void generateJRXML(JasperReport jr, String xmlEncoding, String filename) throws JRException {
    	if (xmlEncoding == null)
    		xmlEncoding = DEFAULT_XML_ENCODING;
    	
		ensurePath(filename);
		log.debug("generating JRXML to " + filename);
    	JRXmlWriter.writeReport(jr, filename, xmlEncoding);
    }

	private static void ensurePath(String filename) {
		File outputFile = new File(filename);
		File parentFile = outputFile.getParentFile();
		if (parentFile != null)
			parentFile.mkdirs();
	}

    protected static void compileOrLoadSubreports(DynamicReport dr, Map _parameters, String namePrefix) throws JRException {
    	int groupnum = 1;
    	for (Iterator iterator = dr.getColumnsGroups().iterator(); iterator.hasNext(); groupnum++) {
			DJGroup group = (DJGroup) iterator.next();
			int subreportNum = 1;
			//Header Subreports
			for (Iterator iterator2 = group.getHeaderSubreports().iterator(); iterator2.hasNext(); subreportNum++) {
				Subreport subreport = (Subreport) iterator2.next();
				String name = namePrefix + "_g" + groupnum +"sr" + subreportNum + "h";
				subreport.setName(name);
			
				if (subreport.getDynamicReport() != null){
                    Map originalParameters = _parameters;
                    if (subreport.getParametersExpression() != null){
                        _parameters = (Map) originalParameters.get(subreport.getParametersExpression());
                    }
					compileOrLoadSubreports(subreport.getDynamicReport(),_parameters, name);
					 JasperReport jp = generateJasperReport(subreport.getDynamicReport(), subreport.getLayoutManager(), _parameters, name);
					 _parameters.put(name, jp);
					 subreport.setReport(jp);
					 log.debug("subreport " + name);
                    _parameters = originalParameters;
				}

			}

			//Footer Subreports
			subreportNum = 1;
			for (Iterator iterator2 = group.getFooterSubreports().iterator(); iterator2.hasNext();subreportNum++) {
				Subreport subreport = (Subreport) iterator2.next();
				String name = namePrefix + "_g" + groupnum + "sr" + subreportNum + "f";
				subreport.setName(name);

				if (subreport.getDynamicReport() != null){
                    Map originalParameters = _parameters;
                    if (subreport.getParametersExpression() != null){
                        _parameters = (Map) originalParameters.get(subreport.getParametersExpression());
                        if (_parameters==null){
                            _parameters = new HashMap();
                            originalParameters.put(subreport.getParametersExpression(),_parameters);
                        }
                    }

					compileOrLoadSubreports(subreport.getDynamicReport(),_parameters, name);
					JasperReport jp = generateJasperReport(subreport.getDynamicReport(), subreport.getLayoutManager(), _parameters, name);
					_parameters.put(name, jp);
					subreport.setReport(jp);
					log.debug("subreport " + name);
                    _parameters = originalParameters;
				}

			}
		}
	}

	/**
     * For every String key, it registers the object as a parameter to make it available
     * in the report.
     * @param jd
     * @param _parameters
     */
	public static void registerParams(DynamicJasperDesign jd, Map _parameters) {
		for (Iterator iterator = _parameters.keySet().iterator(); iterator.hasNext();) {
			Object key = iterator.next();
			if (key instanceof String){
				try {
					Object value = _parameters.get(key);
					if (jd.getParametersMap().get(key) != null){
						log.warn("Parameter \"" + key + "\" already registered, skipping this one: " + value);
						continue;
					}

					JRDesignParameter parameter = new JRDesignParameter();

					if (value == null) //There are some Map implementations that allows nulls values, just go on
						continue;

//					parameter.setValueClassName(value.getClass().getCanonicalName());
					Class clazz = value.getClass().getComponentType();
					if (clazz == null)
						clazz = value.getClass();
					parameter.setValueClass(clazz); //NOTE this is very strange
					//when using an array as subreport-data-source, I must pass the parameter class name like this: value.getClass().getComponentType()
					parameter.setName((String)key);
					jd.addParameter(parameter);
				} catch (JRException e) {
					//nothing to do
				}
			}

		}

	}

	/**
	 * Compiles the report and applies the layout. generatedParams MUST NOT BE NULL
	 * All the key objects from the generatedParams map that are String, will be registered as parameters of the report.
	 * @param dr
	 * @param layoutManager
	 * @param generatedParams
	 * @return
	 * @throws JRException
	 */
	public final static JasperReport generateJasperReport(DynamicReport dr, LayoutManager layoutManager, Map generatedParams) throws JRException {
		log.info("generating JasperReport");
		JasperReport jr = generateJasperReport(dr, layoutManager, generatedParams, "r");
			
		return jr;
	}

	@SuppressWarnings("unchecked")
	public final static JasperReport generateJasperReport(DynamicReport dr, LayoutManager layoutManager, Map generatedParams, String nameprefix) throws JRException {
		log.info("generating JasperReport");
		JasperReport jr = null;
		if (generatedParams == null){
			log.warn("null parameters map passed to DynamicJasperHelper, you wont be able to retrieve some generated values during the layout process.");
			generatedParams = new HashMap();
		}
		
		visitSubreports(dr, generatedParams);
		compileOrLoadSubreports(dr, generatedParams, nameprefix);
		
		DynamicJasperDesign jd = generateJasperDesign(dr);
		registerEntities(jd, dr, layoutManager);
		
		registerParams(jd, generatedParams); //if we have parameters from the outside, we register them
		
		layoutManager.applyLayout(jd, dr);
		JRProperties.setProperty(JRCompiler.COMPILER_PREFIX, "ar.com.fdvs.dj.util.DJJRJdtCompiler");			
		jr = JasperCompileManager.compileReport(jd);
		generatedParams.putAll(jd.getParametersWithValues());
		log.info("Done generating JasperReport");
		return jr;
	}

/**
 * Performs any needed operation on subreports after they are built like ensuring proper subreport with
 * if "fitToParentPrintableArea" flag is set to true
 * @param dr
 * @param _parameters
 * @throws JRException
 */
	@SuppressWarnings("unchecked")
	protected static void visitSubreports(DynamicReport dr, Map _parameters) throws JRException{
    	for (Iterator iterator = dr.getColumnsGroups().iterator(); iterator.hasNext();) {
			DJGroup group = (DJGroup) iterator.next();

			//Header Subreports
			for (Iterator iterator2 = group.getHeaderSubreports().iterator(); iterator2.hasNext();) {
				Subreport subreport = (Subreport) iterator2.next();

				if (subreport.getDynamicReport() != null){
					visitSubreport(dr,subreport,_parameters);
					visitSubreports(subreport.getDynamicReport(),_parameters);
				}

			}

			//Footer Subreports
			for (Iterator iterator2 = group.getFooterSubreports().iterator(); iterator2.hasNext();) {
				Subreport subreport = (Subreport) iterator2.next();

				if (subreport.getDynamicReport() != null){
					visitSubreport(dr,subreport,_parameters);
					visitSubreports(subreport.getDynamicReport(),_parameters);
				}

			}
		}

	}

	protected static void visitSubreport(DynamicReport parentDr, Subreport subreport, Map _parameters) {
		DynamicReport childDr = subreport.getDynamicReport();
		if (subreport.isFitToParentPrintableArea()){
			childDr.getOptions().setPage(parentDr.getOptions().getPage());
			childDr.getOptions().setLeftMargin(parentDr.getOptions().getLeftMargin());
			childDr.getOptions().setRightMargin(parentDr.getOptions().getRightMargin());
		}
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy