1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.struts2.views.jasperreports;
19
20 import org.apache.struts2.util.MakeIterator;
21 import com.opensymphony.xwork2.util.ValueStack;
22 import net.sf.jasperreports.engine.JRDataSource;
23 import net.sf.jasperreports.engine.JRException;
24 import net.sf.jasperreports.engine.JRField;
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27
28 import java.util.Iterator;
29
30 /***
31 * Ported to Struts.
32 *
33 */
34 public class ValueStackDataSource implements JRDataSource {
35
36 /***
37 * Logger for this class
38 */
39 private static Log log = LogFactory.getLog(ValueStackDataSource.class);
40
41
42 Iterator iterator;
43 ValueStack valueStack;
44 boolean firstTimeThrough = true;
45
46
47 /***
48 * Create a value stack data source on the given iterable property
49 *
50 * @param valueStack The value stack to base the data source on
51 * @param dataSource The property to iterate over for the report
52 */
53 public ValueStackDataSource(ValueStack valueStack, String dataSource) {
54 this.valueStack = valueStack;
55
56 Object dataSourceValue = valueStack.findValue(dataSource);
57
58 if (dataSourceValue != null) {
59 if (MakeIterator.isIterable(dataSourceValue)) {
60 iterator = MakeIterator.convert(dataSourceValue);
61 } else {
62 Object[] array = new Object[1];
63 array[0] = dataSourceValue;
64 iterator = MakeIterator.convert(array);
65 }
66 } else {
67 log.warn("Data source value for data source " + dataSource + " was null");
68 }
69 }
70
71
72 /***
73 * Get the value of a given field
74 *
75 * @param field The field to get the value for. The expression language to get the value
76 * of the field is either taken from the description property or from the name of the field
77 * if the description is <code>null</code>.
78 * @return an <code>Object</code> containing the field value or a new
79 * <code>ValueStackDataSource</code> object if the field value evaluates to
80 * an object that can be iterated over.
81 * @throws JRException if there is a problem obtaining the value
82 */
83 public Object getFieldValue(JRField field) throws JRException {
84
85
86
87 String expression = field.getDescription();
88
89 if (expression == null) {
90
91 expression = field.getName();
92 }
93
94 Object value = valueStack.findValue(expression);
95
96 if (log.isDebugEnabled()) {
97 log.debug("field: " + field.getName() + "/" + value);
98 }
99
100 if (MakeIterator.isIterable(value)) {
101
102 return new ValueStackDataSource(this.valueStack, expression);
103 } else {
104 return value;
105 }
106 }
107
108 /***
109 * Is there any more data
110 *
111 * @return <code>true</code> if there are more elements to iterate over and
112 * <code>false</code> otherwise
113 * @throws JRException if there is a problem determining whether there
114 * is more data
115 */
116 public boolean next() throws JRException {
117 if (firstTimeThrough) {
118 firstTimeThrough = false;
119 } else {
120 valueStack.pop();
121 }
122
123 if ((iterator != null) && (iterator.hasNext())) {
124 valueStack.push(iterator.next());
125 log.debug("Pushed next value: " + valueStack.findValue("."));
126
127 return true;
128 } else {
129 log.debug("No more values");
130
131 return false;
132 }
133 }
134 }