Coverage Report - org.as3collections.lists.SortedArrayList
 
Classes in this File Line Coverage Branch Coverage Complexity
SortedArrayList
100%
43/43
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.lists
 31  
 {
 32  
         import org.as3collections.IList;
 33  
         import org.as3collections.ISortedList;
 34  
         import org.as3collections.errors.IndexOutOfBoundsError;
 35  
         import org.as3coreaddendum.system.IComparator;
 36  
         import org.as3utils.ReflectionUtil;
 37  
 
 38  
         /**
 39  
          * A list that provides a <em>total ordering</em> on its elements.
 40  
          * The list is ordered according to the <em>natural ordering</em> of its elements, by a <em>IComparator</em> typically provided at sorted list creation time, or by the arguments provided to the <code>sort</code> or <code>sortOn</code> methods.
 41  
          * <p>For each change that occurs the list is automatically reordered using <code>comparator</code> and <code>options</code>.
 42  
          * If none was provided the default behavior of <code>sort</code> method is used.</p>
 43  
          * <p>The user of this list may change their order at any time using the setters <code>comparator</code> and <code>options</code>, or by calling <code>sort</code> or <code>sortOn</code> methods and imposing other arguments to change the sort behaviour.</p>
 44  
          * <p>It's possible to create unique sorted lists, typed sorted lists and even unique typed sorted lists.
 45  
          * You just sends the <code>SortedArrayList</code> object to the wrappers <code>UniqueSortedList</code> or <code>TypedSortedList</code> or uses the <code>ListUtil.getUniqueSortedList</code>, <code>ListUtil.getTypedSortedList</code> or <code>ListUtil.getUniqueTypedSortedList</code>.</p>
 46  
          * <p>This documentation is partially based in the <em>Java Collections Framework</em> JavaDoc documentation.
 47  
          * For further information see <a href="http://download.oracle.com/javase/6/docs/technotes/guides/collections/index.html" target="_blank">Java Collections Framework</a></p>
 48  
          * 
 49  
          * @example
 50  
          * 
 51  
          * <b>Example 1</b>
 52  
          * 
 53  
          * <listing version="3.0">
 54  
          * import org.as3collections.ISortedList;
 55  
          * import org.as3collections.lists.SortedArrayList;
 56  
          * 
 57  
          * var list1:ISortedList = new SortedArrayList([3, 5, 1, 7], null, Array.NUMERIC | Array.DESCENDING);
 58  
          * 
 59  
          * list1                       // [7,5,3,1]
 60  
          * list1.size()                // 4
 61  
          * 
 62  
          * list1.addAt(3, 8)           // true
 63  
          * list1                       // [8,7,5,3,1]
 64  
          * list1.size()                // 5
 65  
          * 
 66  
          * list1.add(4)                // true
 67  
          * list1                       // [8,7,5,4,3,1]
 68  
          * list1.size()                // 6
 69  
          * 
 70  
          * list1.add(5)                // true
 71  
          * list1                       // [8,7,5,5,4,3,1]
 72  
          * list1.size()                // 7
 73  
          * 
 74  
          * list1.sort(null, Array.NUMERIC)
 75  
          * list1                       // [1,3,4,5,5,7,8]
 76  
          * 
 77  
          * list1.add(2)                // true
 78  
          * list1                       // [8,7,5,5,4,3,2,1]
 79  
          * list1.size()                // 8
 80  
          * 
 81  
          * list1.reverse()
 82  
          * list1                       // [1,2,3,4,5,5,7,8]
 83  
          * 
 84  
          * list1.add(6)                // true
 85  
          * list1                       // [1,2,3,4,5,5,6,7,8]
 86  
          * 
 87  
          * list1.add(9)                // true
 88  
          * list1                       // [1,2,3,4,5,5,6,7,8,9]
 89  
          * 
 90  
          * list1.reverse()
 91  
          * list1                       // [9,8,7,6,5,5,4,3,2,1]
 92  
          * 
 93  
          * list1.add(10)               // true
 94  
          * list1                       // [10,9,8,7,6,5,5,4,3,2,1]
 95  
          * 
 96  
          * list1.add(-1)               // true
 97  
          * list1                       // [10,9,8,7,6,5,5,4,3,2,1,-1]
 98  
          * 
 99  
          * //list1.add("c")            // TypeError: Error #1034: Falha de coerção de tipo: não é possível converter "c" em Number.
 100  
          * </listing>
 101  
          * 
 102  
          * <b>Example 2</b>
 103  
          * 
 104  
          * <listing version="3.0">
 105  
          * import org.as3collections.ISortedList;
 106  
          * import org.as3collections.lists.SortedArrayList;
 107  
          * import org.as3coreaddendum.system.comparators.AlphabeticComparator;
 108  
          * 
 109  
          * var comparator:AlphabeticComparator = new AlphabeticComparator(false);
 110  
          * var arr:Array = ["c", "a", "d", "b"];
 111  
          * var list1:ISortedList = new SortedArrayList(arr, comparator);
 112  
          * 
 113  
          * list1                              // [a,b,c,f]
 114  
          * list1.size()                       // 4
 115  
          * 
 116  
          * list1.addAt(1, "x")                // true
 117  
          * list1                              // [a,b,c,f,x]
 118  
          * list1.size()                       // 5
 119  
          * 
 120  
          * list1.add("d")                     // true
 121  
          * list1                              // [a,b,c,d,f,x]
 122  
          * list1.size()                       // 6
 123  
          * 
 124  
          * list1.add("d")                     // true
 125  
          * list1                              // [a,b,c,d,d,f,x]
 126  
          * list1.size()                       // 7
 127  
          * 
 128  
          * list1.sort()
 129  
          * list1                              // [a,b,c,d,d,f,x]
 130  
          * 
 131  
          * list1.add(2)                       // true
 132  
          * list1                              // [2,a,b,c,d,d,f,x]
 133  
          * list1.size()                       // 8
 134  
          * </listing>
 135  
          * 
 136  
          * <b>Example 3</b>
 137  
          * 
 138  
          * <listing version="3.0">
 139  
          * import org.as3collections.ISortedList;
 140  
          * import org.as3collections.lists.SortedArrayList;
 141  
          * 
 142  
          * var arr:Array = [5, 1, 100, 10, 99];
 143  
          * var list1:ISortedList = new SortedArrayList(arr); // default behavior of the sort method
 144  
          * 
 145  
          * list1                       // [1,10,100,5,99]
 146  
          * list1.size()                // 5
 147  
          * 
 148  
          * list1.add(50)               // true
 149  
          * list1                       // [1,10,100,5,50,99]
 150  
          * list1.size()                // 6
 151  
          * 
 152  
          * list1.sort(null, Array.NUMERIC)
 153  
          * list1                       // [1,5,10,50,99,100]
 154  
          * 
 155  
          * list1.add(200)              // true
 156  
          * list1                       // [1,10,100,200,5,50,99]
 157  
          * list1.size()                // 7
 158  
          * </listing>
 159  
          * 
 160  
          * <b>Example 4 - Unique Sorted List</b>
 161  
          * 
 162  
          * <listing version="3.0">
 163  
          * import org.as3collections.ISortedList;
 164  
          * import org.as3collections.lists.SortedArrayList;
 165  
          * import org.as3collections.utils.ListUtil;
 166  
          * 
 167  
          * var arr:Array = [5, 1, 100, 10, 99, 5];
 168  
          * 
 169  
          * var l1:ISortedList = new SortedArrayList(arr, null, Array.NUMERIC | Array.DESCENDING);
 170  
          * 
 171  
          * var list1:ISortedList = ListUtil.getUniqueSortedList(l1);  // return type is UniqueSortedList
 172  
          * 
 173  
          * list1                 // [100,99,10,5,1]
 174  
          * list1.size()          // 5
 175  
          * 
 176  
          * list1.add(50)         // true
 177  
          * list1                 // [100,99,50,10,5,1]
 178  
          * list1.size()          // 6
 179  
          * 
 180  
          * list1.add(10)         // false
 181  
          * list1                 // [100,99,50,10,5,1]
 182  
          * list1.size()          // 6
 183  
          * </listing>
 184  
          * 
 185  
          * <b>Example 5 - Typed Sorted List</b>
 186  
          * 
 187  
          * <listing version="3.0">
 188  
          * import org.as3collections.ISortedList;
 189  
          * import org.as3collections.lists.SortedArrayList;
 190  
          * import org.as3collections.utils.ListUtil;
 191  
          * 
 192  
          * var arr:Array = [5, 1, 100, 10, 99, 5];
 193  
          * 
 194  
          * var l1:ISortedList = new SortedArrayList(arr, null, Array.NUMERIC | Array.DESCENDING);
 195  
          * 
 196  
          * var list1:ISortedList = ListUtil.getTypedSortedList(l1);  // return type is TypedSortedList
 197  
          * 
 198  
          * list1                 // [100,99,10,5,5,1]
 199  
          * list1.size()          // 6
 200  
          * 
 201  
          * list1.add(50)         // true
 202  
          * list1                 // [100,99,50,10,5,5,1]
 203  
          * list1.size()          // 7
 204  
          * 
 205  
          * list1.add(10)         // true
 206  
          * list1                 // [100,99,50,10,10,5,5,1]
 207  
          * list1.size()          // 8
 208  
          * 
 209  
          * list1.add("a")        // ClassCastError: Invalid element type. element: a | type: String | expected type: int
 210  
          * </listing>
 211  
          * 
 212  
          * <b>Example 6 - Unique Typed Sorted List</b>
 213  
          * 
 214  
          * <listing version="3.0">
 215  
          * import org.as3collections.ISortedList;
 216  
          * import org.as3collections.lists.SortedArrayList;
 217  
          * import org.as3collections.utils.ListUtil;
 218  
          * 
 219  
          * var arr:Array = [5, 1, 100, 10, 99, 5];
 220  
          * 
 221  
          * var l1:ISortedList = new SortedArrayList(arr, null, Array.NUMERIC | Array.DESCENDING);
 222  
          * 
 223  
          * var list1:ISortedList = ListUtil.getUniqueTypedSortedList(l1);  // return type is TypedSortedList
 224  
          * 
 225  
          * list1                 // [100,99,10,5,1]
 226  
          * list1.size()          // 5
 227  
          * 
 228  
          * list1.add(50)         // true
 229  
          * list1                 // [100,99,50,10,5,1]
 230  
          * list1.size()          // 6
 231  
          * 
 232  
          * list1.add(10)         // false
 233  
          * list1                 // [100,99,50,10,5,1]
 234  
          * list1.size()          // 6
 235  
          * 
 236  
          * list1.add("a")        // ClassCastError: Invalid element type. element: a | type: String | expected type: int
 237  
          * </listing>
 238  
          * 
 239  
          * @see org.as3collections.ISortedList ISortedList
 240  
          * @see org.as3collections.lists.ArrayList ArrayList
 241  
          * @see org.as3collections.lists.TypedSortedList TypedSortedList
 242  
          * @see org.as3collections.lists.UniqueSortedList UniqueSortedList
 243  
          * @see org.as3collections.utils.ListUtil#getUniqueSortedList() ListUtil.getUniqueSortedList()
 244  
          * @see org.as3collections.utils.ListUtil#getTypedSortedList() ListUtil.getTypedSortedList()
 245  
          * @see org.as3collections.utils.ListUtil#getUniqueTypedSortedList() ListUtil.getUniqueTypedSortedList()
 246  
          * @author Flávio Silva
 247  
          */
 248  
         public class SortedArrayList extends ArrayList implements ISortedList
 249  
         {
 250  
                 private var _comparator: IComparator;
 251  
                 private var _options: uint;
 252  
                 private var _reversed: Boolean;
 253  
 
 254  
                 /**
 255  
                  * Defines the comparator object to be used automatically to sort.
 256  
                  * <p>If this value change the list is automatically reordered with the new value.</p>
 257  
                  */
 258  
                 public function get comparator(): IComparator { return _comparator; }
 259  
 
 260  
                 public function set comparator(value:IComparator): void
 261  
                 {
 262  1
                         _comparator = value;
 263  1
                         _sort();
 264  1
                 }
 265  
 
 266  
                 /**
 267  
                  * Defines the options to be used automatically to sort.
 268  
                  * <p>If this value change the list is automatically reordered with the new value.</p>
 269  
                  */
 270  
                 public function get options(): uint { return _options; }
 271  
 
 272  
                 public function set options(value:uint): void
 273  
                 {
 274  1
                         _options = value;
 275  1
                         _sort();
 276  1
                 }
 277  
 
 278  
                 /**
 279  
                  * Constructor, creates a new <code>SortedArrayList</code> object.
 280  
                  * 
 281  
                  * @param         source                 an array to fill the list.
 282  
                  * @param         comparator         the comparator object to be used internally to sort.
 283  
                  * @param         options         the options to be used internally to sort.
 284  
                  */
 285  
                 public function SortedArrayList(source:Array = null, comparator:IComparator = null, options:uint = 0)
 286  
                 {
 287  1
                         super(source);
 288  
                         
 289  1
                         _comparator = comparator;
 290  1
                         _options = options;
 291  1
                         _sort();
 292  1
                 }
 293  
 
 294  
                 /**
 295  
                  * Inserts the specified element at the specified position in this list.
 296  
                  * Shifts the element currently at that position (if any) and any subsequent elements to the right (adds one to their indices).
 297  
                  * <p>Before returning, the list is reordered, so there's no guarantee that the element remains in the inserted position.</p>
 298  
                  * 
 299  
                  * @param          index                 index at which the specified element is to be inserted.
 300  
                  * @param          element         the element to be added.
 301  
                  * @throws         org.as3collections.errors.IndexOutOfBoundsError                 if the index is out of range <code>(index &lt; 0 || index &gt; size())</code>. 
 302  
                  * @return         <code>true</code> if this list changed as a result of the call.
 303  
                  */
 304  
                 override public function addAt(index:int, element:*): Boolean
 305  
                 {
 306  1
                         var b:Boolean = super.addAt(index, element);
 307  1
                         if (b) _sort();
 308  1
                         return b;
 309  
                 }
 310  
 
 311  
                 /**
 312  
                  * Creates and return a new <code>SortedArrayList</code> object containing all elements in this list (in the same order).
 313  
                  * 
 314  
                  * @return         a new <code>SortedArrayList</code> object containing all elements in this list (in the same order).
 315  
                   */
 316  
                 override public function clone(): *
 317  
                 {
 318  1
                         return new SortedArrayList(data, _comparator, _options);
 319  
                 }
 320  
 
 321  
                 /**
 322  
                  * Performs an arbitrary, specific evaluation of equality between this object and the <code>other</code> object.
 323  
                  * <p>This implementation considers two differente objects equal if:</p>
 324  
                  * <p>
 325  
                  * <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>
 326  
                  * <li>object A contains all elements of object B</li>
 327  
                  * <li>object B contains all elements of object A</li>
 328  
                  * <li>elements have exactly the same order</li>
 329  
                  * <li>object A and object B has the same type of comparator</li>
 330  
                  * <li>object A and object B has the same options</li>
 331  
                  * </ul></p>
 332  
                  * <p>This implementation takes care of the order of the elements in the list.
 333  
                  * So, for two lists are equal the order of elements returned by the iterator object must be equal.</p>
 334  
                  * 
 335  
                  * @param          other         the object to be compared for equality.
 336  
                  * @return         <code>true</code> if the arbitrary evaluation considers the objects equal.
 337  
                  */
 338  
                 override public function equals(other:*): Boolean
 339  
                 {
 340  1
                         if (this == other) return true;
 341  
                         
 342  1
                         if (!ReflectionUtil.classPathEquals(this, other)) return false;
 343  
                         
 344  1
                         var l:ISortedList = other as ISortedList;
 345  
                         
 346  1
                         if (_options != l.options) return false;
 347  1
                         if (!_comparator && l.comparator) return false;
 348  1
                         if (_comparator && !l.comparator) return false;
 349  1
                         if (!ReflectionUtil.classPathEquals(_comparator, l.comparator)) return false;
 350  
                         
 351  1
                         return super.equals(other);
 352  
                 }
 353  
 
 354  
                 /**
 355  
                  * Reverses the list.
 356  
                  * When this method is called, the list is reversed and an internal status <em>reversed</em> (<code>true</code>/<code>false</code>) is stored.
 357  
                  * When the list is automatically ordered by any change, if status is <em>reversed</em> = <code>true</code>, the list remains reversed.
 358  
                  * Thus, after any change it will remain sorted and reversed as it was before the change.
 359  
                  * A second call to <code>reverse</code> will reverse the list again and change the status to <em>reversed</em> = <code>false</code>.
 360  
                  * The default value is <code>false</code>.
 361  
                  * This condition is not used in the user call to <code>sort</code> or <code>sortOn</code> methods (i.e. even if status is <em>reversed</em> = <code>true</code> it will not be used automatically).
 362  
                  * So if is desirable to reverse the list after directly call <code>sort</code> or <code>sortOn</code> methods, <code>reverse</code> method should be explicitly called after that.
 363  
                  */
 364  
                 override public function reverse(): void
 365  
                 {
 366  1
                         _reversed = !_reversed;
 367  1
                         super.reverse();
 368  1
                 }
 369  
 
 370  
                 /**
 371  
                  * Replaces the element at the specified position in this list with the specified element.
 372  
                  * <p>Before returning, the list is reordered.</p>
 373  
                  * 
 374  
                  * @param          index                 index of the element to replace.
 375  
                  * @param          element         element to be stored at the specified position.
 376  
                  * @throws         org.as3collections.errors.IndexOutOfBoundsError                 if the index is out of range <code>(index &lt; 0 || index &gt;= size())</code>.
 377  
                  * @return         the element previously at the specified position.
 378  
                  */
 379  
                 override public function setAt(index:int, element:*): *
 380  
                 {
 381  1
                         var e:* = super.setAt(index, element);
 382  1
                         _sort();
 383  1
                         return e;
 384  
                 }
 385  
 
 386  
                 /**
 387  
                  * Sorts the objects within this class.
 388  
                  * 
 389  
                  * @param compare
 390  
                  * @param options
 391  
                  * @return
 392  
                  * @see         http://as3coreaddendum.org/en-us/documentation/asdoc/org/as3coreaddendum/system/ISortable.html        org.as3coreaddendum.system.ISortable
 393  
                  */
 394  
                 public function sort(compare:Function = null, options:uint = 0): Array
 395  
                 {
 396  1
                         if (compare != null)
 397  
                         { 
 398  1
                                 return data.sort(compare, options);
 399  
                         }
 400  
                         else
 401  
                         {
 402  1
                                 return data.sort(options);
 403  
                         }
 404  
                 }
 405  
 
 406  
                 /**
 407  
                  * @inheritDoc
 408  
                  * 
 409  
                  * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Array.html#sortOn()
 410  
                  */
 411  
                 public function sortOn(fieldName:*, options:* = null): Array
 412  
                 {
 413  1
                         return data.sortOn(fieldName, options);
 414  
                 }
 415  
 
 416  
                 /**
 417  
                  * Returns a new <code>SortedArrayList</code> that is a view of the portion of this <code>SortedArrayList</code> between the specified <code>fromIndex</code>, inclusive, and <code>toIndex</code>, exclusive.
 418  
                  * <p>Modifications in the returned <code>SortedArrayList</code> object doesn't affect this list.</p>
 419  
                  * 
 420  
                  * @param          fromIndex         the index to start retrieving elements (inclusive).
 421  
                  * @param          toIndex         the index to stop retrieving elements (exclusive).
 422  
                  * @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>.
 423  
                  * @return         a new <code>SortedArrayList</code> that is a view of the specified range within this list.
 424  
                  */
 425  
                 override public function subList(fromIndex:int, toIndex:int): IList
 426  
                 {
 427  1
                         if (isEmpty()) throw new IndexOutOfBoundsError("This list is empty.");
 428  
                         
 429  1
                         checkIndex(fromIndex, size());
 430  1
                         checkIndex(toIndex, size());
 431  1
                         return new SortedArrayList(data.slice(fromIndex, toIndex));
 432  
                 }
 433  
 
 434  
                 /**
 435  
                  * @private
 436  
                  */
 437  
                 protected function _sort(): void
 438  
                 {
 439  1
                         if (_comparator)
 440  
                         {
 441  1
                                 sort(_comparator.compare, _options);
 442  
                         }
 443  
                         else
 444  
                         {
 445  1
                                 sort(null, _options);
 446  
                         }
 447  
                         
 448  1
                         if (_reversed) super.reverse();
 449  1
                 }
 450  
 
 451  
         }
 452  
 
 453  
 }