Coverage Report - org.as3collections.AbstractListMap
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractListMap
100%
98/98
N/A
0
 
 1  
 /*
 2  
  * Licensed under the MIT License
 3  
  * 
 4  
  * Copyright 2010 (c) Flávio Silva, http://flsilva.com
 5  
  *
 6  
  * Permission is hereby granted, free of charge, to any person
 7  
  * obtaining a copy of this software and associated documentation
 8  
  * files (the "Software"), to deal in the Software without
 9  
  * restriction, including without limitation the rights to use,
 10  
  * copy, modify, merge, publish, distribute, sublicense, and/or sell
 11  
  * copies of the Software, and to permit persons to whom the
 12  
  * Software is furnished to do so, subject to the following
 13  
  * conditions:
 14  
  *
 15  
  * The above copyright notice and this permission notice shall be
 16  
  * included in all copies or substantial portions of the Software.
 17  
  *
 18  
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 19  
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 20  
  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 21  
  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 22  
  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 23  
  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 24  
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 25  
  * OTHER DEALINGS IN THE SOFTWARE.
 26  
  * 
 27  
  * http://www.opensource.org/licenses/mit-license.php
 28  
  */
 29  
 
 30  1
 package org.as3collections
 31  
 {
 32  
         import org.as3collections.errors.IndexOutOfBoundsError;
 33  
         import org.as3collections.lists.ArrayList;
 34  
         import org.as3collections.utils.MapUtil;
 35  
         import org.as3coreaddendum.errors.CloneNotSupportedError;
 36  
         import org.as3coreaddendum.errors.UnsupportedOperationError;
 37  
         import org.as3utils.ReflectionUtil;
 38  
 
 39  
         import flash.errors.IllegalOperationError;
 40  
 
 41  
         /**
 42  
          * This class provides a skeletal implementation of the <code>IListMap</code> interface, to minimize the effort required to implement this interface.
 43  
          * <p>This class maintains two <code>ArrayList</code> objects as its source, one for <code>keys</code> and one for <code>values</code>.</p>
 44  
          * <p>This is an abstract class and shouldn't be instantiated directly.</p>
 45  
          * <p>This class makes guarantees as to the order of the map.
 46  
          * The order in which elements are stored is the order in which they were inserted.</p>
 47  
          * <p>The documentation for each non-abstract method in this class describes its implementation in detail.
 48  
          * Each of these methods may be overridden if the map being implemented admits a more efficient implementation.</p>
 49  
          * <p><b>IMPORTANT:</b></p>
 50  
          * <p>This class implements equality through <code>org.as3coreaddendum.system.IEquatable</code> interface in the <code>equals</code> method and in all methods that compares the elements inside this collection (i.e. <code>containsKey</code>, <code>containsValue</code>, <code>put</code>, <code>remove</code>, <code>removeAll</code> and <code>retainAll</code>).</p>
 51  
          * <p>In order to this map uses the <code>equals</code> method of its keys and/or values in comparisons (rather than default '==' operator), <b>all keys and/or values in this map must implement the</b> <code>org.as3coreaddendum.system.IEquatable</code> <b>interface and also the supplied key and/or value.</b></p>
 52  
          * <p>For example:</p>
 53  
          * <p>myMap.containsKey(myKey);</p>
 54  
          * <p>All keys (but in this case only keys) inside <code>myMap</code>, and <code>myKey</code>, must implement the <code>org.as3coreaddendum.system.IEquatable</code> interface so that <code>equals</code> method of each key can be used in the comparison.
 55  
          * Otherwise '==' operator is used. The same is true for values.
 56  
          * The use of equality for keys and values are independent.
 57  
          * It's possible to use only keys that implement <code>IEquatable</code>, only values, both, or none.
 58  
          * This usage varies according to application needs.</p>
 59  
          * <p>All subclasses of this class <em>must</em> conform with this behavior.</p>
 60  
          * 
 61  
          * @see         org.as3collections.IListMap IListMap
 62  
          * @see         org.as3collections.IList IList
 63  
          * @see         org.as3collections.lists.ArrayList ArrayList
 64  
          * @see         http://as3coreaddendum.org/en-us/documentation/asdoc/org/as3coreaddendum/system/IEquatable.html        org.as3coreaddendum.system.IEquatable
 65  
          * @author Flávio Silva
 66  
          */
 67  
         public class AbstractListMap implements IListMap
 68  
         {
 69  
                 /**
 70  
                  * @private
 71  
                  */
 72  
                 protected var _modCount: int;
 73  
 
 74  
                 private var _keys: IList;
 75  
                 private var _values: IList;
 76  
                 
 77  
                 /**
 78  
                  * @inheritDoc
 79  
                  */
 80  
                 public function get allKeysEquatable(): Boolean { return _keys.allEquatable; }
 81  
 
 82  
                 /**
 83  
                  * @inheritDoc
 84  
                  */
 85  
                 public function get allValuesEquatable(): Boolean { return _values.allEquatable; }
 86  
                 
 87  
                 /**
 88  
                  * @inheritDoc
 89  
                  */
 90  
                 public function get modCount(): int { return _modCount; }
 91  
                 
 92  
                 /**
 93  
                  * @private
 94  
                  */
 95  
                 protected function get keys(): IList { return _keys; }
 96  
                 protected function set keys(value:IList): void { _keys = value; }
 97  
 
 98  
                 /**
 99  
                  * @private
 100  
                  */
 101  
                 protected function get values(): IList { return _values; }
 102  
                 protected function set values(value:IList): void { _values = value; }
 103  
 
 104  
                 /**
 105  
                  * Constructor, creates a new AbstractListMap object.
 106  
                  * 
 107  
                  * @param         source         a map with wich fill this map.
 108  
                  * @throws         IllegalOperationError         If this class is instantiated directly, in other words, if there is <b>not</b> another class extending this class.
 109  
                  */
 110  
                 public function AbstractListMap(source:IMap = null)
 111  1
                 {
 112  1
                         if (ReflectionUtil.classPathEquals(this, AbstractListMap))  throw new IllegalOperationError(ReflectionUtil.getClassName(this) + " is an abstract class and shouldn't be instantiated directly.");
 113  
                         
 114  1
                         _init();
 115  
                         
 116  1
                         if (source && !source.isEmpty()) putAll(source);
 117  1
                 }
 118  
 
 119  
                 /**
 120  
                  * Removes all of the mappings from this map (optional operation).
 121  
                  * The map will be empty after this call returns.
 122  
                  * <p>This implementation always throws an <code>UnsupportedOperationError</code>.</p>
 123  
                  * 
 124  
                  * @throws         org.as3coreaddendum.errors.UnsupportedOperationError          if the <code>clear</code> operation is not supported by this map.
 125  
                  */
 126  
                 public function clear(): void
 127  
                 {
 128  1
                         throw new UnsupportedOperationError("Method must be overridden in subclass: " + ReflectionUtil.getClassPath(this));
 129  
                 }
 130  
 
 131  
                 /**
 132  
                  * Creates and return a shallow copy of this collection.
 133  
                  * <p>This implementation always throws a <code>CloneNotSupportedError</code>.</p>
 134  
                  * 
 135  
                  * @throws         org.as3coreaddendum.errors.CloneNotSupportedError          if this map doesn't support clone.
 136  
                  * @return         A new object that is a shallow copy of this instance.
 137  
                   */
 138  
                 public function clone(): *
 139  
                 {
 140  1
                         throw new CloneNotSupportedError("Method must be overridden in subclass: " + ReflectionUtil.getClassPath(this));
 141  
                 }
 142  
 
 143  
                 /**
 144  
                  * @inheritDoc
 145  
                  * 
 146  
                  * @throws         org.as3coreaddendum.errors.ClassCastError                  if the type of the specified key is incompatible with this map (optional).
 147  
                  * @throws         ArgumentError        if the specified key is <code>null</code> and this map does not permit <code>null</code> keys (optional).
 148  
                  */
 149  
                 public function containsKey(key:*): Boolean
 150  
                 {
 151  1
                         return indexOfKey(key) != -1;
 152  
                 }
 153  
 
 154  
                 /**
 155  
                  * @inheritDoc
 156  
                  * 
 157  
                  * @throws         org.as3coreaddendum.errors.ClassCastError                  if the type of the specified value is incompatible with this map (optional).
 158  
                  * @throws         ArgumentError        if the specified value is <code>null</code> and this map does not permit <code>null</code> values (optional).
 159  
                  */
 160  
                 public function containsValue(value:*): Boolean
 161  
                 {
 162  1
                         return indexOfValue(value) != -1;
 163  
                 }
 164  
 
 165  
                 /**
 166  
                  * Returns an <code>ArrayList</code> object that is a view of the mappings contained in this map (in the same order).
 167  
                  * The type of the objects within the list is <code>IMapEntry</code>
 168  
                  * <p>Modifications in the <code>ArrayList</code> object doesn't affect this map.</p>
 169  
                  * 
 170  
                  * @return         an <code>ArrayList</code> object that is a view of the mappings contained in this map.
 171  
                  * @see org.as3collections.IMapEntry IMapEntry
 172  
                  * @see org.as3collections.IList IList
 173  
                  * @see org.as3collections.lists.ArrayList ArrayList
 174  
                   */
 175  
                 public function entryCollection(): ICollection
 176  
                 {
 177  1
                         var list:IList = new ArrayList();
 178  1
                         var it:IIterator = iterator();
 179  
                         var value:*;
 180  
                         var entry:IMapEntry;
 181  
                         
 182  1
                         while (it.hasNext())
 183  
                         {
 184  1
                                 value = it.next();
 185  1
                                 entry = new MapEntry(it.pointer(), value);
 186  1
                                 list.add(entry);
 187  
                         }
 188  
                         
 189  1
                         return list;
 190  
                 }
 191  
 
 192  
                 /**
 193  
                  * This method uses <code>MapUtil.equalConsideringOrder</code> method to perform equality, sending this map and <code>other</code> argument.
 194  
                  * 
 195  
                  * @param          other         the object to be compared for equality.
 196  
                  * @return         <code>true</code> if the arbitrary evaluation considers the objects equal.
 197  
                  * @see         org.as3collections.utils.MapUtil#equalConsideringOrder() MapUtil.equalConsideringOrder()
 198  
                  */
 199  
                 public function equals(other:*): Boolean
 200  
                 {
 201  1
                         return MapUtil.equalConsideringOrder(this, other);
 202  
                 }
 203  
                 
 204  
                 /**
 205  
                  * Returns the key at the specified position in this map.
 206  
                  * <p>This implementation forwards the call to <code>keys.getAt(index)</code>.</p>
 207  
                  * 
 208  
                  * @param         index         index of the key to return.
 209  
                  * @throws         org.as3collections.errors.IndexOutOfBoundsError         if the index is out of range <code>(index &lt; 0 || index &gt;= size())</code>.
 210  
                  * @return         the key at the specified position in this map.
 211  
                  */
 212  
                 public function getKeyAt(index:int): *
 213  
                 {
 214  1
                         return keys.getAt(index);
 215  
                 }
 216  
                 
 217  
                 /**
 218  
                  * Returns the value at the specified position in this map.
 219  
                  * <p>This implementation forwards the call to <code>values.getAt(index)</code>.</p>
 220  
                  * 
 221  
                  * @param         index         index of the value to return.
 222  
                  * @throws         org.as3collections.errors.IndexOutOfBoundsError         if the index is out of range <code>(index &lt; 0 || index &gt;= size())</code>.
 223  
                  * @return         the value at the specified position in this map.
 224  
                  */
 225  
                 public function getValueAt(index:int): *
 226  
                 {
 227  1
                         return values.getAt(index);
 228  
                 }
 229  
 
 230  
                 /**
 231  
                  * Returns an <code>ArrayList</code> object that is a view of the keys contained in this map.
 232  
                  * <p>Modifications in the <code>ArrayList</code> object doesn't affect this map.</p>
 233  
                  * 
 234  
                  * @return         an <code>ArrayList</code> object that is a view of the keys contained in this map.
 235  
                  * @see org.as3collections.IList IList
 236  
                  * @see org.as3collections.lists.ArrayList ArrayList
 237  
                   */
 238  
                 public function getKeys(): ICollection
 239  
                 {
 240  1
                         return _keys.clone();
 241  
                 }
 242  
 
 243  
                 /**
 244  
                  * Returns the value to which the specified key is mapped, or <code>null</code> if this map contains no mapping for the key.
 245  
                  * <p>If this map permits <code>null</code> values, then a return value of <code>null</code> does not <em>necessarily</em> indicate that the map contains no mapping for the key.
 246  
                  * It's possible that the map explicitly maps the key to <code>null</code>.
 247  
                  * The <code>containsKey</code> method may be used to distinguish these two cases.</p>
 248  
                  * <p>This implementation uses <code>indexOfKey</code> method to get the index of the key/value and then calls <code>values.getAt</code> method.</p>
 249  
                  * 
 250  
                  * @param          key         the key whose associated value is to be returned.
 251  
                  * @throws         org.as3coreaddendum.errors.ClassCastError                  if the type of the specified key is incompatible with this map (optional).
 252  
                  * @throws         ArgumentError          if the specified key is <code>null</code> and this map does not permit <code>null</code> keys (optional).
 253  
                  * @return         the value to which the specified key is mapped, or <code>null</code> if this map contains no mapping for the key.
 254  
                  */
 255  
                 public function getValue(key:*): *
 256  
                 {
 257  1
                         var indexKey:int = indexOfKey(key);
 258  1
                         if (indexKey == -1) return null;
 259  
                         
 260  1
                         return _values.getAt(indexKey);
 261  
                 }
 262  
 
 263  
                 /**
 264  
                  * Returns an <code>ArrayList</code> object that is a view of the values contained in this map.
 265  
                  * <p>Modifications in the <code>ArrayList</code> object doesn't affect this map.</p>
 266  
                  * 
 267  
                  * @return         an <code>ArrayList</code> object that is a view of the values contained in this map.
 268  
                  * @see org.as3collections.IList IList
 269  
                  * @see org.as3collections.lists.ArrayList ArrayList
 270  
                   */
 271  
                 public function getValues(): ICollection
 272  
                 {
 273  1
                         return _values.clone();
 274  
                 }
 275  
                 
 276  
                 /**
 277  
                  * Returns a new <code>IListMap</code> object that is a view of the portion of this map whose keys are strictly less than <code>toKey</code>.
 278  
                  * The returned map supports all optional map operations that this map supports.
 279  
                  * <p>This implementation uses <code>subMap(0, indexOfKey(toKey))</code>.</p>
 280  
                  * <p>Note that this implementation will throw an <code>UnsupportedOperationError</code> unless <code>subMap</code> is overridden.</p>
 281  
                  * 
 282  
                  * @param          toKey         high endpoint (exclusive) of the keys in the returned map.
 283  
                  * @throws         ArgumentError         if <code>toKey</code> is <code>null</code> and this map does not permit <code>null</code> keys.
 284  
                  * @throws         ArgumentError         if <code>containsKey(toKey)</code> returns <code>false</code>.
 285  
                  * @return         a new <code>IListMap</code> that is a view of the portion of this map whose keys are strictly less than <code>toKey</code>.
 286  
                  */
 287  
                 public function headMap(toKey:*): IListMap
 288  
                 {
 289  1
                         if (!containsKey(toKey)) throw new ArgumentError("This maps does not contains the specified key: " + toKey);
 290  
                         
 291  1
                         var fromIndex:int = 0;
 292  1
                         var toIndex:int = indexOfKey(toKey);
 293  
                         
 294  1
                         var map:IListMap = subMap(fromIndex, toIndex);
 295  1
                         return map;
 296  
                 }
 297  
                 
 298  
                 /**
 299  
                  * Returns the position of the specified key.
 300  
                  * <p>This implementation forwards the call to <code>keys.indexOf(key)</code>.</p>
 301  
                  * 
 302  
                  * @param          key         the key to search for.
 303  
                  * @return         the position of the specified key.
 304  
                   */
 305  
                 public function indexOfKey(key:*): int
 306  
                 {
 307  1
                         return _keys.indexOf(key);
 308  
                 }
 309  
 
 310  
                 /**
 311  
                  * Returns the position of the specified value.
 312  
                  * <p>This implementation forwards the call to <code>values.indexOf(value)</code>.</p>
 313  
                  * 
 314  
                  * @param          value         the value to search for.
 315  
                  * @return         the position of the specified value.
 316  
                   */
 317  
                 public function indexOfValue(value:*): int
 318  
                 {
 319  1
                         return _values.indexOf(value);
 320  
                 }
 321  
 
 322  
                 /**
 323  
                  * @inheritDoc
 324  
                   */
 325  
                 public function isEmpty(): Boolean
 326  
                 {
 327  1
                         return size() == 0;
 328  
                 }
 329  
 
 330  
                 /**
 331  
                  * Returns an iterator over a set of mappings.
 332  
                  * <p>This implementation always throws an <code>UnsupportedOperationError</code>.</p>
 333  
                  * 
 334  
                  * @return         an iterator over a set of values.
 335  
                  * @throws         org.as3coreaddendum.errors.UnsupportedOperationError          this method must be overridden in subclass.
 336  
                   */
 337  
                 public function iterator(): IIterator
 338  
                 {
 339  1
                         throw new UnsupportedOperationError("Method must be overridden in subclass: " + ReflectionUtil.getClassPath(this));
 340  
                 }
 341  
                 
 342  
                 /**
 343  
                  * Returns a <code>IListMapIterator</code> object to iterate over the mappings in this map (in proper sequence), starting at the specified position in this map.
 344  
                  * The specified index indicates the first value that would be returned by an initial call to <code>next</code>.
 345  
                  * An initial call to <code>previous</code> would return the value with the specified index minus one.
 346  
                  * <p>This implementation always throws an <code>UnsupportedOperationError</code>.</p>
 347  
                  * 
 348  
                  * @param          index         index of first value to be returned from the iterator (by a call to the <code>next</code> method) 
 349  
                  * @return         a <code>IListMapIterator</code> object to iterate over the mappings in this map (in proper sequence), starting at the specified position in this map.
 350  
                  */
 351  
                 public function listMapIterator(index:int = 0): IListMapIterator
 352  
                 {
 353  1
                         throw new UnsupportedOperationError("Method must be overridden in subclass: " + ReflectionUtil.getClassPath(this));
 354  
                 }
 355  
 
 356  
                 /**
 357  
                  * Associates the specified value with the specified key in this map (optional operation).
 358  
                  * If the map previously contained a mapping for the key, the old value is replaced by the specified value, and the order of the key is not affected.
 359  
                  * (A map <code>m</code> is said to contain a mapping for a key <code>k</code> if and only if <code>m.containsKey(k)</code> would return <code>true</code>.) 
 360  
                  * <p>This implementation always throws an <code>UnsupportedOperationError</code>.</p>
 361  
                  * 
 362  
                  * @param          key         key with which the specified value is to be associated.
 363  
                  * @param          value         value to be associated with the specified key.
 364  
                  * @throws         org.as3coreaddendum.errors.UnsupportedOperationError          if the <code>put</code> operation is not supported by this map.
 365  
                  * @throws         org.as3coreaddendum.errors.ClassCastError                                  if the type of the specified key or value is incompatible with this map.
 366  
                  * @throws         ArgumentError                                                                                        if the specified key or value is <code>null</code> and this map does not permit <code>null</code> keys or values.
 367  
                  * @return         the previous value associated with key, or <code>null</code> if there was no mapping for key. (A <code>null</code> return can also indicate that the map previously associated <code>null</code> with key, if the implementation supports <code>null</code> values.)
 368  
                  */
 369  
                 public function put(key:*, value:*): *
 370  
                 {
 371  1
                         throw new UnsupportedOperationError("Method must be overridden in subclass: " + ReflectionUtil.getClassPath(this));
 372  
                 }
 373  
                 
 374  
                 /**
 375  
                  * Associates the specified value with the specified key at the specified position in this map (optional operation).
 376  
                  * Shifts the entry currently at that position (if any) and any subsequent entries to the right (adds one to their indices).
 377  
                  * <p>This implementation always throws an <code>UnsupportedOperationError</code>.</p>
 378  
                  * 
 379  
                  * @param          index         index at which the specified entry is to be inserted.
 380  
                  * @param          key         key with which the specified value is to be associated.
 381  
                  * @param          value         value to be associated with the specified key.
 382  
                  * @throws         org.as3coreaddendum.errors.UnsupportedOperationError          if the <code>putAt</code> operation is not supported by this map.
 383  
                  * @throws         org.as3coreaddendum.errors.ClassCastError                                  if the type of the specified key or value is incompatible with this map.
 384  
                  * @throws         ArgumentError                                                                                          if the specified key or value is <code>null</code> and this map does not permit <code>null</code> keys or values.
 385  
                  * @throws         ArgumentError                                                                                          if this map already contains the specified key.
 386  
                  * @throws         org.as3collections.errors.IndexOutOfBoundsError                 if the index is out of range <code>(index &lt; 0 || index &gt; size())</code>. 
 387  
                  */
 388  
                 public function putAt(index:int, key:*, value:*): void
 389  
                 {
 390  1
                         throw new UnsupportedOperationError("Method must be overridden in subclass: " + ReflectionUtil.getClassPath(this));
 391  
                 }
 392  
 
 393  
                 /**
 394  
                  * Copies all of the mappings from the specified map to this map (optional operation).
 395  
                  * The effect of this call is equivalent to that of calling <code>put(k, v)</code> on this map once for each mapping from key <code>k</code> to value <code>v</code> in the specified map.
 396  
                  * <p>This implementation calls <code>putAllAt(size(), collection)</code>.</p>
 397  
                  * <p>Note that this implementation will throw an <code>UnsupportedOperationError</code> unless <code>putAt</code> is overridden (assuming the specified map is non-empty).</p>
 398  
                  * 
 399  
                  * @param          map         mappings to be stored in this map.
 400  
                  * @throws         org.as3coreaddendum.errors.UnsupportedOperationError          if the <code>putAll</code> operation is not supported by this map.
 401  
                  * @throws         org.as3coreaddendum.errors.ClassCastError                                  if the type of a key or value in the specified map is incompatible with this map.
 402  
                  * @throws         ArgumentError                          if the specified map is <code>null</code>, or if this map does not permit <code>null</code> keys or values, and the specified map contains <code>null</code> keys or values.
 403  
                  */
 404  
                 public function putAll(map:IMap): void
 405  
                 {
 406  1
                         putAllAt(size(), map);
 407  1
                 }
 408  
                 
 409  
                 /**
 410  
                  * Copies all of the mappings from the specified map to this map (optional operation).
 411  
                  * Shifts the entry currently at that position (if any) and any subsequent entries to the right (increases their indices).
 412  
                  * The new entries will appear in this map in the order that they are returned by the specified map's iterator.
 413  
                  * <p>This implementation iterates over the specified map, and calls this map's <code>putAt</code> operation once for each entry returned by the iteration.</p>
 414  
                  * 
 415  
                  * @param          index         index at which to insert the first entry from the specified map.
 416  
                  * @param          map         mappings to be stored in this map.
 417  
                  * @throws         org.as3coreaddendum.errors.UnsupportedOperationError          if the <code>putAllAt</code> operation is not supported by this map.
 418  
                  * @throws         org.as3coreaddendum.errors.ClassCastError                                  if the type of a key or value in the specified map is incompatible with this map.
 419  
                  * @throws         ArgumentError                          if the specified map is <code>null</code>, or if this map does not permit <code>null</code> keys or values, and the specified map contains <code>null</code> keys or values.
 420  
                  */
 421  
                 public function putAllAt(index:int, map:IMap): void
 422  
                 {
 423  1
                         if (!map) throw new ArgumentError("The 'map' argument must not be 'null'.");
 424  1
                         if (map.isEmpty()) return;
 425  1
                         checkIndex(index, size());
 426  
                         
 427  1
                         var it:IIterator = map.iterator();
 428  
                         var value:*;
 429  
                         
 430  1
                         while (it.hasNext())
 431  
                         {
 432  1
                                 value = it.next();
 433  
                                 
 434  1
                                 putAt(index, it.pointer(), value);
 435  1
                                 index++;
 436  
                         }
 437  1
                 }
 438  
 
 439  
                 /**
 440  
                  * This implementation performs a <code>for..in</code> in the specified object, calling <code>put</code> on this map once for each iteration (optional operation).
 441  
                  * 
 442  
                  * @param          o         the object to retrieve the properties.
 443  
                  * @throws         org.as3coreaddendum.errors.UnsupportedOperationError          if the <code>putAllByObject</code> operation is not supported by this map.
 444  
                  * @throws         org.as3coreaddendum.errors.ClassCastError                                  if the type of a key or value in the specified object is incompatible with this map.
 445  
                  * @throws         ArgumentError                          if the specified object is <code>null</code>, or if this map does not permit <code>null</code> keys or values, and the specified object contains <code>null</code> keys or values.
 446  
                  */
 447  
                 public function putAllByObject(o:Object): void
 448  
                 {
 449  1
                         if (!o) throw new ArgumentError("The 'o' argument must not be 'null'.");
 450  
                         
 451  1
                         for (var key:* in o)
 452  
                         {
 453  1
                                 put(key, o[key]);
 454  
                         }
 455  1
                 }
 456  
 
 457  
                 /**
 458  
                  * Associates the specified <code>entry.value</code> with the specified <code>entry.key</code> in this map (optional operation).
 459  
                  * If the map previously contained a mapping for the <code>entry.key</code>, the old value is replaced by the specified <code>entry.value</code>. (A map <code>m</code> is said to contain a mapping for a key <code>k</code> if and only if <code>m.containsKey(k)</code> would return <code>true</code>.) 
 460  
                  * <p>This implementation calls <code>put(entry.key, entry.value)</code>.</p>
 461  
                  * 
 462  
                  * @param          entry         entry to put in this map.
 463  
                  * @throws         org.as3coreaddendum.errors.UnsupportedOperationError          if the <code>putEntry</code> operation is not supported by this map.
 464  
                  * @throws         org.as3coreaddendum.errors.ClassCastError                                  if the type of the specified <code>entry.key</code> or <code>entry.value</code> is incompatible with this map.
 465  
                  * @throws         ArgumentError                          if the specified entry is <code>null</code>, or if the specified <code>entry.key</code> or <code>entry.value</code> is <code>null</code> and this map does not permit <code>null</code> keys or values.
 466  
                  * @return         the previous value associated with <code>entry.key</code>, or <code>null</code> if there was no mapping for <code>entry.key</code>. (A <code>null</code> return can also indicate that the map previously associated <code>null</code> with <code>entry.key</code>, if the implementation supports <code>null</code> values.)
 467  
                  */
 468  
                 public function putEntry(entry:IMapEntry): *
 469  
                 {
 470  1
                         if (!entry) throw new ArgumentError("The 'entry' argument must not be 'null'.");
 471  
                         
 472  1
                         return put(entry.key, entry.value);
 473  
                 }
 474  
 
 475  
                 /**
 476  
                  * Removes the mapping for a key from this map if it is present (optional operation).
 477  
                  * <p>Returns the value to which this map previously associated the key, or <code>null</code> if the map contained no mapping for the key.
 478  
                  * If this map permits <code>null</code> values, then a return value of <code>null</code> does not <em>necessarily</em> indicate that the map contained no mapping for the key.
 479  
                  * It's possible that the map explicitly mapped the key to <code>null</code>.</p>
 480  
                  * <p>The map will not contain a mapping for the specified key once the call returns.</p>
 481  
                  * <p>This implementation always throws an <code>UnsupportedOperationError</code>.</p>
 482  
                  * 
 483  
                  * @param          key         the key whose mapping is to be removed from the map.
 484  
                  * @throws         org.as3coreaddendum.errors.UnsupportedOperationError          if the <code>remove</code> operation is not supported by this map.
 485  
                  * @throws         org.as3coreaddendum.errors.ClassCastError                                  if the type of the specified key is incompatible with this map (optional).
 486  
                  * @throws         ArgumentError                          if the specified key is <code>null</code> and this map does not permit <code>null</code> keys (optional).
 487  
                  * @return         the previous value associated with key, or <code>null</code> if there was no mapping for <code>key</code>.
 488  
                  */
 489  
                 public function remove(key:*): *
 490  
                 {
 491  1
                         throw new UnsupportedOperationError("Method must be overridden in subclass: " + ReflectionUtil.getClassPath(this));
 492  
                 }
 493  
 
 494  
                 /**
 495  
                  * Removes the mapping for a key from this map (if it is present) for each element in the specified collection (optional operation).
 496  
                  * The elements in the specified collection are interpreted as keys.
 497  
                  * <p>This implementation iterates over this map, checking each key returned by the iterator in turn to see if it's contained in the specified collection.
 498  
                  * If it's so contained, it's removed from this map with the iterator's <code>remove</code> method.</p>
 499  
                  * <p>Note that this implementation will throw an <code>UnsupportedOperationError</code> if the iterator returned by the iterator method does not implement the <code>remove</code> method and this map contains one or more keys in common with the specified collection.</p>
 500  
                  * <p>The map will not contain mappings for the elements in the specified collection once the call returns.</p>
 501  
                  * 
 502  
                  * @param          keys         the collection whose elements are interpreted as keys to be removed from the map.
 503  
                  * @throws         org.as3coreaddendum.errors.UnsupportedOperationError          if the <code>removeAll</code> operation is not supported by this map.
 504  
                  * @throws         org.as3coreaddendum.errors.ClassCastError                                  if the type of an element in the specified collection is incompatible with this map (optional).
 505  
                  * @throws         ArgumentError                          if the specified collection is <code>null</code>, or if this map does not permit <code>null</code> keys, and the specified collections contains <code>null</code> elements (optional).
 506  
                  * @return         <code>true</code> if this map changed as a result of the call.
 507  
                  */
 508  
                 public function removeAll(keys:ICollection): Boolean
 509  
                 {
 510  1
                         if (!keys) throw new ArgumentError("The 'keys' argument must not be 'null'.");
 511  1
                         if (keys.isEmpty()) return false;
 512  
                         
 513  1
                         var prevSize:int = size();
 514  1
                         var it:IIterator = iterator();
 515  
                         var value:*;
 516  
                         
 517  1
                         while (it.hasNext())
 518  
                         {
 519  1
                                 value = it.next();
 520  
                                 
 521  1
                                 if (keys.contains(it.pointer())) it.remove();
 522  
                         }
 523  
                         
 524  1
                         return prevSize != size();
 525  
                 }
 526  
                 
 527  
                 /**
 528  
                  * Removes the mapping at the specified position in this map (optional operation).
 529  
                  * Shifts any subsequent mappings to the left (subtracts one from their indices).
 530  
                  * Returns an <code>IMapEntry</code> object containing the mapping (key/value) that was removed from the map.
 531  
                  * <p>This implementation always throws an <code>UnsupportedOperationError</code>.</p> 
 532  
                  * 
 533  
                  * @param          index         the index of the mapping to be removed.
 534  
                  * @throws         org.as3coreaddendum.errors.UnsupportedOperationError          if the <code>removeAt</code> operation is not supported by this map.
 535  
                  * @throws         org.as3collections.errors.IndexOutOfBoundsError                 if the index is out of range <code>(index &lt; 0 || index &gt;= size())</code>.
 536  
                  * @return         an <code>IMapEntry</code> object containing the mapping (key/value) that was removed from the map.
 537  
                  */
 538  
                 public function removeAt(index:int): IMapEntry
 539  
                 {
 540  1
                         throw new UnsupportedOperationError("Method must be overridden in subclass: " + ReflectionUtil.getClassPath(this));
 541  
                 }
 542  
 
 543  
                 /**
 544  
                  * Retains only the mappings in this map that the keys are contained (as elements) in the specified collection (optional operation).
 545  
                  * In other words, removes from this map all of its mappings whose keys are not contained (as elements) in the specified collection.
 546  
                  * The elements in the specified collection are interpreted as keys.
 547  
                  * <p>This implementation iterates over this map and calls <code>IIterator.remove</code> once for each key that are not contained in the specified collection.</p>
 548  
                  * <p>Note that this implementation will throw an <code>UnsupportedOperationError</code> if the iterator returned by the iterator method does not implement the <code>remove</code> method and this map contains one or more keys not present in the specified collection.</p>
 549  
                  * 
 550  
                  * @param          keys         the collection whose elements are interpreted as keys to be retained in the map.
 551  
                  * @throws         org.as3coreaddendum.errors.UnsupportedOperationError          if the <code>retainAll</code> operation is not supported by this map.
 552  
                  * @throws         org.as3coreaddendum.errors.ClassCastError                                  if the types of one or more keys in this map are incompatible with the specified collection (optional).
 553  
                  * @throws         ArgumentError                           if the specified collection contains a <code>null</code> element and this collection does not permit <code>null</code> keys (optional), or if the specified collection is <code>null</code>.
 554  
                  * @return         <code>true</code> if this map changed as a result of the call.
 555  
                  */
 556  
                 public function retainAll(keys:ICollection): Boolean
 557  
                 {
 558  1
                         if (!keys) throw new ArgumentError("The 'keys' argument must not be 'null'.");
 559  1
                         if (keys.isEmpty()) return false;
 560  
                         
 561  1
                         var prevSize:int = size();
 562  1
                         var it:IIterator = iterator();
 563  
                         var value:*;
 564  
                         
 565  1
                         while (it.hasNext())
 566  
                         {
 567  1
                                 value = it.next();
 568  
                                 
 569  1
                                 if (!keys.contains(it.pointer())) it.remove();
 570  
                         }
 571  
                         
 572  1
                         return prevSize != size();
 573  
                 }
 574  
                 
 575  
                 /**
 576  
                  * @inheritDoc
 577  
                  */
 578  
                 public function reverse(): void
 579  
                 {
 580  1
                         if (size() < 2) return;
 581  1
                         keys.reverse();
 582  1
                         values.reverse();
 583  1
                 }
 584  
                 
 585  
                 /**
 586  
                  * Removes all of the mappings whose index is between <code>fromIndex</code>, inclusive, and <code>toIndex</code>, exclusive (optional operation).
 587  
                  * Shifts any subsequent mappings to the left (subtracts their indices).
 588  
                  * <p>If <code>toIndex == fromIndex</code>, this operation has no effect.</p>
 589  
                  * <p>This implementation always throws an <code>UnsupportedOperationError</code>.</p>
 590  
                  * 
 591  
                  * @param          fromIndex         the index to start removing mappings (inclusive).
 592  
                  * @param          toIndex         the index to stop removing mappings (exclusive).
 593  
                  * @throws         org.as3coreaddendum.errors.UnsupportedOperationError          if the <code>removeRange</code> operation is not supported by this map.
 594  
                  * @throws         org.as3collections.errors.IndexOutOfBoundsError                 if <code>fromIndex</code> or <code>toIndex</code> is out of range <code>(index &lt; 0 || index &gt; size())</code>.
 595  
                  * @return         a new map containing all the removed mappings.
 596  
                  */
 597  
                 public function removeRange(fromIndex:int, toIndex:int): IListMap
 598  
                 {
 599  1
                         throw new UnsupportedOperationError("Method must be overridden in subclass: " + ReflectionUtil.getClassPath(this));
 600  
                 }
 601  
                 
 602  
                 /**
 603  
                  * Replaces the key at the specified position in this map with the specified key (optional operation).
 604  
                  * <p>This implementation always throws an <code>UnsupportedOperationError</code>.</p>
 605  
                  * 
 606  
                  * @param          index         index of the key to replace.
 607  
                  * @param          key         key to be stored at the specified position.
 608  
                  * @throws         org.as3coreaddendum.errors.UnsupportedOperationError          if the <code>setKeyAt</code> operation is not supported by this map.
 609  
                  * @throws         org.as3coreaddendum.errors.ClassCastError                                  if the class of the specified key prevents it from being added to this map.
 610  
                  * @throws         ArgumentError                                                                                           if the specified key is <code>null</code> and this map does not permit <code>null</code> keys.
 611  
                  * @throws         ArgumentError                                                                                          if this map already contains the specified key.
 612  
                  * @throws         org.as3collections.errors.IndexOutOfBoundsError                 if the index is out of range <code>(index &lt; 0 || index &gt;= size())</code>.
 613  
                  * @return         the key previously at the specified position.
 614  
                  */
 615  
                 public function setKeyAt(index:int, key:*): *
 616  
                 {
 617  1
                         throw new UnsupportedOperationError("Method must be overridden in subclass: " + ReflectionUtil.getClassPath(this));
 618  
                 }
 619  
                 
 620  
                 /**
 621  
                  * Replaces the value at the specified position in this map with the specified value (optional operation).
 622  
                  * <p>This implementation always throws an <code>UnsupportedOperationError</code>.</p>
 623  
                  * 
 624  
                  * @param          index         index of the value to replace.
 625  
                  * @param          value         value to be stored at the specified position.
 626  
                  * @throws         org.as3coreaddendum.errors.UnsupportedOperationError          if the <code>setValueAt</code> operation is not supported by this map.
 627  
                  * @throws         org.as3coreaddendum.errors.ClassCastError                                  if the class of the specified value prevents it from being added to this map.
 628  
                  * @throws         ArgumentError                                                                                           if the specified value is <code>null</code> and this map does not permit <code>null</code> values.
 629  
                  * @throws         org.as3collections.errors.IndexOutOfBoundsError                 if the index is out of range <code>(index &lt; 0 || index &gt;= size())</code>.
 630  
                  * @return         the value previously at the specified position.
 631  
                  */
 632  
                 public function setValueAt(index:int, value:*): *
 633  
                 {
 634  1
                         throw new UnsupportedOperationError("Method must be overridden in subclass: " + ReflectionUtil.getClassPath(this));
 635  
                 }
 636  
                 
 637  
                 /**
 638  
                  * @inheritDoc
 639  
                   */
 640  
                 public function size(): int
 641  
                 {
 642  1
                         return _keys.size();
 643  
                 }
 644  
                 
 645  
                 /**
 646  
                  * Returns a new map that is a view of the portion of this map between the specified <code>fromIndex</code>, inclusive, and <code>toIndex</code>, exclusive.
 647  
                  * <p>The returned map supports all of the optional map operations supported by this map.</p>
 648  
                  * <p>This implementation always throws an <code>UnsupportedOperationError</code>.</p>
 649  
                  * 
 650  
                  * @param          fromIndex         the index to start retrieving mappings (inclusive).
 651  
                  * @param          toIndex         the index to stop retrieving mappings (exclusive).
 652  
                  * @throws         org.as3coreaddendum.errors.UnsupportedOperationError          if the <code>subMap</code> operation is not supported by this map.
 653  
                  * @throws         org.as3collections.errors.IndexOutOfBoundsError                 if <code>fromIndex</code> or <code>toIndex</code> is out of range <code>(index &lt; 0 || index &gt; size())</code>.
 654  
                  * @return         a new list that is a view of the specified range within this list.
 655  
                  */
 656  
                 public function subMap(fromIndex:int, toIndex:int): IListMap
 657  
                 {
 658  1
                         throw new UnsupportedOperationError("Method must be overridden in subclass: " + ReflectionUtil.getClassPath(this));
 659  
                 }
 660  
                 
 661  
                 /**
 662  
                  * @inheritDoc
 663  
                  * 
 664  
                  * @throws         ArgumentError         if <code>containsKey(fromKey)</code> returns <code>false</code>.
 665  
                  */
 666  
                 public function tailMap(fromKey:*): IListMap
 667  
                 {
 668  1
                         if (!containsKey(fromKey)) throw new ArgumentError("This maps does not contains the specified key: " + fromKey);
 669  
                         
 670  1
                         var fromIndex:int = indexOfKey(fromKey);
 671  1
                         var toIndex:int = size();
 672  
                         
 673  1
                         var map:IListMap = subMap(fromIndex, toIndex);
 674  1
                         return map;
 675  
                 }
 676  
                 
 677  
                 /**
 678  
                  * Returns the string representation of this instance.
 679  
                  * 
 680  
                  * @return         the string representation of this instance.
 681  
                   */
 682  
                 public function toString():String 
 683  
                 {
 684  1
                         return MapUtil.toString(this);
 685  
                 }
 686  
                 
 687  
                 /**
 688  
                  * @private
 689  
                  */
 690  
                 protected function checkIndex(index:int, max:int):void
 691  
                 {
 692  1
                         if (index < 0 || index > max) throw new IndexOutOfBoundsError("The 'index' argument is out of bounds: " + index + " (min: 0, max: " + max + ")");
 693  1
                 }
 694  
                 
 695  
                 /**
 696  
                  * @private
 697  
                  */
 698  
                 protected function keyAdded(key:*): void
 699  
                 {
 700  1
                         _modCount++;
 701  1
                 }
 702  
                 
 703  
                 /**
 704  
                  * @private
 705  
                  */
 706  
                 protected function keyRemoved(key:*): void
 707  
                 {
 708  1
                         _modCount++;
 709  1
                 }
 710  
                 
 711  
                 /**
 712  
                  * @private
 713  
                  */
 714  
                 protected function valueAdded(value:*): void
 715  
                 {
 716  
                         
 717  1
                 }
 718  
                 
 719  
                 /**
 720  
                  * @private
 721  
                  */
 722  
                 protected function valueRemoved(value:*): void
 723  
                 {
 724  
                         
 725  1
                 }
 726  
 
 727  
                 /**
 728  
                  * @private
 729  
                  */
 730  
                 private function _init(): void
 731  
                 {
 732  1
                         _keys                 = new ArrayList();
 733  1
                         _values         = new ArrayList();
 734  1
                 }
 735  
 
 736  
         }
 737  
 
 738  
 }