*/
package org.opendaylight.yangtools.util;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.base.Verify.verify;
+import static java.util.Objects.requireNonNull;
+
import com.google.common.annotations.Beta;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Verify;
import com.google.common.collect.ImmutableMap;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
/**
* A mutable version of {@link ImmutableOffsetMap}. It inherits the set of mappings from the immutable version and
}
@Override
- UnmodifiableMapPhase<K, V> modifiedMap(final List<K> keys, final V[] objects) {
- return new ImmutableOffsetMap.Ordered<>(OffsetMapCache.orderedOffsets(keys), objects);
+ UnmodifiableMapPhase<K, V> modifiedMap(final List<K> keys, final V[] values) {
+ return new ImmutableOffsetMap.Ordered<>(OffsetMapCache.orderedOffsets(keys), values);
}
@Override
- UnmodifiableMapPhase<K, V> unmodifiedMap(final Map<K, Integer> offsets, final V[] objects) {
- return new ImmutableOffsetMap.Ordered<>(offsets, objects);
+ UnmodifiableMapPhase<K, V> unmodifiedMap(final Map<K, Integer> offsetMap, final V[] values) {
+ return new ImmutableOffsetMap.Ordered<>(offsetMap, values);
}
@Override
}
@Override
- UnmodifiableMapPhase<K, V> modifiedMap(final List<K> keys, final V[] objects) {
+ UnmodifiableMapPhase<K, V> modifiedMap(final List<K> keys, final V[] values) {
final Map<K, Integer> offsets = OffsetMapCache.unorderedOffsets(keys);
- return new ImmutableOffsetMap.Unordered<>(offsets, OffsetMapCache.adjustedArray(offsets, keys, objects));
+ return new ImmutableOffsetMap.Unordered<>(offsets, OffsetMapCache.adjustedArray(offsets, keys, values));
}
@Override
- UnmodifiableMapPhase<K, V> unmodifiedMap(final Map<K, Integer> offsets, final V[] objects) {
- return new ImmutableOffsetMap.Unordered<>(offsets, objects);
+ UnmodifiableMapPhase<K, V> unmodifiedMap(final Map<K, Integer> offsetMap, final V[] values) {
+ return new ImmutableOffsetMap.Unordered<>(offsetMap, values);
}
@Override
private HashMap<K, V> newKeys;
private Object[] objects;
private int removed = 0;
+
+ // Fail-fast iterator guard, see java.util.ArrayList for reference.
+ @SuppressFBWarnings("VO_VOLATILE_INCREMENT")
private transient volatile int modCount;
private boolean needClone = true;
MutableOffsetMap(final Map<K, Integer> offsets, final V[] objects, final HashMap<K, V> newKeys) {
- Verify.verify(newKeys.isEmpty());
- this.offsets = Preconditions.checkNotNull(offsets);
- this.objects = Preconditions.checkNotNull(objects);
- this.newKeys = Preconditions.checkNotNull(newKeys);
+ verify(newKeys.isEmpty());
+ this.offsets = requireNonNull(offsets);
+ this.objects = requireNonNull(objects);
+ this.newKeys = requireNonNull(newKeys);
}
@SuppressWarnings("unchecked")
this(offsets, (V[]) new Object[offsets.size()], newKeys);
for (Entry<K, V> e : source.entrySet()) {
- objects[offsets.get(e.getKey())] = Preconditions.checkNotNull(e.getValue());
+ objects[offsets.get(e.getKey())] = requireNonNull(e.getValue());
}
this.needClone = false;
}
- public static <K, V> MutableOffsetMap<K, V> orderedCopyOf(final Map<K, V> m) {
- if (m instanceof Ordered) {
- return ((Ordered<K, V>) m).clone();
+ public static <K, V> MutableOffsetMap<K, V> orderedCopyOf(final Map<K, V> map) {
+ if (map instanceof Ordered) {
+ return ((Ordered<K, V>) map).clone();
}
- if (m instanceof ImmutableOffsetMap) {
- final ImmutableOffsetMap<K, V> om = (ImmutableOffsetMap<K, V>) m;
+ if (map instanceof ImmutableOffsetMap) {
+ final ImmutableOffsetMap<K, V> om = (ImmutableOffsetMap<K, V>) map;
return new Ordered<>(om.offsets(), om.objects());
}
- return new Ordered<>(m);
+ return new Ordered<>(map);
}
- public static <K, V> MutableOffsetMap<K, V> unorderedCopyOf(final Map<K, V> m) {
- if (m instanceof Unordered) {
- return ((Unordered<K, V>) m).clone();
+ public static <K, V> MutableOffsetMap<K, V> unorderedCopyOf(final Map<K, V> map) {
+ if (map instanceof Unordered) {
+ return ((Unordered<K, V>) map).clone();
}
- if (m instanceof ImmutableOffsetMap) {
- final ImmutableOffsetMap<K, V> om = (ImmutableOffsetMap<K, V>) m;
+ if (map instanceof ImmutableOffsetMap) {
+ final ImmutableOffsetMap<K, V> om = (ImmutableOffsetMap<K, V>) map;
return new Unordered<>(om.offsets(), om.objects());
}
- return new Unordered<>(m);
+ return new Unordered<>(map);
}
public static <K, V> MutableOffsetMap<K, V> ordered() {
abstract Object removedObject();
- abstract UnmodifiableMapPhase<K, V> modifiedMap(List<K> keys, V[] objects);
+ abstract UnmodifiableMapPhase<K, V> modifiedMap(List<K> keys, V[] values);
- abstract UnmodifiableMapPhase<K, V> unmodifiedMap(Map<K, Integer> offsets, V[] objects);
+ abstract UnmodifiableMapPhase<K, V> unmodifiedMap(Map<K, Integer> offsetMap, V[] values);
abstract SharedSingletonMap<K, V> singletonMap();
private void cloneArray() {
if (needClone) {
needClone = false;
- if (!EMPTY_ARRAY.equals(objects)) {
+ if (objects.length != 0) {
objects = objects.clone();
}
}
@Override
public final V put(final K key, final V value) {
- Preconditions.checkNotNull(value);
- final Integer offset = offsets.get(Preconditions.checkNotNull(key));
+ requireNonNull(value);
+ final Integer offset = offsets.get(requireNonNull(key));
if (offset != null) {
final Object obj = objects[offset];
}
@Override
- public final Set<Entry<K, V>> entrySet() {
+ public final @NonNull Set<Entry<K, V>> entrySet() {
return new EntrySet();
}
@Override
- public Map<K, V> toUnmodifiableMap() {
+ public @NonNull Map<K, V> toUnmodifiableMap() {
if (removed == 0 && newKeys.isEmpty()) {
// Make sure next modification clones the array, as we leak it to the map we return.
needClone = true;
// Construct the values
@SuppressWarnings("unchecked")
final V[] values = (V[])new Object[keyset.size()];
- int i = 0;
+ int offset = 0;
if (removed != 0) {
if (removed != offsets.size()) {
for (Entry<K, Integer> e : offsets.entrySet()) {
if (o != null && !REMOVED.equals(o)) {
@SuppressWarnings("unchecked")
final V v = (V) o;
- values[i++] = v;
+ values[offset++] = v;
}
}
}
} else {
System.arraycopy(objects, 0, values, 0, offsets.size());
- i = offsets.size();
+ offset = offsets.size();
}
for (V v : newKeys.values()) {
- values[i++] = v;
+ values[offset++] = v;
}
return modifiedMap(keyset, values);
}
@Override
- public final boolean equals(final Object o) {
- if (o == this) {
+ public final boolean equals(final Object obj) {
+ if (obj == this) {
return true;
}
- if (!(o instanceof Map)) {
+ if (!(obj instanceof Map)) {
return false;
}
- if (o instanceof ImmutableOffsetMap) {
- final ImmutableOffsetMap<?, ?> om = (ImmutableOffsetMap<?, ?>) o;
+ if (obj instanceof ImmutableOffsetMap) {
+ final ImmutableOffsetMap<?, ?> om = (ImmutableOffsetMap<?, ?>) obj;
if (newKeys.isEmpty() && offsets.equals(om.offsets())) {
return Arrays.deepEquals(objects, om.objects());
}
- } else if (o instanceof MutableOffsetMap) {
- final MutableOffsetMap<?, ?> om = (MutableOffsetMap<?, ?>) o;
+ } else if (obj instanceof MutableOffsetMap) {
+ final MutableOffsetMap<?, ?> om = (MutableOffsetMap<?, ?>) obj;
if (offsets.equals(om.offsets)) {
return Arrays.deepEquals(objects, om.objects) && newKeys.equals(om.newKeys);
}
// Fall back to brute map compare
- final Map<?, ?> other = (Map<?, ?>)o;
+ final Map<?, ?> other = (Map<?, ?>)obj;
// Size and key sets have to match
if (size() != other.size() || !keySet().equals(other.keySet())) {
// Ensure all objects are present
for (Entry<K, Integer> e : offsets.entrySet()) {
- final Object obj = objects[e.getValue()];
- if (obj != null && !REMOVED.equals(obj) && !obj.equals(other.get(e.getKey()))) {
+ final Object val = objects[e.getValue()];
+ if (val != null && !REMOVED.equals(val) && !val.equals(other.get(e.getKey()))) {
return false;
}
}
}
@Override
- public final Set<K> keySet() {
+ public final @NonNull Set<K> keySet() {
return new KeySet();
}
private final class EntrySet extends AbstractSet<Entry<K, V>> {
@Override
- public Iterator<Entry<K, V>> iterator() {
+ public @NonNull Iterator<Entry<K, V>> iterator() {
return new AbstractSetIterator<Entry<K, V>>() {
@Override
public Entry<K, V> next() {
}
@Override
+ @SuppressWarnings("checkstyle:parameterName")
public boolean contains(final Object o) {
if (!(o instanceof Entry)) {
return false;
}
@Override
+ @SuppressWarnings("checkstyle:parameterName")
public boolean add(final Entry<K, V> e) {
- Preconditions.checkNotNull(e.getValue());
- final V p = MutableOffsetMap.this.put(e.getKey(), e.getValue());
- return !e.getValue().equals(p);
+ final V v = requireNonNull(e.getValue());
+ final V p = MutableOffsetMap.this.put(e.getKey(), v);
+ return !v.equals(p);
}
@Override
+ @SuppressWarnings("checkstyle:parameterName")
public boolean remove(final Object o) {
if (!(o instanceof Entry)) {
return false;
private final class KeySet extends AbstractSet<K> {
@Override
- public Iterator<K> iterator() {
+ public @NonNull Iterator<K> iterator() {
return new AbstractSetIterator<K>() {
@Override
public K next() {
private final Iterator<Entry<K, Integer>> oldIterator = offsets.entrySet().iterator();
private final Iterator<K> newIterator = newKeys.keySet().iterator();
private int expectedModCount = modCount;
- private K currentKey;
- private K nextKey;
+ private @Nullable K currentKey = null;
+ private @Nullable K nextKey;
AbstractSetIterator() {
updateNextKey();
@Override
public final void remove() {
- Preconditions.checkState(currentKey != null);
-
checkModCount();
+ checkState(currentKey != null);
final Integer offset = offsets.get(currentKey);
if (offset != null) {
cloneArray();