| /* |
| * 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.impl; |
| |
| import com.google.gwt.core.client.JavaScriptObject; |
| |
| import java.util.AbstractMap; |
| import java.util.AbstractSet; |
| import java.util.Arrays; |
| import java.util.Iterator; |
| import java.util.Map; |
| import java.util.NoSuchElementException; |
| import java.util.Set; |
| |
| /** |
| * Map used when creating <code>Constants</code> maps. This class is to be |
| * used only by the GWT code. The map is immediately wrapped in |
| * Collections.unmodifiableMap(..) preventing any changes after construction. |
| */ |
| public class ConstantMap extends AbstractMap<String, String> { |
| |
| private static final class EntryImpl implements Entry<String, String> { |
| private final String key; |
| private final String value; |
| |
| private EntryImpl(String key, String value) { |
| assert (key != null); |
| assert (value != null); |
| this.key = key; |
| this.value = value; |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (o instanceof Map.Entry<?, ?>) { |
| Map.Entry<?, ?> other = (Map.Entry<?, ?>) o; |
| // Key and value known to be non-null. |
| if (key.equals(other.getKey()) && value.equals(other.getValue())) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| public String getKey() { |
| return key; |
| } |
| |
| public String getValue() { |
| return value; |
| } |
| |
| /** |
| * Calculate the hash code using Sun's specified algorithm. |
| */ |
| @Override |
| public int hashCode() { |
| int keyHash = 0; |
| int valueHash = 0; |
| if (getKey() != null) { |
| keyHash = getKey().hashCode(); |
| } |
| if (getValue() != null) { |
| valueHash = getValue().hashCode(); |
| } |
| return keyHash ^ valueHash; |
| } |
| |
| public String setValue(String value) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public String toString() { |
| return key + "=" + value; |
| } |
| } |
| |
| /** |
| * The original set of keys. |
| */ |
| private final String[] keys; |
| |
| /* |
| * Stores a fast lookup in a JSO using ':' to prevent conflict with built-in |
| * JavaScript properties. |
| */ |
| @SuppressWarnings("unused") |
| private JavaScriptObject map; |
| |
| public ConstantMap(String keys[], String values[]) { |
| this.keys = keys; |
| |
| init(); |
| |
| for (int i = 0; i < keys.length; ++i) { |
| assert keys[i] != null; |
| assert values[i] != null; |
| putImpl(keys[i], values[i]); |
| } |
| } |
| |
| @Override |
| public boolean containsKey(Object key) { |
| return get(key) != null; |
| } |
| |
| @Override |
| public Set<Map.Entry<String, String>> entrySet() { |
| return new AbstractSet<Entry<String, String>>() { |
| @Override |
| public boolean contains(Object o) { |
| if (!(o instanceof Entry<?, ?>)) { |
| return false; |
| } |
| Entry<?, ?> other = (Entry<?, ?>) o; |
| String value = get(other.getKey()); |
| if (value != null && value.equals(other.getValue())) { |
| return true; |
| } |
| return false; |
| } |
| |
| @Override |
| public Iterator<Map.Entry<String, String>> iterator() { |
| return new Iterator<Entry<String, String>>() { |
| private int next = 0; |
| |
| public boolean hasNext() { |
| return next < ConstantMap.this.size(); |
| } |
| |
| public Entry<String, String> next() { |
| if (!hasNext()) { |
| throw new NoSuchElementException(); |
| } |
| String key = keys[next++]; |
| return new EntryImpl(key, get(key)); |
| } |
| |
| public void remove() { |
| throw new UnsupportedOperationException(); |
| } |
| }; |
| } |
| |
| @Override |
| public int size() { |
| return ConstantMap.this.size(); |
| } |
| }; |
| } |
| |
| @Override |
| public String get(Object key) { |
| return (key instanceof String) ? get((String) key) : null; |
| } |
| |
| public native String get(String key) /*-{ |
| // Prepend ':' to avoid conflicts with built-in Object properties. |
| return this.@com.google.gwt.i18n.client.impl.ConstantMap::map[':' + key]; |
| }-*/; |
| |
| @Override |
| public Set<String> keySet() { |
| return new AbstractSet<String>() { |
| @Override |
| public boolean contains(Object o) { |
| return containsKey(o); |
| } |
| |
| @Override |
| public Iterator<String> iterator() { |
| return Arrays.asList(keys).iterator(); |
| } |
| |
| @Override |
| public int size() { |
| return ConstantMap.this.size(); |
| } |
| }; |
| } |
| |
| @Override |
| public int size() { |
| return keys.length; |
| } |
| |
| /** |
| * Overridable for testing purposes, see ConstantMapTest. |
| */ |
| protected void init() { |
| map = JavaScriptObject.createObject(); |
| } |
| |
| protected native void putImpl(String key, String value) /*-{ |
| // Prepend ':' to avoid conflicts with built-in Object properties. |
| this.@com.google.gwt.i18n.client.impl.ConstantMap::map[':' + key] = value; |
| }-*/; |
| } |