com.google.gwt.i18n.client.Dictionary.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gwt.i18n.client.Dictionary.java

Source

/*
 * 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 <code>Dictionary</code> 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.
 * 
 * <p>
 * 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 <code>Dictionary</code> to access the key/value pairs
 * above:
 * 
 * {@example com.google.gwt.examples.i18n.ThemeDictionaryExample#useThemeDictionary()}
 * </p>
 * 
 * <p>
 * Unlike the family of interfaces that extend
 * {@link com.google.gwt.i18n.client.Localizable} which support static
 * internationalization, the <code>Dictionary</code> 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.
 * </p>
 * 
 * <h3>A Caveat Regarding Locale</h3>
 * The module's host page completely determines the mappings defined for each
 * dictionary without regard to the <code>locale</code> client property. Thus,
 * <code>Dictionary</code> 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
 * <code>locale</code> client property.
 * 
 * <p>
 * See {@link com.google.gwt.i18n.client.Localizable} for background on the
 * <code>locale</code> client property.
 * </p>
 * 
 * <h3>Required Module</h3>
 * Modules that use this interface should inherit
 * <code>com.google.gwt.i18n.I18N</code>.
 * 
 * {@gwt.include com/google/gwt/examples/i18n/InheritsExample.gwt.xml}
 */
public final class Dictionary {

    private static Map<String, Dictionary> cache = new HashMap<String, Dictionary>();
    private static final int MAX_KEYS_TO_SHOW = 20;

    /**
     * Returns the <code>Dictionary</code> 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 <code>Dictionary</code>.
     * 
     * @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 = this.@com.google.gwt.i18n.client.Dictionary::dict;
                                         var value = map[key];
                                         if (value == null || !map.hasOwnProperty(key)) {
                                         this.@com.google.gwt.i18n.client.Dictionary::resourceError(Ljava/lang/String;)(key);
                                         }
                                         return String(value);
                                         }-*/;

    /**
     * The set of keys associated with this dictionary.
     * 
     * @return the Dictionary set
     */
    public Set<String> keySet() {
        HashSet<String> s = new HashSet<String>();
        addKeys(s);
        return s;
    }

    @Override
    public String toString() {
        return label;
    }

    /**
     * Collection of values associated with this dictionary.
     * 
     * @return the values
     */
    public Collection<String> values() {
        ArrayList<String> s = new ArrayList<String>();
        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<String> s) /*-{
                                                   var map = this.@com.google.gwt.i18n.client.Dictionary::dict
                                                   for (var key in map) {
                                                   if (map.hasOwnProperty(key)) {
                                                   s.@java.util.HashSet::add(Ljava/lang/Object;)(key);
                                                   }
                                                   }
                                                   }-*/;

    private native void addValues(ArrayList<String> s) /*-{
                                                       var map = this.@com.google.gwt.i18n.client.Dictionary::dict
                                                       for (var key in map) {
                                                       if (map.hasOwnProperty(key)) {
                                                       var value = this.@com.google.gwt.i18n.client.Dictionary::get(Ljava/lang/String;)(key);
                                                       s.@java.util.ArrayList::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);
                                           }
                                           this.@com.google.gwt.i18n.client.Dictionary::dict = $wnd[name];
                                           } catch(e) {
                                           @com.google.gwt.i18n.client.Dictionary::resourceErrorBadType(Ljava/lang/String;)(name);
                                           }
                                           }-*/;
}