ar.com.fdvs.dj.domain.builders.ReflectiveReportBuilder.java Source code

Java tutorial

Introduction

Here is the source code for ar.com.fdvs.dj.domain.builders.ReflectiveReportBuilder.java

Source

/*
 * 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.domain.builders;

import java.beans.PropertyDescriptor;
import java.util.Collection;
import java.util.Date;

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

/**
 * Builder created to give users an easy way of creating a DynamicReport based on a collection.</br>
 * </br>
 * Usage example: </br>
 * DynamicReport report =
 *      new ReflectiveReportBuilder(data, new String[]{"productLine", "item", "state", "id", "branch", "quantity", "amount"})
 *      .addGroups(3).build();
 * </br>
 * Like with all DJ's builders, it's usage must end with a call to build() mehtod.
 * </br>
 */
public class ReflectiveReportBuilder extends FastReportBuilder {

    private static final Log LOGGER = LogFactory.getLog(ReflectiveReportBuilder.class);

    /**
     * Takes the first item in the collection and adds a column for every property in that item.
     * @param _data the data collection. A not null and nor empty collection should be passed.
     */
    public ReflectiveReportBuilder(final Collection _data) {
        if (_data == null || _data.isEmpty()) {
            throw new IllegalArgumentException("Parameter _data is null or empty");
        }
        final Object item = _data.iterator().next();
        try {
            addProperties(PropertyUtils.getPropertyDescriptors(item));
        } catch (Exception ex) {
            LOGGER.error("", ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    /**
     * Adds a column for every property specified in the array.
     * @param _data the data collection. A not null and nor empty collection should be passed.
     * @param _propertiesNames and array with the names of the desired properties.
     */
    public ReflectiveReportBuilder(final Collection _data, final String[] _propertiesNames) {
        if (_data == null || _data.isEmpty()) {
            throw new IllegalArgumentException("Parameter _data is null or empty");
        }
        if (_propertiesNames == null || _propertiesNames.length == 0) {
            throw new IllegalArgumentException("Parameter _propertiesNames is null or empty");
        }
        final Object item = _data.iterator().next();
        final PropertyDescriptor[] properties = new PropertyDescriptor[_propertiesNames.length];
        try {
            for (int i = 0; i < _propertiesNames.length; i++) {
                final String propertiesName = _propertiesNames[i];
                properties[i] = PropertyUtils.getPropertyDescriptor(item, propertiesName);
            }
            addProperties(properties);
        } catch (Exception ex) {
            LOGGER.error("", ex);
        }
    }

    /**
     * Adds columns for the specified properties.
     * @param _properties the array of <code>PropertyDescriptor</code>s to be added.
     * @throws ColumnBuilderException if an error occurs.
     * @throws ClassNotFoundException if an error occurs.
     */
    private void addProperties(final PropertyDescriptor[] _properties)
            throws ColumnBuilderException, ClassNotFoundException {
        for (int i = 0; i < _properties.length; i++) {
            final PropertyDescriptor property = _properties[i];
            if (isValidProperty(property)) {
                addColumn(getColumnTitle(property), property.getName(), property.getPropertyType().getName(),
                        getColumnWidth(property));
            }
        }
        setUseFullPageWidth(true);
    }

    /**
     * Calculates a column title using camel humps to separate words.
     * @param _property the property descriptor.
     * @return the column title for the given property.
     */
    private static String getColumnTitle(final PropertyDescriptor _property) {
        final StringBuffer buffer = new StringBuffer();
        final String name = _property.getName();
        buffer.append(Character.toUpperCase(name.charAt(0)));
        for (int i = 1; i < name.length(); i++) {
            final char c = name.charAt(i);
            if (Character.isUpperCase(c)) {
                buffer.append(' ');
            }
            buffer.append(c);
        }
        return buffer.toString();
    }

    /**
     * Checks if a property is valid to be included in the report.
     * @param _property the property.
     * @return true if the property is not class, and it is of a valid type.
     */
    private static boolean isValidProperty(final PropertyDescriptor _property) {
        return !"class".equals(_property.getName()) && isValidPropertyClass(_property);
    }

    /**
     * Checks if a property's type is valid to be included in the report.
     * @param _property the property.
     * @return true if the property is is of a valid type.
     */
    private static boolean isValidPropertyClass(final PropertyDescriptor _property) {
        final Class type = _property.getPropertyType();
        return Number.class.isAssignableFrom(type) || type == String.class || Date.class.isAssignableFrom(type)
                || type == Boolean.class;
    }

    /**
     * Calculates the column width according to its type.
     * @param _property the property.
     * @return the column width.
     */
    private static int getColumnWidth(final PropertyDescriptor _property) {
        final Class type = _property.getPropertyType();
        if (Float.class.isAssignableFrom(type) || Double.class.isAssignableFrom(type)) {
            return 70;
        } else if (type == Boolean.class) {
            return 10;
        } else if (Number.class.isAssignableFrom(type)) {
            return 60;
        } else if (type == String.class) {
            return 100;
        } else if (Date.class.isAssignableFrom(type)) {
            return 50;
        } else {
            return 50;
        }
    }
}