1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.renderkit.html;
20
21 import java.io.IOException;
22 import java.util.EnumSet;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Set;
26 import java.util.logging.Level;
27 import java.util.logging.Logger;
28
29 import jakarta.faces.component.UIComponent;
30 import jakarta.faces.component.ValueHolder;
31 import jakarta.faces.component.behavior.ClientBehavior;
32 import jakarta.faces.component.behavior.ClientBehaviorHolder;
33 import jakarta.faces.component.html.HtmlOutputLabel;
34 import jakarta.faces.component.search.SearchExpressionContext;
35 import jakarta.faces.component.search.SearchExpressionHint;
36 import jakarta.faces.context.FacesContext;
37 import jakarta.faces.context.ResponseWriter;
38
39 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFRenderer;
40 import org.apache.myfaces.shared.component.EscapeCapable;
41 import org.apache.myfaces.shared.renderkit.JSFAttr;
42 import org.apache.myfaces.shared.renderkit.RendererUtils;
43 import org.apache.myfaces.shared.renderkit.html.CommonEventUtils;
44 import org.apache.myfaces.shared.renderkit.html.CommonPropertyUtils;
45 import org.apache.myfaces.shared.renderkit.html.HTML;
46 import org.apache.myfaces.shared.renderkit.html.HtmlRenderer;
47 import org.apache.myfaces.shared.renderkit.html.HtmlRendererUtils;
48 import org.apache.myfaces.shared.renderkit.html.util.ResourceUtils;
49
50
51
52
53
54
55
56
57 @JSFRenderer(renderKitId = "HTML_BASIC", family = "jakarta.faces.Output", type = "jakarta.faces.Label")
58 public class HtmlLabelRenderer extends HtmlRenderer
59 {
60 private static final Logger log = Logger.getLogger(HtmlLabelRenderer.class.getName());
61
62 @Override
63 protected boolean isCommonPropertiesOptimizationEnabled(FacesContext facesContext)
64 {
65 return true;
66 }
67
68 @Override
69 protected boolean isCommonEventsOptimizationEnabled(FacesContext facesContext)
70 {
71 return true;
72 }
73
74 @Override
75 public void decode(FacesContext context, UIComponent component)
76 {
77
78 super.decode(context, component);
79
80 HtmlRendererUtils.decodeClientBehaviors(context, component);
81 }
82
83 @Override
84 public void encodeBegin(FacesContext facesContext, UIComponent uiComponent) throws IOException
85 {
86 super.encodeBegin(facesContext, uiComponent);
87
88 ResponseWriter writer = facesContext.getResponseWriter();
89
90 Map<String, List<ClientBehavior>> behaviors = null;
91 if (uiComponent instanceof ClientBehaviorHolder)
92 {
93 behaviors = ((ClientBehaviorHolder) uiComponent).getClientBehaviors();
94 if (!behaviors.isEmpty())
95 {
96 ResourceUtils.renderDefaultJsfJsInlineIfNecessary(facesContext, writer);
97 }
98 }
99
100 encodeBefore(facesContext, writer, uiComponent);
101
102 writer.startElement(HTML.LABEL_ELEM, uiComponent);
103 if (uiComponent instanceof ClientBehaviorHolder)
104 {
105 if (!behaviors.isEmpty())
106 {
107 HtmlRendererUtils.writeIdAndName(writer, uiComponent, facesContext);
108 }
109 else
110 {
111 HtmlRendererUtils.writeIdIfNecessary(writer, uiComponent, facesContext);
112 }
113 long commonPropertiesMarked = 0L;
114 if (isCommonPropertiesOptimizationEnabled(facesContext))
115 {
116 commonPropertiesMarked = CommonPropertyUtils.getCommonPropertiesMarked(uiComponent);
117 }
118 if (behaviors.isEmpty() && isCommonPropertiesOptimizationEnabled(facesContext))
119 {
120 CommonPropertyUtils.renderEventProperties(writer,
121 commonPropertiesMarked, uiComponent);
122 CommonPropertyUtils.renderFocusBlurEventProperties(writer,
123 commonPropertiesMarked, uiComponent);
124 }
125 else
126 {
127 if (isCommonEventsOptimizationEnabled(facesContext))
128 {
129 Long commonEventsMarked = CommonEventUtils.getCommonEventsMarked(uiComponent);
130 CommonEventUtils.renderBehaviorizedEventHandlers(facesContext, writer,
131 commonPropertiesMarked, commonEventsMarked, uiComponent, behaviors);
132 CommonEventUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(
133 facesContext, writer, commonPropertiesMarked, commonEventsMarked, uiComponent, behaviors);
134 }
135 else
136 {
137 HtmlRendererUtils.renderBehaviorizedEventHandlers(facesContext, writer, uiComponent, behaviors);
138 HtmlRendererUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(
139 facesContext, writer,
140 uiComponent, behaviors);
141 }
142 }
143 if (isCommonPropertiesOptimizationEnabled(facesContext))
144 {
145 CommonPropertyUtils.renderLabelPassthroughPropertiesWithoutEvents(writer,
146 commonPropertiesMarked, uiComponent);
147 }
148 else
149 {
150 HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent,
151 HTML.LABEL_PASSTHROUGH_ATTRIBUTES_WITHOUT_EVENTS);
152 }
153 }
154 else
155 {
156 HtmlRendererUtils.writeIdIfNecessary(writer, uiComponent, facesContext);
157 if (isCommonPropertiesOptimizationEnabled(facesContext))
158 {
159 CommonPropertyUtils.renderLabelPassthroughProperties(writer,
160 CommonPropertyUtils.getCommonPropertiesMarked(uiComponent), uiComponent);
161 }
162 else
163 {
164 HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent, HTML.LABEL_PASSTHROUGH_ATTRIBUTES);
165 }
166 }
167
168 String forAttr = getFor(uiComponent);
169
170 if (forAttr != null)
171 {
172 writer.writeAttribute(HTML.FOR_ATTR, getClientId(facesContext, uiComponent, forAttr), JSFAttr.FOR_ATTR);
173 }
174 else
175 {
176 if (log.isLoggable(Level.WARNING))
177 {
178 log.warning("Attribute 'for' of label component with id " + uiComponent.getClientId(facesContext)
179 + " is not defined");
180 }
181 }
182
183
184
185 if (uiComponent instanceof ValueHolder)
186 {
187 String text = RendererUtils.getStringValue(facesContext, uiComponent);
188 if (text != null)
189 {
190 boolean escape;
191 if (uiComponent instanceof HtmlOutputLabel || uiComponent instanceof EscapeCapable)
192 {
193 escape = ((HtmlOutputLabel)uiComponent).isEscape();
194 }
195 else
196 {
197 escape = RendererUtils.getBooleanAttribute(uiComponent,
198 org.apache.myfaces.shared.renderkit.JSFAttr.ESCAPE_ATTR,
199 true);
200 }
201 if (escape)
202 {
203 writer.writeText(text, org.apache.myfaces.shared.renderkit.JSFAttr.VALUE_ATTR);
204 }
205 else
206 {
207 writer.write(text);
208 }
209 }
210 }
211
212 writer.flush();
213
214 encodeAfterStart(facesContext, writer, uiComponent);
215 }
216
217
218
219
220 protected void encodeAfterStart(FacesContext facesContext, ResponseWriter writer, UIComponent uiComponent)
221 throws IOException
222 {
223 }
224
225
226
227
228 protected void encodeBefore(FacesContext facesContext, ResponseWriter writer, UIComponent uiComponent)
229 throws IOException
230 {
231 }
232
233 protected String getFor(UIComponent component)
234 {
235 if (component instanceof HtmlOutputLabel)
236 {
237 return ((HtmlOutputLabel)component).getFor();
238 }
239
240 return (String)component.getAttributes().get(JSFAttr.FOR_ATTR);
241
242 }
243
244 private static final Set<SearchExpressionHint> EXPRESSION_HINTS =
245 EnumSet.of(SearchExpressionHint.RESOLVE_SINGLE_COMPONENT, SearchExpressionHint.IGNORE_NO_RESULT);
246
247 protected String getClientId(FacesContext facesContext, UIComponent uiComponent, String forAttr)
248 {
249 SearchExpressionContext searchExpressionContext = SearchExpressionContext.createSearchExpressionContext(
250 facesContext, uiComponent, EXPRESSION_HINTS, null);
251
252 return facesContext.getApplication().getSearchExpressionHandler().resolveClientId(
253 searchExpressionContext, forAttr);
254 }
255
256 @Override
257 public void encodeEnd(FacesContext facesContext, UIComponent uiComponent) throws IOException
258 {
259 super.encodeEnd(facesContext, uiComponent);
260
261 ResponseWriter writer = facesContext.getResponseWriter();
262
263 encodeBeforeEnd(facesContext, writer, uiComponent);
264
265 writer.endElement(HTML.LABEL_ELEM);
266
267 encodeAfter(facesContext, writer, uiComponent);
268 }
269
270
271
272
273 protected void encodeBeforeEnd(FacesContext facesContext, ResponseWriter writer, UIComponent uiComponent)
274 throws IOException
275 {
276 }
277
278
279
280
281 protected void encodeAfter(FacesContext facesContext, ResponseWriter writer, UIComponent uiComponent)
282 throws IOException
283 {
284 }
285 }