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.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.shared_tomahawk.renderkit.RendererUtils;
29  
30  /**
31   * Tag that allows rendering the first child either by index or the first
32   * rendered one.
33   * <p>
34   * A component that only renders the first child either by index or the first
35   * visible one..
36   * </p>
37   * @JSFComponent
38   *   name = "s:renderOne"
39   *   class = "org.apache.myfaces.custom.renderOne.UIRenderOne"
40   *   tagClass = "org.apache.myfaces.custom.renderOne.UIRenderOneTag"
41   *   
42   * @author Andrew Robinson (latest modification by $Author: skitching $)
43   * @version $Revision: 676950 $ $Date: 2008-07-15 19:09:46 +0300 (Tue, 15 Jul 2008) $
44   */
45  public abstract class AbstractUIRenderOne extends UIComponentBase
46  {
47      public static final String COMPONENT_FAMILY = "javax.faces.Data";
48      public static final String COMPONENT_TYPE = "org.apache.myfaces.UILimitRendered";
49      private static final String RENDERONE_TYPE_FIRST = "first";
50      private static final String RENDERONE_TYPE_INDEX = "index";
51      private static final Integer FIRST_ITEM_INDEX = new Integer("0");
52              
53      /**
54       * The filter type: first|index. first: the first list value should evaluate to a Number 
55       * or a value that can be parsed into an integer. index: A collection, 
56       * array or comma-separated list of numbers. (Default: "first")
57       * 
58       * @JSFProperty
59       * @return the type
60       */
61      public abstract String getType();
62  
63      /**
64       * @param type the type to set
65       */
66      public abstract void setType(String type);
67  
68      /**
69       *  The value valid for the type. If this evaluates to null, the first child will 
70       *  be rendered. 
71       *  If the type is "first", this value will be ignored, as "first" always
72       *  renders the first rendered item. 
73       *  If the type is "index", the value must be a number.      
74       *   
75       * @JSFProperty
76       * @return the value
77       */
78      public abstract Integer getValue();
79  
80      /**
81       * @param value the value to set
82       */
83      public abstract void setValue(Integer value);
84      
85      /**
86       * @see javax.faces.component.UIComponentBase#getRendersChildren()
87       */
88      public boolean getRendersChildren()
89      {
90          return true;
91      }
92      
93      /**
94       * @see javax.faces.component.UIComponentBase#encodeChildren(javax.faces.context.FacesContext)
95       */
96      public void encodeChildren(FacesContext context) throws IOException
97      {
98          if (!isRendered()) 
99          {
100             return;
101         }
102 
103         RendererUtils.renderChild(context, (UIComponent)selectOneChild());
104     }
105     
106     protected Object selectOneChild()
107     {
108       
109       Integer value = getValue();
110       String type = getType();
111       
112       // default is render by count.
113       if (type == null) 
114       {
115           type = RENDERONE_TYPE_FIRST;
116       }
117       
118       // render by index case.
119       if (RENDERONE_TYPE_INDEX.equals(type)) 
120       {
121           
122           // if value by index is not specified then the first element will be 
123           // rendered only.
124           if (value == null) 
125           {
126               value = FIRST_ITEM_INDEX;
127           }
128           
129           // select the child by index.
130           return selectFirstChildByIndex(value);
131       } 
132      
133       // render by count case.
134       if (RENDERONE_TYPE_FIRST.equals(type)) 
135       {
136           
137           // select the first child that has rendered="true".
138           return selectFirstChildOnly();
139       } 
140       else 
141       {
142           throw new IllegalArgumentException("type");
143       }
144     }
145     
146     protected Object selectFirstChildOnly()
147     {
148         for (Iterator iter = getChildren().iterator(); iter.hasNext();)
149         {
150             UIComponent child = (UIComponent)iter.next();
151             if (child.isRendered())
152             {
153                 return child;
154             }
155         }
156         
157         return null;
158     }
159         
160     protected Object selectFirstChildByIndex(Integer value)
161     {      
162         return getChildren().get(value.intValue());
163     }
164 }