| 1 | package desmoj.core.simulator; |
| 2 | |
| 3 | import java.beans.PropertyChangeListener; |
| 4 | import java.util.Iterator; |
| 5 | |
| 6 | import desmoj.core.exception.SimAbortedException; |
| 7 | import desmoj.core.report.ErrorMessage; |
| 8 | import desmoj.core.simulator.Entity; |
| 9 | import desmoj.core.simulator.QueueBased; |
| 10 | |
| 11 | /** |
| 12 | * Is the abstract superclass for all the classes implementing different |
| 13 | * queueing strategies for a waiting-queue. It provides all the basic methods |
| 14 | * for inserting objects in a queue, retrieving objects from a queue and getting |
| 15 | * basic informations about the queue. It is used in many kinds of queue |
| 16 | * implementations where collective functionalities are implemented by |
| 17 | * <code>QueueListStandard</code> and are specified e.g. in <code>QueueListFifo</code> |
| 18 | * or <code>QueueListLifo</code>. |
| 19 | * |
| 20 | * @see QueueBased |
| 21 | * @see Queue |
| 22 | * @see ProcessQueue |
| 23 | * @see QueueListFifo |
| 24 | * @see QueueListLifo |
| 25 | * |
| 26 | * @version DESMO-J, Ver. 2.3.3 copyright (c) 2011 |
| 27 | * @author Soenke Claassen |
| 28 | * @author based upon ideas from Tim Lechler |
| 29 | * |
| 30 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 31 | * you may not use this file except in compliance with the License. You |
| 32 | * may obtain a copy of the License at |
| 33 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 34 | * |
| 35 | * Unless required by applicable law or agreed to in writing, software |
| 36 | * distributed under the License is distributed on an "AS IS" |
| 37 | * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
| 38 | * or implied. See the License for the specific language governing |
| 39 | * permissions and limitations under the License. |
| 40 | * |
| 41 | */ |
| 42 | public abstract class QueueList<E extends Entity> implements PropertyChangeListener, Iterable<E> { |
| 43 | |
| 44 | /** |
| 45 | * The QueueBased object this queuelist serves as a container for. |
| 46 | */ |
| 47 | protected QueueBased clientQ; |
| 48 | |
| 49 | /** |
| 50 | * Uses the java.util.WeakHashMap functionalities to link entities with their entry time. |
| 51 | */ |
| 52 | protected java.util.HashMap<E,TimeInstant> timemap; |
| 53 | |
| 54 | /** |
| 55 | * Should return <code>true</code> if the given <code>Entity</code> is |
| 56 | * contained in the queue; <code>false</code> otherwise. |
| 57 | * |
| 58 | * @return boolean : Should be <code>true</code> if the given |
| 59 | * <code>Entity</code> is contained in the queue; |
| 60 | * <code>false</code> otherwise. |
| 61 | * @param e |
| 62 | * Entity : The <code>Entity</code> we are looking for |
| 63 | * in the queue. |
| 64 | */ |
| 65 | public abstract boolean contains(E e); |
| 66 | |
| 67 | /** |
| 68 | * Should return the first entity in the queue. |
| 69 | * |
| 70 | * @return Entity : The first entity in the queue |
| 71 | */ |
| 72 | public abstract E first(); |
| 73 | |
| 74 | /** |
| 75 | * Returns the <code>Entity</code> queued at the named position. |
| 76 | * The first position is 0, the last one size()-1. |
| 77 | * |
| 78 | * @return Entity : The <code>Entity</code> at the position of |
| 79 | * <code>int</code> or <code>null</code> if no such position exists. |
| 80 | */ |
| 81 | public abstract E get(int index); |
| 82 | |
| 83 | /** |
| 84 | * Returns the position of the named <code>Entity</code>. |
| 85 | * The first position is 0, the last one size()-1. |
| 86 | * |
| 87 | * @return : The position of the <code>Entity</code> or <code>-1</code> if no such exists. |
| 88 | */ |
| 89 | public abstract int get(E element); |
| 90 | |
| 91 | /** |
| 92 | * Should return an abbreviation as a String to identify the sort of |
| 93 | * queueing discipline (like FIFO or LIFO or ...). Is used to display the |
| 94 | * queueing discipline in the report of the QueueBased objects. |
| 95 | * |
| 96 | * @return java.lang.String : An abbreviation to identify the sort of |
| 97 | * queueing discipline (like FIFO or LIFO or ...) |
| 98 | */ |
| 99 | public abstract String getAbbreviation(); |
| 100 | |
| 101 | /** |
| 102 | * Returns the <code>QueueBased</code> object this <code>QueueList</code> |
| 103 | * serves as a queue implementation for. |
| 104 | * |
| 105 | * @return desmoj.QueueBased : The <code>QueueBased</code> object this |
| 106 | * <code>QueueList</code> serves as a container for. |
| 107 | */ |
| 108 | QueueBased getQueueBased() { |
| 109 | return clientQ; |
| 110 | } |
| 111 | |
| 112 | /** |
| 113 | * Should add a new Entity to the queue. |
| 114 | * |
| 115 | * @param e |
| 116 | * Entity : The Entity which will be added to the queue |
| 117 | */ |
| 118 | public abstract void insert(E e); |
| 119 | |
| 120 | /** |
| 121 | * Should insert the <code>Entity</code> "e" right after the position of |
| 122 | * <code>Entity</code> "which" in the queue. Should return |
| 123 | * <code>true</code> if this was done successfully. Be careful with this |
| 124 | * operation. It might disrupt your order of priorities. |
| 125 | * |
| 126 | * @return boolean : Is <code>true</code> if insertion was successfull, |
| 127 | * <code>false</code> otherwise. |
| 128 | * @param e |
| 129 | * Entity : The <code>Entity</code> which will be |
| 130 | * inserted. |
| 131 | * @param which |
| 132 | * Entity : The <code>Entity</code> determining the |
| 133 | * position after which the <code>Entity</code> "e" will be |
| 134 | * inserted in the queue. |
| 135 | */ |
| 136 | abstract boolean insertAfter(E e, E which); |
| 137 | |
| 138 | /** |
| 139 | * Should insert the <code>Entity</code> "e" right before the position of |
| 140 | * <code>Entity</code> "which" in the queue. Should return |
| 141 | * <code>true</code> if this was done successfully. Be careful with this |
| 142 | * operation. It might disrupt your order of priorities. |
| 143 | * |
| 144 | * @return boolean : Is <code>true</code> if insertion was successfull, |
| 145 | * <code>false</code> otherwise. |
| 146 | * @param e |
| 147 | * Entity : The <code>Entity</code> which will be |
| 148 | * inserted. |
| 149 | * @param which |
| 150 | * Entity : The <code>Entity</code> determining the |
| 151 | * position before which the <code>Entity</code> "e" will be |
| 152 | * inserted in the queue. |
| 153 | */ |
| 154 | abstract boolean insertBefore(E e, E which); |
| 155 | |
| 156 | /** |
| 157 | * Should return <code>true</code> if no entities are stored in the queue |
| 158 | * at the moment, <code>false</code> otherwise. |
| 159 | * |
| 160 | * @return boolean : Is <code>true</code> if no entities are stored in the |
| 161 | * queue at the moment, <code>false</code> otherwise. |
| 162 | */ |
| 163 | public abstract boolean isEmpty(); |
| 164 | |
| 165 | /** |
| 166 | * Should return the last <code>Entity</code> in the queue. |
| 167 | * |
| 168 | * @return Entity : The last <code>Entity</code> in the queue. |
| 169 | */ |
| 170 | public abstract E last(); |
| 171 | |
| 172 | /** |
| 173 | * Should return the predecessor of the given <code>Entity</code> "e" in |
| 174 | * the queue. |
| 175 | * |
| 176 | * @return Entity : The <code>Entity</code> before the given |
| 177 | * <code>Entity</code> "e" in the queue. |
| 178 | * @param e |
| 179 | * Entity : The predecessor of this <code>Entity</code> |
| 180 | * will be returned. |
| 181 | */ |
| 182 | abstract E pred(E e); |
| 183 | |
| 184 | /** |
| 185 | * Should remove the given <code>Entity</code> "e" from the queue. If this |
| 186 | * is done successfully <code>true</code> is returned, <code>false</code> |
| 187 | * otherwise. |
| 188 | * |
| 189 | * @return boolean : Is <code>true</code> if the given <code>Entity</code> |
| 190 | * is removed successfully, <code>false</code> otherwise. |
| 191 | * @param e |
| 192 | * Entity : The <code>Entity</code> which is to be |
| 193 | * removed from the queue. |
| 194 | */ |
| 195 | public abstract boolean remove(E e); |
| 196 | |
| 197 | /** |
| 198 | * Removes the <code>Entity</code> queued at the named position. |
| 199 | * * The first position is 0, the last one size()-1. |
| 200 | * |
| 201 | * @return : The method returns <code>true</code> as the <code>Entity</code> |
| 202 | * exists or <code>false></code> if otherwise. |
| 203 | */ |
| 204 | public abstract boolean remove(int index); |
| 205 | |
| 206 | /** |
| 207 | * Should remove the first <code>Entity</code> in the queue and returns |
| 208 | * <code>true</code> if done successfully, <code>false</code> otherwise. |
| 209 | * |
| 210 | * @return boolean : Is <code>true</code> if the first <code>Entity</code> |
| 211 | * in the queue is removed successfully, <code>false</code> |
| 212 | * otherwise. |
| 213 | */ |
| 214 | abstract boolean removeFirst(); |
| 215 | |
| 216 | /** |
| 217 | * Should remove the last <code>Entity</code> in the queue and returns |
| 218 | * <code>true</code> if done successfully, <code>false</code> otherwise. |
| 219 | * |
| 220 | * @return boolean : Is <code>true</code> if the last <code>Entity</code> |
| 221 | * in the queue is removed successfully, <code>false</code> |
| 222 | * otherwise. |
| 223 | */ |
| 224 | abstract boolean removeLast(); |
| 225 | |
| 226 | /** |
| 227 | * Should send a warning to the error output by forwarding it to the |
| 228 | * associated <code>QueueBased's sendWarning</code> method. Warnings |
| 229 | * should only be sent if the <code>QueueBased</code>'s flag for queue |
| 230 | * implementation warnings is set to <code>true</code>. |
| 231 | * |
| 232 | * @param description |
| 233 | * java.lang.String : describing the error |
| 234 | * @param location |
| 235 | * java.lang.String : describing the location the error occurred |
| 236 | * @param reason |
| 237 | * java.lang.String : describing the possible cause for this |
| 238 | * error |
| 239 | * @param prevention |
| 240 | * java.lang.String : telling what to do to prevent this error |
| 241 | * @see QueueBased |
| 242 | */ |
| 243 | abstract void sendWarning(String description, String location, |
| 244 | String reason, String prevention); |
| 245 | |
| 246 | /** |
| 247 | * Sets the client queue for which the entities are stored. Is needed, |
| 248 | * because this can not be done in the no-arg constructor. |
| 249 | * |
| 250 | * @param queueBase |
| 251 | * desmoj.QueueBased : The QueueBased using this queueing system. |
| 252 | */ |
| 253 | public void setQueueBased(QueueBased queueBase) { |
| 254 | |
| 255 | // DOA if no real QueueBased object is given |
| 256 | if (queueBase == null) { |
| 257 | throw (new SimAbortedException(new ErrorMessage(null, |
| 258 | "Can not create QueueListStandardFifo! Simulation aborted.", |
| 259 | "Class : QueueListStandardFifo / Method : setClientQueue" |
| 260 | + "(QueueBased queueBase) ", |
| 261 | "The reference to the QueueBased object needed is a null " |
| 262 | + "reference.", |
| 263 | "Always check to give valid references only.", null))); |
| 264 | } |
| 265 | |
| 266 | clientQ = queueBase; // set reference to my client using me as a |
| 267 | // container |
| 268 | |
| 269 | } |
| 270 | |
| 271 | /** |
| 272 | * Returns the actual size of the QueueList. |
| 273 | * |
| 274 | * @return : The method returns the size as an <code>int</code>. |
| 275 | * The value is 0 if no Entity is in line. |
| 276 | */ |
| 277 | public int size() |
| 278 | { |
| 279 | return clientQ.length(); |
| 280 | } |
| 281 | |
| 282 | /** |
| 283 | * This method is used for statistical data in the class QueueBased. |
| 284 | * |
| 285 | */ |
| 286 | void statisticalInsert(E e) |
| 287 | { |
| 288 | |
| 289 | timemap.put(e, clientQ.presentTime()); // saves time of insertion |
| 290 | |
| 291 | clientQ.addItem(); // update statistics |
| 292 | } |
| 293 | |
| 294 | /** |
| 295 | * This method is used for statistical data in the class QueueBased. |
| 296 | * |
| 297 | */ |
| 298 | void statisticalRemove(E e) |
| 299 | { |
| 300 | clientQ.deleteItem(timemap.get(e)); // tell QueueBased the entry time for update |
| 301 | // statistics |
| 302 | |
| 303 | timemap.remove(e); // removes the entity from timemap |
| 304 | } |
| 305 | |
| 306 | /** |
| 307 | * Should return the successor of the given <code>Entity</code> "e" in the |
| 308 | * queue. |
| 309 | * |
| 310 | * @return Entity : The <code>Entity</code> after the given |
| 311 | * <code>Entity</code> "e" in the queue. |
| 312 | * @param e |
| 313 | * Entity : The successor of this <code>Entity</code> |
| 314 | * will be returned. |
| 315 | */ |
| 316 | public abstract E succ(E e); |
| 317 | |
| 318 | /** |
| 319 | * Should return a string representation of the queue. |
| 320 | * |
| 321 | * @return java.lang.String : The string representation of the queue. |
| 322 | */ |
| 323 | public abstract String toString(); |
| 324 | |
| 325 | /** |
| 326 | * Returns an iterator over the entities enqueued. |
| 327 | * |
| 328 | * @return java.lang.Iterator<E> : An iterator over the entities enqueued. |
| 329 | */ |
| 330 | public Iterator<E> iterator() { |
| 331 | return new QueueListIterator(this); |
| 332 | } |
| 333 | |
| 334 | /** |
| 335 | * Private queue list iterator, e.g. required for processing all queue elements in a |
| 336 | * for-each-loop. |
| 337 | */ |
| 338 | private class QueueListIterator implements Iterator<E> { |
| 339 | |
| 340 | QueueList<E> clientQ; |
| 341 | E next, lastReturned; |
| 342 | |
| 343 | public QueueListIterator(QueueList<E> clientQ) { |
| 344 | this.clientQ = clientQ; |
| 345 | next = clientQ.first(); |
| 346 | lastReturned = null; |
| 347 | } |
| 348 | public boolean hasNext() { |
| 349 | return next != null; |
| 350 | } |
| 351 | public E next() { |
| 352 | lastReturned = next; |
| 353 | next = clientQ.succ(next); |
| 354 | return lastReturned; |
| 355 | } |
| 356 | public void remove() { |
| 357 | clientQ.remove(lastReturned); |
| 358 | } |
| 359 | } |
| 360 | } |