| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /// This defines a class for loading locale data incrementally from |
| 6 * This defines a class for loading locale data incrementally from | 6 /// an external source as JSON. The external sources expected are either |
| 7 * an external source as JSON. The external sources expected are either | 7 /// local files or via HTTP request. |
| 8 * local files or via HTTP request. | |
| 9 */ | |
| 10 | 8 |
| 11 library lazy_locale_data; | 9 library lazy_locale_data; |
| 12 | 10 |
| 13 import 'dart:async'; | 11 import 'dart:async'; |
| 14 import 'dart:convert'; | 12 import 'dart:convert'; |
| 15 import 'intl_helpers.dart'; | 13 import 'intl_helpers.dart'; |
| 16 | 14 |
| 17 /** | 15 /// This implements the very basic map-type operations which are used |
| 18 * This implements the very basic map-type operations which are used | 16 /// in locale lookup, and looks them up based on a URL that defines |
| 19 * in locale lookup, and looks them up based on a URL that defines | 17 /// the external source. |
| 20 * the external source. | |
| 21 */ | |
| 22 class LazyLocaleData { | 18 class LazyLocaleData { |
| 23 /// This holds the data we have loaded. | 19 /// This holds the data we have loaded. |
| 24 Map map; | 20 Map map; |
| 25 | 21 |
| 26 /// The object that actually does the data reading. | 22 /// The object that actually does the data reading. |
| 27 LocaleDataReader _reader; | 23 LocaleDataReader _reader; |
| 28 | 24 |
| 29 /** | 25 /// In order to avoid a potentially remote call to see if a locale |
| 30 * In order to avoid a potentially remote call to see if a locale | 26 /// is available, we hold a complete list of all the available |
| 31 * is available, we hold a complete list of all the available | 27 /// locales. |
| 32 * locales. | |
| 33 */ | |
| 34 List availableLocales; | 28 List availableLocales; |
| 35 | 29 |
| 36 /** | 30 /// Given a piece of remote data, apply [_creationFunction] to it to |
| 37 * Given a piece of remote data, apply [_creationFunction] to it to | 31 /// convert it into the right form. Typically this means converting it |
| 38 * convert it into the right form. Typically this means converting it | 32 /// from a Map into an object form. |
| 39 * from a Map into an object form. | |
| 40 */ | |
| 41 Function _creationFunction; | 33 Function _creationFunction; |
| 42 | 34 |
| 43 /** | 35 /// The set of available locales. |
| 44 * The set of available locales. | |
| 45 */ | |
| 46 Set availableLocaleSet; | 36 Set availableLocaleSet; |
| 47 | 37 |
| 48 /** | 38 /// The constructor. The [_reader] specifies where the data comes |
| 49 * The constructor. The [_reader] specifies where the data comes | 39 /// from. The [_creationFunction] creates the appropriate data type |
| 50 * from. The [_creationFunction] creates the appropriate data type | 40 /// from the remote data (which typically comes in as a Map). The |
| 51 * from the remote data (which typically comes in as a Map). The | 41 /// [keys] lists the set of remotely available locale names so we know which |
| 52 * [keys] lists the set of remotely available locale names so we know which | 42 /// things can be fetched without having to check remotely. |
| 53 * things can be fetched without having to check remotely. | |
| 54 */ | |
| 55 LazyLocaleData(this._reader, this._creationFunction, List keys) { | 43 LazyLocaleData(this._reader, this._creationFunction, List keys) { |
| 56 map = new Map(); | 44 map = new Map(); |
| 57 availableLocales = keys; | 45 availableLocales = keys; |
| 58 availableLocaleSet = new Set.from(availableLocales); | 46 availableLocaleSet = new Set.from(availableLocales); |
| 59 } | 47 } |
| 60 | 48 |
| 61 /** | 49 /// Tests if we have data for the locale available. Note that this returns |
| 62 * Tests if we have data for the locale available. Note that this returns | 50 /// true even if the data is known to be available remotely but not yet |
| 63 * true even if the data is known to be available remotely but not yet loaded. | 51 /// loaded. |
| 64 */ | |
| 65 bool containsKey(String locale) => availableLocaleSet.contains(locale); | 52 bool containsKey(String locale) => availableLocaleSet.contains(locale); |
| 66 | 53 |
| 67 /** Returns the list of keys/locale names. */ | 54 /// Returns the list of keys/locale names. |
| 68 List get keys => availableLocales; | 55 List get keys => availableLocales; |
| 69 | 56 |
| 70 /** | 57 /// Returns the data stored for [localeName]. If no data has been loaded |
| 71 * Returns the data stored for [localeName]. If no data has been loaded | 58 /// for [localeName], throws an exception. If no data is available for |
| 72 * for [localeName], throws an exception. If no data is available for | 59 /// [localeName] then throw an exception with a different message. |
| 73 * [localeName] then throw an exception with a different message. | |
| 74 */ | |
| 75 operator [](String localeName) { | 60 operator [](String localeName) { |
| 76 if (containsKey(localeName)) { | 61 if (containsKey(localeName)) { |
| 77 var data = map[localeName]; | 62 var data = map[localeName]; |
| 78 if (data == null) { | 63 if (data == null) { |
| 79 throw new LocaleDataException( | 64 throw new LocaleDataException( |
| 80 "Locale $localeName has not been initialized." | 65 "Locale $localeName has not been initialized." |
| 81 " Call initializeDateFormatting($localeName, <data url>) first"); | 66 " Call initializeDateFormatting($localeName, <data url>) first"); |
| 82 } else { | 67 } else { |
| 83 return data; | 68 return data; |
| 84 } | 69 } |
| 85 } else { | 70 } else { |
| 86 unsupportedLocale(localeName); | 71 unsupportedLocale(localeName); |
| 87 } | 72 } |
| 88 } | 73 } |
| 89 | 74 |
| 90 /** | 75 /// Throw an exception indicating that the locale has no data available, |
| 91 * Throw an exception indicating that the locale has no data available, | 76 /// either locally or remotely. |
| 92 * either locally or remotely. | |
| 93 */ | |
| 94 unsupportedLocale(localeName) { | 77 unsupportedLocale(localeName) { |
| 95 throw new LocaleDataException('Locale $localeName has no data available'); | 78 throw new LocaleDataException('Locale $localeName has no data available'); |
| 96 } | 79 } |
| 97 | 80 |
| 98 /** | 81 /// Initialize for locale. Internal use only. As a user, call |
| 99 * Initialize for locale. Internal use only. As a user, call | 82 /// initializeDateFormatting instead. |
| 100 * initializeDateFormatting instead. | |
| 101 */ | |
| 102 Future initLocale(String localeName) { | 83 Future initLocale(String localeName) { |
| 103 var data = _reader.read(localeName); | 84 var data = _reader.read(localeName); |
| 104 return jsonData(data).then((input) { | 85 return jsonData(data).then((input) { |
| 105 map[localeName] = _creationFunction(input); | 86 map[localeName] = _creationFunction(input); |
| 106 }); | 87 }); |
| 107 } | 88 } |
| 108 | 89 |
| 109 /** | 90 /// Given a Future [input] whose value is expected to be a string in JSON |
| 110 * Given a Future [input] whose value is expected to be a string in JSON form, | 91 /// form, return another future that parses the JSON into a usable format. |
| 111 * return another future that parses the JSON into a usable format. | |
| 112 */ | |
| 113 Future jsonData(Future input) { | 92 Future jsonData(Future input) { |
| 114 return input.then((response) => JSON.decode(response)); | 93 return input.then((response) => JSON.decode(response)); |
| 115 } | 94 } |
| 116 } | 95 } |
| OLD | NEW |