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.util.ObjectUtil; 19 import org.as2lib.env.except.IllegalArgumentException; 20 import org.as2lib.env.reflect.ReflectUtil; 21 import org.as2lib.data.holder.Queue; 22 import org.as2lib.data.holder.Iterator; 23 24 /** 25 * {@code TypedQueue} is a wrapper for {@link Queue} instances that ensures that 26 * only values of a specific type can be added to the wrapped queue. 27 * 28 * <p>This class simply delegates all method invocations to the wrapped queue. If 29 * the specific method is responsible for adding values it first checks if the values 30 * to add are of the expected type. If they are the method invocation is forwarded, 31 * otherwise an {@link IllegalArgumentException} is thrown. 32 * 33 * @author Simon Wacker 34 */ 35 class org.as2lib.data.holder.queue.TypedQueue extends BasicClass implements Queue { 36 37 /** The wrapped queue. */ 38 private var queue:Queue; 39 40 /** The type of the values that can be added. */ 41 private var type:Function; 42 43 /** 44 * Constructs a new {@code TypedQueue} instance. 45 * 46 * <p>If the passed-in {@code queue} does already contain values, these values do 47 * not get type-checked. 48 * 49 * @param type the type of the values that are allowed to be added 50 * @param queue the queue to wrap 51 * @throws IllegalArgumentException if the passed-in {@code type} is {@code null} 52 * or {@code undefined} 53 * @throws IllegalArgumentException if {@code queue} is {@code null} or 54 * {@code undefined} 55 */ 56 public function TypedQueue(type:Function, queue:Queue) { 57 if (!type) throw new IllegalArgumentException("Argument 'type' [" + type + "] must not be 'null' nor 'undefined'.", this, arguments); 58 if (!queue) throw new IllegalArgumentException("Argument 'queue' [" + queue + "] must not be 'null' nor 'undefined'.", this, arguments); 59 this.type = type; 60 this.queue = queue; 61 } 62 63 /** 64 * Returns the type that all values in the wrapped queue have. 65 * 66 * <p>This is the type passed-in on construction. 67 * 68 * @return the type the all values of the wrapped queue have 69 */ 70 public function getType(Void):Function { 71 return type; 72 } 73 74 /** 75 * Adds the passed-in {@code value} to this queue. 76 * 77 * <p>The value is only enqueued if it is of the expected type. 78 * 79 * @param value the value to add 80 * @throws IllegalArgumentException if the type of the passed-in {@code value} is 81 * invalid 82 */ 83 public function enqueue(value):Void { 84 validate(value); 85 queue.enqueue(value); 86 } 87 88 /** 89 * Removes the firstly inserted value. 90 * 91 * @return the firstly inserted value 92 * @throws org.as2lib.data.holder.EmptyDataHolderException if this queue is empty 93 */ 94 public function dequeue(Void) { 95 return queue.dequeue(); 96 } 97 98 /** 99 * Returns the firstly inserted value. 100 * 101 * @return the firstly inserted value 102 * @throws org.as2lib.data.holder.EmptyDataHolderException if this queue is empty 103 */ 104 public function peek(Void) { 105 return queue.peek(); 106 } 107 /** 108 * Returns an iterator that can be used to iterate over the values of this queue. 109 * 110 * @return an iterator to iterate over this queue's values 111 * @see #toArray 112 */ 113 public function iterator(Void):Iterator { 114 return queue.iterator(); 115 } 116 117 /** 118 * Returns whether this queue contains any values. 119 * 120 * @return {@code true} if this queue contains no values else {@code false} 121 */ 122 public function isEmpty(Void):Boolean { 123 return queue.isEmpty(); 124 } 125 126 /** 127 * Returns the number of enqueued elements. 128 * 129 * @return the number of enqueued elements 130 * @see #enqueue 131 */ 132 public function size(Void):Number { 133 return queue.size(); 134 } 135 136 /** 137 * Returns an array representation of this queue. 138 * 139 * <p>The elements are copied onto the array in a 'first-in, first-out' order, 140 * similar to the order of the elements returned by a succession of calls to the 141 * {@link #dequeue} method. 142 * 143 * @return the array representation of this queue 144 */ 145 public function toArray(Void):Array { 146 return queue.toArray(); 147 } 148 149 /** 150 * Returns the string representation of the wrapped queue. 151 * 152 * @return the string representation of the wrapped queue 153 */ 154 public function toString():String { 155 return queue.toString(); 156 } 157 158 /** 159 * Validates the passed-in {@code value} based on its type. 160 * 161 * @param value the value whose type shall be validated 162 * @throws IllegalArgumentException if the type of the {@code value} is invalid 163 */ 164 private function validate(value):Void { 165 if (!ObjectUtil.typesMatch(value, type)) { 166 throw new IllegalArgumentException("Type mismatch between value [" + value + "] and type [" + ReflectUtil.getTypeNameForType(type) + "].", this, arguments); 167 } 168 } 169 170 }