]> source.dussan.org Git - vaadin-framework.git/commitdiff
Moved Locale data handling to LocaleService (#11378)
authorArtur Signell <artur@vaadin.com>
Tue, 28 May 2013 09:00:15 +0000 (12:00 +0300)
committerVaadin Code Review <review@vaadin.com>
Wed, 29 May 2013 12:33:17 +0000 (12:33 +0000)
The locale data is now tracked per UI instance and no longer sent in every request.

Change-Id: I4bebd00327da6f8d812181fd76a85eb6196d0010

client/src/com/vaadin/client/ApplicationConnection.java
client/src/com/vaadin/client/LocaleService.java
server/src/com/vaadin/server/JsonPaintTarget.java
server/src/com/vaadin/server/LegacyCommunicationManager.java
server/src/com/vaadin/server/LocaleService.java [new file with mode: 0644]
server/src/com/vaadin/server/communication/LocaleWriter.java [deleted file]
server/src/com/vaadin/server/communication/UidlWriter.java
server/src/com/vaadin/ui/AbstractComponent.java
server/src/com/vaadin/ui/UI.java
shared/src/com/vaadin/shared/ui/ui/UIState.java
uitest/src/com/vaadin/tests/components/datefield/DateFieldLocale.java

index 087ee87262b440eec871fbffa1fd437ea584bc95..24275dadb9e4fbc434ce57cf2e344e7f73f4c6f7 100644 (file)
@@ -1350,16 +1350,6 @@ public class ApplicationConnection {
                 handleUIDLDuration.logDuration(" * Loading widgets completed",
                         10);
 
-                Profiler.enter("Handling locales");
-                if (json.containsKey("locales")) {
-                    VConsole.log(" * Handling locales");
-                    // Store locale data
-                    JsArray<ValueMap> valueMapArray = json
-                            .getJSValueMapArray("locales");
-                    LocaleService.addLocales(valueMapArray);
-                }
-                Profiler.leave("Handling locales");
-
                 Profiler.enter("Handling meta information");
                 ValueMap meta = null;
                 if (json.containsKey("meta")) {
@@ -1399,6 +1389,17 @@ public class ApplicationConnection {
                 JsArrayObject<StateChangeEvent> pendingStateChangeEvents = updateConnectorState(
                         json, createdConnectorIds);
 
+                /*
+                 * Doing this here so that locales are available also to the
+                 * connectors which get a state change event before the UI.
+                 */
+                Profiler.enter("Handling locales");
+                VConsole.log(" * Handling locales");
+                // Store locale data
+                LocaleService
+                        .addLocales(getUIConnector().getState().localeServiceState.localeData);
+                Profiler.leave("Handling locales");
+
                 // Update hierarchy, do not fire events
                 ConnectorHierarchyUpdateResult connectorHierarchyUpdateResult = updateConnectorHierarchy(json);
 
index 4009c95531ce10bc2437dde705973e275d01cab2..69345d71749a925b3a305fc115b6e2211c56dc4e 100644 (file)
 package com.vaadin.client;
 
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.logging.Logger;
 
-import com.google.gwt.core.client.JsArray;
+import com.vaadin.shared.ui.ui.UIState.LocaleData;
 
 /**
  * Date / time etc. localisation service for all widgets. Caches all loaded
@@ -31,16 +33,17 @@ import com.google.gwt.core.client.JsArray;
  */
 public class LocaleService {
 
-    private static Map<String, ValueMap> cache = new HashMap<String, ValueMap>();
-    private static String defaultLocale;
+    private static Map<String, LocaleData> cache = new HashMap<String, LocaleData>();
 
-    public static void addLocale(ValueMap valueMap) {
+    private static String defaultLocale;
 
-        final String key = valueMap.getString("name");
+    public static void addLocale(LocaleData localeData) {
+        final String key = localeData.name;
         if (cache.containsKey(key)) {
             cache.remove(key);
         }
-        cache.put(key, valueMap);
+        getLogger().fine("Received locale data for " + localeData.name);
+        cache.put(key, localeData);
         if (cache.size() == 1) {
             setDefaultLocale(key);
         }
@@ -61,8 +64,7 @@ public class LocaleService {
     public static String[] getMonthNames(String locale)
             throws LocaleNotLoadedException {
         if (cache.containsKey(locale)) {
-            final ValueMap l = cache.get(locale);
-            return l.getStringArray("mn");
+            return cache.get(locale).monthNames;
         } else {
             throw new LocaleNotLoadedException(locale);
         }
@@ -71,8 +73,7 @@ public class LocaleService {
     public static String[] getShortMonthNames(String locale)
             throws LocaleNotLoadedException {
         if (cache.containsKey(locale)) {
-            final ValueMap l = cache.get(locale);
-            return l.getStringArray("smn");
+            return cache.get(locale).shortMonthNames;
         } else {
             throw new LocaleNotLoadedException(locale);
         }
@@ -81,8 +82,7 @@ public class LocaleService {
     public static String[] getDayNames(String locale)
             throws LocaleNotLoadedException {
         if (cache.containsKey(locale)) {
-            final ValueMap l = cache.get(locale);
-            return l.getStringArray("dn");
+            return cache.get(locale).dayNames;
         } else {
             throw new LocaleNotLoadedException(locale);
         }
@@ -91,8 +91,7 @@ public class LocaleService {
     public static String[] getShortDayNames(String locale)
             throws LocaleNotLoadedException {
         if (cache.containsKey(locale)) {
-            final ValueMap l = cache.get(locale);
-            return l.getStringArray("sdn");
+            return cache.get(locale).shortDayNames;
         } else {
             throw new LocaleNotLoadedException(locale);
         }
@@ -101,8 +100,7 @@ public class LocaleService {
     public static int getFirstDayOfWeek(String locale)
             throws LocaleNotLoadedException {
         if (cache.containsKey(locale)) {
-            final ValueMap l = cache.get(locale);
-            return l.getInt("fdow");
+            return cache.get(locale).firstDayOfWeek;
         } else {
             throw new LocaleNotLoadedException(locale);
         }
@@ -111,8 +109,7 @@ public class LocaleService {
     public static String getDateFormat(String locale)
             throws LocaleNotLoadedException {
         if (cache.containsKey(locale)) {
-            final ValueMap l = cache.get(locale);
-            return l.getString("df");
+            return cache.get(locale).dateFormat;
         } else {
             throw new LocaleNotLoadedException(locale);
         }
@@ -121,8 +118,7 @@ public class LocaleService {
     public static boolean isTwelveHourClock(String locale)
             throws LocaleNotLoadedException {
         if (cache.containsKey(locale)) {
-            final ValueMap l = cache.get(locale);
-            return l.getBoolean("thc");
+            return cache.get(locale).twelveHourClock;
         } else {
             throw new LocaleNotLoadedException(locale);
         }
@@ -131,8 +127,7 @@ public class LocaleService {
     public static String getClockDelimiter(String locale)
             throws LocaleNotLoadedException {
         if (cache.containsKey(locale)) {
-            final ValueMap l = cache.get(locale);
-            return l.getString("hmd");
+            return cache.get(locale).hourMinuteDelimiter;
         } else {
             throw new LocaleNotLoadedException(locale);
         }
@@ -141,20 +136,19 @@ public class LocaleService {
     public static String[] getAmPmStrings(String locale)
             throws LocaleNotLoadedException {
         if (cache.containsKey(locale)) {
-            final ValueMap l = cache.get(locale);
-            return l.getStringArray("ampm");
+            return new String[] { cache.get(locale).am, cache.get(locale).pm };
         } else {
             throw new LocaleNotLoadedException(locale);
         }
-
     }
 
-    public static void addLocales(JsArray<ValueMap> valueMapArray) {
-        for (int i = 0; i < valueMapArray.length(); i++) {
-            addLocale(valueMapArray.get(i));
-
+    public static void addLocales(List<LocaleData> localeDatas) {
+        for (LocaleData localeData : localeDatas) {
+            addLocale(localeData);
         }
-
     }
 
+    private static Logger getLogger() {
+        return Logger.getLogger(LocaleService.class.getName());
+    }
 }
index ca70391f64450c81f47ecd5787479ad89d6a2430..cd09b2a44b5a24eb39ea48b3f771751530cfd3a0 100644 (file)
@@ -388,10 +388,6 @@ public class JsonPaintTarget implements PaintTarget {
             getUsedResources().add("layouts/" + value + ".html");
         }
 
-        if (name.equals("locale")) {
-            manager.requireLocale(value);
-        }
-
     }
 
     @Override
index c0194db2436f2bca2af63287f6cd104a300dd446..ad662cf6df5ea185dc7148305340d418bf16b464 100644 (file)
 
 package com.vaadin.server;
 
-import java.io.IOException;
-import java.io.PrintWriter;
 import java.io.Serializable;
-import java.io.Writer;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.security.GeneralSecurityException;
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 import java.util.logging.Level;
@@ -37,7 +31,6 @@ import org.json.JSONException;
 import org.json.JSONObject;
 
 import com.vaadin.server.ClientConnector.ConnectorErrorEvent;
-import com.vaadin.server.communication.LocaleWriter;
 import com.vaadin.shared.ApplicationConstants;
 import com.vaadin.shared.JavaScriptConnectorState;
 import com.vaadin.shared.communication.SharedState;
@@ -69,9 +62,6 @@ public class LegacyCommunicationManager implements Serializable {
      */
     private final VaadinSession session;
 
-    // TODO Refactor to UI shared state (#11378)
-    private List<String> locales;
-
     // TODO Move to VaadinSession (#11409)
     private DragAndDropService dragAndDropService;
 
@@ -88,7 +78,6 @@ public class LegacyCommunicationManager implements Serializable {
      */
     public LegacyCommunicationManager(VaadinSession session) {
         this.session = session;
-        requireLocale(session.getLocale().toString());
     }
 
     protected VaadinSession getSession() {
@@ -312,52 +301,6 @@ public class LegacyCommunicationManager implements Serializable {
         return dragAndDropService;
     }
 
-    /**
-     * Prints the queued (pending) locale definitions to a {@link PrintWriter}
-     * in a (UIDL) format that can be sent to the client and used there in
-     * formatting dates, times etc.
-     * 
-     * @deprecated As of 7.1. See #11378.
-     * 
-     * @param outWriter
-     */
-    @Deprecated
-    public void printLocaleDeclarations(Writer writer) throws IOException {
-        new LocaleWriter().write(locales, writer);
-    }
-
-    /**
-     * Queues 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.
-     * 
-     * @deprecated As of 7.1. See #11378.
-     * 
-     * @see Locale#toString()
-     * 
-     * @param value
-     */
-    @Deprecated
-    public void requireLocale(String value) {
-        if (locales == null) {
-            locales = new ArrayList<String>();
-            locales.add(session.getLocale().toString());
-        }
-        if (!locales.contains(value)) {
-            locales.add(value);
-        }
-    }
-
-    /**
-     * @deprecated As of 7.1. See #11378.
-     */
-    @Deprecated
-    public void resetLocales() {
-        locales = null;
-    }
-
     /**
      * @deprecated As of 7.1. Will be removed in the future.
      */
@@ -486,10 +429,6 @@ public class LegacyCommunicationManager implements Serializable {
         getClientCache(ui).clear();
         ui.getConnectorTracker().markAllConnectorsDirty();
         ui.getConnectorTracker().markAllClientSidesUninitialized();
-
-        // Reset sent locales
-        resetLocales();
-        requireLocale(session.getLocale().toString());
     }
 
     private static final Logger getLogger() {
diff --git a/server/src/com/vaadin/server/LocaleService.java b/server/src/com/vaadin/server/LocaleService.java
new file mode 100644 (file)
index 0000000..347c4da
--- /dev/null
@@ -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());
+    }
+
+}
diff --git a/server/src/com/vaadin/server/communication/LocaleWriter.java b/server/src/com/vaadin/server/communication/LocaleWriter.java
deleted file mode 100644 (file)
index c05649d..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * 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.communication;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.io.Writer;
-import java.text.DateFormat;
-import java.text.DateFormatSymbols;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.GregorianCalendar;
-import java.util.List;
-import java.util.Locale;
-import java.util.logging.Logger;
-
-/**
- * Serializes locale information to JSON.
- * 
- * @author Vaadin Ltd
- * @since 7.1
- * @deprecated See <a href="http://dev.vaadin.com/ticket/11378">ticket
- *             #11378</a>.
- */
-@Deprecated
-public class LocaleWriter implements Serializable {
-
-    /**
-     * Writes a JSON object containing localized strings of the given locales.
-     * 
-     * @param locales
-     *            The list of {@link Locale}s to write.
-     * @param writer
-     *            The {@link Writer} used to write the JSON.
-     * @throws IOException
-     *             If the serialization fails.
-     * 
-     */
-    public void write(List<String> locales, Writer writer) throws IOException {
-
-        // Send locale informations to client
-        writer.write("[");
-        // TODO locales are currently sent on each request; this will be fixed
-        // by implementing #11378.
-        for (int pendingLocalesIndex = 0; pendingLocalesIndex < locales.size(); pendingLocalesIndex++) {
-
-            final Locale l = generateLocale(locales.get(pendingLocalesIndex));
-            // Locale name
-            writer.write("{\"name\":\"" + l.toString() + "\",");
-
-            /*
-             * Month names (both short and full)
-             */
-            final DateFormatSymbols dfs = new DateFormatSymbols(l);
-            final String[] short_months = dfs.getShortMonths();
-            final String[] months = dfs.getMonths();
-            writer.write("\"smn\":[\""
-                    + // ShortMonthNames
-                    short_months[0] + "\",\"" + short_months[1] + "\",\""
-                    + short_months[2] + "\",\"" + short_months[3] + "\",\""
-                    + short_months[4] + "\",\"" + short_months[5] + "\",\""
-                    + short_months[6] + "\",\"" + short_months[7] + "\",\""
-                    + short_months[8] + "\",\"" + short_months[9] + "\",\""
-                    + short_months[10] + "\",\"" + short_months[11] + "\""
-                    + "],");
-            writer.write("\"mn\":[\""
-                    + // MonthNames
-                    months[0] + "\",\"" + months[1] + "\",\"" + months[2]
-                    + "\",\"" + months[3] + "\",\"" + months[4] + "\",\""
-                    + months[5] + "\",\"" + months[6] + "\",\"" + months[7]
-                    + "\",\"" + months[8] + "\",\"" + months[9] + "\",\""
-                    + months[10] + "\",\"" + months[11] + "\"" + "],");
-
-            /*
-             * Weekday names (both short and full)
-             */
-            final String[] short_days = dfs.getShortWeekdays();
-            final String[] days = dfs.getWeekdays();
-            writer.write("\"sdn\":[\""
-                    + // ShortDayNames
-                    short_days[1] + "\",\"" + short_days[2] + "\",\""
-                    + short_days[3] + "\",\"" + short_days[4] + "\",\""
-                    + short_days[5] + "\",\"" + short_days[6] + "\",\""
-                    + short_days[7] + "\"" + "],");
-            writer.write("\"dn\":[\""
-                    + // DayNames
-                    days[1] + "\",\"" + days[2] + "\",\"" + days[3] + "\",\""
-                    + days[4] + "\",\"" + days[5] + "\",\"" + days[6] + "\",\""
-                    + days[7] + "\"" + "],");
-
-            /*
-             * First day of week (0 = sunday, 1 = monday)
-             */
-            final Calendar cal = new GregorianCalendar(l);
-            writer.write("\"fdow\":" + (cal.getFirstDayOfWeek() - 1) + ",");
-
-            /*
-             * Date formatting (MM/DD/YYYY etc.)
-             */
-
-            DateFormat dateFormat = DateFormat.getDateTimeInstance(
-                    DateFormat.SHORT, DateFormat.SHORT, l);
-            if (!(dateFormat instanceof SimpleDateFormat)) {
-                getLogger().warning(
-                        "Unable to get default date pattern for locale "
-                                + l.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);
-            }
-
-            writer.write("\"df\":\"" + 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 + "\",");
-            writer.write("\"thc\":" + twelve_hour_clock + ",");
-            writer.write("\"hmd\":\"" + hour_min_delimiter + "\"");
-            if (twelve_hour_clock) {
-                final String[] ampm = dfs.getAmPmStrings();
-                writer.write(",\"ampm\":[\"" + ampm[0] + "\",\"" + ampm[1]
-                        + "\"]");
-            }
-            writer.write("}");
-            if (pendingLocalesIndex < locales.size() - 1) {
-                writer.write(",");
-            }
-        }
-        writer.write("]"); // Close locales
-    }
-
-    /**
-     * Constructs a {@link Locale} instance to be sent to the client based on a
-     * short locale description string.
-     * 
-     * @see #requireLocale(String)
-     * 
-     * @param value
-     * @return
-     */
-    private Locale generateLocale(String value) {
-        final String[] temp = value.split("_");
-        if (temp.length == 1) {
-            return new Locale(temp[0]);
-        } else if (temp.length == 2) {
-            return new Locale(temp[0], temp[1]);
-        } else {
-            return new Locale(temp[0], temp[1], temp[2]);
-        }
-    }
-
-    private static final Logger getLogger() {
-        return Logger.getLogger(LocaleWriter.class.getName());
-    }
-}
index 60a884a63534a686b486320c522438d02d76b30e..f715569424c26f2f20625a11ed4175cc5a23906c 100644 (file)
@@ -283,10 +283,6 @@ public class UidlWriter implements Serializable {
                         + new JSONArray(styleDependencies).toString());
             }
 
-            // add any pending locale definitions requested by the client
-            writer.write(", \"locales\": ");
-            manager.printLocaleDeclarations(writer);
-
             if (manager.getDragAndDropService() != null) {
                 manager.getDragAndDropService().printJSONResponse(writer);
             }
index 06060dbf91eb474283644a28b2a0912857c323f3..9ff36a42d20dd57f016509c3fd54be2bad18bfea 100644 (file)
@@ -291,7 +291,10 @@ public abstract class AbstractComponent extends AbstractClientConnector
     public void setLocale(Locale locale) {
         this.locale = locale;
 
-        // FIXME: Reload value if there is a converter
+        if (locale != null && isAttached()) {
+            getUI().getLocaleService().addLocale(locale);
+        }
+
         markAsDirty();
     }
 
@@ -556,6 +559,10 @@ public abstract class AbstractComponent extends AbstractClientConnector
             focus();
         }
         setActionManagerViewer();
+        if (locale != null) {
+            getUI().getLocaleService().addLocale(locale);
+        }
+
     }
 
     /*
index 545c2c73659139d4ab3af5348c60924939a750e4..706f7c436b16a2a4815fb7333d13037627228e76 100644 (file)
@@ -30,6 +30,7 @@ import com.vaadin.event.ActionManager;
 import com.vaadin.event.MouseEvents.ClickEvent;
 import com.vaadin.event.MouseEvents.ClickListener;
 import com.vaadin.navigator.Navigator;
+import com.vaadin.server.LocaleService;
 import com.vaadin.server.Page;
 import com.vaadin.server.PaintException;
 import com.vaadin.server.PaintTarget;
@@ -494,6 +495,9 @@ public abstract class UI extends AbstractSingleComponentContainer implements
 
     private boolean hasPendingPush = false;
 
+    private LocaleService localeService = new LocaleService(this,
+            getState(false).localeServiceState);
+
     /**
      * This method is used by Component.Focusable objects to request focus to
      * themselves. Focus renders must be handled at window level (instead of
@@ -1052,6 +1056,7 @@ public abstract class UI extends AbstractSingleComponentContainer implements
     @Override
     public void attach() {
         super.attach();
+        getLocaleService().addLocale(getLocale());
     }
 
     /**
@@ -1428,4 +1433,16 @@ public abstract class UI extends AbstractSingleComponentContainer implements
     public void setOverlayContainerLabel(String overlayContainerLabel) {
         getState().overlayContainerLabel = overlayContainerLabel;
     }
+
+    /**
+     * Returns the locale service which handles transmission of Locale data to
+     * the client.
+     * 
+     * @since 7.1
+     * @return The LocaleService for this UI
+     */
+    public LocaleService getLocaleService() {
+        return localeService;
+    }
+
 }
index 16c1ed16c7f7617a14b9d4ccc41c2c7ac192aa0a..f01d5d81007b3c28cb206dd059880de79af5d5d0 100644 (file)
 package com.vaadin.shared.ui.ui;
 
 import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
 
+import com.vaadin.server.LocaleService;
+import com.vaadin.server.Page;
 import com.vaadin.shared.communication.PushMode;
 import com.vaadin.shared.ui.TabIndexState;
 
@@ -50,10 +54,34 @@ public class UIState extends TabIndexState {
      * State related to the {@link Page} class.
      */
     public PageState pageState = new PageState();
+    /**
+     * State related to the {@link LocaleService} class.
+     */
+    public LocaleServiceState localeServiceState = new LocaleServiceState();
 
     {
         primaryStyleName = "v-ui";
         // Default is 1 for legacy reasons
         tabIndex = 1;
     }
+
+    public static class LocaleServiceState implements Serializable {
+        public List<LocaleData> localeData = new ArrayList<LocaleData>();
+    }
+
+    public static class LocaleData implements Serializable {
+        public String name;
+        public String[] monthNames;
+        public String[] shortMonthNames;
+        public String[] shortDayNames;
+        public String[] dayNames;
+        public int firstDayOfWeek;
+        public String dateFormat;
+        public boolean twelveHourClock;
+        public String hourMinuteDelimiter;
+        public String am;
+        public String pm;
+
+    }
+
 }
index 5d06895d1143425dc4ba0f987568645255bfed6f..a4fe2b0285e0acf652fc690e73bb6dfe1984bcfb 100644 (file)
@@ -16,7 +16,7 @@ public class DateFieldLocale extends TestBase {
         final DateField dateField = new DateField("DateField");
         dateField.setLocale(new Locale("fi", "FI"));
         dateField.setCaption(dateField.getLocale().toString());
-        dateField.setValue(new Date());
+        dateField.setValue(new Date(2013 - 1900, 7 - 1, 27));
         dateField.setResolution(DateField.RESOLUTION_DAY);
 
         addComponent(new Button("Change locale", new ClickListener() {