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 }