001    /**
002     * ========================================
003     * JFreeReport : a free Java report library
004     * ========================================
005     *
006     * Project Info:  http://reporting.pentaho.org/
007     *
008     * (C) Copyright 2000-2007, by Object Refinery Limited, Pentaho Corporation and Contributors.
009     *
010     * This library is free software; you can redistribute it and/or modify it under the terms
011     * of the GNU Lesser General Public License as published by the Free Software Foundation;
012     * either version 2.1 of the License, or (at your option) any later version.
013     *
014     * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
015     * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016     * See the GNU Lesser General Public License for more details.
017     *
018     * You should have received a copy of the GNU Lesser General Public License along with this
019     * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
020     * Boston, MA 02111-1307, USA.
021     *
022     * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
023     * in the United States and other countries.]
024     *
025     * ------------
026     * $Id: StaticDataRow.java 3525 2007-10-16 11:43:48Z tmorgner $
027     * ------------
028     * (C) Copyright 2000-2005, by Object Refinery Limited.
029     * (C) Copyright 2005-2007, by Pentaho Corporation.
030     */
031    package org.jfree.report.data;
032    
033    import java.util.Collections;
034    import java.util.HashMap;
035    import java.util.Map;
036    
037    import org.jfree.report.DataFlags;
038    import org.jfree.report.DataRow;
039    import org.jfree.report.DataSourceException;
040    import org.jfree.report.util.IntegerCache;
041    
042    /**
043     * This is a static datarow holding a value for each name in the datarow. This
044     * datarow does not hold dataflags and thus does not track the changes done to
045     * the data inside.
046     * <p/>
047     * The StaticDataRow is a derived view and is used to provide a safe collection
048     * of the values of the previous datarow.
049     *
050     * @author Thomas Morgner
051     */
052    public class StaticDataRow implements DataRow
053    {
054      private String[] names;
055      private Object[] values;
056      private Map nameCache;
057    
058      protected StaticDataRow()
059      {
060      }
061    
062      protected StaticDataRow(final StaticDataRow dataRow)
063      {
064        if (dataRow == null)
065        {
066          throw new NullPointerException();
067        }
068    
069        this.nameCache = dataRow.nameCache;
070        this.names = dataRow.names;
071        this.values = dataRow.values;
072      }
073    
074      public StaticDataRow(final DataRow dataRow) throws DataSourceException
075      {
076        if (dataRow == null)
077        {
078          throw new NullPointerException();
079        }
080    
081        final HashMap nameCache = new HashMap();
082        synchronized (dataRow)
083        {
084          final int columnCount = dataRow.getColumnCount();
085          this.names = new String[columnCount];
086          this.values = new Object[dataRow.getColumnCount()];
087          for (int i = 0; i < columnCount; i++)
088          {
089            names[i] = dataRow.getColumnName(i);
090            values[i] = dataRow.get(i);
091            if (names[i] != null)
092            {
093              nameCache.put(names[i], IntegerCache.getInteger(i));
094            }
095          }
096        }
097        this.nameCache = Collections.unmodifiableMap(nameCache);
098      }
099    
100      public StaticDataRow(final String[] names, final Object[] values)
101      {
102        setData(names, values);
103      }
104    
105      protected void setData(final String[] names, final Object[] values)
106      {
107        if (names == null)
108        {
109          throw new NullPointerException();
110        }
111        if (values == null)
112        {
113          throw new NullPointerException();
114        }
115        if (names.length != values.length)
116        {
117          throw new IndexOutOfBoundsException();
118        }
119        this.names = (String[]) names.clone();
120        this.values = (Object[]) values.clone();
121    
122        final HashMap nameCache = new HashMap();
123        for (int i = 0; i < names.length; i++)
124        {
125          final String name = names[i];
126          if (name != null)
127          {
128            nameCache.put(name, IntegerCache.getInteger(i));
129          }
130        }
131        this.nameCache = Collections.unmodifiableMap(nameCache);
132      }
133    
134      protected void updateData(final Object[] values)
135      {
136        if (values.length != this.values.length)
137        {
138          throw new IllegalArgumentException("You should preserve the number of columns.");
139        }
140    
141        this.values = (Object[]) values.clone();
142      }
143    
144      /**
145       * Returns the value of the expression or column in the tablemodel using the
146       * given column number as index. For functions and expressions, the
147       * <code>getValue()</code> method is called and for columns from the
148       * tablemodel the tablemodel method <code>getValueAt(row, column)</code> gets
149       * called.
150       *
151       * @param col the item index.
152       * @return the value.
153       * @throws IllegalStateException if the datarow detected a deadlock.
154       */
155      public Object get(final int col) throws DataSourceException
156      {
157        return values[col];
158      }
159    
160      /**
161       * Returns the value of the function, expression or column using its specific
162       * name. The given name is translated into a valid column number and the the
163       * column is queried. For functions and expressions, the
164       * <code>getValue()</code> method is called and for columns from the
165       * tablemodel the tablemodel method <code>getValueAt(row, column)</code> gets
166       * called.
167       *
168       * @param col the item index.
169       * @return the value.
170       * @throws IllegalStateException if the datarow detected a deadlock.
171       */
172      public Object get(final String col) throws DataSourceException
173      {
174        final Integer idx = (Integer) nameCache.get(col);
175        if (idx == null)
176        {
177          return null;
178        }
179        return values[idx.intValue()];
180      }
181    
182      /**
183       * Returns the name of the column, expression or function. For columns from
184       * the tablemodel, the tablemodels <code>getColumnName</code> method is
185       * called. For functions, expressions and report properties the assigned name
186       * is returned.
187       *
188       * @param col the item index.
189       * @return the name.
190       */
191      public String getColumnName(final int col) throws DataSourceException
192      {
193        return names[col];
194      }
195    
196      /**
197       * Returns the number of columns, expressions and functions and marked
198       * ReportProperties in the report.
199       *
200       * @return the item count.
201       */
202      public int getColumnCount() throws DataSourceException
203      {
204        return values.length;
205      }
206    
207      public DataFlags getFlags(final String col) throws DataSourceException
208      {
209        return new DefaultDataFlags(col, get(col), false);
210      }
211    
212      public DataFlags getFlags(final int col) throws DataSourceException
213      {
214        return new DefaultDataFlags(names[col], values[col], false);
215      }
216    }