View Javadoc

1   /*
2    * $Id: ValueStackDataSource.java 651946 2008-04-27 13:41:38Z apetrelli $
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  
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          //TODO: move the code to return a ValueStackDataSource to a seperate
91          //      method when and if the JRDataSource interface is updated to support
92          //      this.
93          String expression = field.getDescription();
94  
95          if (expression == null) {
96              //Description is optional so use the field name as a default
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             //                return new ValueStackDataSource(this.valueStack, field.getName());
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 }