Coverage Report - javax.faces.model.DataModel
 
Classes in this File Line Coverage Branch Coverage Complexity
DataModel
26%
6/23
8%
1/12
1.867
DataModel$DataModelIterator
0%
0/12
0%
0/2
1.867
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one
 3  
  * or more contributor license agreements.  See the NOTICE file
 4  
  * distributed with this work for additional information
 5  
  * regarding copyright ownership.  The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the
 7  
  * "License"); you may not use this file except in compliance
 8  
  * with the License.  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,
 13  
  * software distributed under the License is distributed on an
 14  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15  
  * KIND, either express or implied.  See the License for the
 16  
  * specific language governing permissions and limitations
 17  
  * under the License.
 18  
  */
 19  
 package javax.faces.model;
 20  
 
 21  
 import java.util.ArrayList;
 22  
 import java.util.Iterator;
 23  
 import java.util.List;
 24  
 import java.util.NoSuchElementException;
 25  
 
 26  
 /**
 27  
   * Represents the data presented by a UIData component, together with
 28  
   * some state information about the currently selected row within the
 29  
   * datalist for use by listeners on UIData components. This class allows
 30  
   * managed bean code to avoid binding directly to UIData components for
 31  
   * typical uses.
 32  
   * <p> 
 33  
   * Note that DataModel and its standard subclasses are not serializable,
 34  
   * as there is no state in a DataModel object itself that needs to be
 35  
   * preserved between render and restore-view. UIData components therefore
 36  
   * do not store their DataModel when serialized; they just evaluate their
 37  
   * "value" EL expression to refetch the object during the 
 38  
   * apply-request-values phase.
 39  
   * <p>
 40  
   * Because DataModel is not serializable, any managed bean that needs to
 41  
   * be serialized and which has a member of type DataModel should therefore
 42  
   * mark that member transient. If there is a need to preserve the datalist
 43  
   * contained within the DataModel then ensure a reference to that list is
 44  
   * stored in a non-transient member, or use a custom serialization method
 45  
   * that explicitly serializes dataModel.getWrappedData.
 46  
   *  
 47  
   * See Javadoc of
 48  
  * <a href="http://java.sun.com/javaee/javaserverfaces/1.2/docs/api/index.html">JSF Specification</a> for more.
 49  
 */
 50  32
 public abstract class DataModel<E> implements Iterable<E>
 51  
 {
 52  2
     private final static DataModelListener[] EMPTY_DATA_MODEL_LISTENER = new DataModelListener[]{};
 53  
     // FIELDS
 54  
     private List<DataModelListener> _listeners;
 55  
     
 56  32
     private DataModelListener[] _cachedListenersArray = null;
 57  
 
 58  
     // METHODS
 59  
     public void addDataModelListener(DataModelListener listener)
 60  
     {
 61  0
         if (listener == null)
 62  
         {
 63  0
             throw new NullPointerException("listener");
 64  
         }
 65  0
         if (_listeners == null)
 66  
         {
 67  0
             _listeners = new ArrayList<DataModelListener>();
 68  
         }
 69  0
         _listeners.add(listener);
 70  0
         _cachedListenersArray = null;
 71  0
     }
 72  
 
 73  
     public DataModelListener[] getDataModelListeners()
 74  
     {
 75  220
         if (_listeners == null)
 76  
         {
 77  220
             return EMPTY_DATA_MODEL_LISTENER;
 78  
         }
 79  0
         if (_cachedListenersArray == null)
 80  
         {
 81  0
             _cachedListenersArray = _listeners.toArray(new DataModelListener[_listeners.size()]);
 82  
         }
 83  0
         return _cachedListenersArray;
 84  
     }
 85  
 
 86  
     /**
 87  
      * <p>
 88  
      * Return the number of rows of data available. 
 89  
      * </p>
 90  
      * <p>
 91  
      * If the number of rows of data available is not known then -1 is returned.
 92  
      * This may happen for DataModels that wrap sources of data such as 
 93  
      * java.sql.ResultSet that provide an iterator to access the "next item"
 94  
      * rather than a fixed-size collection of data.
 95  
      * </p>
 96  
      *
 97  
      * @return the number of rows available.
 98  
      */
 99  
     abstract public int getRowCount();
 100  
 
 101  
     /**
 102  
      * Return the object associated with the current row index.
 103  
      * <p>
 104  
      * Method isRowAvailable may be called before attempting to access
 105  
      * this method, to ensure that the data is available.
 106  
      *
 107  
      * @return The object associated with the current row index.
 108  
      * @throws RuntimeException subclass of some kind if the current row index
 109  
      * is not within the range of the current wrappedData property.
 110  
      */
 111  
     abstract public E getRowData();
 112  
 
 113  
     /**
 114  
      * Get the current row index.
 115  
      * @return The current row index.
 116  
      */
 117  
     abstract public int getRowIndex();
 118  
 
 119  
     /**
 120  
      * Get the entire collection of data associated with this component. Note that
 121  
      * the actual type of the returned object depends upon the concrete
 122  
      * subclass of DataModel; the object will represent an "ordered sequence
 123  
      * of components", but may be implemented as an array, java.util.List,
 124  
      * java.sql.ResultSet or other similar types.
 125  
      *
 126  
      * @return the wrapped object.
 127  
      */
 128  
     abstract public Object getWrappedData();
 129  
 
 130  
     /**
 131  
      * Returns true if a call to getRowData will return a valid object.
 132  
      * @return true if a call to getRowData will return a valid object. false otherwise.
 133  
      */
 134  
     abstract public boolean isRowAvailable();
 135  
     
 136  
     /**
 137  
      * {@inheritDoc}
 138  
      * 
 139  
      * @since 2.0
 140  
      */
 141  
     public Iterator<E> iterator()
 142  
     {
 143  0
         return new DataModelIterator();
 144  
     }
 145  
 
 146  
     public void removeDataModelListener(DataModelListener listener)
 147  
     {
 148  0
         if (listener == null)
 149  
         {
 150  0
             throw new NullPointerException("listener");
 151  
         }
 152  0
         if (_listeners != null)
 153  
         {
 154  0
             _listeners.remove(listener);
 155  
         }
 156  0
         _cachedListenersArray = null;
 157  0
     }
 158  
 
 159  
     /**
 160  
      * Set the current row index. This affects the behaviour of the
 161  
      * getRowData method in particular.
 162  
      * 
 163  
      * @param rowIndex The row index. It may be -1 to indicate "no row",
 164  
      *                 or may be a value between 0 and getRowCount()-1. 
 165  
      */
 166  
     abstract public void setRowIndex(int rowIndex);
 167  
 
 168  
     /**
 169  
      * Set the entire list of data associated with this component. Note that
 170  
      * the actual type of the provided object must match the expectations
 171  
      * of the concrete subclass of DataModel. See getWrappedData.
 172  
      *
 173  
      * @param data The object to be wrapped.
 174  
      */
 175  
     abstract public void setWrappedData(Object data);
 176  
     
 177  32
     private class DataModelIterator implements Iterator<E>
 178  
     {
 179  0
         private int nextRowIndex = 0;
 180  
         
 181  
         public DataModelIterator()
 182  0
         {
 183  0
             setRowIndex(nextRowIndex);
 184  0
         }
 185  
         
 186  
         public boolean hasNext()
 187  
         {
 188  
             //row count could be unknown, like in ResultSetDataModel
 189  0
             return isRowAvailable();
 190  
         }
 191  
 
 192  
         public E next()
 193  
         {
 194  
             // TODO: Go to the EG with this, we need a getRowData(int) for thread safety.
 195  
             //       Or the spec needs to specify that the iterator alters the selected row explicitely
 196  0
             if (hasNext())
 197  
             {
 198  
                 // TODO: Double-check if this cast is safe. It should be...
 199  0
                 E data = (E) getRowData();
 200  0
                 nextRowIndex++;
 201  0
                 setRowIndex(nextRowIndex);
 202  0
                 return data; 
 203  
                 
 204  
             }
 205  
             
 206  0
             throw new NoSuchElementException("Couldn't find any element in DataModel at index " + nextRowIndex);
 207  
         }
 208  
 
 209  
         public void remove()
 210  
         {
 211  0
             throw new UnsupportedOperationException();
 212  
         }
 213  
     }
 214  
 }