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