Coverage Report - org.as3collections.queues.PriorityQueue
 
Classes in this File Line Coverage Branch Coverage Complexity
PriorityQueue
100%
44/44
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.queues 
 31  
 {
 32  
         import org.as3collections.ICollection;
 33  
         import org.as3collections.IIterator;
 34  
         import org.as3collections.lists.ArrayList;
 35  
         import org.as3collections.utils.CollectionUtil;
 36  
         import org.as3coreaddendum.errors.ClassCastError;
 37  
         import org.as3coreaddendum.events.PriorityEvent;
 38  
         import org.as3coreaddendum.system.IComparator;
 39  
         import org.as3coreaddendum.system.IPriority;
 40  
         import org.as3coreaddendum.system.comparators.PriorityComparator;
 41  
         import org.as3utils.ReflectionUtil;
 42  
 
 43  
         import flash.errors.IllegalOperationError;
 44  
         import flash.events.IEventDispatcher;
 45  
 
 46  
         /**
 47  
          * This queue uses a <code>org.as3coreaddendum.system.comparators.PriorityComparator</code> object to sort the elements.
 48  
          * All elements must implement the <code>org.as3coreaddendum.system.IPriority</code> interface, otherwise a <code>org.as3coreaddendum.errors.ClassCastError</code> is thrown.
 49  
          * <p>This queue also adds an event listener on elements to <code>org.as3coreaddendum.events.PriorityEvent</code> (if elements implement <code>flash.events.IEventDispatcher</code>).
 50  
          * Thus this queue keeps itself automatically sorted if its elements dispatch a <code>org.as3coreaddendum.events.PriorityEvent</code> when its priority changes.</p>
 51  
          * 
 52  
          * @example
 53  
          * 
 54  
          * <listing version="3.0">
 55  
          * package test
 56  
          * {
 57  
          *     import org.as3coreaddendum.system.IPriority;
 58  
          * 
 59  
          *     public class TestPriority extends EventDispatcher implements IPriority
 60  
          *     {
 61  
          *         private var _name:String;
 62  
          *         private var _priority:int;
 63  
          * 
 64  
          *         public function get priority(): int { return _priority; }
 65  
          * 
 66  
          *         public function set priority(value : int) : void
 67  
          *         {
 68  
          *             _priority = value;
 69  
          *             dispatchEvent(new PriorityEvent(PriorityEvent.CHANGED, _priority));
 70  
          *         }
 71  
          * 
 72  
          *         public function TestPriority(name:String, priority:int)
 73  
          *         {
 74  
          *             _name = name;
 75  
          *             _priority = priority;
 76  
          *         }
 77  
          * 
 78  
          *         public function toString(): String
 79  
          *         {
 80  
          *             return "[TestPriority " + _name + "]";
 81  
          *         }
 82  
          *     }
 83  
          * }
 84  
          * </listing>
 85  
          * 
 86  
          * <listing version="3.0">
 87  
          * import org.as3collections.ISortedQueue;
 88  
          * import org.as3collections.queues.PriorityQueue;
 89  
          * import test.TestPriority;
 90  
          * 
 91  
          * var queue1:ISortedQueue = new PriorityQueue();
 92  
          * 
 93  
          * var o1:TestPriority = new TestPriority("o1", 1);
 94  
          * var o2:TestPriority = new TestPriority("o2", 2);
 95  
          * var o3:TestPriority = new TestPriority("o3", 3);
 96  
          * var o4:TestPriority = new TestPriority("o4", 4);
 97  
          * 
 98  
          * queue1.offer(o2)            // true
 99  
          * queue1                      // [[TestPriority o2]]
 100  
          * queue1.size()               // 1
 101  
          * 
 102  
          * queue1.offer(o3)            // true
 103  
          * queue1                      // [[TestPriority o3],[TestPriority o2]]
 104  
          * queue1.size()               // 2
 105  
          * 
 106  
          * queue1.offer(o2)            // true
 107  
          * queue1                      // [[TestPriority o3],[TestPriority o2],[TestPriority o2]]
 108  
          * 
 109  
          * queue1.offer(o1)            // true
 110  
          * queue1                      // [[TestPriority o3],[TestPriority o2],[TestPriority o2],[TestPriority o1]]
 111  
          * 
 112  
          * queue1.offer(o4)            // true
 113  
          * queue1                      // [[TestPriority o4],[TestPriority o3],[TestPriority o2],[TestPriority o2],[TestPriority o1]]
 114  
          * 
 115  
          * queue1.offer(1)             // false
 116  
          * queue1                      // [[TestPriority o4],[TestPriority o3],[TestPriority o2],[TestPriority o2],[TestPriority o1]]
 117  
          * 
 118  
          * queue1.add(1)               // ClassCastError: The element must implement the 'org.as3coreaddendum.system.IPriority' interface. Type received: int
 119  
          * </listing>
 120  
          * 
 121  
          * @see         http://as3coreaddendum.org/en-us/documentation/asdoc/org/as3coreaddendum/system/IPriority.html        org.as3coreaddendum.system.IPriority
 122  
          * @see         http://as3coreaddendum.org/en-us/documentation/asdoc/org/as3coreaddendum/events/PriorityEvent.html        org.as3coreaddendum.events.PriorityEvent
 123  
          * @author Flávio Silva
 124  
          */
 125  
         public class PriorityQueue extends SortedQueue
 126  
         {
 127  
                 /**
 128  
                  * <code>PriorityQueue</code> does not allow changing its <code>comparator</code> object.
 129  
                  * <p><code>PriorityQueue</code> was designed to be used exclusively with its default comparator object.
 130  
                  * If you want to change the comparator object using this setter, consider using <code>SortedQueue</code> class instead.</p>
 131  
                  * <p>If this setter is used an <code>IllegalOperationError</code> is thrown.</p>
 132  
                  */
 133  
                 override public function set comparator(value:IComparator): void
 134  
                 {
 135  1
                         throw new IllegalOperationError("PriorityQueue does not allow changing its comparator object.\nIf you want to change it consider using SortedQueue class instead.");
 136  
                 }
 137  
                 
 138  
                 /**
 139  
                  * <code>PriorityQueue</code> does not allow changing its options.
 140  
                  * <p><code>PriorityQueue</code> was designed to be used exclusively with its default options.
 141  
                  * If you want to change the options using this setter, consider using <code>SortedQueue</code> class instead.</p>
 142  
                  * <p>If this setter is used an <code>IllegalOperationError</code> is thrown.</p>
 143  
                  */
 144  
                 override public function set options(value:uint): void
 145  
                 {
 146  1
                         throw new IllegalOperationError("PriorityQueue does not allow changing its options.\nIf you want to change it consider using SortedQueue class instead.");
 147  
                 }
 148  
                 
 149  
                 /**
 150  
                  * Constructor, creates a new <code>PriorityQueue</code> object.
 151  
                  * 
 152  
                  * @param         source                 an array to fill the queue.
 153  
                  * @throws         org.as3coreaddendum.errors.ClassCastError                  if one or more elements in the <code>source</code> argument do not implement the <code>org.as3coreaddendum.system.IPriority</code> interface.
 154  
                  */
 155  
                 public function PriorityQueue(source:Array = null): void
 156  
                 {
 157  1
                         validateCollection(new ArrayList(source));
 158  
                         
 159  1
                         super(source, new PriorityComparator());
 160  1
                 }
 161  
 
 162  
                 /**
 163  
                  * Inserts the specified element into this queue if it is possible to do so immediately without violating restrictions.
 164  
                  * This method differs from <code>offer</code> only in that it throws an error if the element cannot be inserted.
 165  
                  * <p>This implementation returns the result of <code>offer</code> unless the element cannot be inserted.</p>
 166  
                  * <p>This implementation only allow elements that implements the <code>org.as3coreaddendum.system.IPriority</code> interface.
 167  
                  * A <code>org.as3coreaddendum.errors.ClassCastError</code> is thrown if the element does not implements this interface.</p>
 168  
                  * 
 169  
                  * @param element
 170  
                  * @throws         ArgumentError          if the specified element is <code>null</code>.
 171  
                  * @throws         org.as3coreaddendum.errors.ClassCastError                  if the element does not implements the <code>org.as3coreaddendum.system.IPriority</code> interface.
 172  
                  * @throws         flash.errors.IllegalOperationError                          if the specified element cannot be inserted.
 173  
                  * @return         <code>true</code> if this queue changed as a result of the call.
 174  
                  */
 175  
                 override public function add(element:*): Boolean
 176  
                 {
 177  1
                         if (element == null) throw new ArgumentError("The 'element' argument must not be 'null'.");
 178  1
                         validateElement(element);
 179  
                         
 180  1
                         var b:Boolean = offer(element);
 181  
                         
 182  1
                         if (!b) throw new IllegalOperationError("The element cannot be inserted: " + element);
 183  
                         
 184  1
                         return b;
 185  
                 }
 186  
 
 187  
                 /**
 188  
                  * Creates and return a new <code>PriorityQueue</code> object containing all elements in this queue (in the same order).
 189  
                  * 
 190  
                  * @return         a new <code>PriorityQueue</code> object containing all elements in this queue (in the same order).
 191  
                   */
 192  
                 override public function clone(): *
 193  
                 {
 194  1
                         var q:PriorityQueue = new PriorityQueue(data);
 195  1
                         return q;
 196  
                 }
 197  
                 
 198  
                 /**
 199  
                  * Inserts the specified element into this queue if it is possible to do so immediately without violating restrictions.
 200  
                  * When using a restricted queue (like <code>TypedQueue</code> and <code>UniqueQueue</code>), this method is generally preferable to <code>add</code>, which can fail to insert an element only by throwing an error. 
 201  
                  * <p>This implementation only allow elements that implements the <code>org.as3coreaddendum.system.IPriority</code> interface.
 202  
                  * If the element does not implements this interface the method returns <code>false</code>.</p>
 203  
                  * <p>Before returning, the queue is reordered.</p>
 204  
                  * 
 205  
                  * @param          element         the element to add.
 206  
                  * @return         <code>true</code> if the element was added to this queue, else <code>false</code>. 
 207  
                  */
 208  
                 override public function offer(element:*): Boolean
 209  
                 {
 210  1
                         if (element == null || !isValidElement(element)) return false;
 211  
                         
 212  1
                         return super.offer(element);
 213  
                 }
 214  
                 
 215  
                 /**
 216  
                  * @private
 217  
                  */
 218  
                 override protected function elementAdded(element:*):void
 219  
                 {
 220  1
                         super.elementAdded(element);
 221  1
                         if (element && element is IEventDispatcher) addPriorityEventListenerToElement(element);
 222  1
                 }
 223  
                 
 224  
                 /**
 225  
                  * @private
 226  
                  */
 227  
                 override protected function elementRemoved(element:*):void
 228  
                 {
 229  1
                         super.elementRemoved(element);
 230  1
                         if (element && element is IEventDispatcher) removePriorityEventListenerFromElement(element);
 231  1
                 }
 232  
                 
 233  
                 /**
 234  
                  * @private
 235  
                  */
 236  
                 protected function isValidElement(element:*): Boolean
 237  
                 {
 238  1
                         return element is IPriority;
 239  
                 }
 240  
                 
 241  
                 /**
 242  
                  * @private
 243  
                  */
 244  
                 protected function validateCollection(collection:ICollection): void
 245  
                 {
 246  1
                         if (!collection || collection.isEmpty()) return;
 247  
                         
 248  1
                         var containsOnlyType:Boolean = CollectionUtil.containsOnlyType(collection, IPriority, false);
 249  1
                         if (containsOnlyType) return;
 250  
                         
 251  1
                         var it:IIterator = collection.iterator();
 252  
                         var element:*;
 253  
                         
 254  1
                         while (it.hasNext())
 255  
                         {
 256  1
                                 element = it.next();
 257  1
                                 if (!isValidElement(element)) break;
 258  
                         }
 259  
                         
 260  1
                         var error:ClassCastError = getInvalidElementError(element);
 261  1
                         throw error;
 262  
                 }
 263  
                 
 264  
                 /**
 265  
                  * @private
 266  
                  */
 267  
                 protected function validateElement(element:*): void
 268  
                 {
 269  1
                         if (isValidElement(element)) return;
 270  
                         
 271  1
                         var error:ClassCastError = getInvalidElementError(element);
 272  1
                         throw error;
 273  
                 }
 274  
                 
 275  
                 /**
 276  
                  * @private
 277  
                  */
 278  
                 private function addPriorityEventListenerToElement(element:IEventDispatcher):void
 279  
                 {
 280  1
                         element.addEventListener(PriorityEvent.CHANGED, elementPriorityChanged, false, 0, true);
 281  1
                 }
 282  
                 
 283  
                 /**
 284  
                  * @private
 285  
                  */
 286  
                 private function elementPriorityChanged(event:PriorityEvent):void
 287  
                 {
 288  1
                         _sort();
 289  1
                 }
 290  
                 
 291  
                 /**
 292  
                  * @private
 293  
                  */
 294  
                 private function getInvalidElementError(element:*): ClassCastError
 295  
                 {
 296  1
                         var message:String = "Element must implement org.as3coreaddendum.system.IPriority\n";
 297  1
                         message += "element: <" + element + ">\n";
 298  1
                         message += "element type: <" + ReflectionUtil.getClassPath(element) + ">";
 299  
                         
 300  1
                         return new ClassCastError(message);
 301  
                 }
 302  
                 
 303  
                 /**
 304  
                  * @private
 305  
                  */
 306  
                 private function removePriorityEventListenerFromElement(element:IEventDispatcher):void
 307  
                 {
 308  1
                         element.removeEventListener(PriorityEvent.CHANGED, elementPriorityChanged, false);
 309  1
                 }
 310  
                 
 311  
         }
 312  
 
 313  
 }