View Javadoc

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 org.apache.myfaces.custom.datalist;
20  
21  import java.util.Iterator;
22  import java.util.Map;
23  
24  import javax.faces.component.UIComponent;
25  import javax.faces.context.FacesContext;
26  
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  import org.apache.myfaces.component.UserRoleAware;
30  
31  /**
32   * Similar to dataTable, but does not render a table. 
33   * 
34   * Instead the layout attribute controls how each dataRow is rendered. 
35   * 
36   * Unless otherwise specified, all attributes accept static values or EL expressions.
37   * 
38   * @JSFComponent
39   *   name = "t:dataList"
40   *   class = "org.apache.myfaces.custom.datalist.HtmlDataList"
41   *   tagClass = "org.apache.myfaces.custom.datalist.HtmlDataListTag"
42   * @since 1.1.7
43   * @author Manfred Geiler (latest modification by $Author: lu4242 $)
44   * @version $Revision: 1327690 $ $Date: 2012-04-18 16:30:58 -0500 (Wed, 18 Apr 2012) $
45   */
46  public abstract class AbstractHtmlDataList
47          extends org.apache.myfaces.component.html.ext.HtmlDataTableHack
48          implements UserRoleAware
49  {
50      public static final String COMPONENT_TYPE = "org.apache.myfaces.HtmlDataList";
51      private static final String DEFAULT_RENDERER_TYPE = "org.apache.myfaces.List";
52          
53      private static Log log = LogFactory.getLog(AbstractHtmlDataList.class);
54      private static final int PROCESS_DECODES = 1;
55      private static final int PROCESS_VALIDATORS = 2; // not currently in use
56      private static final int PROCESS_UPDATES = 3; // not currently in use
57  
58      /**
59       * Throws NullPointerException if context is null.  Sets row index to -1, 
60       * calls processChildren, sets row index to -1.
61       */
62  
63      public void processDecodes(FacesContext context)
64      {
65  
66          if (context == null)
67              throw new NullPointerException("context");
68          if (!isRendered())
69              return;
70  
71          setRowIndex(-1);
72          processChildren(context, PROCESS_DECODES);
73          setRowIndex(-1);
74          try
75          {
76              decode(context);
77          }
78          catch (RuntimeException e)
79          {
80              context.renderResponse();
81              throw e;
82          }        
83      }
84  
85      public void processUpdates(FacesContext context)
86      {
87          if (context == null)
88              throw new NullPointerException("context");
89          if (!isRendered())
90              return;
91  
92          setRowIndex(-1);
93          processChildren(context, PROCESS_UPDATES);
94          setRowIndex(-1);
95          checkUpdateModelError(context);
96      }
97  
98      public void processValidators(FacesContext context)
99      {
100         if (context == null)
101             throw new NullPointerException("context");
102         if (!isRendered())
103             return;
104 
105         setRowIndex(-1);
106         processChildren(context, PROCESS_VALIDATORS);
107         setRowIndex(-1);
108         checkUpdateModelError(context);        
109     }
110 
111     /**
112      * Iterates over all children, processes each according to the specified 
113      * process action if the child is rendered.
114      */
115 
116     public void processChildren(FacesContext context, int processAction)
117     {
118         // use this method for processing other than decode ?
119         int first = getFirst();
120         int rows = getRows();
121         int last = rows == 0 ? getRowCount() : first + rows;
122 
123         if (log.isTraceEnabled())
124         {
125             log.trace("processing " + getChildCount()
126                             + " children: starting at " + first
127                             + ", ending at " + last);
128         }
129 
130         for (int rowIndex = first; last == -1 || rowIndex < last; rowIndex++)
131         {
132 
133             setRowIndex(rowIndex);
134 
135             if (!isRowAvailable())
136             {
137                 if (log.isTraceEnabled())
138                 {
139                     log.trace("scrolled past the last row, aborting");
140                 }
141                 break;
142             }
143 
144             for (Iterator it = getChildren().iterator(); it.hasNext();)
145             {
146                 UIComponent child = (UIComponent) it.next();
147                 if (child.isRendered())
148                     process(context, child, processAction);
149             }
150         }
151     }
152 
153     /**
154      * Copy and pasted from UIData in order to maintain binary compatibility.
155      */
156 
157     private void process(FacesContext context, UIComponent component,
158             int processAction)
159     {
160         switch (processAction)
161         {
162         case PROCESS_DECODES:
163             component.processDecodes(context);
164             break;
165         case PROCESS_VALIDATORS:
166             component.processValidators(context);
167             break;
168         case PROCESS_UPDATES:
169             component.processUpdates(context);
170             break;
171         }
172     }
173     
174     public void setRowIndex(int rowIndex)
175     {
176         super.setRowIndex(rowIndex);
177         String rowIndexVar = getRowIndexVar();
178         String rowCountVar = getRowCountVar();
179         if (rowIndexVar != null || rowCountVar != null)
180         {
181             Map requestMap = FacesContext.getCurrentInstance().getExternalContext().getRequestMap();
182             if (rowIndex >= 0)
183             {
184                 //regular row index, update request scope variables
185                 if (rowIndexVar != null)
186                 {
187                     requestMap.put(getRowIndexVar(), new Integer(rowIndex));
188                 }
189                 if (rowCountVar != null)
190                 {
191                     requestMap.put(getRowCountVar(), new Integer(getRowCount()));
192                 }
193             }
194             else
195             {
196                 //rowIndex == -1 means end of loop --> remove request scope variables
197                 if (rowIndexVar != null)
198                 {
199                     requestMap.remove(getRowIndexVar());
200                 }
201                 if (rowCountVar != null)
202                 {
203                     requestMap.remove(getRowCountVar());
204                 }
205             }
206         }
207     }
208 
209     protected void restoreDescendantComponentStates(Object state)
210     {
211         restoreDescendantComponentStates(getChildren().iterator(), state, true);
212     }
213 
214     protected Object saveDescendantComponentStates()
215     {
216         return saveDescendantComponentStates(getChildren().iterator(), true);
217     }
218 
219     /**
220      * A parameter name, under which the rowCount is set in request 
221      * scope similar to the var parameter.
222      * 
223      * @JSFProperty
224      */
225     public abstract String getRowCountVar();
226     
227     /**
228      *  A parameter name, under which the current rowIndex is set in 
229      *  request scope similar to the var parameter.
230      * 
231      * @JSFProperty
232      */
233     public abstract String getRowIndexVar();
234 
235     /**
236      * simple|unorderedList|orderedList
237      * <ul>
238      *   <li>simple = for each dataRow all children are simply rendered</li>
239      *   <li>unorderedList = the list is rendered as HTML unordered list (= bullet list)</li>
240      *   <li>orderedList = the list is rendered as HTML ordered list</li>
241      * </ul>
242      * Default: simple
243      * 
244      * @JSFProperty
245      */
246     public abstract String getLayout();
247     
248     /**
249      * CSS class to be applied to individual items in the list
250      * 
251      * @JSFProperty
252      */
253     public abstract String getItemStyleClass();
254     
255     /**
256      * OnClick handler to be applied to individual items in the list
257      * 
258      * @JSFProperty
259      */
260     public abstract String getItemOnClick();
261 }