com.google.gwt.i18n.client.Dictionary Maven / Gradle / Ivy
/*
* Copyright 2007 Google Inc.
*
* 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.google.gwt.i18n.client;
import com.google.gwt.core.client.JavaScriptObject;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Set;
/**
* Provides dynamic string lookup of key/value string pairs defined in a
* module's host HTML page. Each unique instance of Dictionary
is
* bound to a named JavaScript object that resides in the global namespace of
* the host page's window object. The bound JavaScript object is used directly
* as an associative array.
*
*
* For example, suppose you define the following JavaScript object in your host
* page:
*
* {@gwt.include com/google/gwt/examples/i18n/ThemeDictionaryExample.js}
*
* You can then use a Dictionary
to access the key/value pairs
* above:
*
* {@example com.google.gwt.examples.i18n.ThemeDictionaryExample#useThemeDictionary()}
*
*
*
* Unlike the family of interfaces that extend
* {@link com.google.gwt.i18n.client.Localizable} which support static
* internationalization, the Dictionary
class is fully dynamic.
* As a result, a variety of error conditions (particularly those involving key
* mismatches) cannot be caught until runtime. Similarly, the GWT compiler is
* unable discard unused dictionary values since the structure cannot be
* statically analyzed.
*
*
* A Caveat Regarding Locale
* The module's host page completely determines the mappings defined for each
* dictionary without regard to the locale
client property. Thus,
* Dictionary
is the most flexible of the internationalization
* types and may provide the simplest form of integration with existing
* localization systems which were not specifically designed to use GWT's
* locale
client property.
*
*
* See {@link com.google.gwt.i18n.client.Localizable} for background on the
* locale
client property.
*
*
* Required Module
* Modules that use this interface should inherit
* com.google.gwt.i18n.I18N
.
*
* {@gwt.include com/google/gwt/examples/i18n/InheritsExample.gwt.xml}
*/
public final class Dictionary {
private static Map cache =
new HashMap();
private static final int MAX_KEYS_TO_SHOW = 20;
/**
* Returns the Dictionary
object associated with the given
* name.
*
* @param name
* @return specified dictionary
* @throws MissingResourceException
*/
public static Dictionary getDictionary(String name) {
Dictionary target = cache.get(name);
if (target == null) {
target = new Dictionary(name);
cache.put(name, target);
}
return target;
}
static void resourceErrorBadType(String name) {
throw new MissingResourceException("'" + name
+ "' is not a JavaScript object and cannot be used as a Dictionary",
null, name);
}
private JavaScriptObject dict;
private String label;
/**
* Constructor for Dictionary
.
*
* @param name name of linked JavaScript Object
*/
private Dictionary(String name) {
if (name == null || "".equals(name)) {
throw new IllegalArgumentException(
"Cannot create a Dictionary with a null or empty name");
}
this.label = "Dictionary " + name;
attach(name);
if (dict == null) {
throw new MissingResourceException(
"Cannot find JavaScript object with the name '" + name + "'", name,
null);
}
}
/**
* Get the value associated with the given Dictionary key.
*
* We have to call Object.hasOwnProperty to verify that the value is
* defined on this object, rather than a superclass, since normal Object
* properties are also visible on this object.
*
* @param key to lookup
* @return the value
* @throws MissingResourceException if the value is not found
*/
public native String get(String key) /*-{
// In Firefox, jsObject.hasOwnProperty(key) requires a primitive string
key = String(key);
var map = [email protected]::dict;
var value = map[key];
if (value == null || !map.hasOwnProperty(key)) {
[email protected]::resourceError(Ljava/lang/String;)(key);
}
return String(value);
}-*/;
/**
* The set of keys associated with this dictionary.
*
* @return the Dictionary set
*/
public Set keySet() {
HashSet s = new HashSet();
addKeys(s);
return s;
}
@Override
public String toString() {
return label;
}
/**
* Collection of values associated with this dictionary.
*
* @return the values
*/
public Collection values() {
ArrayList s = new ArrayList();
addValues(s);
return s;
}
void resourceError(String key) {
String error = "Cannot find '" + key + "' in " + this;
throw new MissingResourceException(error, this.toString(), key);
}
private native void addKeys(HashSet s) /*-{
var map = [email protected]::dict
for (var key in map) {
if (map.hasOwnProperty(key)) {
[email protected]::add(Ljava/lang/Object;)(key);
}
}
}-*/;
private native void addValues(ArrayList s) /*-{
var map = [email protected]::dict
for (var key in map) {
if (map.hasOwnProperty(key)) {
var value = [email protected]::get(Ljava/lang/String;)(key);
[email protected]::add(Ljava/lang/Object;)(value);
}
}
}-*/;
private native void attach(String name)/*-{
try {
if (typeof($wnd[name]) != "object") {
@com.google.gwt.i18n.client.Dictionary::resourceErrorBadType(Ljava/lang/String;)(name);
}
[email protected]::dict = $wnd[name];
} catch(e) {
@com.google.gwt.i18n.client.Dictionary::resourceErrorBadType(Ljava/lang/String;)(name);
}
}-*/;
}