org.richfaces.renderkit.CalendarRendererBase.java Source code

Java tutorial

Introduction

Here is the source code for org.richfaces.renderkit.CalendarRendererBase.java

Source

/**
 * License Agreement.
 *
 *  JBoss RichFaces - Ajax4jsf Component Library
 *
 * Copyright (C) 2007  Exadel, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 */

package org.richfaces.renderkit;

import java.io.IOException;
import java.text.DateFormatSymbols;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.TimeZone;

import javax.el.ValueExpression;
import javax.faces.application.Application;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.convert.DateTimeConverter;
import javax.faces.event.PhaseId;

import org.ajax4jsf.context.AjaxContext;
import org.ajax4jsf.event.AjaxEvent;
import org.ajax4jsf.javascript.JSFunction;
import org.ajax4jsf.javascript.JSFunctionDefinition;
import org.ajax4jsf.javascript.JSReference;
import org.ajax4jsf.javascript.ScriptUtils;
import org.ajax4jsf.renderkit.AjaxRendererUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.richfaces.component.UICalendar;
import org.richfaces.component.util.ComponentUtil;
import org.richfaces.event.CurrentDateChangeEvent;

/**
 * @author Nick Belaevski - mailto:nbelaevski@exadel.com created 08.06.2007
 * 
 */
public class CalendarRendererBase extends TemplateEncoderRendererBase {

    protected static final String MONTH_LABELS_SHORT = "monthLabelsShort";

    protected static final String MONTH_LABELS = "monthLabels";

    protected static final String WEEK_DAY_LABELS_SHORT = "weekDayLabelsShort";

    protected static final String WEEK_DAY_LABELS = "weekDayLabels";

    /**
     * The constant used to resolve id of hidden input placed on the page
     * for storing current date in "MM/yyyy" format.
     * Actual id of hidden input used on the page is #{clientId}InputCurrentDate
     */
    public static final String CURRENT_DATE_INPUT = "InputCurrentDate";

    public static final String CURRENT_DATE_PRELOAD = "PreloadCurrentDate";

    protected static final String MARKUP_SUFFIX = "Markup";

    public static final String CALENDAR_BUNDLE = "org.richfaces.renderkit.calendar";

    private final static Log log = LogFactory.getLog(CalendarRendererBase.class);

    /*
     * (non-Javadoc)
     * 
     * @see org.ajax4jsf.framework.renderer.RendererBase#getComponentClass()
     */
    protected Class<? extends UIComponent> getComponentClass() {
        return UICalendar.class;
    }

    public void addPopupToAjaxRendered(FacesContext context, UICalendar component) {

        AjaxContext ajaxContext = AjaxContext.getCurrentInstance(context);
        Set<String> ajaxRenderedAreas = ajaxContext.getAjaxRenderedAreas();
        String clientId = component.getClientId(context);

        if (ajaxContext.isAjaxRequest() && ajaxRenderedAreas.contains(clientId)) {
            ajaxRenderedAreas.add(clientId + "Popup");

            ajaxRenderedAreas.add(clientId + "IFrame");

            ajaxRenderedAreas.add(clientId + "Script");
        }
    }

    @Override
    public Object getConvertedValue(FacesContext context, UIComponent component, Object submittedValue)
            throws ConverterException {

        if ((context == null) || (component == null)) {
            throw new NullPointerException();
        }

        // skip conversion of already converted date
        if (submittedValue instanceof Date) {
            return (Date) submittedValue;
        }

        // Store submitted value in the local variable as a string
        String newValue = (String) submittedValue;
        // if we have no local value, try to get the valueExpression.
        ValueExpression valueExpression = component.getValueExpression("value");
        Converter converter = null;

        UICalendar calendar = (UICalendar) component;
        converter = calendar.getConverter();

        if ((converter == null) && (valueExpression != null)) {
            Class<? extends Object> converterType = valueExpression.getType(context.getELContext());
            if ((converterType != null) && (converterType != Object.class)) {
                // if getType returns a type for which we support a default
                // conversion, acquire an appropriate converter instance.
                converter = getConverterForClass(converterType, context);
            }
        }

        // in case the converter hasn't been set, try to use default DateTimeConverter
        if (converter == null) {
            converter = createDefaultConverter();
        }
        setupDefaultConverter(converter, calendar);

        return converter.getAsObject(context, component, newValue);
    }

    private Converter getConverterForClass(Class<? extends Object> converterClass, FacesContext context) {
        if (converterClass == null) {
            return null;
        }

        try {
            Application application = context.getApplication();
            return (application.createConverter(converterClass));
        } catch (Exception e) {
            log.warn(e.getLocalizedMessage(), e);
            return null;
        }
    }

    /**
     * Returns hours and minutes from "defaultTime" attribute as a String with
     * special format: hours:"value_hours",minutes:"value_minutes"
     * 
     * @param calendar - UICalendar
     * 
     * @return hours and minutes from "defaultTime" attribute
     */
    public String getPreparedDefaultTime(UICalendar calendar) {
        return calendar.getPreparedDefaultTime();
    }

    /**
     * Overloads getFormattedValue to take a advantage of a previously
     * obtained converter.
     * @param context the FacesContext for the current request
     * @param component UIComponent of interest
     * @param currentValue the current value of <code>component</code>
     * @param converter the component's converter
     * @return the currentValue after any associated Converter has been
     *  applied
     *
     * @throws ConverterException if the value cannot be converted
     */
    protected String getFormattedValue(FacesContext context, UIComponent component, Object currentValue,
            Converter converter) throws ConverterException {

        // formatting is supported only for components that support
        // converting value attributes.
        if (!(component instanceof UICalendar)) {
            if (currentValue != null) {
                return currentValue.toString();
            }
            return null;
        }
        UICalendar calendar = (UICalendar) component;

        // if value is null and no converter attribute is specified, then
        // return a zero length String.
        if (currentValue == null) {
            return "";
        }

        if (converter == null) {
            // If there is a converter attribute, use it to to ask application
            // instance for a converter with this identifier.
            converter = calendar.getConverter();
        }

        if (converter == null) {
            // Do not look for "by-type" converters for Strings
            if (currentValue instanceof String) {
                return (String) currentValue;
            }

            // if converter attribute set, try to acquire a converter
            // using its class type.
            Class<? extends Object> converterType = currentValue.getClass();
            converter = getConverterForClass(converterType, context);

            // if there is no default converter available for this identifier,
            // assume the model type to be String.
            if (converter == null) {
                // in case the converter hasn't been set, try to use default DateTimeConverter
                converter = createDefaultConverter();
            }
        }
        setupDefaultConverter(converter, calendar);

        return converter.getAsString(context, calendar, currentValue);
    }

    /**
     * @param context the FacesContext for the current request
     * @param component UIComponent of interest
     * @param currentValue the current value of <code>component</code>
     *
     * @return the currentValue after any associated Converter has been
     *  applied
     *
     * @throws ConverterException if the value cannot be converted
     */
    protected String getFormattedValue(FacesContext context, UIComponent component, Object currentValue)
            throws ConverterException {
        return getFormattedValue(context, component, currentValue, null);
    }

    /**
     * Creates default <code>DateTimeConverter</code> for the calendar
     * @param calendar - calendar component
     * 
     * @return created converter
     */
    protected static Converter createDefaultConverter() {
        return new DateTimeConverter();
    }

    /**
     * Setup the default converter provided by JSF API
     * (<code>DateTimeConverter</code>) with the component settings 
     * @param converter
     * @param calendar
     * @return
     */
    protected static Converter setupDefaultConverter(Converter converter, UICalendar calendar) {
        // skip id converter is null
        if (converter == null) {
            return null;
        }

        if (converter instanceof DateTimeConverter) {
            DateTimeConverter defaultConverter = (DateTimeConverter) converter;
            defaultConverter.setPattern(calendar.getDatePattern());
            defaultConverter.setLocale(calendar.getAsLocale(calendar.getLocale()));
            defaultConverter.setTimeZone(calendar.getTimeZone());
        }

        return converter;
    }

    protected void doDecode(FacesContext context, UIComponent component) {
        // TODO Auto-generated method stub
        super.doDecode(context, component);

        String clientId = component.getClientId(context);

        Map<String, String> requestParameterMap = context.getExternalContext().getRequestParameterMap();

        String currentDateString = (String) requestParameterMap.get(clientId + CURRENT_DATE_INPUT);

        if (currentDateString != null) {
            CurrentDateChangeEvent ev = new CurrentDateChangeEvent(component, currentDateString);
            ev.setPhaseId(PhaseId.PROCESS_VALIDATIONS);
            ev.queue();
        }

        if (requestParameterMap.get(clientId + CURRENT_DATE_PRELOAD) != null) {
            // TODO nick - nick - queue this event when ValueChangeEvent is
            // queued?
            new AjaxEvent(component).queue();

            AjaxContext ajaxContext = AjaxContext.getCurrentInstance(context);
            if (ajaxContext.isAjaxRequest(context)) {
                ajaxContext.addAreasToProcessFromComponent(context, component);
            }
        }

        String selectedDateString = (String) requestParameterMap.get(clientId + "InputDate");
        if (selectedDateString != null) {
            ((UICalendar) component).setSubmittedValue(selectedDateString);
        }
    }

    public void encodeChildren(FacesContext context, UIComponent calendar) throws IOException {

    }

    public void writeClass(FacesContext context, UIComponent component) throws IOException {

        UICalendar calendar = (UICalendar) component;
        String styleClass = (String) calendar.getAttributes().get("styleClass");
        if (styleClass != null && styleClass.length() != 0) {
            ResponseWriter writer = context.getResponseWriter();
            writer.writeText(",\n className: '" + styleClass + "'", null);
        }
    }

    public void writeDayStyleClass(FacesContext context, UIComponent component) throws IOException {

        UICalendar calendar = (UICalendar) component;
        String dayStyleClass = (String) calendar.getAttributes().get("dayStyleClass");
        if (dayStyleClass != null && dayStyleClass.length() != 0) {
            ResponseWriter writer = context.getResponseWriter();
            writer.writeText(",\n dayStyleClass: " + dayStyleClass, null);
        }

    }

    public void writeIsDayEnabled(FacesContext context, UIComponent component) throws IOException {
        UICalendar calendar = (UICalendar) component;
        String isDayEnabled = (String) calendar.getAttributes().get("isDayEnabled");
        if (isDayEnabled != null && isDayEnabled.length() != 0) {
            ResponseWriter writer = context.getResponseWriter();
            writer.writeText(",\n isDayEnabled: " + isDayEnabled, null);
        }
    }

    public void writeMarkupScriptBody(FacesContext context, UIComponent component, boolean children)
            throws IOException {
        writeScriptBody(context, component, children);
    }

    public void writeOptionalFacetMarkupScriptBody(FacesContext context, UIComponent component, String facetName)
            throws IOException {

        UIComponent facet = component.getFacet(facetName);
        if (facet != null && facet.isRendered()) {
            ResponseWriter writer = context.getResponseWriter();
            writer.writeText(",\n " + facetName + MARKUP_SUFFIX + ": ", null);
            writeMarkupScriptBody(context, facet, false);
        }
    }

    public void dayCellClass(FacesContext context, UIComponent component) throws IOException {
        // if cellWidth/Height is set send dayCellClass to script
        String cellwidth = (String) component.getAttributes().get("cellWidth");
        String cellheight = (String) component.getAttributes().get("cellHeight");
        ResponseWriter writer = context.getResponseWriter();
        String clientId = component.getClientId(context);
        String divStyle = "";
        if (cellwidth != null && cellwidth.length() != 0) {
            if (cellwidth.contains("px") || cellwidth.contains("%")) {
                divStyle = divStyle + "width:" + cellwidth + ";";
            } else {
                divStyle = divStyle + "width:" + cellwidth + "px;";
            }
        }
        if (cellheight != null && cellheight.length() != 0) {
            if (cellheight.contains("px") || cellheight.contains("%")) {
                divStyle = divStyle + "height:" + cellheight.toString() + ";";
            } else {
                divStyle = divStyle + "height:" + cellheight.toString() + "px;";
            }
        }

        if (divStyle.length() != 0) {
            writer.startElement("style", component);
            getUtils().writeAttribute(writer, "type", "text/css");
            writer.writeText("." + clientId.replace(':', '_') + "DayCell{" + divStyle + "}", null);
            writer.endElement("style");
        }
    }

    public void writeDayCellClass(FacesContext context, UIComponent component) throws IOException {

        String cellwidth = (String) component.getAttributes().get("cellWidth");
        String cellheight = (String) component.getAttributes().get("cellHeight");
        ResponseWriter writer = context.getResponseWriter();
        if (cellwidth != null && cellwidth.length() != 0 || cellheight != null && cellheight.length() != 0) {
            String clientId = component.getClientId(context);
            writer.writeText(",\n dayCellClass: '" + clientId.replace(':', '_') + "DayCell'", null);
        }
    }

    public void writeFacetMarkupScriptBody(FacesContext context, UIComponent component, String facetName)
            throws IOException {

        UIComponent facet = component.getFacet(facetName);
        if (facet != null && facet.isRendered()) {
            ResponseWriter writer = context.getResponseWriter();
            writer.writeText(",\n " + facetName + MARKUP_SUFFIX + ": ", null);
            writeMarkupScriptBody(context, facet, false);
        }
    }

    public void writePreloadBody(FacesContext context, UICalendar calendar) throws IOException {
        Object preload = calendar.getPreload();
        if (preload != null) {
            ResponseWriter writer = context.getResponseWriter();
            writer.write(ScriptUtils.toScript(preload));
        }
    }

    public void writeSubmitFunction(FacesContext context, UICalendar calendar) throws IOException {
        ResponseWriter writer = context.getResponseWriter();

        JSFunction ajaxFunction = AjaxRendererUtils.buildAjaxFunction(calendar, context,
                AjaxRendererUtils.AJAX_FUNCTION_NAME);
        ajaxFunction.addParameter(JSReference.NULL);

        HashMap<String, Object> params = new HashMap<String, Object>();
        params.put(calendar.getClientId(context) + CURRENT_DATE_PRELOAD, Boolean.TRUE);

        Map<String, Object> options = AjaxRendererUtils.buildEventOptions(context, calendar, params);
        options.put("calendar", JSReference.THIS);

        String oncomplete = AjaxRendererUtils.getAjaxOncomplete(calendar);
        JSFunctionDefinition oncompleteDefinition = new JSFunctionDefinition();
        oncompleteDefinition.addParameter("request");
        oncompleteDefinition.addParameter("event");
        oncompleteDefinition.addParameter("data");
        oncompleteDefinition.addToBody("this.calendar.load(data, true);");
        if (oncomplete != null) {
            oncompleteDefinition.addToBody(oncomplete);
        }

        options.put("oncomplete", oncompleteDefinition);
        JSReference requestValue = new JSReference("requestValue");
        ajaxFunction.addParameter(options);
        JSFunctionDefinition definition = new JSFunctionDefinition();
        definition.addParameter(requestValue);
        definition.addToBody(ajaxFunction);
        writer.write(definition.toScript());
    }

    public void writeEventHandlerFunction(FacesContext context, UIComponent component, String eventName)
            throws IOException {

        ResponseWriter writer = context.getResponseWriter();
        Object script = component.getAttributes().get(eventName);
        if (script != null && !script.equals("")) {
            JSFunctionDefinition onEventDefinition = new JSFunctionDefinition();
            onEventDefinition.addParameter("event");
            onEventDefinition.addToBody(script);
            writer.writeText(",\n" + eventName + ": " + onEventDefinition.toScript(), null);
        }
    }

    public String getInputValue(FacesContext context, UIComponent component) {
        UICalendar calendar = (UICalendar) component;
        // Fix for myFaces 1.1.x RF-997
        String returnValue = null;
        Object value = calendar.getSubmittedValue();
        if (value != null) {
            try {
                returnValue = getFormattedValue(context, calendar, value);
            } catch (Exception e) {
                if (log.isDebugEnabled()) {
                    log.debug(" InputValue: " + e.toString(), e);
                }
                returnValue = (String) value;
            }
        } else {
            returnValue = getFormattedValue(context, calendar, calendar.getValue());
        }

        return returnValue;
    }

    public void writeSymbols(FacesContext facesContext, UICalendar calendar) throws IOException {
        ResponseWriter writer = facesContext.getResponseWriter();
        Map<String, String[]> symbolsMap = getSymbolsMap(facesContext, calendar);
        Iterator<Map.Entry<String, String[]>> entryIterator = symbolsMap.entrySet().iterator();
        writer.writeText(", \n", null);
        while (entryIterator.hasNext()) {
            Map.Entry<String, String[]> entry = (Map.Entry<String, String[]>) entryIterator.next();

            writer.writeText(ScriptUtils.toScript(entry.getKey()), null);
            writer.writeText(": ", null);
            writer.writeText(ScriptUtils.toScript(entry.getValue()), null);

            if (entryIterator.hasNext()) {
                writer.writeText(", \n", null);
            }
        }
    }

    private static String[] shiftDates(int minimum, int maximum, String[] labels) {
        if (minimum == 0 && (maximum - minimum == labels.length - 1)) {
            return labels;
        }

        String[] shiftedLabels = new String[maximum - minimum + 1];
        System.arraycopy(labels, minimum, shiftedLabels, 0, maximum - minimum + 1);

        return shiftedLabels;
    }

    protected Map<String, String[]> getSymbolsMap(FacesContext facesContext, UICalendar calendar) {
        Map<String, String[]> map = new HashMap<String, String[]>();

        Locale locale = calendar.getAsLocale(calendar.getLocale());
        Calendar cal = calendar.getCalendar();
        int maximum = cal.getActualMaximum(Calendar.DAY_OF_WEEK);
        int minimum = cal.getActualMinimum(Calendar.DAY_OF_WEEK);

        int monthMax = cal.getActualMaximum(Calendar.MONTH);
        int monthMin = cal.getActualMinimum(Calendar.MONTH);

        DateFormatSymbols symbols = new DateFormatSymbols(locale);
        String[] weekDayLabels = ComponentUtil.asArray(calendar.getWeekDayLabels());
        if (weekDayLabels == null) {
            weekDayLabels = symbols.getWeekdays();
            weekDayLabels = shiftDates(minimum, maximum, weekDayLabels);
        }

        String[] weekDayLabelsShort = ComponentUtil.asArray(calendar.getWeekDayLabelsShort());
        if (weekDayLabelsShort == null) {
            weekDayLabelsShort = symbols.getShortWeekdays();
            weekDayLabelsShort = shiftDates(minimum, maximum, weekDayLabelsShort);
        }

        String[] monthLabels = ComponentUtil.asArray(calendar.getMonthLabels());
        if (monthLabels == null) {
            monthLabels = symbols.getMonths();
            monthLabels = shiftDates(monthMin, monthMax, monthLabels);
        }

        String[] monthLabelsShort = ComponentUtil.asArray(calendar.getMonthLabelsShort());
        if (monthLabelsShort == null) {
            monthLabelsShort = symbols.getShortMonths();
            monthLabelsShort = shiftDates(monthMin, monthMax, monthLabelsShort);
        }

        map.put(WEEK_DAY_LABELS, weekDayLabels);
        map.put(WEEK_DAY_LABELS_SHORT, weekDayLabelsShort);
        map.put(MONTH_LABELS, monthLabels);
        map.put(MONTH_LABELS_SHORT, monthLabelsShort);

        return map;
    }

    public String getFirstWeekDay(FacesContext context, UICalendar calendar) throws IOException {
        return String.valueOf(calendar.getFirstWeekDay());
    }

    public String getMinDaysInFirstWeek(FacesContext context, UICalendar calendar) throws IOException {
        return String.valueOf(calendar.getMinDaysInFirstWeek());
    }

    public String getCurrentDateAsString(FacesContext context, UICalendar calendar, Date date) throws IOException {

        Format formatter = new SimpleDateFormat("MM/yyyy");
        return formatter.format(date);
    }

    public String getCurrentDate(FacesContext context, UICalendar calendar, Date date) throws IOException {
        return ScriptUtils.toScript(formatDate(date));
    }

    public String getSelectedDate(FacesContext context, UICalendar calendar) throws IOException {
        Object returnValue = null;

        if (calendar.isValid()) {
            Date date;
            Object value = calendar.getValue();
            date = calendar.getAsDate(value);
            if (date != null) {
                returnValue = formatSelectedDate(calendar.getTimeZone(), date);
            }
        }
        return ScriptUtils.toScript(returnValue);
    }

    public static Object formatDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        JSFunction result = new JSFunction("new Date");
        result.addParameter(Integer.valueOf(calendar.get(Calendar.YEAR)));
        result.addParameter(Integer.valueOf(calendar.get(Calendar.MONTH)));
        result.addParameter(Integer.valueOf(calendar.get(Calendar.DATE)));

        return result;
    }

    public static Object formatSelectedDate(TimeZone timeZone, Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeZone(timeZone);
        calendar.setTime(date);
        JSFunction result = new JSFunction("new Date");
        result.addParameter(Integer.valueOf(calendar.get(Calendar.YEAR)));
        result.addParameter(Integer.valueOf(calendar.get(Calendar.MONTH)));
        result.addParameter(Integer.valueOf(calendar.get(Calendar.DATE)));
        result.addParameter(Integer.valueOf(calendar.get(Calendar.HOUR_OF_DAY)));
        result.addParameter(Integer.valueOf(calendar.get(Calendar.MINUTE)));
        result.addParameter(new Integer(0));
        return result;
    }

    /**
     * Write labels used in the Calendar component, taken from message bundles.
     * Try to use bundle1 at first. If the 1st bundle is null or it doesn't
     * contain requested message key, use the bundle2.
     * @param bundle1 - 1st bundle to be used as a source for messages
     * @param bundle2 - 2nd bundle to be used as a source for messages
     * @param name - name of the requested label
     * @param writer - response writer
     * @throws IOException
     */
    public void writeStringsFromBundle(ResourceBundle bundle1, ResourceBundle bundle2, String name,
            ResponseWriter writer) throws IOException {
        String label = null;
        String bundleKey = "RICH_CALENDAR_" + name.toUpperCase() + "_LABEL";

        if (bundle1 != null) {
            try {
                label = bundle1.getString(bundleKey);
            } catch (MissingResourceException mre) {
                // Current key was not found, ignore this exception;
            }
        }
        // Current key wasn't found in application bundle, use CALENDAR_BUNDLE,
        // if it is not null
        if ((label == null) && (bundle2 != null)) {
            try {
                label = bundle2.getString(bundleKey);
            } catch (MissingResourceException mre) {
                // Current key was not found, ignore this exception;
            }
        }

        writeStringFoundInBundle(name, label, writer);
    }

    public void writeStringFoundInBundle(String name, String value, ResponseWriter writer) throws IOException {
        if (null != value) {
            if (!("close").equals(name.toLowerCase())) {
                writer.writeText(name.toLowerCase() + ":'" + value + "', ", null);
            } else {
                writer.writeText("close:'" + value + "'", null);
            }
        } else {
            if (!("close").equals(name.toLowerCase())) {
                writer.writeText(name.toLowerCase() + ":'" + name + "', ", null);
            } else {
                writer.writeText("close:'x'", null);
            }
        }

    }

    public void writeLabels(FacesContext context, UICalendar calendar) throws IOException {

        ResourceBundle bundle1 = null;
        ResourceBundle bundle2 = null;
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        String messageBundle = context.getApplication().getMessageBundle();
        Object locale = calendar.getLocale();
        if (null != messageBundle) {
            bundle1 = ResourceBundle.getBundle(messageBundle, calendar.getAsLocale(locale), loader);
        }
        try {
            bundle2 = ResourceBundle.getBundle(CALENDAR_BUNDLE, calendar.getAsLocale(locale), loader);

        } catch (MissingResourceException e) {
            //No external bundle was found, ignore this exception.            
        }

        ResponseWriter writer = context.getResponseWriter();
        writer.writeText(",\n labels:{", null);
        if (null != bundle1 || null != bundle2) {
            writeStringsFromBundle(bundle1, bundle2, "Apply", writer);
            writeStringsFromBundle(bundle1, bundle2, "Today", writer);
            writeStringsFromBundle(bundle1, bundle2, "Clean", writer);
            writeStringsFromBundle(bundle1, bundle2, "Cancel", writer);
            writeStringsFromBundle(bundle1, bundle2, "OK", writer);
            writeStringsFromBundle(bundle1, bundle2, "Close", writer);
        } else {
            // No bundles were found, use default labels.
            writer.writeText("apply:'Apply', today:'Today', clean:'Clean', ok:'OK', cancel:'Cancel', close:'x'",
                    null);
        }
        writer.writeText("}", null);

    }
}