Sunday, November 12, 2006

use ListDataSource to easily pass object to JasperReports

Nowadays OR mapping framework and web framework are widely used in application, most of them use value objects go through entire transaction life cycle. But most of the applications also have report requirements, one of the most popular report engine framework is JasperReports.
If the same value objects can pass into report engine without having to transfer them or query database again to make another java type object, it will make the transaction more neater and easier to maintain.

Here is my implementation of JRDataSource, it is called ListDataSource, you just have to pass into java.util.List of value object(java.lang.Object) or implementation of java.util.Map.

Below are the code:

import java.util.Iterator;
import java.util.List;
import java.util.Map;

import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRField;

import org.apache.commons.beanutils.MethodUtils;

/**
 * @author Matt Jiang (matt.jiang@gmail.com)
 * @version 1.0
 */
public class ListDataSource implements JRDataSource {

  private List records = null;
  private Iterator iterator = null;
  private Object currentRow = null;
  private boolean disableReflection = false;
  
  public ListDataSource(List records, boolean disableReflection) {
    
    this.disableReflection = disableReflection;
    this.records = records;
    if (records != null)
      this.iterator = records.iterator();
  }
  
  public ListDataSource(List records) {
    
    this(records, false);
  }
  
  /**
   * cursor switch to next record
   */
  public boolean next() throws JRException {

    boolean hasNext = false;
    
    if (iterator != null) {
      hasNext = iterator.hasNext();
      if (hasNext)
        currentRow = iterator.next();
    }
    
    return hasNext;
  }

  /**
   * fieldName is defined in JasperReports, it will used as a key of Map or be transfered to getter method 
   * to retrieve value by java reflection. 
   */
  public Object getFieldValue(JRField jrField) throws JRException {

    String fieldName = jrField.getName();
    String methodName = makeGetter(fieldName);
    Object fieldValue;
    
    if (currentRow instanceof Map)
      fieldValue = retrieveValueFromMap((Map)currentRow, fieldName);
    else {
      if (disableReflection)
        fieldValue = currentRow;
      else
        fieldValue = retrieveValueFromReflection(currentRow, fieldName);
    }
    
    return fieldValue;
  }
  
  private Object retrieveValueFromMap(Map currentRow, String fieldName) {
    
    return currentRow.get(fieldName);
  }
  
  private Object retrieveValueFromReflection(Object currentRow, String fieldName) {
    
    Object fieldValue = null;
    try {
      fieldValue = MethodUtils.invokeMethod(currentRow, makeGetter(fieldName), null);
    } catch (Exception e) {
      e.printStackTrace();
      ; // ignore this exception on purpose
    }
    return fieldValue;
  }
  
  private String makeGetter(String fieldName) {
    
    StringBuffer getter = new StringBuffer();
    getter.append("get").append(fieldName.substring(0, 1).toUpperCase()).append(fieldName.substring(1));
    return getter.toString();
  }

  public String size() {
    
    String size = "0";
    if (records != null) {
      size = String.valueOf(records.size());
    }
    
    return size;
  }
}

Tuesday, November 07, 2006

Hello World

Haha... You see the title, if your career is the same as mine, then you have known what my job is.
Sometimes I write some tiny utility or a framework, I am pleasure to share my idea and source code to everyone, and hope you can give me some advice as well.

Nice to meet you here.