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 }