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.DatePickerTag;
28  import org.apache.myfaces.tobago.internal.taglib.DateTag;
29  import org.apache.myfaces.tobago.internal.taglib.FormTag;
30  
31  import javax.el.MethodExpression;
32  import javax.el.ValueExpression;
33  import javax.servlet.jsp.JspException;
34  
35  /**
36   * Renders a date input field with a date picker and 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:date value="#{value}">
47   *     ...
48   *   &lt;/tc:in>
49   * &lt;/tc:panel>
50   * </pre>
51   */
52  @Tag(name = "date")
53  @ExtensionTag(
54      baseClassName = "org.apache.myfaces.tobago.internal.taglib.DateTag",
55      faceletHandler = "org.apache.myfaces.tobago.facelets.extension.DateExtensionHandler")
56  public class DateExtensionTag extends TobagoExtensionBodyTagSupport {
57  
58    private static final long serialVersionUID = 1L;
59  
60    private ValueExpression binding;
61    private ValueExpression converter;
62    private MethodExpression validator;
63    private ValueExpression disabled;
64    private ValueExpression focus;
65    private ValueExpression label;
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 inline;
74    private ValueExpression onchange;
75    private ValueExpression tabIndex;
76    private ValueExpression markup;
77    private ValueExpression validatorMessage;
78    private ValueExpression converterMessage;
79    private ValueExpression requiredMessage;
80    private String fieldId;
81    private String pickerId;
82    private String formId;
83  
84    private ValueExpression labelWidth;
85    private LabelExtensionTag labelTag;
86    private DateTag dateTag;
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 (labelWidth != null) {
100       labelTag.setColumns(createStringValueExpression(labelWidth.getExpressionString() + ";*;auto"));
101     } else {
102       labelTag.setColumns(createStringValueExpression("auto;*;auto"));
103     }
104     if (tip != null) {
105       labelTag.setTip(tip);
106     }
107     if (rendered != null) {
108       labelTag.setRendered(rendered);
109     }
110     if (markup != null) {
111       labelTag.setMarkup(markup);
112     }
113     labelTag.setParent(getParent());
114     labelTag.setJspId(nextJspId());
115     labelTag.doStartTag();
116 
117     dateTag = new DateTag();
118     dateTag.setPageContext(pageContext);
119     if (value != null) {
120       dateTag.setValue(value);
121     }
122     if (valueChangeListener != null) {
123       dateTag.setValueChangeListener(valueChangeListener);
124     }
125     if (placeholder != null) {
126       dateTag.setPlaceholder(placeholder);
127     }
128     if (binding != null) {
129       dateTag.setBinding(binding);
130     }
131     if (converter != null) {
132       dateTag.setConverter(converter);
133     }
134     if (validator != null) {
135       dateTag.setValidator(validator);
136     }
137     if (disabled != null) {
138       dateTag.setDisabled(disabled);
139     }
140     if (onchange != null) {
141       dateTag.setOnchange(onchange);
142     }
143     if (focus != null) {
144       dateTag.setFocus(focus);
145     }
146     if (fieldId != null) {
147       dateTag.setId(fieldId);
148     }
149     if (label != null) {
150       dateTag.setLabel(label);
151     }
152     if (inline != null) {
153       dateTag.setInline(inline);
154     }
155     if (readonly != null) {
156       dateTag.setReadonly(readonly);
157     }
158     if (required != null) {
159       dateTag.setRequired(required);
160     }
161     if (markup != null) {
162       dateTag.setMarkup(markup);
163     }
164     if (tabIndex != null) {
165       dateTag.setTabIndex(tabIndex);
166     }
167     if (validatorMessage != null) {
168       dateTag.setValidatorMessage(validatorMessage);
169     }
170     if (converterMessage != null) {
171       dateTag.setConverterMessage(converterMessage);
172     }
173     if (requiredMessage != null) {
174       dateTag.setRequiredMessage(requiredMessage);
175     }
176 
177     dateTag.setParent(labelTag);
178     dateTag.setJspId(nextJspId());
179     dateTag.doStartTag();
180 
181     return super.doStartTag();
182   }
183 
184   @Override
185   public int doEndTag() throws JspException {
186     dateTag.doEndTag();
187     FormTag formTag = new FormTag();
188     formTag.setPageContext(pageContext);
189     formTag.setParent(labelTag);
190     if (formId != null) {
191       formTag.setId(formId);
192     }
193     formTag.setJspId(nextJspId());
194     formTag.doStartTag();
195 
196     DatePickerTag datePicker = new DatePickerTag();
197     datePicker.setPageContext(pageContext);
198     datePicker.setFor("@auto");
199     if (tabIndex != null) {
200       datePicker.setTabIndex(tabIndex);
201     }
202     if (markup != null) {
203       datePicker.setMarkup(markup);
204     }
205     datePicker.setParent(formTag);
206     if (pickerId != null) {
207       datePicker.setId(pickerId);
208     }
209     datePicker.setJspId(nextJspId());
210     datePicker.doStartTag();
211     datePicker.doEndTag();
212     formTag.doEndTag();
213 
214     labelTag.doEndTag();
215     return super.doEndTag();
216   }
217 
218   @Override
219   public void release() {
220     super.release();
221     binding = null;
222     converter = null;
223     validator = null;
224     disabled = null;
225     labelWidth = null;
226     focus = null;
227     label = null;
228     inline = null;
229     readonly = null;
230     rendered = null;
231     required = null;
232     tip = null;
233     placeholder = null;
234     value = null;
235     valueChangeListener = null;
236     onchange = null;
237     markup = null;
238     tabIndex = null;
239     labelTag = null;
240     dateTag = null;
241     validatorMessage = null;
242     converterMessage = null;
243     requiredMessage = null;
244     fieldId = null;
245     pickerId = null;
246     formId = null;
247   }
248 
249   /**
250    * The current value of this component.
251    */
252   @TagAttribute
253   @UIComponentTagAttribute(type = "java.lang.Object")
254   public void setValue(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   @TagAttribute
265   @UIComponentTagAttribute(
266           type = {},
267           expression = DynamicExpression.METHOD_EXPRESSION_REQUIRED,
268           methodSignature = "javax.faces.event.ValueChangeEvent")
269   public void setValueChangeListener(MethodExpression valueChangeListener) {
270     this.valueChangeListener = valueChangeListener;
271   }
272 
273   /**
274    * Text value to display as label.
275    * If text contains an underscore the next character is used as accesskey.
276    */
277   @TagAttribute
278   @UIComponentTagAttribute()
279   public void setLabel(ValueExpression label) {
280     this.label = label;
281   }
282 
283   /**
284    * Client side script function to add to this component's onchange handler.
285    */
286   @TagAttribute
287   @UIComponentTagAttribute()
288   public void setOnchange(ValueExpression onchange) {
289     this.onchange = onchange;
290   }
291 
292   /**
293    * Flag indicating this component should receive the focus.
294    */
295   @TagAttribute
296   @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
297   public void setFocus(ValueExpression focus) {
298     this.focus = focus;
299   }
300 
301   /**
302    * The value binding expression linking this
303    * component to a property in a backing bean.
304    */
305   @TagAttribute
306   @UIComponentTagAttribute(type = "javax.faces.component.UIComponent")
307   public void setBinding(ValueExpression binding) {
308     this.binding = binding;
309   }
310 
311   /**
312    * Flag indicating whether or not this component should be rendered
313    * (during Render Response Phase), or processed on any subsequent form submit.
314    */
315   @TagAttribute
316   @UIComponentTagAttribute(type = "boolean", defaultValue = "true")
317   public void setRendered(ValueExpression rendered) {
318     this.rendered = rendered;
319   }
320 
321   /**
322    * An expression that specifies the Converter for this component.
323    * If the value binding expression is a String,
324    * the String is used as an ID to look up a Converter.
325    * If the value binding expression is a Converter,
326    * uses that instance as the converter.
327    * The value can either be a static value (ID case only)
328    * or an EL expression.
329    */
330   @TagAttribute
331   @UIComponentTagAttribute(type = "javax.faces.convert.Converter",
332       expression = DynamicExpression.VALUE_EXPRESSION)
333   public void setConverter(ValueExpression converter) {
334     this.converter = converter;
335   }
336 
337   /**
338    * A method binding EL expression,
339    * accepting FacesContext, UIComponent,
340    * and Object parameters, and returning void, that validates
341    * the component's local value.
342    */
343   @TagAttribute
344   @UIComponentTagAttribute(type = {},
345       expression = DynamicExpression.METHOD_EXPRESSION,
346       methodSignature = { "javax.faces.context.FacesContext", "javax.faces.component.UIComponent", "java.lang.Object" })
347   public void setValidator(MethodExpression validator) {
348     this.validator = validator;
349   }
350 
351   /**
352    * Flag indicating this component should rendered as an inline element.
353    * @deprecated This should be handled by e.g. a flow layout manager (since 1.5.0)
354    */
355   @TagAttribute
356   @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
357   @Deprecated
358   public void setInline(ValueExpression inline) {
359     this.inline = inline;
360   }
361 
362   /**
363    * Flag indicating that this component will prohibit changes by the user.
364    */
365   @TagAttribute
366   @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
367   public void setReadonly(ValueExpression readonly) {
368     this.readonly = readonly;
369   }
370 
371   /**
372    * Flag indicating that this element is disabled.
373    */
374   @TagAttribute()
375   @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
376   public void setDisabled(ValueExpression disabled) {
377     this.disabled = disabled;
378   }
379 
380   /**
381    * Flag indicating that a value is required.
382    * If the value is an empty string a
383    * ValidationError occurs and a Error Message is rendered.
384    */
385   @TagAttribute
386   @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
387   public void setRequired(ValueExpression required) {
388     this.required = required;
389   }
390 
391   /**
392    * Text value to display as tooltip.
393    */
394   @TagAttribute
395   @UIComponentTagAttribute()
396   public void setTip(ValueExpression tip) {
397     this.tip = tip;
398   }
399 
400   /**
401    * Displays a short text in the input field, that describes the meaning of this field.
402    * This is part of HTML 5, the theme should emulate the behaviour, when the browser doesn't support it.
403    */
404   @TagAttribute
405   @UIComponentTagAttribute()
406   public void setPlaceholder(ValueExpression placeholder) {
407     this.placeholder = placeholder;
408   }
409 
410    /**
411    * The width for the label component. Default: 'auto'.
412    * This value is used in the gridLayouts columns attribute.
413    * See gridLayout tag for valid values.
414    */
415   @TagAttribute
416   @UIComponentTagAttribute()
417   public void setLabelWidth(ValueExpression labelWidth) {
418     this.labelWidth = labelWidth;
419   }
420 
421   /**
422    * Indicate markup of this component.
423    * Possible value is 'none'. But this can be overridden in the theme.
424    */
425   @TagAttribute
426   @UIComponentTagAttribute(type = "java.lang.String[]", defaultValue = "none")
427   public void setMarkup(ValueExpression markup) {
428     this.markup = markup;
429   }
430 
431   @TagAttribute
432   @UIComponentTagAttribute(type = "java.lang.Integer")
433   public void setTabIndex(ValueExpression tabIndex) {
434     this.tabIndex = tabIndex;
435   }
436 
437   /**
438    * An expression that specifies the validator message
439    */
440   @TagAttribute
441   @UIComponentTagAttribute()
442   public void setValidatorMessage(ValueExpression validatorMessage) {
443     this.validatorMessage = validatorMessage;
444   }
445 
446   /**
447    * An expression that specifies the converter message
448    */
449   @TagAttribute
450   @UIComponentTagAttribute()
451   public void setConverterMessage(ValueExpression converterMessage) {
452     this.converterMessage = converterMessage;
453   }
454 
455   /**
456    * An expression that specifies the required message
457    */
458   @TagAttribute
459   @UIComponentTagAttribute()
460   public void setRequiredMessage(ValueExpression requiredMessage) {
461     this.requiredMessage = requiredMessage;
462   }
463 
464   /**
465    * The component identifier for the input field component inside of the container.
466    * This value must be unique within the closest parent component that is a naming container.
467    */
468   @TagAttribute(rtexprvalue = true)
469   @UIComponentTagAttribute
470   public void setFieldId(String fieldId) {
471     this.fieldId = fieldId;
472   }
473 
474   /**
475    * The component identifier for the automatically created picker component inside of the container.
476    * This value must be unique within the closest parent component that is a naming container.
477    */
478   @TagAttribute(rtexprvalue = true)
479   @UIComponentTagAttribute
480   public void setPickerId(String pickerId) {
481     this.pickerId = pickerId;
482   }
483 
484   /**
485    * The component identifier for the automatically created form 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 setFormId(String formId) {
491     this.formId = formId;
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 }