--- /dev/null
+/*
+ * (C) Copyright 2017 Pantheon Technologies, s.r.o. and others.
+ *
+ * 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.opendaylight.yangtools.triemap;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.AbstractSet;
+import java.util.Map.Entry;
+
+/**
+ * Abstract base class for implementing {@link TrieMap} entry sets.
+ *
+ * @author Robert Varga
+ *
+ * @param <K> the type of entry keys
+ * @param <V> the type of entry values
+ */
+abstract class AbstractEntrySet<K, V> extends AbstractSet<Entry<K, V>> {
+ private final TrieMap<K, V> map;
+
+ AbstractEntrySet(final TrieMap<K, V> map) {
+ this.map = checkNotNull(map);
+ }
+
+ final TrieMap<K, V> map() {
+ return map;
+ }
+
+ @Override
+ public final boolean contains(final Object o) {
+ if (!(o instanceof Entry)) {
+ return false;
+ }
+
+ final Entry<?, ?> e = (Entry<?, ?>) o;
+ final Object key = e.getKey();
+ if (key == null) {
+ return false;
+ }
+
+ final V v = map.get(key);
+ return v != null && v.equals(e.getValue());
+ }
+
+ @Override
+ public final int size() {
+ return map.size();
+ }
+}
--- /dev/null
+/*
+ * (C) Copyright 2017 Pantheon Technologies, s.r.o. and others.
+ *
+ * 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.opendaylight.yangtools.triemap;
+
+import static org.opendaylight.yangtools.triemap.ImmutableTrieMap.unsupported;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map.Entry;
+
+/**
+ * {@link AbstractEntrySet} implementation guarding against attempts to mutate the underlying map.
+ *
+ * @author Robert Varga
+ *
+ * @param <K> the type of entry keys
+ * @param <V> the type of entry values
+ */
+final class ImmutableEntrySet<K, V> extends AbstractEntrySet<K, V> {
+ ImmutableEntrySet(final TrieMap<K, V> map) {
+ super(map);
+ }
+
+ @Override
+ public void clear() {
+ throw unsupported();
+ }
+
+ @Override
+ public Iterator<Entry<K, V>> iterator() {
+ return map().immutableIterator();
+ }
+
+ @Override
+ public boolean remove(final Object o) {
+ throw unsupported();
+ }
+
+ @Override
+ public boolean removeAll(final Collection<?> c) {
+ throw unsupported();
+ }
+
+ @Override
+ public boolean retainAll(final Collection<?> c) {
+ throw unsupported();
+ }
+}
import com.google.common.annotations.Beta;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import java.util.Iterator;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Function;
return this;
}
+ @Override
+ ImmutableEntrySet<K, V> createEntrySet() {
+ return new ImmutableEntrySet<>(this);
+ }
+
@Override
boolean isReadOnly() {
return true;
return root;
}
- private static UnsupportedOperationException unsupported() {
+ static UnsupportedOperationException unsupported() {
return new UnsupportedOperationException("Attempted to modify a read-only view");
}
+
+ @Override
+ Iterator<Entry<K, V>> iterator() {
+ return immutableIterator();
+ }
}
*/
package org.opendaylight.yangtools.triemap;
-import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkArgument;
-import java.util.AbstractSet;
import java.util.Iterator;
import java.util.Map.Entry;
* @param <K> the type of keys
* @param <V> the type of values
*/
-final class EntrySet<K, V> extends AbstractSet<Entry<K, V>> {
- private final TrieMap<K, V> map;
-
- EntrySet(final TrieMap<K, V> map) {
- this.map = checkNotNull(map);
+final class MutableEntrySet<K, V> extends AbstractEntrySet<K, V> {
+ MutableEntrySet(final TrieMap<K, V> map) {
+ super(map);
}
@Override
- public Iterator<Entry<K, V>> iterator() {
- return map.iterator();
+ public boolean add(final Entry<K, V> e) {
+ final K k = e.getKey();
+ checkArgument(k != null);
+ final V v = e.getValue();
+ checkArgument(v != null);
+
+ final V prev = map().putIfAbsent(k, v);
+ return prev == null || !v.equals(prev);
}
@Override
- public boolean contains(final Object o) {
- if (!(o instanceof Entry)) {
- return false;
- }
+ public void clear() {
+ map().clear();
+ }
- final Entry<?, ?> e = (Entry<?, ?>) o;
- if (e.getKey() == null) {
- return false;
- }
- final V v = map.get(e.getKey());
- return v != null && v.equals(e.getValue());
+ @Override
+ public Iterator<Entry<K, V>> iterator() {
+ return map().iterator();
}
@Override
return false;
}
- return map.remove(key, value);
- }
-
- @Override
- public final int size() {
- return map.size();
- }
-
- @Override
- public final void clear() {
- map.clear();
+ return map().remove(key, value);
}
}
import com.google.common.annotations.Beta;
import com.google.common.base.Verify;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import java.util.Iterator;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
}
}
+ @Override
+ MutableEntrySet<K, V> createEntrySet() {
+ // FIXME: it would be nice to have a ReadWriteTrieMap with read-only iterator
+ // if (readOnlyEntrySet) return ImmutableEntrySet(this);
+ return new MutableEntrySet<>(this);
+ }
+
@Override
boolean isReadOnly() {
return false;
this.nv = nv;
}
}
+
+ @Override
+ Iterator<Entry<K, V>> iterator() {
+ return new TrieMapIterator<>(0, this);
+ }
}
public abstract class TrieMap<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K,V>, Serializable {
private static final long serialVersionUID = 1L;
- /**
- * EntrySet
- */
- private final EntrySet<K, V> entrySet = new EntrySet<>(this);
private final Equivalence<? super K> equiv;
+ private AbstractEntrySet<K, V> entrySet;
+
TrieMap(final Equivalence<? super K> equiv) {
this.equiv = equiv;
}
@Override
public final Set<Entry<K, V>> entrySet() {
- return entrySet;
+ AbstractEntrySet<K, V> ret = entrySet;
+ if (ret == null) {
+ entrySet = ret = createEntrySet();
+ }
+ return ret;
}
@Override
/* internal methods implemented by subclasses */
+ abstract AbstractEntrySet<K, V> createEntrySet();
+
abstract boolean isReadOnly();
abstract INode<K, V> RDCSS_READ_ROOT(boolean abort);
+ /**
+ * Return an iterator over a TrieMap.
+ *
+ * If this is a read-only snapshot, it would return a read-only iterator.
+ *
+ * If it is the original TrieMap or a non-readonly snapshot, it would return
+ * an iterator that would allow for updates.
+ *
+ * @return
+ */
+ abstract Iterator<Entry<K, V>> iterator();
+
/* internal methods provided for subclasses */
+ /**
+ * Return an iterator over a TrieMap.
+ * This is a read-only iterator.
+ *
+ * @return
+ */
+ final Iterator<Entry<K, V>> immutableIterator() {
+ return new TrieMapReadOnlyIterator<>(0, immutableSnapshot());
+ }
+
@SuppressWarnings("null")
static <V> V toNullable(final Optional<V> opt) {
return opt.orElse(null);
return (V) res;
}
-
- /**
- * Return an iterator over a TrieMap.
- *
- * If this is a read-only snapshot, it would return a read-only iterator.
- *
- * If it is the original TrieMap or a non-readonly snapshot, it would return
- * an iterator that would allow for updates.
- *
- * @return
- */
- final Iterator<Entry<K, V>> iterator() {
- // FIXME: it would be nice to have a ReadWriteTrieMap with read-only iterator
- return isReadOnly() ? new TrieMapReadOnlyIterator<>(0, this) : new TrieMapIterator<>(0, this);
- }
-
- /**
- * Return an iterator over a TrieMap.
- * This is a read-only iterator.
- *
- * @return
- */
- final Iterator<Entry<K, V>> readOnlyIterator() {
- return new TrieMapReadOnlyIterator<>(0, immutableSnapshot());
- }
}
@Test(expected = NoSuchElementException.class)
public void testEmptyReadOnlyIterator() {
- failAdvance(TrieMap.create().readOnlyIterator());
+ failAdvance(TrieMap.create().immutableIterator());
}
@Test(expected = NoSuchElementException.class)
@Test(expected = UnsupportedOperationException.class)
public void testReadOnlyIteratorSet() {
- trySet(bt.readOnlyIterator());
+ trySet(bt.immutableIterator());
}
@Test(expected = UnsupportedOperationException.class)
public void testReadOnlyIteratorRemove() {
- tryRemove(bt.readOnlyIterator());
+ tryRemove(bt.immutableIterator());
}
@Test(expected = UnsupportedOperationException.class)
public void testReadOnlySnapshotReadOnlyIteratorSet() {
- trySet(bt.immutableSnapshot().readOnlyIterator());
+ trySet(bt.immutableSnapshot().immutableIterator());
}
@Test(expected = UnsupportedOperationException.class)
public void testReadOnlySnapshotReadOnlyIteratorRemove() {
- tryRemove(bt.immutableSnapshot().readOnlyIterator());
+ tryRemove(bt.immutableSnapshot().immutableIterator());
}
@Test(expected = UnsupportedOperationException.class)