/* * 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. */ 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; }-*/; }