/* * OMGraphicHash.java * * Created on August 18, 2006, 9:29 AM * * To change this template, choose Tools | Options and locate the template under * the Source Creation and Management node. Right-click the template and choose * Open. You can then make changes to the template in the Source Editor. */ package com.bbn.openmap.omGraphics; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; /** * This is an OMGraphicsList sub-class with a Map interface. Access is backed by * a HashMap. Insertion and removal of OMGraphics is through the Map interface. * <p> * The add(OMGraphic), addOMGraphic(OMGraphic), remove(OMGraphic), and * removeOMGraphicAt(int) method are disabled and will throw a RuntimeException * if called. * <p> * This class is suited for use as the top OMGraphicList in an OMHandlerLayer * that has a large number of OMGraphic objects and needs to access those * objects using a unique key. * <p> * * @see com.bbn.openmap.omGraphics.OMGraphicList * @author David J. Ward */ public class OMGraphicHash extends OMGraphicList { private HashMap<Object, OMGraphic> graphicHash = new HashMap<Object, OMGraphic>(); /** * Creates a new instance of OMGraphicHash */ public OMGraphicHash() { super(); } /** * Construct an OMGraphicList with an initial capacity. * * @param initialCapacity the initial capacity of the list */ public OMGraphicHash(int initialCapacity) { super(initialCapacity); } /** * Returns the value to which this map maps the specified key. Returns * <tt>null</tt> if the map contains no mapping for this key. A return value * of <tt>null</tt> does not <i>necessarily</i> indicate that the map * contains no mapping for the key; it's also possible that the map * explicitly maps the key to <tt>null</tt>. The <tt>containsKey</tt> * operation may be used to distinguish these two cases. * * <p> * More formally, if this map contains a mapping from a key <tt>k</tt> to a * value <tt>v</tt> such that <tt>(key==null ? k==null : * key.equals(k))</tt>, then this method returns <tt>v</tt>; otherwise it * returns <tt>null</tt>. (There can be at most one such mapping.) * * @param obj key whose associated value is to be returned. * @return the value to which this map maps the specified key, or * <tt>null</tt> if the map contains no mapping for this key. * * @throws ClassCastException if the key is of an inappropriate type for * this map (optional). * @throws NullPointerException if the key is <tt>null</tt> and this map * does not permit <tt>null</tt> keys (optional). * * @see #containsKey(Object) */ public OMGraphic get(Object obj) { return graphicHash.get(obj); } /** * Returns <tt>true</tt> if this map contains a mapping for the specified * key. More formally, returns <tt>true</tt> if and only if this map * contains a mapping for a key <tt>k</tt> such that * <tt>(key==null ? k==null : key.equals(k))</tt>. (There can be at most one * such mapping.) * * @param obj key whose presence in this map is to be tested. * @return <tt>true</tt> if this map contains a mapping for the specified * key. * * @throws ClassCastException if the key is of an inappropriate type for * this map (optional). * @throws NullPointerException if the key is <tt>null</tt> and this map * does not permit <tt>null</tt> keys (optional). */ public boolean containsKey(Object obj) { return graphicHash.containsKey(obj); } /** * Returns <tt>true</tt> if this map maps one or more keys to the specified * value. More formally, returns <tt>true</tt> if and only if this map * contains at least one mapping to a value <tt>v</tt> such that * <tt>(value==null ? v==null : value.equals(v))</tt>. This operation will * probably require time linear in the map size for most implementations of * the <tt>Map</tt> interface. * * @param obj value whose presence in this map is to be tested. * @return <tt>true</tt> if this map maps one or more keys to the specified * value. * @throws ClassCastException if the value is of an inappropriate type for * this map (optional). * @throws NullPointerException if the value is <tt>null</tt> and this map * does not permit <tt>null</tt> values (optional). */ public boolean containsValue(OMGraphic obj) { return graphicHash.containsValue(obj); } /** * Returns a set view of the mappings contained in this map. Each element in * the returned set is a {@link java.util.Map.Entry}. The set is backed by the map, so * changes to the map are reflected in the set, and vice-versa. If the map * is modified while an iteration over the set is in progress (except * through the iterator's own <tt>remove</tt> operation, or through the * <tt>setValue</tt> operation on a map entry returned by the iterator) the * results of the iteration are undefined. The set supports element removal, * which removes the corresponding mapping from the map, via the * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>, <tt>removeAll</tt>, * <tt>retainAll</tt> and <tt>clear</tt> operations. It does not support the * <tt>add</tt> or <tt>addAll</tt> operations. * * @return a set view of the mappings contained in this map. */ public java.util.Set<Map.Entry<Object, OMGraphic>> entrySet() { return graphicHash.entrySet(); } /** * Returns a set view of the keys contained in this map. The set is backed * by the map, so changes to the map are reflected in the set, and * vice-versa. If the map is modified while an iteration over the set is in * progress (except through the iterator's own <tt>remove</tt> operation), * the results of the iteration are undefined. The set supports element * removal, which removes the corresponding mapping from the map, via the * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>, <tt>removeAll</tt> * <tt>retainAll</tt>, and <tt>clear</tt> operations. It does not support * the add or <tt>addAll</tt> operations. * * @return a set view of the keys contained in this map. */ public java.util.Set<Object> keySet() { return graphicHash.keySet(); } /** * Associates the specified value with the specified key in this map * (optional operation). If the map previously contained a mapping for this * key, the old value is replaced by the specified value. (A map <tt>m</tt> * is said to contain a mapping for a key <tt>k</tt> if and only if * {@link #containsKey(Object) m.containsKey(k)} would return <tt>true</tt> * .)) * * @param key key with which the specified value is to be associated. * @param graphic value to be associated with the specified key. * @return previous value associated with specified key, or <tt>null</tt> if * there was no mapping for key. A <tt>null</tt> return can also * indicate that the map previously associated <tt>null</tt> with * the specified key, if the implementation supports <tt>null</tt> * values. * * @throws UnsupportedOperationException if the <tt>put</tt> operation is * not supported by this map. * @throws ClassCastException if the class of the specified key or value * prevents it from being stored in this map. * @throws IllegalArgumentException if some aspect of this key or value * prevents it from being stored in this map. * @throws NullPointerException if this map does not permit <tt>null</tt> * keys or values, and the specified key or value is <tt>null</tt>. */ public Object put(Object key, OMGraphic graphic) { // first remove the OMGraphic from the list // Don't allow duplicate graphics in hash, that is multiple // key resolving to a single graphic. This would be very bad. if (graphicHash.containsValue(graphic)) { // now we know that we have this graphic in the // hash, now lets find the associated key. // This requires walkin the keySet. ArrayList<Object> keysToRemove = new ArrayList<Object>(); for (Map.Entry<Object, OMGraphic> entry : graphicHash.entrySet()) { if (entry.getValue().equals(graphic)) { keysToRemove.add((Object) entry.getKey()); } } for (Object obj : keysToRemove) { graphicHash.remove(obj); } super.remove((OMGraphic) graphic); } if (graphicHash.containsKey(key)) { super.remove((OMGraphic) graphic); } super.add(graphic); return graphicHash.put(key, graphic); } /** * Copies all of the mappings from the specified map to this map (optional * operation). The effect of this call is equivalent to that of calling * {@link #put(Object,OMGraphic) put(k, v)} on this map once for each * mapping from key <tt>k</tt> to value <tt>v</tt> in the specified map. The * behavior of this operation is unspecified if the specified map is * modified while the operation is in progress. * * @param map Mappings to be stored in this map. * * @throws UnsupportedOperationException if the <tt>putAll</tt> method is * not supported by this map. * * @throws ClassCastException if the class of a key or value in the * specified map prevents it from being stored in this map. * * @throws IllegalArgumentException some aspect of a key or value in the * specified map prevents it from being stored in this map. * @throws NullPointerException if the specified map is <tt>null</tt>, or if * this map does not permit <tt>null</tt> keys or values, and the * specified map contains <tt>null</tt> keys or values. */ public void putAll(Map<Object, OMGraphic> map) { graphicHash.putAll(map); } /** * Removes the mapping for this key from this map if it is present (optional * operation). More formally, if this map contains a mapping from key * <tt>k</tt> to value <tt>v</tt> such that * <code>(key==null ? k==null : key.equals(k))</code>, that mapping is * removed. (The map can contain at most one such mapping.) * * <p> * Returns the value to which the map previously associated the key, or * <tt>null</tt> if the map contained no mapping for this key. (A * <tt>null</tt> return can also indicate that the map previously associated * <tt>null</tt> with the specified key if the implementation supports * <tt>null</tt> values.) The map will not contain a mapping for the * specified key once the call returns. * * @param key key whose mapping is to be removed from the map. * @return previous value associated with specified key, or <tt>null</tt> if * there was no mapping for key. * * @throws ClassCastException if the key is of an inappropriate type for * this map (optional). * @throws NullPointerException if the key is <tt>null</tt> and this map * does not permit <tt>null</tt> keys (optional). * @throws UnsupportedOperationException if the <tt>remove</tt> method is * not supported by this map. */ public boolean remove(Object key) { OMGraphic graphic = graphicHash.remove(key); return super.remove(graphic); } /** * Returns a collection view of the values contained in this map. The * collection is backed by the map, so changes to the map are reflected in * the collection, and vice-versa. If the map is modified while an iteration * over the collection is in progress (except through the iterator's own * <tt>remove</tt> operation), the results of the iteration are undefined. * The collection supports element removal, which removes the corresponding * mapping from the map, via the <tt>Iterator.remove</tt>, * <tt>Collection.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and * <tt>clear</tt> operations. It does not support the add or <tt>addAll</tt> * operations. * * @return a collection view of the values contained in this map. */ public java.util.Collection<OMGraphic> values() { return graphicHash.values(); } /** used to hold off the IllegalArgumentException during cloning */ private boolean cloningInProgress; /** * @return a duplicate list full of shallow copies of each of the OMGraphics * contained on the list. */ public synchronized Object clone() { cloningInProgress = true; OMGraphicHash omgl = (OMGraphicHash) super.clone(); omgl.graphicHash = (HashMap<Object, OMGraphic>) graphicHash.clone(); cloningInProgress = false; return omgl; } /** * Add an OMGraphic to the list. * <p> * For OMGraphicHash this method will throw an * <code>IllegalArgumentException</code> because adding a graphic must be * done through <code>put(key,value)</code>. */ public boolean add(OMGraphic g) { // Prevent adding a graphic using the OMGraphic List. // OMGraphicHash entry must be added through the Map interface. if (cloningInProgress) { return super.add(g); } throw new RuntimeException("addOMGraphic() not permitted for OMGraphicHash(). Use put(key, OMGraphic) instead."); } /** * Remove the graphic at the location number. * * <p> * For OMGraphicHash this method will throw an * <code>IllegalArgumentException</code> because removing a graphic must be * done through <code>remove(key)</code>. * * @param location the location of the OMGraphic to remove. */ public OMGraphic remove(int location) { // Prevent removing a specific graphic using the OMGraphic List. // OMGraphicHash entry must be remove using remove(Object). throw new RuntimeException("removeOMGraphicAt() not permitted for OMGraphicHash(). Use remove(key) instead."); } /** * Remove the graphic. * * <p> * For OMGraphicHash this method will throw an * <code>IllegalArgumentException</code> because removing a graphic must be * done through <code>remove(key)</code>. * * @param graphic the OMGraphic object to remove. * @return true if graphic was on the list, false if otherwise. */ public boolean remove(OMGraphic graphic) { // Prevent removing a specific graphic using the OMGraphic List. // OMGraphicHash entry must be remove using remove(Object). throw new RuntimeException("remove(OMGraphic) not permitted for OMGraphicHash(). Use remove(key) instead."); } /** * Remove all elements from the graphic list. */ public void clear() { super.clear(); graphicHash.clear(); } public void restore(OMGeometry source) { super.restore(source); if (source instanceof OMGraphicHash) { this.putAll(((OMGraphicHash)source).graphicHash); } } }