001: /*
002: * Copyright (c) 2002-2003 by OpenSymphony
003: * All rights reserved.
004: */
005: package com.opensymphony.webwork.views.jasperreports;
006:
007: import com.opensymphony.webwork.util.MakeIterator;
008: import com.opensymphony.xwork.util.OgnlValueStack;
009: import net.sf.jasperreports.engine.JRDataSource;
010: import net.sf.jasperreports.engine.JRException;
011: import net.sf.jasperreports.engine.JRField;
012: import org.apache.commons.logging.Log;
013: import org.apache.commons.logging.LogFactory;
014:
015: import java.util.Iterator;
016:
017: /**
018: * Ported to WebWork2.
019: *
020: * @author <a href="hermanns@aixcept.de">Rainer Hermanns</a>
021: * @version $Id: OgnlValueStackDataSource.java 1282 2005-10-09 04:26:58Z plightbo $
022: */
023: public class OgnlValueStackDataSource implements JRDataSource {
024:
025: /**
026: * Logger for this class
027: */
028: private static Log log = LogFactory
029: .getLog(OgnlValueStackDataSource.class);
030:
031: Iterator iterator;
032: OgnlValueStack valueStack;
033: boolean firstTimeThrough = true;
034:
035: /**
036: * Create a value stack data source on the given iterable property
037: *
038: * @param valueStack The value stack to base the data source on
039: * @param dataSource The property to iterate over for the report
040: */
041: public OgnlValueStackDataSource(OgnlValueStack valueStack,
042: String dataSource) {
043: this .valueStack = valueStack;
044:
045: Object dataSourceValue = valueStack.findValue(dataSource);
046:
047: if (dataSourceValue != null) {
048: if (MakeIterator.isIterable(dataSourceValue)) {
049: iterator = MakeIterator.convert(dataSourceValue);
050: } else {
051: Object[] array = new Object[1];
052: array[0] = dataSourceValue;
053: iterator = MakeIterator.convert(array);
054: }
055: } else {
056: log.warn("Data source value for data source " + dataSource
057: + " was null");
058: }
059: }
060:
061: /**
062: * Get the value of a given field
063: *
064: * @param field The field to get the value for. The expression language to get the value
065: * of the field is either taken from the description property or from the name of the field
066: * if the description is <code>null</code>.
067: * @return an <code>Object</code> containing the field value or a new
068: * <code>OgnlValueStackDataSource</code> object if the field value evaluates to
069: * an object that can be iterated over.
070: * @throws JRException if there is a problem obtaining the value
071: */
072: public Object getFieldValue(JRField field) throws JRException {
073: //TODO: move the code to return a OgnlValueStackDataSource to a seperate
074: // method when and if the JRDataSource interface is updated to support
075: // this.
076: String expression = field.getDescription();
077:
078: if (expression == null) {
079: //Description is optional so use the field name as a default
080: expression = field.getName();
081: }
082:
083: Object value = valueStack.findValue(expression);
084:
085: if (log.isDebugEnabled()) {
086: log.debug("field: " + field.getName() + "/" + value);
087: }
088:
089: if (MakeIterator.isIterable(value)) {
090: // return new OgnlValueStackDataSource(this.valueStack, field.getName());
091: return new OgnlValueStackDataSource(this .valueStack,
092: expression);
093: } else {
094: return value;
095: }
096: }
097:
098: /**
099: * Is there any more data
100: *
101: * @return <code>true</code> if there are more elements to iterate over and
102: * <code>false</code> otherwise
103: * @throws JRException if there is a problem determining whether there
104: * is more data
105: */
106: public boolean next() throws JRException {
107: if (firstTimeThrough) {
108: firstTimeThrough = false;
109: } else {
110: valueStack.pop();
111: }
112:
113: if ((iterator != null) && (iterator.hasNext())) {
114: valueStack.push(iterator.next());
115: log
116: .debug("Pushed next value: "
117: + valueStack.findValue("."));
118:
119: return true;
120: } else {
121: log.debug("No more values");
122:
123: return false;
124: }
125: }
126: }
|