View Javadoc

1   /*
2    * $Id: ValueStackDataSource.java 451544 2006-09-30 05:38:02Z mrdon $
3    *
4    * Copyright 2006 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
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          //TODO: move the code to return a ValueStackDataSource to a seperate
85          //      method when and if the JRDataSource interface is updated to support
86          //      this.
87          String expression = field.getDescription();
88  
89          if (expression == null) {
90              //Description is optional so use the field name as a default
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             //                return new ValueStackDataSource(this.valueStack, field.getName());
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 }