diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TAbstractMap.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TAbstractMap.java new file mode 100644 index 000000000..8e422840c --- /dev/null +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TAbstractMap.java @@ -0,0 +1,275 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * 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 org.teavm.classlib.java.util; + +import org.teavm.classlib.java.io.TSerializable; +import org.teavm.classlib.java.lang.TObject; +import org.teavm.classlib.java.lang.TUnsupportedOperationException; + +/** + * + * @author Alexey Andreev + */ +public abstract class TAbstractMap extends TObject implements TMap { + public static class SimpleEntry implements TMap.Entry, TSerializable { + private K key; + private V value; + + public SimpleEntry(K key, V value) { + this.key = key; + this.value = value; + } + + public SimpleEntry(TMap.Entry entry) { + this(entry.getKey(), entry.getValue()); + } + + @Override + public V getValue() { + return value; + } + + @Override + public V setValue(V value) { + V old = this.value; + this.value = value; + return old; + } + + @Override + public K getKey() { + return key; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof TMap.Entry)) { + return false; + } + TMap.Entry other = (TMap.Entry)obj; + if (getKey() == null ? other.getKey() != null : !getKey().equals(other.getKey())) { + return false; + } + return getValue() == null ? other.getValue() == null : getValue().equals(other.getValue()); + } + + @Override + public int hashCode() { + return (getKey() == null ? 0 : getKey().hashCode()) ^ (getValue() == null ? 0 : getValue().hashCode()); + } + + @Override + public String toString() { + return String.valueOf(getKey()) + "=" + String.valueOf(getValue()); + } + } + + public static class SimpleImmutableEntry implements TMap.Entry, TSerializable { + private K key; + private V value; + + public SimpleImmutableEntry(K key, V value) { + this.key = key; + this.value = value; + } + + public SimpleImmutableEntry(TMap.Entry entry) { + this(entry.getKey(), entry.getValue()); + } + + @Override + public V getValue() { + return value; + } + + @Override + public V setValue(V value) { + throw new TUnsupportedOperationException(); + } + + @Override + public K getKey() { + return key; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof TMap.Entry)) { + return false; + } + TMap.Entry other = (TMap.Entry)obj; + if (getKey() == null ? other.getKey() != null : !getKey().equals(other.getKey())) { + return false; + } + return getValue() == null ? other.getValue() == null : getValue().equals(other.getValue()); + } + + @Override + public int hashCode() { + return (getKey() == null ? 0 : getKey().hashCode()) ^ (getValue() == null ? 0 : getValue().hashCode()); + } + + @Override + public String toString() { + return String.valueOf(getKey()) + "=" + String.valueOf(getValue()); + } + } + + private KeySet cachedKeySet; + private Values cachedValues; + + protected TAbstractMap() { + } + + @Override + public int size() { + return entrySet().size(); + } + + @Override + public boolean isEmpty() { + return size() == 0; + } + + @Override + public boolean containsValue(Object value) { + for (TIterator> iter = entrySet().iterator(); iter.hasNext();) { + V knownValue = iter.next().getValue(); + if (TObjects.equals(value, knownValue)) { + return true; + } + } + return false; + } + + @Override + public boolean containsKey(Object key) { + for (TIterator> iter = entrySet().iterator(); iter.hasNext();) { + K knownKey = iter.next().getKey(); + if (TObjects.equals(key, knownKey)) { + return true; + } + } + return false; + } + + @Override + public V get(Object key) { + for (TIterator> iter = entrySet().iterator(); iter.hasNext();) { + TMap.Entry entry = iter.next(); + if (TObjects.equals(key, entry.getKey())) { + return entry.getValue(); + } + } + return null; + } + + @Override + public V put(K key, V value) { + throw new TUnsupportedOperationException(); + } + + @Override + public void putAll(TMap m) { + for (TIterator> iter = m.entrySet().iterator(); + iter.hasNext();) { + TMap.Entry entry = iter.next(); + put(entry.getKey(), entry.getValue()); + } + } + + @Override + public V remove(Object key) { + for (TIterator> iter = entrySet().iterator(); iter.hasNext();) { + TMap.Entry entry = iter.next(); + if (TObjects.equals(key, entry.getKey())) { + iter.remove(); + return entry.getValue(); + } + } + return null; + } + + @Override + public abstract TSet> entrySet(); + + @Override + public void clear() { + entrySet().clear(); + } + + @Override + public TSet keySet() { + if (cachedKeySet == null) { + cachedKeySet = new KeySet(); + } + return cachedKeySet; + } + + @Override + public TCollection values() { + if (cachedValues == null) { + cachedValues = new Values(); + } + return cachedValues; + } + + private class KeySet extends TAbstractSet { + @Override + public TIterator iterator() { + final TIterator> iter = TAbstractMap.this.entrySet().iterator(); + return new TIterator() { + @Override public boolean hasNext() { + return iter.hasNext(); + } + @Override public K next() { + return iter.next().getKey(); + } + @Override public void remove() { + iter.remove(); + } + }; + } + + @Override + public int size() { + return TAbstractMap.this.size(); + } + } + + private class Values extends TAbstractCollection { + @Override + public int size() { + return TAbstractMap.this.size(); + } + + @Override + public TIterator iterator() { + final TIterator> iter = TAbstractMap.this.entrySet().iterator(); + return new TIterator() { + @Override public boolean hasNext() { + return iter.hasNext(); + } + @Override public V next() { + return iter.next().getValue(); + } + @Override public void remove() { + iter.remove(); + } + }; + } + } +} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TAbstractSet.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TAbstractSet.java new file mode 100644 index 000000000..9cced5978 --- /dev/null +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TAbstractSet.java @@ -0,0 +1,47 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * 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 org.teavm.classlib.java.util; + +/** + * + * @author Alexey Andreev + */ +public abstract class TAbstractSet extends TAbstractCollection implements TSet { + public TAbstractSet() { + super(); + } + + @Override + public boolean removeAll(TCollection c) { + boolean modified = false; + if (size() < c.size()) { + for (TIterator iter = iterator(); iter.hasNext();) { + E elem = iter.next(); + if (c.contains(elem)) { + modified = true; + iter.remove(); + } + } + } else { + for (TIterator iter = c.iterator(); iter.hasNext();) { + if (remove(iter.next())) { + modified = true; + } + } + } + return modified; + } +} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TMap.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TMap.java index 61f095350..a49464bc9 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TMap.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TMap.java @@ -15,8 +15,6 @@ */ package org.teavm.classlib.java.util; -import org.teavm.classlib.java.lang.TObject; - /** * * @author Alexey Andreev @@ -34,15 +32,15 @@ public interface TMap { boolean isEmpty(); - boolean containsKey(TObject key); + boolean containsKey(Object key); - boolean containsValue(TObject value); + boolean containsValue(Object value); - V get(TObject key); + V get(Object key); V put(K key, V value); - V remove(TObject key); + V remove(Object key); void putAll(TMap m); diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TObjects.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TObjects.java new file mode 100644 index 000000000..24ce4c006 --- /dev/null +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TObjects.java @@ -0,0 +1,58 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * 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 org.teavm.classlib.java.util; + +import org.teavm.classlib.java.lang.TObject; + +/** + * + * @author Alexey Andreev + */ +public final class TObjects extends TObject { + public static boolean equals(Object a, Object b) { + if (a == b) { + return true; + } + return a == null ? b == null : a.equals(b); + } + + public static int hashCode(Object o) { + return o == null ? 0 : o.hashCode(); + } + + public static String toString(Object o) { + return toString(o, "null"); + } + + public static String toString(Object o, String nullDefault) { + return o != null ? o.toString() : nullDefault; + } + + public static int compare(T a, T b, TComparator c) { + return a == null && b == null ? 0 : c.compare(a, b); + } + + public static T requireNonNull(T obj) { + return requireNonNull(obj, ""); + } + + public static T requireNonNull(T obj, String message) { + if (obj == null) { + throw new NullPointerException(message); + } + return obj; + } +}