Sketcher2 source code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

194 lines
4.5 KiB

package com.jotuntech.sketcher.common;
import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
/**
* This map is for storing values with keys. A value can be located
* with a key and vice versa. This class will assume that no mutations to the keys
* are made. Values may implement Copyable to get included in copy() operations
* performed on the map.
*
* @author Thor Harald Johansen
*
* @param <V> Type of values this map will store
*/
public class TwoWayHashMap<K, V> implements Map<K, V>, Copyable<TwoWayHashMap<K, V>> {
private Map<K, V> keyMap;
private Map<V, K> valueMap;
private List<ChangeListener> changeListeners;
private Integer autoKey;
/** Create new integer map */
public TwoWayHashMap() {
keyMap = new LinkedHashMap<K, V>();
valueMap = new IdentityHashMap<V, K>();
changeListeners = new LinkedList<ChangeListener>();
autoKey = new Integer(1);
}
@SuppressWarnings("unchecked")
public TwoWayHashMap(TwoWayHashMap<K, V> map) {
keyMap = new LinkedHashMap<K, V>();
valueMap = new IdentityHashMap<V, K>();
changeListeners = new LinkedList<ChangeListener>();
autoKey = map.autoKey;
for(Map.Entry<K, V> e : map.keyMap.entrySet()) {
if(e.getValue() instanceof Copyable<?>) {
put(e.getKey(), ((Copyable<V>)e.getValue()).copy());
} else {
put(e.getKey(), e.getValue());
}
}
}
/** Insert value into map under specified key */
public V put(K key, V value) {
/** Put key into key map, store old value */
V oldValue = keyMap.put(key, value);
/** Remove old value from value map */
valueMap.remove(oldValue);
/** Put value into value map */
valueMap.put(value, key);
/** Notify change listener method */
change();
/** Return old value */
return oldValue;
}
/** Insert value into map and auto-assign key
*
* @return Auto-assigned key
*/
@SuppressWarnings("unchecked")
public K put(V value) {
/** Put value into map */
put((K) autoKey, value);
/** Increment auto key and return previous one */
return (K) autoKey++;
}
/** Remove entry for specified key from map
*
* @return Entry that was removed, or null if no such entry.
*/
public V remove(Object key) {
/** Remove key from key map, store old value */
V oldValue = keyMap.remove(key);
/** Remove old value from value map */
valueMap.remove(oldValue);
/** Notify change listener method */
change();
/** Return old value */
return oldValue;
}
/** Remove entry for specified value from map
*
* @return Key of entry that was removed, or null if no such entry.
*/
public K removeByValue(V value) {
/** Remove old value from value map, store old key */
K oldKey = valueMap.remove(value);
/** Remove old key from key map */
keyMap.remove(oldKey);
/** Notify change listener method */
change();
/** Return old key */
return oldKey;
}
/** Get value for specified key */
public V get(Object key) {
return keyMap.get(key);
}
/** Get key for specified value */
public K getKeyForValue(V value) {
return valueMap.get(value);
}
/** Get entry set from map */
public Set<Map.Entry<K, V>> entrySet() {
return keyMap.entrySet();
}
/** Get set of keys from map */
public Set<K> keySet() {
return keyMap.keySet();
}
/** Get collection of values from map */
public Collection<V> values() {
return keyMap.values();
}
public void addChangeListener(ChangeListener l) {
changeListeners.add(l);
}
/** Notify listeners of change to map */
public void change() {
for(ChangeListener l : changeListeners) {
l.stateChanged(new ChangeEvent(this));
}
}
public TwoWayHashMap<K, V> copy() {
return new TwoWayHashMap<K, V>(this);
}
public void clear() {
keyMap.clear();
valueMap.clear();
change();
}
public void setNextKey(Integer nextKey) {
this.autoKey = nextKey;
}
public Integer getNextKey() {
return autoKey;
}
public boolean containsKey(Object key) {
return keyMap.containsKey(key);
}
public boolean containsValue(Object value) {
return valueMap.containsKey(value);
}
public boolean isEmpty() {
return keyMap.isEmpty();
}
public void putAll(Map<? extends K, ? extends V> m) {
throw new UnsupportedOperationException();
}
public int size() {
return keyMap.size();
}
}