Coverage Report - org.as3collections.maps.SortedArrayListMap
 
Classes in this File Line Coverage Branch Coverage Complexity
SortedArrayListMap
100%
78/78
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.maps 
 31  
 {
 32  
         import org.as3collections.IListMap;
 33  
         import org.as3collections.IMap;
 34  
         import org.as3collections.ISortedMap;
 35  
         import org.as3collections.SortMapBy;
 36  
         import org.as3collections.lists.ArrayList;
 37  
         import org.as3coreaddendum.system.IComparator;
 38  
         import org.as3utils.ArrayUtil;
 39  
         import org.as3utils.ReflectionUtil;
 40  
 
 41  
         /**
 42  
          * A map that provides a <em>total ordering</em> on its mappings.
 43  
          * The map is ordered according to the <em>natural ordering</em> of its keys or values, by a <em>IComparator</em> typically provided at sorted map creation time, or by the arguments provided to the <code>sort</code> or <code>sortOn</code> methods.
 44  
          * <p>For each change that occurs the map is automatically ordered using the <code>comparator</code> and <code>options</code>.
 45  
          * If none was provided the default behavior of the <code>sort</code> method is used.</p>
 46  
          * The <code>sortBy</code> property defines whether the sorting will be made by <code>key</code> or <code>value</code>.
 47  
          * <p>The user of this map may change their order at any time by calling the <code>sort</code> or <code>sortOn</code> method and imposing others arguments to change the sort behaviour.</p>
 48  
          * <p>It's possible to create typed sorted maps.
 49  
          * You just sends the <code>SortedArrayListMap</code> object to the wrapper <code>TypedSortedMap</code> or uses the <code>MapUtil.getTypedSortedMap</code>.</p>
 50  
          * 
 51  
          * @example
 52  
          * 
 53  
          * <listing version="3.0">
 54  
          * import org.as3collections.ISortedMap;
 55  
          * import org.as3collections.maps.SortedArrayListMap;
 56  
          * 
 57  
          * var map1:ISortedMap = new SortedArrayListMap();
 58  
          * 
 59  
          * map1.put("e", 1)            // null
 60  
          * map1.put("d", 2)            // null
 61  
          * map1.put("c", 3)            // null
 62  
          * map1.put("b", 4)            // null
 63  
          * map1.put("a", 5)            // null
 64  
          * 
 65  
          * map1                        // {a=5,b=4,c=3,d=2,e=1}
 66  
          * 
 67  
          * map1.firstKey()             // a
 68  
          * map1.lastKey()              // e
 69  
          * 
 70  
          * map1.sortBy = SortMapBy.VALUE;
 71  
          * 
 72  
          * map1                        // {e=1,d=2,c=3,b=4,a=5}
 73  
          * 
 74  
          * map1.firstKey()             // e
 75  
          * map1.lastKey()              // a
 76  
          * 
 77  
          * map1.sort(null, Array.NUMERIC);
 78  
          * 
 79  
          * map1                        // {e=1,d=2,c=3,b=4,a=5}
 80  
          * 
 81  
          * map1.sort(null, Array.NUMERIC | Array.DESCENDING);
 82  
          * 
 83  
          * map1                        // {a=5,b=4,c=3,d=2,e=1}
 84  
          * 
 85  
          * map1.sortBy = SortMapBy.KEY;
 86  
          * 
 87  
          * map1                        // {a=5,b=4,c=3,d=2,e=1}
 88  
          * 
 89  
          * map1.headMap("d")           // {a=5,b=4,c=3}
 90  
          * map1.tailMap("b")           // {b=4,c=3,d=2,e=1}
 91  
          * map1.subMap("b", "d")       // {b=4,c=3}
 92  
          * </listing>
 93  
          * 
 94  
          * @see org.as3collections.utils.MapUtil#getTypedSortedMap() MapUtil.getTypedSortedMap()
 95  
          * @author Flávio Silva
 96  
          */
 97  
         public class SortedArrayListMap extends ArrayListMap implements ISortedMap
 98  
         {
 99  
                 private var _comparator: IComparator;
 100  
                 private var _options: uint;
 101  
                 private var _sortBy: SortMapBy;
 102  
 
 103  
                 /**
 104  
                  * Defines the comparator object to be used automatically to sort.
 105  
                  * <p>If this value change the map is automatically reordered with the new value.</p>
 106  
                  */
 107  
                 public function get comparator(): IComparator { return _comparator; }
 108  
 
 109  
                 public function set comparator(value:IComparator): void
 110  
                 {
 111  1
                         _comparator = value;
 112  1
                         _sort();
 113  1
                 }
 114  
 
 115  
                 /**
 116  
                  * Defines the options to be used automatically to sort.
 117  
                  * <p>If this value change the list is automatically reordered with the new value.</p>
 118  
                  */
 119  
                 public function get options(): uint { return _options; }
 120  
 
 121  
                 public function set options(value:uint): void
 122  
                 {
 123  1
                         _options = value;
 124  1
                         _sort();
 125  1
                 }
 126  
 
 127  
                 /**
 128  
                  * Defines whether the map should be sorted by its keys or values. The default is <code>SortMapBy.KEY</code>.
 129  
                  * <p>If this value change the map is automatically reordered with the new value.</p>
 130  
                  * 
 131  
                  * @throws         ArgumentError           if try to set a <code>null</code> value.
 132  
                  */
 133  
                 public function get sortBy(): SortMapBy { return _sortBy; }
 134  
 
 135  
                 public function set sortBy(value:SortMapBy): void
 136  
                 {
 137  1
                         if (!value) throw new ArgumentError("Argument must no be null.");
 138  1
                         _sortBy = value;
 139  1
                         _sort();
 140  1
                 }
 141  
 
 142  
                 /**
 143  
                  * Constructor, creates a new <code>SortedArrayListMap</code> object.
 144  
                  * 
 145  
                  * @param         source                 a map with wich fill this map.
 146  
                  * @param         comparator         the comparator object to be used internally to sort.
 147  
                  * @param         options         the options to be used internally to sort.
 148  
                  */
 149  
                 public function SortedArrayListMap(source:IMap = null, comparator:IComparator = null, options:uint = 0)
 150  
                 {
 151  1
                         super(source);
 152  
                         
 153  1
                         _comparator = comparator;
 154  1
                         _options = options;
 155  1
                         _sortBy = SortMapBy.KEY;
 156  1
                         _sort();
 157  1
                 }
 158  
 
 159  
                 /**
 160  
                  * Creates and return a new <code>SortedArrayListMap</code> object containing all elements in this map (in the same order).
 161  
                  * 
 162  
                  * @return         a new <code>SortedArrayListMap</code> object containing all elements in this map (in the same order).
 163  
                   */
 164  
                 override public function clone(): *
 165  
                 {
 166  1
                         return new SortedArrayListMap(this, _comparator, _options);
 167  
                 }
 168  
                 
 169  
                 /**
 170  
                  * Performs an arbitrary, specific evaluation of equality between this object and the <code>other</code> object.
 171  
                  * <p>This implementation considers two differente objects equal if:</p>
 172  
                  * <p>
 173  
                  * <ul><li>object A and object B are instances of the same class (i.e. if they have <b>exactly</b> the same type)</li>
 174  
                  * <li>object A contains all mappings of object B</li>
 175  
                  * <li>object B contains all mappings of object A</li>
 176  
                  * <li>mappings have exactly the same order</li>
 177  
                  * <li>object A and object B has the same type of comparator</li>
 178  
                  * <li>object A and object B has the same options</li>
 179  
                  * <li>object A and object B has the same sortBy</li>
 180  
                  * </ul></p>
 181  
                  * <p>This implementation takes care of the order of the mappings in the map.
 182  
                  * So, for two maps are equal the order of mappings returned by the iterator must be equal.</p>
 183  
                  * 
 184  
                  * @param          other         the object to be compared for equality.
 185  
                  * @return         <code>true</code> if the arbitrary evaluation considers the objects equal.
 186  
                  */
 187  
                 override public function equals(other:*): Boolean
 188  
                 {
 189  1
                         if (this == other) return true;
 190  
                         
 191  1
                         if (!ReflectionUtil.classPathEquals(this, other)) return false;
 192  
                         
 193  1
                         var m:ISortedMap = other as ISortedMap;
 194  
                         
 195  1
                         if (_sortBy != m.sortBy) return false;
 196  1
                         if (_options != m.options) return false;
 197  1
                         if (!_comparator && m.comparator) return false;
 198  1
                         if (_comparator && !m.comparator) return false;
 199  1
                         if (!ReflectionUtil.classPathEquals(_comparator, m.comparator)) return false;
 200  
                         
 201  1
                         return super.equals(other);
 202  
                 }
 203  
 
 204  
                 /**
 205  
                  * @inheritDoc
 206  
                  */
 207  
                 override public function put(key:*, value:*): *
 208  
                 {
 209  1
                         var old:* = super.put(key, value);
 210  1
                         _sort();
 211  1
                         return old;
 212  
                 }
 213  
                 
 214  
                 /**
 215  
                  * @inheritDoc
 216  
                  */
 217  
                 override public function putAt(index:int, key:*, value:*): void
 218  
                 {
 219  1
                         super.putAt(index, key, value);
 220  1
                         _sort();
 221  1
                 }
 222  
 
 223  
                 /**
 224  
                  * @inheritDoc
 225  
                  */
 226  
                 override public function setKeyAt(index:int, key:*): *
 227  
                 {
 228  1
                         var old:* = super.setKeyAt(index, key);
 229  1
                         if (_sortBy == SortMapBy.KEY) _sort();
 230  1
                         return old;
 231  
                 }
 232  
                 
 233  
                 /**
 234  
                  * @inheritDoc
 235  
                  */
 236  
                 override public function setValueAt(index:int, value:*): *
 237  
                 {
 238  1
                         var old:* = super.setValueAt(index, value);
 239  1
                         if (_sortBy == SortMapBy.VALUE) _sort();
 240  1
                         return old;
 241  
                 }
 242  
 
 243  
                 /**
 244  
                  * Sorts the objects within this class.
 245  
                  * <p>For more info see <code>org.as3coreaddendum.system.ISortable.sort()</code> in the link below.</p>
 246  
                  * 
 247  
                  * @param compare
 248  
                  * @param options
 249  
                  * @return
 250  
                  */
 251  
                 public function sort(compare:Function = null, options:uint = 0): Array
 252  
                 {
 253  
                         var sortArray:Array;
 254  
                         var otherArray:Array;
 255  
                         
 256  1
                         if (_sortBy == SortMapBy.KEY)
 257  
                         {
 258  1
                                 sortArray = keys.toArray();
 259  1
                                 otherArray = values.toArray();
 260  
                         }
 261  
                         else
 262  
                         {
 263  1
                                 sortArray = values.toArray();
 264  1
                                 otherArray = keys.toArray();
 265  
                         }
 266  
                         
 267  
                         var arr:Array;
 268  
                         
 269  1
                         if (compare != null)
 270  
                         { 
 271  1
                                 arr = sortArray.sort(compare, options | Array.RETURNINDEXEDARRAY);
 272  
                         }
 273  
                         else
 274  
                         {
 275  1
                                 arr = sortArray.sort(options | Array.RETURNINDEXEDARRAY);
 276  
                         }
 277  
                         
 278  1
                         ArrayUtil.swapPositions(sortArray, arr);
 279  1
                         ArrayUtil.swapPositions(otherArray, arr);
 280  
                         
 281  1
                         if (_sortBy == SortMapBy.KEY)
 282  
                         {
 283  1
                                 keys = new ArrayList(sortArray);
 284  1
                                 values = new ArrayList(otherArray);
 285  
                         }
 286  
                         else
 287  
                         {
 288  1
                                 keys = new ArrayList(otherArray);
 289  1
                                 values = new ArrayList(sortArray);
 290  
                         }
 291  
                         
 292  1
                         return arr;
 293  
                 }
 294  
 
 295  
                 /**
 296  
                  * @inheritDoc
 297  
                  * 
 298  
                  * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Array.html#sortOn()
 299  
                  */
 300  
                 public function sortOn(fieldName:*, options:* = null): Array
 301  
                 {
 302  
                         var sortArray:Array;
 303  
                         var otherArray:Array;
 304  
                         
 305  1
                         if (_sortBy == SortMapBy.KEY)
 306  
                         {
 307  1
                                 sortArray = keys.toArray();
 308  1
                                 otherArray = values.toArray();
 309  
                         }
 310  
                         else
 311  
                         {
 312  1
                                 sortArray = values.toArray();
 313  1
                                 otherArray = keys.toArray();
 314  
                         }
 315  
                         
 316  1
                         var arr:Array = sortArray.sortOn(fieldName, options | Array.RETURNINDEXEDARRAY);
 317  
                         
 318  1
                         ArrayUtil.swapPositions(sortArray, arr);
 319  1
                         ArrayUtil.swapPositions(otherArray, arr);
 320  
                         
 321  1
                         if (_sortBy == SortMapBy.KEY)
 322  
                         {
 323  1
                                 keys = new ArrayList(sortArray);
 324  1
                                 values = new ArrayList(otherArray);
 325  
                         }
 326  
                         else
 327  
                         {
 328  1
                                 keys = new ArrayList(otherArray);
 329  1
                                 values = new ArrayList(sortArray);
 330  
                         }
 331  
                         
 332  1
                         return arr;
 333  
                 }
 334  
                 
 335  
                 /**
 336  
                  *@inheritDoc 
 337  
                  * 
 338  
                  * @param          fromIndex         the index to start retrieving mappings (inclusive).
 339  
                  * @param          toIndex         the index to stop retrieving mappings (exclusive).
 340  
                  * @throws         org.as3coreaddendum.errors.UnsupportedOperationError          if the <code>subMap</code> operation is not supported by this map.
 341  
                  * @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>.
 342  
                  * @return         a new list that is a view of the specified range within this list.
 343  
                  */
 344  
                 override public function subMap(fromIndex:int, toIndex:int): IListMap
 345  
                 {
 346  1
                         var map:ISortedMap = super.subMap(fromIndex, toIndex) as ISortedMap;
 347  1
                         map.comparator = comparator;
 348  1
                         map.options = options;
 349  
                         
 350  1
                         return map;
 351  
                 }
 352  
                 
 353  
                 /**
 354  
                  * @private
 355  
                  */
 356  
                 override protected function createEmptyMap(): IListMap
 357  
                 {
 358  1
                         return new SortedArrayListMap();
 359  
                 }
 360  
                 
 361  
                 /**
 362  
                  * @private
 363  
                  */
 364  
                 protected function _sort(): void
 365  
                 {
 366  1
                         if (_comparator)
 367  
                         {
 368  1
                                 sort(_comparator.compare, _options);
 369  
                         }
 370  
                         else
 371  
                         {
 372  1
                                 sort(null, _options);
 373  
                         }
 374  1
                 }
 375  
         }
 376  
 
 377  
 }