1 /* 2 * Copyright the original author or authors. 3 * 4 * Licensed under the MOZILLA PUBLIC LICENSE, Version 1.1 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.mozilla.org/MPL/MPL-1.1.html 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 import org.as2lib.core.BasicClass; 18 import org.as2lib.data.holder.Queue; 19 import org.as2lib.data.holder.Iterator; 20 import org.as2lib.data.holder.array.ArrayIterator; 21 import org.as2lib.data.holder.EmptyDataHolderException; 22 import org.as2lib.util.Stringifier; 23 import org.as2lib.data.holder.queue.QueueStringifier; 24 25 /** 26 * {@code LinearQueue} stores values in a 'first-in, first-out' manner. 27 * 28 * <p>This class is a linear implementation of the {@code Queue} interface. This 29 * means that enqueued values are stored in a linear manner and that you can store 30 * as many values as you please. There are also queues that store values in a cyclic 31 * manner. These queues can normally only hold a prescribed number of values and 32 * overwrite old values or throw an exception if you try to enqueue more values. 33 * 34 * <p>'first-in, first-out' means that the first value that has been enqueued/added 35 * to the queue is the first that gets dequeued/removed. 36 * 37 * <p>The usage of a queue is quite simple. You have one method to add/enqueue values 38 * {@link #enqueue} and one method to remove/dequeue them {@link #dequeue}. You can 39 * also peek at the beginning of the queue to see what value has been added/enqueued 40 * at first without removing it {@link #peek}. 41 * 42 * <p>If you want to iterate over the values of the queue you can either use the 43 * iterator returned by the {@link #iterator} method or the array that contains the 44 * queue's values returned by the {@link #toArray} method. 45 * 46 * <p>The two methods {@link #isEmpty} and {@link #size} let you find 47 * out whether the queue contains values and how many values it contains. 48 * 49 * <p>You can modify the string representation that is returned by the {@link #toString} 50 * method with the static {@link #setStringifier} method. 51 * 52 * <p>Example: 53 * <code> 54 * // construct the queue 55 * var queue:Queue = new LinearQueue(); 56 * queue.enqueue("value1"); 57 * queue.enqueue("value2"); 58 * queue.enqueue("value3"); 59 * // use the queue 60 * trace(queue.peek()); 61 * while (!queue.isEmpty()) { 62 * trace(queue.pop()); 63 * } 64 * </code> 65 * 66 * <p>Output: 67 * <pre> 68 * value1 69 * value1 70 * value2 71 * value3 72 * </pre> 73 * 74 * <p>You can alternatively pass-in the content of the queue on construction. 75 * <code> 76 * var queue:Queue = new LinearQueue(["value1", "value2", "value3"]); 77 * // .. 78 * </code> 79 * 80 * @author Simon Wacker 81 */ 82 class org.as2lib.data.holder.queue.LinearQueue extends BasicClass implements Queue { 83 84 /** Stringifies queues. */ 85 private static var stringifier:Stringifier; 86 87 /** Contains the inserted elements. */ 88 private var data:Array; 89 90 /** 91 * Returns the stringifier that stringifies queues. 92 * 93 * <p>If no stringifier has been set manually via the static {@link #setStringifier} 94 * method an instance of class {@link QueueStringifier} will be returned. 95 * 96 * @return the stringifier that stringifies queues 97 */ 98 public static function getStringifier(Void):Stringifier { 99 if (!stringifier) stringifier = new QueueStringifier(); 100 return stringifier; 101 } 102 103 /** 104 * Sets the new stringifier that stringifies queues. 105 * 106 * <p>If the passed-in {@code queueStringifier} is {@code null} or {@code undefined}, 107 * the static {@link #getStringifier} method will return the default stringifier. 108 * 109 * @param queueStringifier the new queue stringifier 110 */ 111 public static function setStringifier(queueStringifier:Stringifier):Void { 112 stringifier = queueStringifier; 113 } 114 115 /** 116 * Constructs a new {@code LinearQueue} instance. 117 * 118 * <p>The queue steps through the passed-in {@code source} beginning at position 0 119 * and enqueues all contained elements. 120 * 121 * <p>Example: 122 * <code> 123 * var queue:LinearQueue = new LinearQueue([1, 2, 3]); 124 * while (!queue.isEmpty()) { 125 * trace(queue.dequeue()); 126 * } 127 * </code> 128 * 129 * <p>The output is made in the following order: 1, 2, 3 130 * 131 * @param source (optional) an array that contains values to populate this queue with 132 */ 133 public function LinearQueue(source:Array) { 134 if (source) { 135 data = source.concat(); 136 } else { 137 data = new Array(); 138 } 139 } 140 141 /** 142 * Adds the passed-in {@code value} to this queue. 143 * 144 * <p>{@code null} and {@code undefined} values are allowed. 145 * 146 * @param value the value to add 147 */ 148 public function enqueue(value):Void { 149 data.push(value); 150 } 151 152 /** 153 * Removes and returns the firstly inserted value. 154 * 155 * @return the firstly inserted value 156 * @throws EmptyDataHolderException if this queue is empty 157 */ 158 public function dequeue(Void) { 159 if (isEmpty()) { 160 throw new EmptyDataHolderException("You tried to dequeue an element from an empty Queue.", this, arguments); 161 } 162 return data.shift(); 163 } 164 165 /** 166 * Returns the firstly inserted value. 167 * 168 * @return the firstly inserted value 169 * @throws EmptyDataHolderException if this queue is empty 170 */ 171 public function peek(Void) { 172 if (isEmpty()) { 173 throw new EmptyDataHolderException("You tried to peek an element from an empty Queue.", this, arguments); 174 } 175 return data[0]; 176 } 177 178 /** 179 * Returns an iterator that can be used to iterate over the values of this queue. 180 * 181 * @return an iterator to iterate over this queue's values 182 * @see #toArray 183 */ 184 public function iterator(Void):Iterator { 185 return (new ArrayIterator(data.concat())); 186 } 187 188 /** 189 * Returns whether this queue contains any values. 190 * 191 * @return {@code true} if this queue contains no values else {@code false} 192 */ 193 public function isEmpty(Void):Boolean { 194 return (data.length < 1); 195 } 196 197 /** 198 * Returns the number of enqueued elements. 199 * 200 * @return the number of enqueued elements 201 * @see #enqueue 202 */ 203 public function size(Void):Number { 204 return data.length; 205 } 206 207 /** 208 * Returns an array representation of this queue. 209 * 210 * <p>The elements are copied onto the array in a 'first-in, first-out' order, 211 * similar to the order of the elements returned by a succession of calls to the 212 * {@link #dequeue} method. 213 * ################################################################################ 214 * @return the array representation of this queue 215 */ 216 public function toArray(Void):Array { 217 return data.concat(); 218 } 219 220 /** 221 * Returns the string representation of this queue. 222 * 223 * <p>The string representation is obtained via the stringifier returned by the 224 * static {@link #getStringifier} method. 225 * 226 * @return the string representation of this queue 227 */ 228 public function toString():String { 229 return getStringifier().execute(this); 230 } 231 232 }