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