/*
* Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.yangtools.util;
import com.google.common.base.Preconditions;
import com.romix.scala.collection.concurrent.TrieMap;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A TrieMap facade tracking modifications. Since we change structures based on
* their size, and determining the size of a TrieMap is expensive, we make sure
* to update it as we go.
*
* <p>FIXME: this map does not support modification view the keySet()/values()/entrySet()
* methods.
*
* @param <K> Key type
* @param <V> Value type
*/
final class ReadWriteTrieMap<K, V> implements Map<K, V> {
private static final Logger LOG = LoggerFactory.getLogger(ReadOnlyTrieMap.class);
private final TrieMap<K, V> delegate;
private int size;
ReadWriteTrieMap() {
this.delegate = new TrieMap<>();
this.size = 0;
}
ReadWriteTrieMap(final TrieMap<K, V> delegate, final int size) {
this.delegate = Preconditions.checkNotNull(delegate);
this.size = size;
}
Map<K, V> toReadOnly() {
final Map<K, V> ret = new ReadOnlyTrieMap<>(delegate, size);
LOG.trace("Converted read-write TrieMap {} to read-only {}", this, ret);
return ret;
}
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public boolean containsKey(final Object key) {
return delegate.containsKey(key);
}
@Override
public boolean containsValue(final Object value) {
return delegate.containsValue(value);
}
@Override
public V get(final Object key) {
return delegate.get(key);
}
@Override
public V put(final K key, final V value) {
final V ret = delegate.put(key, value);
if (ret == null) {
size++;
}
return ret;
}
@Override
public V remove(final Object key) {
final V ret = delegate.remove(key);
if (ret != null) {
size--;
}
return ret;
}
@Override
public void putAll(@Nonnull final Map<? extends K, ? extends V> m) {
for (Entry<? extends K, ? extends V> e : m.entrySet()) {
put(e.getKey(), e.getValue());
}
}
@Override
public void clear() {
delegate.clear();
size = 0;
}
@Override
public Set<K> keySet() {
return Collections.unmodifiableSet(delegate.keySet());
}
@Override
public Collection<V> values() {
return Collections.unmodifiableCollection(delegate.values());
}
@Override
public Set<Entry<K, V>> entrySet() {
return Collections.unmodifiableSet(delegate.entrySet());
}
@Override
public boolean equals(final Object o) {
return delegate.equals(o);
}
@Override
public int hashCode() {
return delegate.hashCode();
}
}