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.List;
23
24 /**
25 * Represents the data presented by a UIData component, together with
26 * some state information about the currently selected row within the
27 * datalist for use by listeners on UIData components. This class allows
28 * managed bean code to avoid binding directly to UIData components for
29 * typical uses.
30 * <p>
31 * Note that DataModel and its standard subclasses are not serializable,
32 * as there is no state in a DataModel object itself that needs to be
33 * preserved between render and restore-view. UIData components therefore
34 * do not store their DataModel when serialized; they just evaluate their
35 * "value" EL expression to refetch the object during the
36 * apply-request-values phase.
37 * <p>
38 * Because DataModel is not serializable, any managed bean that needs to
39 * be serialized and which has a member of type DataModel should therefore
40 * mark that member transient. If there is a need to preserve the datalist
41 * contained within the DataModel then ensure a reference to that list is
42 * stored in a non-transient member, or use a custom serialization method
43 * that explicitly serializes dataModel.getWrappedData.
44 *
45 * See Javadoc of <a href="http://java.sun.com/javaee/javaserverfaces/1.2/docs/api/index.html">JSF Specification</a> for more.
46 *
47 * @author Thomas Spiegl (latest modification by $Author: lu4242 $)
48 * @version $Revision: 1203272 $ $Date: 2011-11-17 12:06:55 -0500 (Thu, 17 Nov 2011) $
49 */
50 public abstract class DataModel
51 {
52 private final static DataModelListener[] EMPTY_DATA_MODEL_LISTENER = new DataModelListener[]{};
53 // FIELDS
54 private List<DataModelListener> _listeners;
55
56 private DataModelListener[] _cachedListenersArray = null;
57
58 // METHODS
59 public void addDataModelListener(DataModelListener listener)
60 {
61 if (listener == null) throw new NullPointerException("listener");
62 if (_listeners == null)
63 {
64 _listeners = new ArrayList<DataModelListener>();
65 }
66 _listeners.add(listener);
67 _cachedListenersArray = null;
68 }
69
70 public DataModelListener[] getDataModelListeners()
71 {
72 if (_listeners == null)
73 {
74 return EMPTY_DATA_MODEL_LISTENER;
75 }
76 if (_cachedListenersArray == null)
77 {
78 _cachedListenersArray = _listeners.toArray(new DataModelListener[_listeners.size()]);
79 }
80 return _cachedListenersArray;
81 }
82
83 /**
84 * <p>
85 * Return the number of rows of data available.
86 * </p>
87 * <p>
88 * If the number of rows of data available is not known then -1 is returned.
89 * This may happen for DataModels that wrap sources of data such as
90 * java.sql.ResultSet that provide an iterator to access the "next item"
91 * rather than a fixed-size collection of data.
92 * </p>
93 *
94 * @return the number of rows available.
95 */
96 abstract public int getRowCount();
97
98 /**
99 * Return the object associated with the current row index.
100 * <p>
101 * Method isRowAvailable may be called before attempting to access
102 * this method, to ensure that the data is available.
103 *
104 * @return The object associated with the current row index.
105 * @throws RuntimeException subclass of some kind if the current row index
106 * is not within the range of the current wrappedData property.
107 */
108 abstract public Object getRowData();
109
110 /**
111 * Get the current row index.
112 * @return The current row index.
113 */
114 abstract public int getRowIndex();
115
116 /**
117 * Get the entire collection of data associated with this component. Note that
118 * the actual type of the returned object depends upon the concrete
119 * subclass of DataModel; the object will represent an "ordered sequence
120 * of components", but may be implemented as an array, java.util.List,
121 * java.sql.ResultSet or other similar types.
122 *
123 * @return the wrapped object.
124 */
125 abstract public Object getWrappedData();
126
127 /**
128 * Returns true if a call to getRowData will return a valid object.
129 * @return true if a call to getRowData will return a valid object. false otherwise.
130 */
131 abstract public boolean isRowAvailable();
132
133 public void removeDataModelListener(DataModelListener listener)
134 {
135 if (listener == null) throw new NullPointerException("listener");
136 if (_listeners != null)
137 {
138 _listeners.remove(listener);
139 }
140 _cachedListenersArray = null;
141 }
142
143 /**
144 * Set the current row index. This affects the behaviour of the
145 * getRowData method in particular.
146 *
147 * @param rowIndex The row index. It may be -1 to indicate "no row",
148 * or may be a value between 0 and getRowCount()-1.
149 */
150 abstract public void setRowIndex(int rowIndex);
151
152 /**
153 * Set the entire list of data associated with this component. Note that
154 * the actual type of the provided object must match the expectations
155 * of the concrete subclass of DataModel. See getWrappedData.
156 *
157 * @param data The object to be wrapped.
158 */
159 abstract public void setWrappedData(Object data);
160 }