View Javadoc

1   /*
2    * $Id: ValueStackDataSource.java 471756 2006-11-06 15:01:43Z husted $
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
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          //TODO: move the code to return a ValueStackDataSource to a seperate
88          //      method when and if the JRDataSource interface is updated to support
89          //      this.
90          String expression = field.getDescription();
91  
92          if (expression == null) {
93              //Description is optional so use the field name as a default
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             //                return new ValueStackDataSource(this.valueStack, field.getName());
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 }