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 | } |