com.sun.webui.jsf.component.Calendar Maven / Gradle / Ivy
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2007-2018 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://oss.oracle.com/licenses/CDDL+GPL-1.1
* or LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.webui.jsf.component;
import com.sun.faces.annotation.Component;
import com.sun.faces.annotation.Property;
import com.sun.webui.jsf.converter.DateConverter;
import com.sun.webui.jsf.validator.DateInRangeValidator;
import com.sun.webui.jsf.util.JavaScriptUtilities;
import java.text.DateFormat;
import java.util.Date;
import java.util.TimeZone;
import javax.el.ValueExpression;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.validator.Validator;
/**
* The Calendar component is used to allow a user to select a date.
*/
@Component(type = "com.sun.webui.jsf.Calendar", family = "com.sun.webui.jsf.Calendar", displayName = "Calendar", tagName = "calendar",
helpKey = "projrave_ui_elements_palette_wdstk-jsf1.2_calendar",
propertiesHelpKey = "projrave_ui_elements_palette_wdstk-jsf1.2_propsheets_calendar_props")
public class Calendar extends Field implements DateManager, NamingContainer {
private static final String DATE_PICKER_LINK_FACET = "datePickerLink";//NOI18N
private static final String DATE_PICKER_LINK_ID = "_datePickerLink";//NOI18N
private static final String DATE_PICKER_FACET = "datePicker";//NOI18N
private static final String DATE_PICKER_ID = "_datePicker";//NOI18N
public static final String PATTERN_ID = "_pattern"; //NOI18N
private DateConverter dateConverter = null;
/** Creates a new instance of Calendar */
public Calendar() {
super();
setRendererType("com.sun.webui.jsf.Calendar");
}
/**
* Return the family for this component.
*/
@Override
public String getFamily() {
return "com.sun.webui.jsf.Calendar";
}
/**
* This method returns the ImageHyperlink that serves as the "button" to
* show or hide the calendar date picker display.
*
* @param context The current FacesContext.
* @return The ImageHyperlink to show or hide the calendar date picker.
*/
public ImageHyperlink getDatePickerLink(FacesContext context) {
UIComponent component = getFacet(DATE_PICKER_LINK_FACET);
ImageHyperlink datePickerLink;
if (component instanceof ImageHyperlink) {
datePickerLink = (ImageHyperlink) component;
} else {
datePickerLink = new ImageHyperlink();
getFacets().put(DATE_PICKER_LINK_FACET, datePickerLink);
}
datePickerLink.setId(DATE_PICKER_LINK_ID);
datePickerLink.setAlign("middle"); //NOI18N
// render the image hyperlink to show/hide the calendar
StringBuffer js = new StringBuffer(200);
js.append("javascript: ").append(getJavaScriptObjectName(context)).append(".toggle(); return false;"); //NOI18N
// Don't set Javascript as the URL -- bugtraq #6306848.
datePickerLink.setOnClick(js.toString());
// We should do this, but unfortunately the component can't be enabled
// from the client-side yet.
//component.getAttributes().put("disabled", new Boolean(isDisabled())); //NOI18N
return datePickerLink;
}
public CalendarMonth getDatePicker() {
UIComponent comp = getFacet(DATE_PICKER_FACET);
if (comp == null || !(comp instanceof CalendarMonth)) {
CalendarMonth datePicker = new CalendarMonth();
datePicker.setPopup(true);
datePicker.setId(DATE_PICKER_ID);
getFacets().put(DATE_PICKER_FACET, datePicker);
comp = datePicker;
}
((CalendarMonth) comp).setJavaScriptObjectName(getJavaScriptObjectName(FacesContext.getCurrentInstance()));
return (CalendarMonth) comp;
}
public String getJavaScriptObjectName(FacesContext context) {
return JavaScriptUtilities.getDomNode(getFacesContext(), this);
}
@Override
public Converter getConverter() {
// We add the validator at this point, if needed...
Validator[] validators = getValidators();
int len = validators.length;
boolean found = false;
for (int i = 0; i < len; ++i) {
if (validators[i] instanceof DateInRangeValidator) {
found = true;
break;
}
}
if (!found) {
addValidator(new DateInRangeValidator());
}
Converter converter = super.getConverter();
if (converter == null) {
if (dateConverter == null) {
dateConverter = new DateConverter();
}
converter = dateConverter;
}
return converter;
}
@Override
public String getReadOnlyValueString(FacesContext context) {
if (getValue() == null) {
return "-"; //NOI18N
} else {
return super.getReadOnlyValueString(context);
}
}
public DateFormat getDateFormat() {
return getDatePicker().getDateFormat();
}
// Since the value of the minDate attribute could change, we can't
// cache this in an attribute.
public Date getFirstAvailableDate() {
Date minDate = getMinDate();
if (minDate == null) {
java.util.Calendar calendar = getDatePicker().getCalendar();
calendar.add(java.util.Calendar.YEAR, -100);
calendar.set(java.util.Calendar.HOUR_OF_DAY, 0);
calendar.set(java.util.Calendar.MINUTE, 0);
calendar.set(java.util.Calendar.SECOND, 0);
calendar.set(java.util.Calendar.MILLISECOND, 0);
minDate = calendar.getTime();
}
return minDate;
}
public Date getLastAvailableDate() {
Date maxDate = getMaxDate();
if (maxDate == null) {
Date minDate = getFirstAvailableDate();
java.util.Calendar calendar = getDatePicker().getCalendar();
calendar.setTime(minDate);
calendar.add(java.util.Calendar.YEAR, 200);
calendar.set(java.util.Calendar.HOUR_OF_DAY, 23);
calendar.set(java.util.Calendar.MINUTE, 59);
calendar.set(java.util.Calendar.SECOND, 59);
calendar.set(java.util.Calendar.MILLISECOND, 999);
maxDate = calendar.getTime();
}
return maxDate;
}
/**
* Implement this method so that it returns the DOM ID of the
* HTML element which should receive focus when the component
* receives focus, and to which a component label should apply.
* Usually, this is the first element that accepts input.
*
* @param context The FacesContext for the request
* @return The client id, also the JavaScript element id
*
* @deprecated
* @see #getLabeledElementId
* @see #getFocusElementId
*/
@Override
public String getPrimaryElementID(FacesContext context) {
return getLabeledElementId(context);
}
/**
* Returns the absolute ID of an HTML element suitable for use as
* the value of an HTML LABEL element's for
attribute.
* If the ComplexComponent
has sub-compoents, and one of
* the sub-components is the target of a label, if that sub-component
* is a ComplexComponent
, then
* getLabeledElementId
must called on the sub-component and
* the value returned. The value returned by this
* method call may or may not resolve to a component instance.
*
* @param context The FacesContext used for the request
* @return An abolute id suitable for the value of an HTML LABEL element's
* for
attribute.
*/
@Override
public String getLabeledElementId(FacesContext context) {
// The id of the calendar component is assigned to the
// the HTML table element that lays out an optional
// specified label, an input text field and an icon button
// to launch the calendar.
//
// The element id returned is the text field since this is the
// element that the label, that typically calls this method,
// is interested in so that it can render the required and
// invalid icons appropriately.
//
// Input id is defined in the Field super class of CalendarBase.
// The field component is responsible for the input text field
// as well.
//
return this.getClientId(context).concat(INPUT_ID);
}
/**
* Returns the id of an HTML element suitable to
* receive the focus.
* If the ComplexComponent
has sub-compoents, and one of
* the sub-components is to reveive the focus, if that sub-component
* is a ComplexComponent
, then
* getFocusElementId
must called on the sub-component and
* the value returned. The value returned by this
* method call may or may not resolve to a component instance.
*
* This implementation returns the value of
* getLabeledElementId
.
*
*
* @param context The FacesContext used for the request
*/
@Override
public String getFocusElementId(FacesContext context) {
return getLabeledElementId(context);
}
/**
* Update the datePicker with an explicitly set date format pattern.
*/
public void setDateFormatPattern(String dateFormatPattern) {
_setDateFormatPattern(dateFormatPattern);
CalendarMonth dp = getDatePicker();
dp.setDateFormatPattern(dateFormatPattern);
}
/**
* Update the datePicker with an explicitly set time zone.
*/
public void setTimeZone(TimeZone timeZone) {
_setTimeZone(timeZone);
CalendarMonth dp = getDatePicker();
dp.setTimeZone(timeZone);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Tag attribute methods
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Flag indicating that an input value for this field is mandatory, and
* failure to provide one will trigger a validation error.
*/
@Property(name = "required")
@Override
public void setRequired(boolean required) {
super.setRequired(required);
}
// Hide maxLength
@Property(name = "maxLength", isHidden = true, isAttribute = false)
@Override
public int getMaxLength() {
return super.getMaxLength();
}
// Hide text
@Property(name = "text", isHidden = true, isAttribute = false)
@Override
public Object getText() {
return super.getText();
}
// Hide trim
@Property(name = "trim", isHidden = true, isAttribute = false)
@Override
public boolean isTrim() {
return super.isTrim();
}
/**
* Return the ValueExpression
stored for the
* specified name (if any), respecting any property aliases.
*
* @param name Name of value binding expression to retrieve
*/
@Override
public ValueExpression getValueExpression(String name) {
if (name.equals("selectedDate")) {
return super.getValueExpression("value");
}
return super.getValueExpression(name);
}
/**
* Set the ValueExpression
stored for the
* specified name (if any), respecting any property
* aliases.
*
* @param name Name of value binding to set
* @param binding ValueExpression to set, or null to remove
*/
@Override
public void setValueExpression(String name, ValueExpression binding) {
if (name.equals("selectedDate")) {
super.setValueExpression("value", binding);
return;
}
super.setValueExpression(name, binding);
}
/**
* The date format pattern to use (i.e. yyyy-MM-dd). The
* component uses an instance of
* java.text.SimpleDateFormat
and you may specify
* a pattern to be used by this component, with the following
* restriction: the format pattern must include yyyy
(not
* yy
), MM
, and dd
; and no
* other parts of time may be displayed. If a pattern is not
* specified, a locale-specific default is used.
*
* If you change the date format pattern, you may also need to
* change the dateFormatPatternHelp
attribute. See the
* documentation for that attribute.
*
*/
@Property(name = "dateFormatPattern", displayName = "Date Format Pattern", category = "Appearance", editorClassName = "com.sun.webui.jsf.component.propertyeditors.DateFormatPatternsEditor", shortDescription = "The date format pattern to use (e.g., yyyy-MM-dd).")
private String dateFormatPattern = null;
/**
* The date format pattern to use (i.e. yyyy-MM-dd). The
* component uses an instance of
* java.text.SimpleDateFormat
and you may specify
* a pattern to be used by this component, with the following
* restriction: the format pattern must include yyyy
(not
* yy
), MM
, and dd
; and no
* other parts of time may be displayed. If a pattern is not
* specified, a locale-specific default is used.
*
* If you change the date format pattern, you may also need to
* change the dateFormatPatternHelp
attribute. See the
* documentation for that attribute.
*
*/
public String getDateFormatPattern() {
if (this.dateFormatPattern != null) {
return this.dateFormatPattern;
}
ValueExpression _vb = getValueExpression("dateFormatPattern");
if (_vb != null) {
return (String) _vb.getValue(getFacesContext().getELContext());
}
return null;
}
/**
* The date format pattern to use (i.e. yyyy-MM-dd). The
* component uses an instance of
* java.text.SimpleDateFormat
and you may specify
* a pattern to be used by this component, with the following
* restriction: the format pattern must include yyyy
(not
* yy
), MM
, and dd
; and no
* other parts of time may be displayed. If a pattern is not
* specified, a locale-specific default is used.
*
* If you change the date format pattern, you may also need to
* change the dateFormatPatternHelp
attribute. See the
* documentation for that attribute.
*
* @see #getDateFormatPattern()
*/
private void _setDateFormatPattern(String dateFormatPattern) {
this.dateFormatPattern = dateFormatPattern;
}
/**
* A message below the textfield for the date, indicating the
* string format to use when entering a date as text into the
* textfield.
*
* The component internally relies on an instance of
* java.text.SimpleDateFormat
to produce the hint.
* The default hint is constructed by invoking the
* toLocalizedPattern()
method on the
* SimpleDateFormat
instance and converting this
* String to lower case.
*
* Due to a bug in
* SimpleDateFormat
,
* toLocalizedPattern()
does not actually produce
* locale-appropriate strings for most locales (it works for
* German, but not for other locales). If the default value for
* the dateFormtPattern
is used, the
* component takes care of the localization itself, but if the default
* is overridden, you may need to override the hint on a
* per-locale basis too.
*/
@Property(name = "dateFormatPatternHelp", displayName = "Date Format Pattern Help", category = "Appearance", editorClassName = "com.sun.rave.propertyeditors.StringPropertyEditor")
private String dateFormatPatternHelp = null;
/**
* A message below the textfield for the date, indicating the
* string format to use when entering a date as text into the
* textfield.
*
* The component internally relies on an instance of
* java.text.SimpleDateFormat
to produce the hint.
* The default hint is constructed by invoking the
* toLocalizedPattern()
method on the
* SimpleDateFormat
instance and converting this
* String to lower case.
*
* Due to a bug in
* SimpleDateFormat
,
* toLocalizedPattern()
does not actually produce
* locale-appropriate strings for most locales (it works for
* German, but not for other locales). If the default value for
* the dateFormtPattern
is used, the
* component takes care of the localization itself, but if the default
* is overridden, you may need to override the hint on a
* per-locale basis too.
*/
public String getDateFormatPatternHelp() {
if (this.dateFormatPatternHelp != null) {
return this.dateFormatPatternHelp;
}
ValueExpression _vb = getValueExpression("dateFormatPatternHelp");
if (_vb != null) {
return (String) _vb.getValue(getFacesContext().getELContext());
}
return null;
}
/**
* A message below the textfield for the date, indicating the
* string format to use when entering a date as text into the
* textfield.
*
* The component internally relies on an instance of
* java.text.SimpleDateFormat
to produce the hint.
* The default hint is constructed by invoking the
* toLocalizedPattern()
method on the
* SimpleDateFormat
instance and converting this
* String to lower case.
*
* Due to a bug in
* SimpleDateFormat
,
* toLocalizedPattern()
does not actually produce
* locale-appropriate strings for most locales (it works for
* German, but not for other locales). If the default value for
* the dateFormtPattern
is used, the
* component takes care of the localization itself, but if the default
* is overridden, you may need to override the hint on a
* per-locale basis too.
* @see #getDateFormatPatternHelp()
*/
public void setDateFormatPatternHelp(String dateFormatPatternHelp) {
this.dateFormatPatternHelp = dateFormatPatternHelp;
}
/**
* A java.util.Date
object representing the last
* selectable day. The default value is 200 years after the
* minDate
(which is evaluated first).
* The value of this attribute is reflected in the years that
* are available for selection in the month display. In future
* releases of this component, web application users will also not
* be able to view months after this date, or select days that
* follow this date. At present such dates can be selected, but
* will not be validated when the form is submitted.
*/
@Property(name = "maxDate", displayName = "Last selectable date", category = "Data", editorClassName = "com.sun.rave.propertyeditors.binding.ValueBindingPropertyEditor", shortDescription = "The last selectable date.")
private java.util.Date maxDate = null;
/**
* A java.util.Date
object representing the last
* selectable day. The default value is 200 years after the
* minDate
(which is evaluated first).
* The value of this attribute is reflected in the years that
* are available for selection in the month display. In future
* releases of this component, web application users will also not
* be able to view months after this date, or select days that
* follow this date. At present such dates can be selected, but
* will not be validated when the form is submitted.
*/
public java.util.Date getMaxDate() {
if (this.maxDate != null) {
return this.maxDate;
}
ValueExpression _vb = getValueExpression("maxDate");
if (_vb != null) {
return (java.util.Date) _vb.getValue(getFacesContext().getELContext());
}
return null;
}
/**
* A java.util.Date
object representing the last
* selectable day. The default value is 200 years after the
* minDate
(which is evaluated first).
* The value of this attribute is reflected in the years that
* are available for selection in the month display. In future
* releases of this component, web application users will also not
* be able to view months after this date, or select days that
* follow this date. At present such dates can be selected, but
* will not be validated when the form is submitted.
* @see #getMaxDate()
*/
public void setMaxDate(java.util.Date maxDate) {
this.maxDate = maxDate;
}
/**
* A java.util.Date
object representing the first
* selectable day. The default value is 100 years prior to today's date.
* The value of this attribute is reflected in the years that
* are available for selection in the month display. In future
* releases of this component, web application users will also not
* be able to view months before this date, or select days that
* precede this date. At present such dates can be selected, but
* will not be validated when the form is submitted.
*/
@Property(name = "minDate", displayName = "First selectable date", category = "Data", editorClassName = "com.sun.rave.propertyeditors.binding.ValueBindingPropertyEditor", shortDescription = "The first selectable date.")
private java.util.Date minDate = null;
/**
* A java.util.Date
object representing the first
* selectable day. The default value is 100 years prior to today's date.
* The value of this attribute is reflected in the years that
* are available for selection in the month display. In future
* releases of this component, web application users will also not
* be able to view months before this date, or select days that
* precede this date. At present such dates can be selected, but
* will not be validated when the form is submitted.
*/
public java.util.Date getMinDate() {
if (this.minDate != null) {
return this.minDate;
}
ValueExpression _vb = getValueExpression("minDate");
if (_vb != null) {
return (java.util.Date) _vb.getValue(getFacesContext().getELContext());
}
return null;
}
/**
* A java.util.Date
object representing the first
* selectable day. The default value is 100 years prior to today's date.
* The value of this attribute is reflected in the years that
* are available for selection in the month display. In future
* releases of this component, web application users will also not
* be able to view months before this date, or select days that
* precede this date. At present such dates can be selected, but
* will not be validated when the form is submitted.
* @see #getMinDate()
*/
public void setMinDate(java.util.Date minDate) {
this.minDate = minDate;
}
/**
* A java.util.Date
object representing the currently
* selected calendar date.
*/
@Property(name = "selectedDate", displayName = "Selected Date", category = "Data", editorClassName = "com.sun.rave.propertyeditors.binding.ValueBindingPropertyEditor", shortDescription = "The date currently selected.")
public java.util.Date getSelectedDate() {
return (java.util.Date) getValue();
}
/**
* A java.util.Date
object representing the currently
* selected calendar date.
* @see #getSelectedDate()
*/
public void setSelectedDate(java.util.Date selectedDate) {
setValue((Object) selectedDate);
}
/**
* The java.util.TimeZone
used with this
* component. Unless set, the default TimeZone for the locale in
* javax.faces.component.UIViewRoot
is used.
*/
@Property(name = "timeZone", displayName = "Time Zone", category = "Appearance", isHidden = true)
private java.util.TimeZone timeZone = null;
/**
* The java.util.TimeZone
used with this
* component. Unless set, the default TimeZone for the locale in
* javax.faces.component.UIViewRoot
is used.
*/
public java.util.TimeZone getTimeZone() {
if (this.timeZone != null) {
return this.timeZone;
}
ValueExpression _vb = getValueExpression("timeZone");
if (_vb != null) {
return (java.util.TimeZone) _vb.getValue(getFacesContext().getELContext());
}
return null;
}
/**
* The java.util.TimeZone
used with this
* component. Unless set, the default TimeZone for the locale in
* javax.faces.component.UIViewRoot
is used.
* @see #getTimeZone()
*/
private void _setTimeZone(java.util.TimeZone timeZone) {
this.timeZone = timeZone;
}
/**
* Restore the state of this component.
*/
@Override
public void restoreState(FacesContext _context, Object _state) {
Object _values[] = (Object[]) _state;
super.restoreState(_context, _values[0]);
this.dateFormatPattern = (String) _values[1];
this.dateFormatPatternHelp = (String) _values[2];
this.maxDate = (java.util.Date) _values[3];
this.minDate = (java.util.Date) _values[4];
this.timeZone = (java.util.TimeZone) _values[5];
}
/**
* Save the state of this component.
*/
@Override
public Object saveState(FacesContext _context) {
Object _values[] = new Object[6];
_values[0] = super.saveState(_context);
_values[1] = this.dateFormatPattern;
_values[2] = this.dateFormatPatternHelp;
_values[3] = this.maxDate;
_values[4] = this.minDate;
_values[5] = this.timeZone;
return _values;
}
}