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.commons.renderOne;
20  
21  import java.io.IOException;
22  import java.util.Iterator;
23  
24  import javax.faces.component.UIComponent;
25  import javax.faces.component.UIComponentBase;
26  import javax.faces.context.FacesContext;
27  
28  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
29  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
30  
31  /**
32   * Tag that allows rendering the first child either by index or the first
33   * rendered one.
34   * <p>
35   * A component that only renders the first child either by index or the first
36   * visible one..
37   * </p>
38   *   
39   * @author Andrew Robinson (latest modification by $Author: lu4242 $)
40   * @version $Revision: 1021615 $ $Date: 2010-10-11 22:45:18 -0500 (Mon, 11 Oct 2010) $
41   */
42  @JSFComponent(
43          name = "mc:renderOne",
44          clazz = "org.apache.myfaces.commons.renderOne.UIRenderOne",
45          tagClass = "org.apache.myfaces.commons.renderOne.UIRenderOneTag")
46  public abstract class AbstractUIRenderOne extends UIComponentBase
47  {
48      public static final String COMPONENT_FAMILY = "javax.faces.Data";
49      public static final String COMPONENT_TYPE = "org.apache.myfaces.commons.UILimitRendered";
50      private static final String RENDERONE_TYPE_FIRST = "first";
51      private static final String RENDERONE_TYPE_INDEX = "index";
52      private static final Integer FIRST_ITEM_INDEX = new Integer("0");
53  
54      /**
55       * The filter type: first|index. first: the first list value should evaluate to a Number 
56       * or a value that can be parsed into an integer. index: A collection, 
57       * array or comma-separated list of numbers. (Default: "first")
58       * 
59       * @return the type
60       */
61      @JSFProperty
62      public abstract String getType();
63  
64      /**
65       * @param type the type to set
66       */
67      public abstract void setType(String type);
68  
69      /**
70       *  The value valid for the type. If this evaluates to null, the first child will 
71       *  be rendered. 
72       *  If the type is "first", this value will be ignored, as "first" always
73       *  renders the first rendered item. 
74       *  If the type is "index", the value must be a number.      
75       *   
76       * @return the value
77       */
78      @JSFProperty
79      public abstract Integer getValue();
80  
81      /**
82       * @param value the value to set
83       */
84      public abstract void setValue(Integer value);
85  
86      /**
87       * @see javax.faces.component.UIComponentBase#getRendersChildren()
88       */
89      public boolean getRendersChildren()
90      {
91          return true;
92      }
93  
94      /**
95       * @see javax.faces.component.UIComponentBase#encodeChildren(javax.faces.context.FacesContext)
96       */
97      public void encodeChildren(FacesContext context) throws IOException
98      {
99          if (!isRendered())
100         {
101             return;
102         }
103 
104         renderChild(context, (UIComponent) selectOneChild());
105     }
106 
107     /**
108      * TODO:Copied from shared_tomahawk.renderkit.RendererUtils
109      * It could be good to move it to myfaces commons utils
110      */
111     private static void renderChild(FacesContext facesContext, UIComponent child)
112             throws IOException
113     {
114         if (!child.isRendered())
115         {
116             return;
117         }
118 
119         child.encodeBegin(facesContext);
120         if (child.getRendersChildren())
121         {
122             child.encodeChildren(facesContext);
123         }
124         else
125         {
126             renderChildren(facesContext, child);
127         }
128         child.encodeEnd(facesContext);
129     }
130 
131     /**
132      * TODO:Copied from shared_tomahawk.renderkit.RendererUtils
133      * It could be good to move it to myfaces commons utils
134      */
135     private static void renderChildren(FacesContext facesContext,
136             UIComponent component) throws IOException
137     {
138         if (component.getChildCount() > 0)
139         {
140             for (Iterator it = component.getChildren().iterator(); it.hasNext();)
141             {
142                 UIComponent child = (UIComponent) it.next();
143                 renderChild(facesContext, child);
144             }
145         }
146     }
147 
148     protected Object selectOneChild()
149     {
150 
151         Integer value = getValue();
152         String type = getType();
153 
154         // default is render by count.
155         if (type == null)
156         {
157             type = RENDERONE_TYPE_FIRST;
158         }
159 
160         // render by index case.
161         if (RENDERONE_TYPE_INDEX.equals(type))
162         {
163 
164             // if value by index is not specified then the first element will be 
165             // rendered only.
166             if (value == null)
167             {
168                 value = FIRST_ITEM_INDEX;
169             }
170 
171             // select the child by index.
172             return selectFirstChildByIndex(value);
173         }
174 
175         // render by count case.
176         if (RENDERONE_TYPE_FIRST.equals(type))
177         {
178 
179             // select the first child that has rendered="true".
180             return selectFirstChildOnly();
181         }
182         else
183         {
184             throw new IllegalArgumentException("type");
185         }
186     }
187 
188     protected Object selectFirstChildOnly()
189     {
190         for (Iterator iter = getChildren().iterator(); iter.hasNext();)
191         {
192             UIComponent child = (UIComponent) iter.next();
193             if (child.isRendered())
194             {
195                 return child;
196             }
197         }
198 
199         return null;
200     }
201 
202     protected Object selectFirstChildByIndex(Integer value)
203     {
204         return getChildren().get(value.intValue());
205     }
206 }