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  
20  package org.apache.myfaces.tobago.internal.taglib.extension;
21  
22  import org.apache.myfaces.tobago.apt.annotation.DynamicExpression;
23  import org.apache.myfaces.tobago.apt.annotation.ExtensionTag;
24  import org.apache.myfaces.tobago.apt.annotation.Tag;
25  import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
26  import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
27  import org.apache.myfaces.tobago.internal.taglib.InTag;
28  import org.slf4j.Logger;
29  import org.slf4j.LoggerFactory;
30  
31  import javax.el.MethodExpression;
32  import javax.el.ValueExpression;
33  import javax.servlet.jsp.JspException;
34  
35  /**
36   * Renders a text input field with a label.
37   * <br />
38   * Short syntax of:
39   * <p/>
40   * <pre>
41   * &lt;tc:panel>
42   *   &lt;f:facet name="layout">
43   *     &lt;tc:gridLayout columns="auto;*"/>
44   *   &lt;/f:facet>
45   *   &lt;tc:label value="#{label}" for="@auto"/>
46   *   &lt;tc:in value="#{value}">
47   *     ...
48   *   &lt;/tc:in>
49   * &lt;/tc:panel>
50   * </pre>
51   */
52  
53  @Tag(name = "in")
54  @ExtensionTag(
55      baseClassName = "org.apache.myfaces.tobago.internal.taglib.InTag",
56      faceletHandler = "org.apache.myfaces.tobago.facelets.extension.InExtensionHandler")
57  public class InExtensionTag extends TobagoExtensionBodyTagSupport {
58  
59    private ValueExpression binding;
60    private ValueExpression converter;
61    private MethodExpression validator;
62    private ValueExpression disabled;
63    private ValueExpression focus;
64    private ValueExpression label;
65    private ValueExpression accessKey;
66    private ValueExpression password;
67    private ValueExpression readonly;
68    private ValueExpression rendered;
69    private ValueExpression required;
70    private ValueExpression tip;
71    private ValueExpression placeholder;
72    private ValueExpression value;
73    private MethodExpression valueChangeListener;
74    private ValueExpression onchange;
75    @Deprecated
76    private MethodExpression suggestMethod;
77    @Deprecated
78    private ValueExpression suggestMinChars;
79    @Deprecated
80    private ValueExpression suggestDelay;
81    private ValueExpression markup;
82    private ValueExpression labelWidth;
83    private ValueExpression tabIndex;
84    private ValueExpression validatorMessage;
85    private ValueExpression converterMessage;
86    private ValueExpression requiredMessage;
87    private String fieldId;
88  
89    private LabelExtensionTag labelTag;
90    private InTag inTag;
91  
92    @Override
93    public int doStartTag() throws JspException {
94  
95      labelTag = new LabelExtensionTag();
96      labelTag.setPageContext(pageContext);
97      if (id != null) {
98        labelTag.setId(id);
99      }
100     if (label != null) {
101       labelTag.setValue(label);
102     }
103     if (accessKey != null) {
104       labelTag.setAccessKey(accessKey);
105     }
106     if (tip != null) {
107       labelTag.setTip(tip);
108     }
109     if (rendered != null) {
110       labelTag.setRendered(rendered);
111     }
112     if (labelWidth != null) {
113       labelTag.setColumns(createStringValueExpression(labelWidth.getExpressionString() + ";*"));
114     }
115     if (markup != null) {
116       labelTag.setMarkup(markup);
117     }
118     labelTag.setParent(getParent());
119     labelTag.setJspId(nextJspId());
120     labelTag.doStartTag();
121 
122     inTag = new InTag();
123     inTag.setPageContext(pageContext);
124     if (value != null) {
125       inTag.setValue(value);
126     }
127     if (valueChangeListener != null) {
128       inTag.setValueChangeListener(valueChangeListener);
129     }
130     if (label != null) {
131       inTag.setLabel(label);
132     }
133     if (placeholder != null) {
134       inTag.setPlaceholder(placeholder);
135     }
136     if (binding != null) {
137       inTag.setBinding(binding);
138     }
139     if (converter != null) {
140       inTag.setConverter(converter);
141     }
142     if (validator != null) {
143       inTag.setValidator(validator);
144     }
145     if (onchange != null) {
146       inTag.setOnchange(onchange);
147     }
148     if (suggestMethod != null) {
149       inTag.setSuggestMethod(suggestMethod);
150     }
151     if (suggestMinChars != null) {
152       inTag.setSuggestMinChars(suggestMinChars);
153     }
154     if (suggestDelay != null) {
155       inTag.setSuggestDelay(suggestDelay);
156     }
157     if (disabled != null) {
158       inTag.setDisabled(disabled);
159     }
160     if (focus != null) {
161       inTag.setFocus(focus);
162     }
163     if (fieldId != null) {
164       inTag.setId(fieldId);
165     }
166     if (password != null) {
167       inTag.setPassword(password);
168     }
169     if (readonly != null) {
170       inTag.setReadonly(readonly);
171     }
172     if (required != null) {
173       inTag.setRequired(required);
174     }
175     if (markup != null) {
176       inTag.setMarkup(markup);
177     }
178     if (tabIndex != null) {
179       inTag.setTabIndex(tabIndex);
180     }
181     if (validatorMessage != null) {
182       inTag.setValidatorMessage(validatorMessage);
183     }
184     if (converterMessage != null) {
185       inTag.setConverterMessage(converterMessage);
186     }
187     if (requiredMessage != null) {
188       inTag.setRequiredMessage(requiredMessage);
189     }
190     inTag.setParent(labelTag);
191     inTag.setJspId(nextJspId());
192     inTag.doStartTag();
193 
194     return super.doStartTag();
195   }
196 
197   @Override
198   public int doEndTag() throws JspException {
199     inTag.doEndTag();
200     labelTag.doEndTag();
201     return super.doEndTag();
202   }
203 
204   private static final Logger LOG = LoggerFactory.getLogger(InExtensionTag.class);
205 
206   @Override
207   public void release() {
208     super.release();
209     binding = null;
210     converter = null;
211     validator = null;
212     disabled = null;
213     labelWidth = null;
214     focus = null;
215     label = null;
216     accessKey = null;
217     password = null;
218     readonly = null;
219     rendered = null;
220     required = null;
221     tip = null;
222     placeholder = null;
223     value = null;
224     valueChangeListener = null;
225     onchange = null;
226     suggestMethod = null;
227     suggestMinChars = null;
228     suggestDelay = null;
229     markup = null;
230     tabIndex = null;
231     inTag = null;
232     labelTag = null;
233     validatorMessage = null;
234     converterMessage = null;
235     requiredMessage = null;
236     fieldId = null;
237   }
238 
239   /**
240    * Indicate markup of this component.
241    * Possible value is 'none'. But this can be overridden in the theme.
242    */
243   @TagAttribute
244   @UIComponentTagAttribute(defaultValue = "none", type = "java.lang.String[]")
245   public void setMarkup(final ValueExpression markup) {
246     this.markup = markup;
247   }
248 
249   /**
250    * The current value of this component.
251    */
252   @TagAttribute
253   @UIComponentTagAttribute(type = "java.lang.Object")
254   public void setValue(final ValueExpression value) {
255     this.value = value;
256   }
257 
258   /**
259    * MethodBinding representing a value change listener method
260    * that will be notified when a new value has been set for this input component.
261    * The expression must evaluate to a public method that takes a ValueChangeEvent
262    * parameter, with a return type of void.
263    *
264    * @param valueChangeListener
265    */
266   @TagAttribute
267   @UIComponentTagAttribute(
268       type = {},
269       expression = DynamicExpression.METHOD_EXPRESSION_REQUIRED,
270       methodSignature = "javax.faces.event.ValueChangeEvent")
271   public void setValueChangeListener(final MethodExpression valueChangeListener) {
272     this.valueChangeListener = valueChangeListener;
273   }
274 
275   /**
276    * Text value to display as label.
277    * If text contains an underscore the next character is used as accesskey.
278    */
279   @TagAttribute
280   @UIComponentTagAttribute()
281   public void setLabel(final ValueExpression label) {
282     this.label = label;
283   }
284 
285   /**
286    * The accessKey of this component.
287    */
288   @TagAttribute
289   @UIComponentTagAttribute(type = "java.lang.Character")
290   public void setAccessKey(final javax.el.ValueExpression accessKey) {
291     this.accessKey = accessKey;
292   }
293 
294   /**
295    * Flag indicating this component should receive the focus.
296    */
297   @TagAttribute
298   @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
299   public void setFocus(final ValueExpression focus) {
300     this.focus = focus;
301   }
302 
303   /**
304    * The value binding expression linking this
305    * component to a property in a backing bean.
306    */
307   @TagAttribute
308   @UIComponentTagAttribute(type = "javax.faces.component.UIComponent")
309   public void setBinding(final ValueExpression binding) {
310     this.binding = binding;
311   }
312 
313   /**
314    * Flag indicating whether or not this component should be rendered
315    * (during Render Response Phase), or processed on any subsequent form submit.
316    */
317   @TagAttribute
318   @UIComponentTagAttribute(type = "boolean", defaultValue = "true")
319   public void setRendered(final ValueExpression rendered) {
320     this.rendered = rendered;
321   }
322 
323   /**
324    * An expression that specifies the Converter for this component.
325    * If the value binding expression is a String,
326    * the String is used as an ID to look up a Converter.
327    * If the value binding expression is a Converter,
328    * uses that instance as the converter.
329    * The value can either be a static value (ID case only)
330    * or an EL expression.
331    */
332   @TagAttribute
333   @UIComponentTagAttribute(type = "javax.faces.convert.Converter",
334       expression = DynamicExpression.VALUE_EXPRESSION)
335   public void setConverter(final ValueExpression converter) {
336     this.converter = converter;
337   }
338 
339   /**
340    * Clientside script function to add to this component's onchange handler.
341    */
342   @TagAttribute
343   @UIComponentTagAttribute()
344   public void setOnchange(final ValueExpression onchange) {
345     this.onchange = onchange;
346   }
347 
348   /**
349    * MethodBinding which generates a list of suggested input values based on
350    * the currently entered text, which could be retrieved via getSubmittedValue() on the UIIn.
351    * The expression has to evaluate to a public method which has a javax.faces.component.UIInput parameter
352    * and returns a List&lt;String>(deprecated), a List&lt;org.apache.myfaces.tobago.model.AutoSuggestItem>
353    * or a org.apache.myfaces.tobago.model.AutoSuggestItems.
354    *
355    * @deprecated since 2.0.0, please use tc:suggest
356    */
357   @Deprecated
358   @TagAttribute
359   @UIComponentTagAttribute(type = {},
360       expression = DynamicExpression.METHOD_EXPRESSION_REQUIRED,
361       methodSignature = "javax.faces.component.UIInput")
362   public void setSuggestMethod(final MethodExpression suggestMethod) {
363     this.suggestMethod = suggestMethod;
364   }
365 
366   /**
367    * Minimum number of chars to type before the list will be requested.
368    *
369    * @since 1.5.9
370    * @deprecated since 2.0.0
371    */
372   @Deprecated
373   @TagAttribute
374   @UIComponentTagAttribute(type = "java.lang.Integer", defaultValue = "1")
375   public void setSuggestMinChars(final ValueExpression suggestMinChars) {
376     this.suggestMinChars = suggestMinChars;
377   }
378 
379   /**
380    * Time in milli seconds before the list will be requested.
381    *
382    * @since 1.5.9
383    * @deprecated since 2.0.0
384    */
385   @Deprecated
386   @TagAttribute
387   @UIComponentTagAttribute(type = "java.lang.Integer", defaultValue = "300")
388   public void setSuggestDelay(final ValueExpression suggestDelay) {
389     this.suggestDelay = suggestDelay;
390   }
391 
392   /**
393    * A method binding EL expression,
394    * accepting FacesContext, UIComponent,
395    * and Object parameters, and returning void, that validates
396    * the component's local value.
397    */
398   @TagAttribute
399   @UIComponentTagAttribute(type = {},
400       expression = DynamicExpression.METHOD_EXPRESSION,
401       methodSignature = {"javax.faces.context.FacesContext", "javax.faces.component.UIComponent", "java.lang.Object"})
402   public void setValidator(final MethodExpression validator) {
403     this.validator = validator;
404   }
405 
406   /**
407    * Flag indicating whether or not this component should be rendered as
408    * password field , so you will not see the typed charakters.
409    */
410   @TagAttribute
411   @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
412   public void setPassword(final ValueExpression password) {
413     this.password = password;
414   }
415 
416   /**
417    * Flag indicating that this component will prohibit changes by the user.
418    */
419   @TagAttribute
420   @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
421   public void setReadonly(final ValueExpression readonly) {
422     this.readonly = readonly;
423   }
424 
425   /**
426    * Flag indicating that this element is disabled.
427    */
428   @TagAttribute()
429   @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
430   public void setDisabled(final ValueExpression disabled) {
431     this.disabled = disabled;
432   }
433 
434   /**
435    * Flag indicating that a value is required.
436    * If the value is an empty string a
437    * ValidationError occurs and a Error Message is rendered.
438    */
439   @TagAttribute
440   @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
441   public void setRequired(final ValueExpression required) {
442     this.required = required;
443   }
444 
445   /**
446    * Text value to display as tooltip.
447    */
448   @TagAttribute
449   @UIComponentTagAttribute()
450   public void setTip(final ValueExpression tip) {
451     this.tip = tip;
452   }
453 
454   /**
455    * Displays a short text in the input field, that describes the meaning of this field.
456    * This is part of HTML 5, the theme should emulate the behaviour, when the browser doesn't support it.
457    */
458   @TagAttribute
459   @UIComponentTagAttribute()
460   public void setPlaceholder(final ValueExpression placeholder) {
461     this.placeholder = placeholder;
462   }
463 
464   /**
465    * The width for the label component. Default: 'auto'.
466    * This value is used in the gridLayouts columns attribute.
467    * See gridLayout tag for valid values.
468    */
469   @TagAttribute
470   @UIComponentTagAttribute()
471   public void setLabelWidth(final ValueExpression labelWidth) {
472     this.labelWidth = labelWidth;
473   }
474 
475   @TagAttribute
476   @UIComponentTagAttribute(type = "java.lang.Integer")
477   public void setTabIndex(final ValueExpression tabIndex) {
478     this.tabIndex = tabIndex;
479   }
480 
481   /**
482    * An expression that specifies the validator message
483    */
484   @TagAttribute
485   @UIComponentTagAttribute()
486   public void setValidatorMessage(final ValueExpression validatorMessage) {
487     this.validatorMessage = validatorMessage;
488   }
489 
490   /**
491    * An expression that specifies the converter message
492    */
493   @TagAttribute
494   @UIComponentTagAttribute()
495   public void setConverterMessage(final ValueExpression converterMessage) {
496     this.converterMessage = converterMessage;
497   }
498 
499   /**
500    * An expression that specifies the required message
501    */
502   @TagAttribute
503   @UIComponentTagAttribute()
504   public void setRequiredMessage(final ValueExpression requiredMessage) {
505     this.requiredMessage = requiredMessage;
506   }
507 
508   /**
509    * The component identifier for the input field component inside of the container.
510    * This value must be unique within the closest parent component that is a naming container.
511    */
512   @TagAttribute(rtexprvalue = true)
513   @UIComponentTagAttribute
514   public void setFieldId(final String fieldId) {
515     this.fieldId = fieldId;
516   }
517 
518   /**
519    * The component identifier for this component.
520    * This value must be unique within the closest parent component that is a naming container.
521    * For tx components the id will be set to the container (e. g. the panel).
522    * To set the id of the input field, you have to use the attribute "fieldId".
523    */
524   @TagAttribute(rtexprvalue = true)
525   @UIComponentTagAttribute
526   public void setId(final String id) {
527     super.setId(id);
528   }
529 }