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