/*
* Copyright (c) 2014 Globo.com - ATeam
* All rights reserved.
*
* This source is subject to the Apache License, Version 2.0.
* Please see the LICENSE file for more information.
*
* Authors: See AUTHORS file
*
* 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.globo.galeb.collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Map;
import java.util.TreeMap;
/**
* Class IndexedMap.
*
* @author See AUTHORS file.
* @version 1.0.0, Nov 8, 2014.
* @param <K> the key type
* @param <V> the value type
*/
public class IndexedMap<K, V> extends TreeMap<K, V> {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = 7940164428900645591L;
/** The indexed keys. */
private Map<Integer, K> indexedKeys = new HashMap<>();
/** The last index. */
private int lastIndex = 0;
/**
* Instantiates a new indexed map.
*/
public IndexedMap() {
super();
}
/**
* Instantiates a new indexed map.
*
* @param map the map
*/
public IndexedMap(Map<? extends K, ? extends V> map) {
super(map);
putAllToIndex(map);
}
/* (non-Javadoc)
* @see java.util.HashMap#put(java.lang.Object, java.lang.Object)
*/
@Override
public V put(K key, V value) {
lastIndex = getNextIndex();
indexedKeys.put(lastIndex, key);
return super.put(key, value);
}
/**
* Put a key/value and to index with 'index'.
*
* @param key the key
* @param value the value
* @param index the index
* @return the v
*/
public V put(K key, V value, int index) {
lastIndex = index;
indexedKeys.put(index, key);
return super.put(key, value);
}
/* (non-Javadoc)
* @see java.util.HashMap#putAll(java.util.Map)
*/
@Override
public void putAll(Map<? extends K, ? extends V> m) {
putAllToIndex(m);
super.putAll(m);
}
/* (non-Javadoc)
* @see java.util.HashMap#remove(java.lang.Object)
*/
@Override
public V remove(Object key) {
indexedKeys.remove(key);
return super.remove(key);
}
/* (non-Javadoc)
* @see java.util.HashMap#clear()
*/
@Override
public void clear() {
super.clear();
indexedKeys.clear();
}
/**
* Put all to index.
*
* @param map the map
*/
private void putAllToIndex(Map<? extends K, ? extends V> map) {
lastIndex = getNextIndex();
for (K key: map.keySet()) {
indexedKeys.put(lastIndex, key);
lastIndex++;
}
}
/**
* Gets the next index.
*
* @return the next index
*/
private synchronized Integer getNextIndex() {
return indexedKeys.isEmpty() ? 0 : Collections.max(indexedKeys.keySet()) + 1;
}
/**
* Gets the value by index.
*
* @param index the index
* @return the value by index
*/
public V getValueByIndex(Integer index) {
try {
return super.get(indexedKeys.get(index));
} catch (RuntimeException ignore) {
return null;
}
}
/**
* Gets the key by index.
*
* @param index the index
* @return the key by index
*/
public K getKeyByIndex(Integer index) {
return indexedKeys.get(index);
}
/**
* Reindex the keys
*/
public void reindex() {
indexedKeys.clear();
putAllToIndex(this);
}
/**
* Gets the index.
*
* @param key the key
* @return the index
*/
public Integer getIndex(K key) {
Integer index = -1;
if (this.containsKey(key)) {
for (Entry<Integer, K> entry : indexedKeys.entrySet()) {
if (entry.getValue() == key) {
index = entry.getKey();
break;
}
}
}
return index;
}
/**
* Gets the last index.
*
* @return the last index
*/
public int getLastIndex() {
return lastIndex;
}
}