diff options
Diffstat (limited to 'server/src/com/vaadin/server/LocaleService.java')
-rw-r--r-- | server/src/com/vaadin/server/LocaleService.java | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/server/src/com/vaadin/server/LocaleService.java b/server/src/com/vaadin/server/LocaleService.java new file mode 100644 index 0000000000..347c4da5c6 --- /dev/null +++ b/server/src/com/vaadin/server/LocaleService.java @@ -0,0 +1,211 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed 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 com.vaadin.server; + +import java.text.DateFormat; +import java.text.DateFormatSymbols; +import java.text.SimpleDateFormat; +import java.util.GregorianCalendar; +import java.util.Locale; +import java.util.logging.Logger; + +import com.vaadin.shared.ui.ui.UIState.LocaleData; +import com.vaadin.shared.ui.ui.UIState.LocaleServiceState; +import com.vaadin.ui.UI; + +/** + * Server side service which handles locale and the transmission of locale date + * to the client side LocaleService. + * + * @since 7.1 + * @author Vaadin Ltd + */ +public class LocaleService { + + private UI ui; + + private LocaleServiceState state; + + /** + * Creates a LocaleService bound to the given UI + * + * @since 7.1 + * @param ui + * The UI which owns the LocaleService + */ + public LocaleService(UI ui, LocaleServiceState state) { + this.ui = ui; + this.state = state; + } + + /** + * Retrieves the UI this service is bound to + * + * @since 7.1 + * @return the UI for this service + */ + public UI getUI() { + return ui; + } + + /** + * Adds a locale to be sent to the client (browser) for date and time entry + * etc. All locale specific information is derived from server-side + * {@link Locale} instances and sent to the client when needed, eliminating + * the need to use the {@link Locale} class and all the framework behind it + * on the client. + * + * @param locale + * The locale which is required on the client side + */ + public void addLocale(Locale locale) { + for (LocaleData data : getState(false).localeData) { + if (data.name.equals(locale.toString())) { + // Already there + return; + } + } + + getState(true).localeData.add(createLocaleData(locale)); + } + + /** + * Returns the state for this service + * <p> + * The state is transmitted inside the UI state rather than as an individual + * entity. + * </p> + * + * @since 7.1 + * @param markAsDirty + * true to mark the state as dirty + * @return a LocaleServiceState object that can be read in any case and + * modified if markAsDirty is true + */ + private LocaleServiceState getState(boolean markAsDirty) { + if (markAsDirty) { + getUI().markAsDirty(); + } + + return state; + } + + /** + * Creates a LocaleData instance for transportation to the client + * + * @since 7.1 + * @param locale + * The locale for which to create a LocaleData object + * @return A LocaleData object with information about the given locale + */ + protected LocaleData createLocaleData(Locale locale) { + LocaleData localeData = new LocaleData(); + localeData.name = locale.toString(); + + final DateFormatSymbols dfs = new DateFormatSymbols(locale); + localeData.shortMonthNames = dfs.getShortMonths(); + localeData.monthNames = dfs.getMonths(); + // Client expects 0 based indexing, DateFormatSymbols use 1 based + localeData.shortDayNames = new String[7]; + localeData.dayNames = new String[7]; + String[] sDayNames = dfs.getShortWeekdays(); + String[] lDayNames = dfs.getWeekdays(); + for (int i = 0; i < 7; i++) { + localeData.shortDayNames[i] = sDayNames[i + 1]; + localeData.dayNames[i] = lDayNames[i + 1]; + } + + /* + * First day of week (0 = sunday, 1 = monday) + */ + final java.util.Calendar cal = new GregorianCalendar(locale); + localeData.firstDayOfWeek = cal.getFirstDayOfWeek() - 1; + + /* + * Date formatting (MM/DD/YYYY etc.) + */ + + DateFormat dateFormat = DateFormat.getDateTimeInstance( + DateFormat.SHORT, DateFormat.SHORT, locale); + if (!(dateFormat instanceof SimpleDateFormat)) { + getLogger().warning( + "Unable to get default date pattern for locale " + + locale.toString()); + dateFormat = new SimpleDateFormat(); + } + final String df = ((SimpleDateFormat) dateFormat).toPattern(); + + int timeStart = df.indexOf("H"); + if (timeStart < 0) { + timeStart = df.indexOf("h"); + } + final int ampm_first = df.indexOf("a"); + // E.g. in Korean locale AM/PM is before h:mm + // TODO should take that into consideration on client-side as well, + // now always h:mm a + if (ampm_first > 0 && ampm_first < timeStart) { + timeStart = ampm_first; + } + // Hebrew locale has time before the date + final boolean timeFirst = timeStart == 0; + String dateformat; + if (timeFirst) { + int dateStart = df.indexOf(' '); + if (ampm_first > dateStart) { + dateStart = df.indexOf(' ', ampm_first); + } + dateformat = df.substring(dateStart + 1); + } else { + dateformat = df.substring(0, timeStart - 1); + } + + localeData.dateFormat = dateformat.trim(); + + /* + * Time formatting (24 or 12 hour clock and AM/PM suffixes) + */ + final String timeformat = df.substring(timeStart, df.length()); + /* + * Doesn't return second or milliseconds. + * + * We use timeformat to determine 12/24-hour clock + */ + final boolean twelve_hour_clock = timeformat.indexOf("a") > -1; + // TODO there are other possibilities as well, like 'h' in french + // (ignore them, too complicated) + final String hour_min_delimiter = timeformat.indexOf(".") > -1 ? "." + : ":"; + // outWriter.print("\"tf\":\"" + timeformat + "\","); + localeData.twelveHourClock = twelve_hour_clock; + localeData.hourMinuteDelimiter = hour_min_delimiter; + if (twelve_hour_clock) { + final String[] ampm = dfs.getAmPmStrings(); + localeData.am = ampm[0]; + localeData.pm = ampm[1]; + } + + return localeData; + } + + private static Logger getLogger() { + return Logger.getLogger(LocaleService.class.getName()); + } + +} |