org.apache.myfaces.custom.date.HtmlDateRenderer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tomahawk Show documentation
Show all versions of tomahawk Show documentation
JSF components and utilities that can be used with any JSF implementation.
This library is compatible with both JSF1.1 and JSF1.2; however for JSF1.2 users there
is an alternative build of Tomahawk available that takes advantage of JSF1.2 features to
offer some additional benefits.
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.myfaces.custom.date;
import java.io.IOException;
import java.text.DateFormatSymbols;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import java.util.StringTokenizer;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.convert.ConverterException;
import org.apache.myfaces.component.UserRoleUtils;
import org.apache.myfaces.custom.calendar.DateBusinessConverter;
import org.apache.myfaces.custom.calendar.DefaultDateBusinessConverter;
import org.apache.myfaces.custom.calendar.FunctionCallProvider;
import org.apache.myfaces.custom.calendar.HtmlCalendarRenderer;
import org.apache.myfaces.custom.calendar.HtmlCalendarRenderer.CalendarDateTimeConverter;
import org.apache.myfaces.custom.date.AbstractHtmlInputDate.UserData;
import org.apache.myfaces.shared_tomahawk.renderkit.JSFAttr;
import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRenderer;
import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
import org.apache.myfaces.shared_tomahawk.renderkit.html.util.JavascriptUtils;
import org.apache.myfaces.shared_tomahawk.util.MessageUtils;
import org.apache.myfaces.tomahawk.util.Constants;
/**
* @JSFRenderer
* renderKitId = "HTML_BASIC"
* family = "javax.faces.Input"
* type = "org.apache.myfaces.Date"
*
* @author Sylvain Vieujot (latest modification by $Author: lu4242 $)
* @version $Revision: 992388 $ $Date: 2010-09-03 12:30:51 -0500 (Fri, 03 Sep 2010) $
*/
public class HtmlDateRenderer extends HtmlRenderer {
/**
* The message identifier of the {@link FacesMessage} to be created if
* the input is not a valid date.
*/
public static final String DATE_MESSAGE_ID = "org.apache.myfaces.Date.INVALID";
private static final String ID_DAY_POSTFIX = ".day";
private static final String ID_MONTH_POSTFIX = ".month";
private static final String ID_YEAR_POSTFIX = ".year";
private static final String ID_HOURS_POSTFIX = ".hours";
private static final String ID_MINUTES_POSTFIX = ".minutes";
private static final String ID_SECONDS_POSTFIX = ".seconds";
private static final String ID_AMPM_POSTFIX = ".ampm";
static public String getClientIdForDaySubcomponent(String clientId)
{
return clientId + ID_DAY_POSTFIX;
}
protected boolean isDisabled(FacesContext facesContext, HtmlInputDate inputDate) {
if( !UserRoleUtils.isEnabledOnUserRole(inputDate) )
return false;
return inputDate.isDisabled();
}
public void encodeEnd(FacesContext facesContext, UIComponent uiComponent) throws IOException {
RendererUtils.checkParamValidity(facesContext, uiComponent, HtmlInputDate.class);
HtmlInputDate inputDate = (HtmlInputDate) uiComponent;
Locale currentLocale = facesContext.getViewRoot().getLocale();
UserData userData = null;
String type = inputDate.getType();
boolean ampm = inputDate.isAmpm();
String clientId = uiComponent.getClientId(facesContext);
if (null == inputDate.getConverter())
{
userData = (UserData) inputDate.getSubmittedValue();
if( userData == null )
userData = inputDate.getUserData(currentLocale);
}
else
{
//Use converter to get the value as string and
//create a UserData decoding it.
String value = org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils.getStringValue(facesContext, inputDate);
//Create a UserData bean
userData = inputDate.getUserData(currentLocale);
if (null != value)
{
StringTokenizer st = new StringTokenizer(value,"\n");
while(st.hasMoreTokens())
{
String token = st.nextToken();
if (token.startsWith("year="))
{
userData.setYear(token.substring(5));
}
if (token.startsWith("month="))
{
userData.setMonth(token.substring(6));
}
if (token.startsWith("day="))
{
userData.setDay(token.substring(4));
}
if (token.startsWith("hours="))
{
userData.setHours(token.substring(6));
}
if (token.startsWith("minutes="))
{
userData.setMinutes(token.substring(8));
}
if (token.startsWith("seconds="))
{
userData.setSeconds(token.substring(8));
}
if (token.startsWith("ampm="))
{
userData.setAmpm(token.substring(5));
}
}
}
}
boolean disabled = isDisabled(facesContext, inputDate);
boolean readonly = inputDate.isReadonly();
ResponseWriter writer = facesContext.getResponseWriter();
HtmlRendererUtils.writePrettyLineSeparator(facesContext);
writer.startElement(HTML.SPAN_ELEM, uiComponent);
writer.writeAttribute(HTML.ID_ATTR, clientId, null);
if( ! (type.equals("time") || type.equals("short_time"))){
encodeInputDay(inputDate, writer, clientId, userData, disabled, readonly);
encodeInputMonth(inputDate, writer, clientId, userData, currentLocale, disabled, readonly);
encodeInputYear(inputDate, writer, clientId, userData, disabled, readonly);
if( inputDate.isPopupCalendar() && ! disabled && ! readonly )
encodePopupCalendarButton(facesContext, uiComponent, writer, clientId, currentLocale);
}
if( type.equals("both") || type.equals("full")){
writer.write(" ");
}
if( ! type.equals("date")){
encodeInputHours(uiComponent, writer, clientId, userData, disabled, readonly);
writer.write(":");
encodeInputMinutes(uiComponent, writer, clientId, userData, disabled, readonly);
if (type.equals("full")|| type.equals("time")) {
writer.write(":");
encodeInputSeconds(uiComponent, writer, clientId, userData, disabled, readonly);
}
if (ampm) {
encodeInputAmpm(uiComponent, writer, clientId, userData, disabled, readonly, currentLocale);
}
}
writer.endElement(HTML.SPAN_ELEM);
}
protected void encodeInputField(UIComponent uiComponent, ResponseWriter writer, String id,
String value, int size, boolean disabled, boolean readonly) throws IOException {
writer.startElement(HTML.INPUT_ELEM, uiComponent);
HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent, HTML.UNIVERSAL_ATTRIBUTES);
HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent, HTML.EVENT_HANDLER_ATTRIBUTES);
HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent, HTML.INPUT_ATTRIBUTES);
HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent, HTML.COMMON_FIELD_EVENT_ATTRIBUTES);
if (disabled) {
writer.writeAttribute(HTML.DISABLED_ATTR, Boolean.TRUE, null);
}
if( readonly ) {
writer.writeAttribute(HTML.READONLY_ATTR, Boolean.TRUE, null);
}
writer.writeAttribute(HTML.ID_ATTR, id, null);
writer.writeAttribute(HTML.NAME_ATTR, id, null);
writer.writeAttribute(HTML.SIZE_ATTR, Integer.toString(size), null);
writer.writeAttribute(HTML.MAXLENGTH_ATTR, Integer.toString(size), null);
if (value != null) {
writer.writeAttribute(HTML.VALUE_ATTR, value, null);
}
writer.endElement(HTML.INPUT_ELEM);
}
protected void encodeInputDay(UIComponent uiComponent, ResponseWriter writer, String clientId,
UserData userData, boolean disabled, boolean readonly) throws IOException {
encodeInputField(uiComponent, writer, getClientIdForDaySubcomponent(clientId), userData.getDay(), 2, disabled, readonly);
}
protected void encodeInputMonth(UIComponent uiComponent, ResponseWriter writer, String clientId, UserData userData, Locale currentLocale,
boolean disabled, boolean readonly) throws IOException {
writer.startElement(HTML.SELECT_ELEM, uiComponent);
writer.writeAttribute(HTML.ID_ATTR, clientId + ID_MONTH_POSTFIX, null);
writer.writeAttribute(HTML.NAME_ATTR, clientId + ID_MONTH_POSTFIX, null);
writer.writeAttribute(HTML.SIZE_ATTR, "1", null);
HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent, HTML.UNIVERSAL_ATTRIBUTES);
HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent, HTML.EVENT_HANDLER_ATTRIBUTES);
HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent, HTML.COMMON_FIELD_EVENT_ATTRIBUTES);
if (disabled) {
writer.writeAttribute(HTML.DISABLED_ATTR, Boolean.TRUE, null);
}
if (readonly) {
writer.writeAttribute(HTML.READONLY_ATTR, Boolean.TRUE, null);
}
int selectedMonth = userData.getMonth() == null ? -1 : Integer.parseInt(userData.getMonth())-1;
String[] months = HtmlCalendarRenderer.mapMonths(new DateFormatSymbols(currentLocale));
encodeEmptyInputMonthSelection(uiComponent, writer, selectedMonth);
for (int i = 0; i < months.length; i++) {
String monthName = months[i];
String monthNumber = Integer.toString(i+1);
writer.write("\t\t");
writer.startElement(HTML.OPTION_ELEM, uiComponent);
writer.writeAttribute(HTML.VALUE_ATTR, monthNumber, null);
if (i == selectedMonth)
writer.writeAttribute(HTML.SELECTED_ATTR, HTML.SELECTED_ATTR, null);
writer.writeText(monthName, null);
writer.endElement(HTML.OPTION_ELEM);
}
// bug #970747: force separate end tag
writer.writeText("", null);
writer.endElement(HTML.SELECT_ELEM);
}
protected void encodeEmptyInputMonthSelection(UIComponent component, ResponseWriter writer, int selectedMonth) throws IOException{
writer.startElement(HTML.OPTION_ELEM, component);
writer.writeAttribute(HTML.VALUE_ATTR, "-1", null);
if(selectedMonth == -1)
writer.writeAttribute(HTML.SELECTED_ATTR, HTML.SELECTED_ATTR, null);
writer.writeText(((HtmlInputDate)component).getEmptyMonthSelection(), null);
writer.endElement(HTML.OPTION_ELEM);
}
protected void encodeInputYear(UIComponent uiComponent, ResponseWriter writer, String clientId,
UserData userData, boolean disabled, boolean readonly) throws IOException {
encodeInputField(uiComponent, writer, clientId + ID_YEAR_POSTFIX, userData.getYear(), 4, disabled, readonly);
}
protected void encodeInputHours(UIComponent uiComponent, ResponseWriter writer, String clientId,
UserData userData, boolean disabled, boolean readonly) throws IOException {
encodeInputField(uiComponent, writer, clientId + ID_HOURS_POSTFIX, userData.getHours(), 2, disabled, readonly);
}
protected void encodeInputMinutes(UIComponent uiComponent, ResponseWriter writer, String clientId,
UserData userData, boolean disabled, boolean readonly) throws IOException {
encodeInputField(uiComponent, writer, clientId + ID_MINUTES_POSTFIX, userData.getMinutes(), 2, disabled, readonly);
}
protected void encodeInputSeconds(UIComponent uiComponent, ResponseWriter writer, String clientId,
UserData userData, boolean disabled, boolean readonly) throws IOException {
encodeInputField(uiComponent, writer, clientId + ID_SECONDS_POSTFIX, userData.getSeconds(), 2, disabled, readonly);
}
protected void encodeAmpmChoice(DateFormatSymbols symbols, UIComponent uiComponent, ResponseWriter writer, int calendar_ampm, int selected) throws IOException {
String[] ampm_choices = symbols.getAmPmStrings();
writer.write("\t\t");
writer.startElement(HTML.OPTION_ELEM, uiComponent);
writer.writeAttribute(HTML.VALUE_ATTR, new Integer(calendar_ampm), null);
if (calendar_ampm == selected)
writer.writeAttribute(HTML.SELECTED_ATTR, HTML.SELECTED_ATTR, null);
writer.writeText(ampm_choices[calendar_ampm], null);
writer.endElement(HTML.OPTION_ELEM);
}
protected void encodeInputAmpm(UIComponent uiComponent, ResponseWriter writer, String clientId,
UserData userData, boolean disabled, boolean readonly, Locale currentLocale) throws IOException {
writer.startElement(HTML.SELECT_ELEM, uiComponent);
writer.writeAttribute(HTML.ID_ATTR, clientId + ID_AMPM_POSTFIX, null);
writer.writeAttribute(HTML.NAME_ATTR, clientId + ID_AMPM_POSTFIX, null);
writer.writeAttribute(HTML.SIZE_ATTR, "1", null);
HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent, HTML.UNIVERSAL_ATTRIBUTES);
HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent, HTML.EVENT_HANDLER_ATTRIBUTES);
HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent, HTML.COMMON_FIELD_EVENT_ATTRIBUTES);
if (disabled) {
writer.writeAttribute(HTML.DISABLED_ATTR, Boolean.TRUE, null);
}
if (readonly) {
writer.writeAttribute(HTML.READONLY_ATTR, Boolean.TRUE, null);
}
DateFormatSymbols symbols = new DateFormatSymbols(currentLocale);
int selectedAmpm = userData.getAmpm() == null ? -1 : Integer.parseInt(userData.getAmpm());
encodeEmtypAmpmChoice(uiComponent, writer, selectedAmpm);
encodeAmpmChoice(symbols, uiComponent, writer, Calendar.AM, selectedAmpm);
encodeAmpmChoice(symbols, uiComponent, writer, Calendar.PM, selectedAmpm);
// bug #970747: force separate end tag
writer.writeText("", null);
writer.endElement(HTML.SELECT_ELEM);
}
protected void encodeEmtypAmpmChoice(UIComponent component, ResponseWriter writer, int selectedAmpm) throws IOException{
writer.startElement(HTML.OPTION_ELEM, component);
writer.writeAttribute(HTML.VALUE_ATTR, "-1", null);
if(selectedAmpm == -1)
writer.writeAttribute(HTML.SELECTED_ATTR, HTML.SELECTED_ATTR, null);
writer.writeText(((HtmlInputDate)component).getEmptyAmpmSelection(), null);
writer.endElement(HTML.OPTION_ELEM);
}
protected void encodePopupCalendarButton(FacesContext facesContext, UIComponent uiComponent, ResponseWriter writer, String clientId, Locale currentLocale) throws IOException{
DateFormatSymbols symbols = new DateFormatSymbols(currentLocale);
HtmlCalendarRenderer.addScriptAndCSSResources(facesContext,uiComponent);
String calendarVar = JavascriptUtils.getValidJavascriptName(
uiComponent.getClientId(facesContext)+"CalendarVar",false);
String dateFormat = CalendarDateTimeConverter.createJSPopupFormat(facesContext, null);
String localizedLanguageScript = HtmlCalendarRenderer.getLocalizedLanguageScript(facesContext,
symbols,Calendar.getInstance(currentLocale).getFirstDayOfWeek(),
uiComponent,calendarVar);
writer.startElement(HTML.SPAN_ELEM,uiComponent);
writer.writeAttribute(HTML.ID_ATTR,uiComponent.getClientId(facesContext)+"Span",
JSFAttr.ID_ATTR);
writer.endElement(HTML.SPAN_ELEM);
writer.startElement(HTML.SCRIPT_ELEM,uiComponent);
writer.writeAttribute(HTML.SCRIPT_TYPE_ATTR,HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT,null);
writer.writeText("var "+calendarVar+"=new org_apache_myfaces_PopupCalendar();\n",null);
writer.write(localizedLanguageScript);
writer.writeText(calendarVar+".init(document.getElementById('"+
uiComponent.getClientId(facesContext)+"Span"+"'));\n",null);
writer.endElement(HTML.SCRIPT_ELEM);
HtmlCalendarRenderer.getScriptBtn(writer, facesContext, uiComponent,
dateFormat,"...",new FunctionCallProvider(){
public String getFunctionCall(FacesContext facesContext, UIComponent uiComponent, String dateFormat)
{
String clientId = uiComponent.getClientId(facesContext);
String clientVar = JavascriptUtils.getValidJavascriptName(clientId+"CalendarVar",true);
return clientVar+"._popUpCalendarForInputDate('"+clientId+"','"+dateFormat+"');";
}
});
}
public void decode(FacesContext facesContext, UIComponent uiComponent) {
RendererUtils.checkParamValidity(facesContext, uiComponent, HtmlInputDate.class);
HtmlInputDate inputDate = (HtmlInputDate) uiComponent;
if( isDisabled(facesContext, inputDate) ) // For safety, do not set the submited value if the component is disabled.
return;
if (null != inputDate.getConverter())
{
//Instead of use a custom object to encode data,
//we have to encode all info in a String, so the converter
//can convert it to a String if the value
//is invalid.
String clientId = inputDate.getClientId(facesContext);
String type = inputDate.getType();
Map requestMap = facesContext.getExternalContext().getRequestParameterMap();
StringBuffer submittedValue = new StringBuffer();
if( ! (type.equals( "time" ) || type.equals( "short_time" )) )
{
submittedValue.append("year=");
submittedValue.append((String) requestMap.get(clientId + ID_YEAR_POSTFIX) );
submittedValue.append("\n");
submittedValue.append("month=");
submittedValue.append((String) requestMap.get(clientId + ID_MONTH_POSTFIX));
submittedValue.append("\n");
submittedValue.append("day=");
submittedValue.append((String) requestMap.get(getClientIdForDaySubcomponent(clientId)) );
submittedValue.append("\n");
}
if( ! type.equals( "date" ) )
{
submittedValue.append("hours=");
submittedValue.append((String) requestMap.get(clientId + ID_HOURS_POSTFIX) );
submittedValue.append("\n");
submittedValue.append("minutes=");
submittedValue.append((String) requestMap.get(clientId + ID_MINUTES_POSTFIX) );
submittedValue.append("\n");
if (type.equals("full") || type.equals("time"))
{
submittedValue.append("seconds=");
submittedValue.append((String) requestMap.get(clientId + ID_SECONDS_POSTFIX) );
submittedValue.append("\n");
}
if (inputDate.isAmpm())
{
submittedValue.append("ampm=");
submittedValue.append((String) requestMap.get(clientId + ID_AMPM_POSTFIX) );
submittedValue.append("\n");
}
}
if (submittedValue.charAt(submittedValue.length()-1) == '\n' )
{
submittedValue.deleteCharAt(submittedValue.length()-1);
}
inputDate.setSubmittedValue( submittedValue.toString() );
}
else
{
//Use AbstractHtmlInputDate.UserData to save submitted value
Locale currentLocale = facesContext.getViewRoot().getLocale();
UserData userData = (UserData) inputDate.getSubmittedValue();
if( userData == null )
userData = inputDate.getUserData(currentLocale);
String clientId = inputDate.getClientId(facesContext);
String type = inputDate.getType();
Map requestMap = facesContext.getExternalContext().getRequestParameterMap();
if( ! (type.equals( "time" ) || type.equals( "short_time" )) ){
userData.setDay( (String) requestMap.get(getClientIdForDaySubcomponent(clientId)) );
userData.setMonth( (String) requestMap.get(clientId + ID_MONTH_POSTFIX) );
userData.setYear( (String) requestMap.get(clientId + ID_YEAR_POSTFIX) );
}
if( ! type.equals( "date" ) ){
userData.setHours( (String) requestMap.get(clientId + ID_HOURS_POSTFIX) );
userData.setMinutes( (String) requestMap.get(clientId + ID_MINUTES_POSTFIX) );
if (type.equals("full") || type.equals("time"))
userData.setSeconds( (String) requestMap.get(clientId + ID_SECONDS_POSTFIX) );
if (inputDate.isAmpm()) {
userData.setAmpm( (String) requestMap.get(clientId + ID_AMPM_POSTFIX) );
}
}
inputDate.setSubmittedValue( userData );
}
}
private DateBusinessConverter getDateBusinessConverter(AbstractHtmlInputDate component)
{
DateBusinessConverter dateBusinessConverter = component.getDateBusinessConverter();
if (dateBusinessConverter == null)
{
dateBusinessConverter = new DefaultDateBusinessConverter();
}
return dateBusinessConverter;
}
public Object getConvertedValue(FacesContext context, UIComponent uiComponent, Object submittedValue) throws ConverterException {
HtmlInputDate inputDate = (HtmlInputDate) uiComponent;
if (inputDate.getConverter() == null)
{
UserData userData = (UserData) submittedValue;
Date date = null;
try {
date = userData.parse();
} catch (ParseException e) {
Object[] args = {uiComponent.getId()};
throw new ConverterException(MessageUtils.getMessage(Constants.TOMAHAWK_DEFAULT_BUNDLE, FacesMessage.SEVERITY_ERROR, DATE_MESSAGE_ID, args, context));
}
return getDateBusinessConverter(inputDate).getBusinessValue(context, inputDate, date);
}
else
{
if (submittedValue != null && !(submittedValue instanceof String))
{
if (RendererUtils.NOTHING.equals(submittedValue))
{
return null;
}
throw new IllegalArgumentException("Submitted value of type String for component : "
+ RendererUtils.getPathToComponent(inputDate) + "expected");
}
return inputDate.getConverter().getAsObject(context, inputDate, (String) submittedValue);
}
}
}