/* File: CheckedMap.java Originally written by Doug Lea and released into the public domain. Thanks for the assistance and support of Sun Microsystems Labs, Agorics Inc, Loral, and everyone contributing, testing, and using this code. History: Date Who What 24Sep95 dl@cs.oswego.edu Create from collections.java working file 13Oct95 dl Misc clean-up */ package collections; import java.util.Enumeration; import java.util.NoSuchElementException; /** * * * CheckedMap supports standard update operations on maps. * * @author Doug Lea * @version 0.93 * *
For an introduction to this package see Overview . **/ public class CheckedMap extends CheckedCollection implements UpdatableMap { /** * Wrap Map m inside a checker **/ public CheckedMap(UpdatableMap m) { super(m); } /** * Make a Checked clone of underlying collection **/ protected Object clone() throws CloneNotSupportedException { return new CheckedMap((UpdatableMap)(thys.duplicate())); } /** * return casted version of CheckedCollection.thys. **/ public UpdatableMap thys() { return (UpdatableMap)thys; } /** * return casted version of CheckedCollection.prev. **/ public UpdatableMap prev() { return (UpdatableMap)prev; } /** * Checks collections.Map.canIncludeKey according to its specification * @see collections.Map#canIncludeKey **/ public boolean canIncludeKey(Object key) { preCheck(); boolean result = thys().canIncludeKey(key); assert(!(result == true && key == null)); assert(thys.sameStructure(prev)); postCheck(); return result; } /** * Checks collections.Map.includesKey according to its specification * @see collections.Map#includesKey **/ public synchronized boolean includesKey(Object key) { preCheck(); boolean result = thys().includesKey(key); assert(!(result == true && !thys().canInclude(key))); assert(thys.sameStructure(prev)); postCheck(); return result; } /** * Checks collections.Map.includesAt according to its specification * @see collections.Map#includesAt **/ public synchronized boolean includesAt(Object key, Object value) { preCheck(); boolean result = thys().includesAt(key, value); assert(!(result == true && (!thys().includesKey(key) || !thys().includes(value)))); assert(thys.sameStructure(prev)); postCheck(); return result; } /** * Checks collections.Map.keys according to its specification * @see collections.Map#keys **/ public synchronized CollectionEnumeration keys() { int c = thys().size(); CollectionEnumeration k = keys(); while (k.hasMoreElements()) { assert(k.numberOfRemainingElements() == c); --c; Object key = k.nextElement(); Object v = thys().at(k); assert(thys().canIncludeKey(key)); assert(thys().canInclude(v)); assert(thys().aKeyOf(v) != null); assert(thys().includesKey(key)); assert(thys().includes(v)); assert(thys().includesAt(k, v)); } postCheck(); // return a new one return thys().keys(); } /** * Checks collections.Map.at according to its specification * @see collections.Map#at **/ public synchronized Object at(Object key) throws NoSuchElementException { preCheck(); try { Object result = thys().at(key); assert(thys().includesAt(key, result)); assert(thys.sameStructure(prev)); postCheck(); return result; } catch (NoSuchElementException ex) { assert(!thys().includesKey(key)); assert(thys.sameStructure(prev)); postCheck(); throw ex; } } /** * Checks collections.Map.aKeyOf according to its specification * @see collections.Map#aKeyOf **/ public synchronized Object aKeyOf(Object element) { preCheck(); Object result = thys().aKeyOf(element); assert((result == null && !thys().includes(element)) || (thys().at(result).equals(element))); assert(thys.sameStructure(prev)); postCheck(); return result; } /** * Checks collections.UpdatableMap.putAt according to its specification * @see collections.UpdatableMap#putAt **/ public synchronized void putAt(Object key, Object element) throws IllegalElementException { preCheck(); try { thys().putAt(key, element); checkPut(thys(), prev(), key, element, true); postCheck(); } catch (IllegalElementException ex) { assert(!canIncludeKey(key) || !canInclude(element)); assert(thys.sameStructure(prev)); postCheck(); throw ex; } } /** * Checks collections.Map.puttingAt. * @see collections.Map#puttingAt **/ public synchronized Map puttingAt(Object key, Object element) throws IllegalElementException { preCheck(); try { Map nc = thys().puttingAt(key, element); checkPut(nc, thys(), key, element, false); assert(thys.sameStructure(prev)); postCheck(); return nc; } catch (IllegalElementException ex) { assert(!canIncludeKey(key) || !canInclude(element)); assert(thys.sameStructure(prev)); postCheck(); throw ex; } } /** * Checks collections.UpdatableMap.removeAt according to its specification * @see collections.UpdatableMap#removeAt **/ public synchronized void removeAt(Object key) { preCheck(); thys().removeAt(key); checkRemoveAt(thys(), prev(), key, true); postCheck(); } /** * Checks collections.Map.removingAt * @see collections.Map#removingAt **/ public synchronized Map removingAt(Object key) { preCheck(); Map nc = thys().removingAt(key); checkRemoveAt(nc, thys(), key, false); assert(thys.sameStructure(prev)); postCheck(); return nc; } /** * Checks collections.UpdatableMap.replaceElement according to its specification * @see collections.UpdatableMap#replaceElement **/ public synchronized void replaceElement(Object key, Object oldElement, Object newElement) throws IllegalElementException { preCheck(); try { thys().replaceElement(key, oldElement, newElement); assert((!thys().includesAt(key, oldElement) || thys().includesAt(key, newElement))); assert(thys().size() == prev().size()); assert(!(thys().version() == prevVersion && prev().includesAt(key, oldElement))); CollectionEnumeration prevKeys = prev().keys(); while (prevKeys.hasMoreElements()) { Object k = prevKeys.nextElement(); assert((k.equals(key) || thys().includesAt(k, prev().at(k)))); } postCheck(); } catch (IllegalElementException ex) { assert(!canInclude(newElement)); assert(thys.sameStructure(prev)); postCheck(); throw ex; } } /** * Helper for checking put* **/ protected void checkPut(Map nc, Map oc, Object key, Object element, boolean verchk) { assert(nc.canIncludeKey(key)); assert(nc.canInclude(element)); int reqSize = oc.size(); if (!oc.includesKey(key)) reqSize = reqSize + 1; assert(nc.includesAt(key, element)); assert(nc.size() == reqSize); CollectionEnumeration os = oc.keys(); while (os.hasMoreElements()) { Object k = os.nextElement(); assert((k.equals(key) || nc.includesAt(k, oc.at(k)))); } if (verchk) { int nv = ((UpdatableCollection)nc).version(); assert((nv == prevVersion) == oc.includesAt(key, element)); } nc.checkImplementation(); } /** * Helper for checking remov* **/ protected void checkRemoveAt(Map nc, Map oc, Object key, boolean verchk) { int reqSize = oc.size(); if (oc.includesKey(key)) reqSize = reqSize - 1; assert(!nc.includesKey(key)); assert(nc.size() == reqSize); CollectionEnumeration os = oc.keys(); while (os.hasMoreElements()) { Object k = os.nextElement(); assert((k.equals(key) || nc.includesAt(k, oc.at(k)))); } if (verchk) { int nv = ((UpdatableCollection)nc).version(); assert((nv == prevVersion) == !oc.includesKey(key)); } nc.checkImplementation(); } };