EMMA Coverage Report (generated Sun Feb 05 10:43:15 CET 2012)
[all classes][desmoj.core.report]

COVERAGE SUMMARY FOR SOURCE FILE [MessageDistributor.java]

nameclass, %method, %block, %line, %
MessageDistributor.java0%   (0/2)0%   (0/16)0%   (0/441)0%   (0/164)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class MessageDistributor0%   (0/1)0%   (0/15)0%   (0/420)0%   (0/157)
MessageDistributor (): void 0%   (0/1)0%   (0/21)0%   (0/12)
deRegister (MessageReceiver): void 0%   (0/1)0%   (0/42)0%   (0/14)
deRegister (MessageReceiver, Class): void 0%   (0/1)0%   (0/36)0%   (0/13)
deRegister (MessageReceiver, String): void 0%   (0/1)0%   (0/44)0%   (0/17)
isOn (Class): boolean 0%   (0/1)0%   (0/19)0%   (0/8)
isRegistered (Class): boolean 0%   (0/1)0%   (0/14)0%   (0/6)
linkOf (Class): MessageDistributor$MLink 0%   (0/1)0%   (0/22)0%   (0/6)
receive (Message): void 0%   (0/1)0%   (0/42)0%   (0/13)
receive (Reporter): void 0%   (0/1)0%   (0/27)0%   (0/8)
register (MessageReceiver, Class): void 0%   (0/1)0%   (0/38)0%   (0/13)
register (MessageReceiver, String): void 0%   (0/1)0%   (0/49)0%   (0/17)
skip (Class): void 0%   (0/1)0%   (0/17)0%   (0/7)
skip (Class, int): void 0%   (0/1)0%   (0/21)0%   (0/9)
switchOff (Class): void 0%   (0/1)0%   (0/14)0%   (0/7)
switchOn (Class): void 0%   (0/1)0%   (0/14)0%   (0/7)
     
class MessageDistributor$MLink0%   (0/1)0%   (0/1)0%   (0/21)0%   (0/7)
MessageDistributor$MLink (MessageDistributor$MLink, Class, boolean): void 0%   (0/1)0%   (0/21)0%   (0/7)

1package desmoj.core.report;
2 
3import java.util.Vector;
4 
5/**
6 * The central object for distributing the messages generated by a simulation
7 * run. The MessageDistributor can receive messages and reporters and forwards
8 * them to the <code>MessageReceiver</code> objects registered at this
9 * MessageDistributor. When registering, the <code>MessageReceiver</code> has
10 * to pass a type to identify which type of messages they want to have
11 * forwarded. Note that multiple <code>MessageReceiver</code> s can be
12 * registered to get the same type of messages as well as a
13 * <code>MessageReceiver</code> can be registered with different types of
14 * messages, if it is capable of handling such. This enables a modeller i.e. to
15 * get the error messages displayed on screen additional to the file being
16 * stored on harddisk by default. This is also handy if a simulation should be
17 * run as an Applet thus having no or restricted disk access and using multiple
18 * scrollable windows instead.
19 * 
20 * @version DESMO-J, Ver. 2.3.3 copyright (c) 2011
21 * @author Tim Lechler
22 * 
23 * Licensed under the Apache License, Version 2.0 (the "License");
24 * you may not use this file except in compliance with the License. You
25 * may obtain a copy of the License at
26 * http://www.apache.org/licenses/LICENSE-2.0
27 *
28 * Unless required by applicable law or agreed to in writing, software
29 * distributed under the License is distributed on an "AS IS"
30 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
31 * or implied. See the License for the specific language governing
32 * permissions and limitations under the License.
33 *
34 */
35public class MessageDistributor implements MessageReceiver {
36 
37        /**
38         * The special class for reporters to send all reporters to the experiment's
39         * standard report ouput.
40         */
41        private static Class<?> reporters;
42 
43        /**
44         * The first item of the list of registered message types.
45         */
46        private MLink _head;
47 
48        /**
49         * The inner class messagelink keeps track of the types of messages and
50         * their related messagereceiver objects. Designed as an inner class to
51         * messagedistributor, not visible outside.
52         * 
53         * @author Tim Lechler
54         */
55        private static class MLink {
56 
57                /**
58                 * The link to the next link for the next messagetype
59                 */
60                MLink next;
61 
62                /**
63                 * The type of message that a messagereceiver object is registered with.
64                 */
65                Class<?> msgType;
66 
67                /**
68                 * The Vector filled with messagereceivers registered to receive
69                 * messages of the attached type.
70                 */
71                Vector<MessageReceiver> clients;
72 
73                /**
74                 * Flag to state whether the current type of message is being
75                 * distributed or currently not distributed. Can be set via
76                 * <code>SwitchOn()</code> or <code>SwitchOff()</code> methods.
77                 */
78                boolean isOn;
79 
80                /**
81                 * Counts the number of future messages to be skipped. This is necessary
82                 * to blend out any model activities that are related to internal
83                 * operations and thus would confuse the modeller.
84                 */
85                int skipCount;
86 
87                /**
88                 * Constructs a link with the given parameters. This is just a
89                 * convenient shorthand for setting up the parameters each at a time.
90                 */
91                MLink(MLink nextLink, Class<?> messageType, boolean showing) {
92                        isOn = showing; // switches output to receivers on (true) or off
93                        // (false)
94                        next = nextLink; // ref to next messageType
95                        skipCount = 0; // no messages to be skipped now
96                        msgType = messageType; // the class of the MessageType
97                        clients = new Vector<MessageReceiver>(3); // max. number of standard clients are
98                        // 2,
99                        // so we have one spare for each type
100 
101                }
102 
103        }
104 
105        /**
106         * Constructs a new messagedistributor.
107         */
108        public MessageDistributor() {
109 
110                super();
111 
112                try {
113                        reporters = Class.forName("desmoj.core.report.Reporter");
114                } catch (ClassNotFoundException cnfEx) {
115                        throw (new desmoj.core.exception.DESMOJException(
116                                        new ErrorMessage(
117                                                        null,
118                                                        "Can't find class \"desmoj.core.report.Reporter\"!",
119                                                        "MessageDistributor-Contructor.",
120                                                        "The classfile is probably missing or does not reside in the"
121                                                                        + "folder /desmoj/report.",
122                                                        "Make sure to have the DESMOJ framework installed correctly",
123                                                        null)));
124                }
125 
126        }
127 
128        /**
129         * De-registers the given messagereceiver from all types of Messages it was
130         * registered at. The given messagereceiver is taken from all lists of
131         * messagereceiver.
132         * 
133         * @param out
134         *            MessageReceiver : The messagereceiver to be removed from all
135         *            messages' lists of receivers
136         */
137        public void deRegister(MessageReceiver out) {
138 
139                // check parameter
140                if (out == null)
141                        return; // invalid param, so just return
142 
143                if (_head == null)
144                        return; // nobody registered yet
145 
146                // now scan through all queues and issue removal
147                for (MLink tmp = _head; tmp != null; tmp = tmp.next) {
148 
149                        tmp.clients.removeElement(out);
150                        if (tmp.clients.isEmpty()) { // if last is taken, trash
151                                // messagelink
152 
153                                if (tmp == _head) {
154                                        _head = _head.next; // special care for first element in
155                                        // list
156                                        return; // there can't be any more left to check
157                                } else {
158                                        tmp = tmp.next; // remove MessageLink
159                                        if (tmp == null)
160                                                return; // there can't be any more left to check
161                                }
162 
163                        }
164 
165                }
166 
167        }
168 
169        /**
170         * De-registers a messagereceiver object to stop receiving messages of the
171         * given type. The given messagereceiver object is taken from the list of
172         * messagereceiver receiving messages of the passed messagetype. If invalid
173         * parameters are given (i.e. <code>null</code> references) this method
174         * simply returns
175         * 
176         * @param out
177         *            MessageReceiver : The messagereceiver to be de-registered
178         * @param messageType
179         *            java.lang.Class : The type of messages the messagereceiver
180         *            should be deregistered from
181         */
182        public void deRegister(MessageReceiver out, Class<?> messageType) {
183 
184                // check parameters
185                if (out == null)
186                        return; // invalid params
187 
188                if (messageType == null)
189                        return; // invalid params
190 
191                // get link for messageType
192                MLink tmp = linkOf(messageType);
193 
194                if (tmp == null)
195                        return; // not registered, so why bother and return
196 
197                // from here on everything must be checked so...
198                tmp.clients.removeElement(out); // ...get rid of the client
199 
200                if (tmp.clients.isEmpty()) { // if last is taken, trash messagelink
201 
202                        if (tmp == _head) {
203                                _head = _head.next; // special care for first element in list
204                        } else {
205                                tmp = tmp.next; // remove MessageLink
206                        }
207 
208                }
209 
210        }
211 
212        /**
213         * De-registers a messagereceiver object to stop receiving messages of the
214         * given type. The given messagereceiver object is taken from the list of
215         * messagereceivers receiving messages of the passed messagetype. If invalid
216         * parameters are given (i.e. <code>null</code> references) this method
217         * simply returns
218         * 
219         * @param out
220         *            MessageReceiver : The messagereceiver to be de-registered
221         * @param className
222         *            String : The type of messages the messagereceiver
223         *            should be deregistered from
224         */
225        public void deRegister(MessageReceiver out, String className) {
226 
227                // check parameters
228                if (out == null)
229                        return; // invalid params
230                if (className == null)
231                        return; // invalid params
232 
233                // get the type
234                Class<?> messageType = null;
235 
236                try {
237                        messageType = Class.forName(className);
238                } catch (ClassNotFoundException cnfx) {
239                        return; // send message that class is not in scope
240                }
241 
242                // get link for messageType
243                MLink tmp = linkOf(messageType);
244                if (tmp == null)
245                        return; // not registered, so why bother and retur
246 
247                // from here on everything must be checked so...
248                tmp.clients.removeElement(out); // ...get rid of the client
249 
250                if (tmp.clients.isEmpty()) { // if last is taken, trash messagelink
251 
252                        if (tmp == _head) {
253                                _head = _head.next; // special care for first element in list
254                        } else {
255                                tmp = tmp.next; // remove MessageLink
256                        }
257 
258                }
259 
260        }
261 
262        /**
263         * Checks if the current messagetype is switched on to be distributed. If
264         * not, no messages of the given type are distributed or the given type of
265         * message is not registered here.
266         * 
267         * @return boolean : Is <code>true</code> if the type of message is
268         *         distributed <code>false</code> if not or messagetype is not
269         *         registered here
270         */
271        public boolean isOn(Class<?> messageType) {
272 
273                if (messageType == null)
274                        return false;
275 
276                MLink tmp = linkOf(messageType);
277 
278                if (tmp == null)
279                        return false; // type not registered here
280 
281                if (tmp.isOn) {
282                        return true;
283                } else
284                        return false;
285 
286        }
287 
288        /**
289         * Checks if the given messagetype is registered at this messagedistributor.
290         * 
291         * @return boolean : Is <code>true</code> if the messagetype is
292         *         registered, <code>false</code> if not
293         */
294        public boolean isRegistered(Class<?> messageType) {
295 
296                if (messageType == null)
297                        return false;
298 
299                MLink tmp = linkOf(messageType);
300 
301                if (tmp == null)
302                        return false; // type not registered here
303                else
304                        return true;
305 
306        }
307 
308        /**
309         * Returns the messagelink for the given class or <code>null</code> if the
310         * class is not already registered.
311         * 
312         * @return MessageLink : The messagelink for the given class or
313         *         <code>null</code> if the given class is not registered yet
314         * @param messageType
315         *            java.lang.Class : The class that the link is needed for
316         */
317        private MLink linkOf(Class<?> messageType) {
318 
319                if (_head == null)
320                        return null;
321                else {
322 
323                        for (MLink tmp = _head; tmp != null; tmp = tmp.next) {
324                                if (tmp.msgType == messageType)
325                                        return tmp;
326                        }
327 
328                }
329 
330                return null;
331 
332        }
333 
334        /**
335         * Receives a message and forwards it to all messagereceiver objects
336         * registered with the type of message sent. Messages are sent, if the type
337         * of message is switched on and if the skipCounter is zero, thus not
338         * skipping any messages of that type.
339         * 
340         * @param m
341         *            Message : The message to be forwarded to all registered
342         *            MessageReceivers
343         */
344        public void receive(Message m) {
345 
346                if (m == null)
347                        return; // again nulls
348 
349                MLink tmp = linkOf(m.getClass()); // get link in list of msgTypes
350 
351                if (tmp == null)
352                        return; // is null if type not registered here, so return???
353                
354                // checks if the message has to be skipped
355                if (tmp.skipCount > 0) {
356                        tmp.skipCount--;
357                        return;
358                }
359 
360                // check if messages of this type should be distributed to their
361                // message receivers
362                if (!tmp.isOn)
363                        return;
364 
365                // loop + send to all receivers
366                for (int i = 0; i < tmp.clients.size(); i++) {
367                        ((MessageReceiver) tmp.clients.elementAt(i)).receive(m);
368                }
369 
370        }
371 
372        /**
373         * Receives a reporter and forwards it to all messagereceiver objects
374         * registered with the type of reporter sent.
375         * 
376         * @param r
377         *            Reporter : The reporter to be forwarded to all registered
378         *            messagereceivers.
379         */
380        public void receive(desmoj.core.report.Reporter r) {
381 
382                if (r == null)
383                        return; // again nulls
384 
385                MLink tmp = linkOf(reporters); // get link in list of msgTypes
386 
387                if (tmp == null)
388                        return; // is null if type not registered here, so return???
389 
390                for (int i = 0; i < tmp.clients.size(); i++) { // loop and
391                        ((MessageReceiver) tmp.clients.elementAt(i)).receive(r);
392                }
393 
394        }
395 
396        /**
397         * Registers a messagereceiver object to receive messages of the given type.
398         * 
399         * @param out
400         *            MessageReceiver : The messagereceiver to be registered
401         * @param messageType
402         *            java.lang.Class : The type of messages the messagereceiver is
403         *            registered with
404         */
405        public void register(MessageReceiver out, Class<?> messageType) {
406 
407                // check parameters
408                if (out == null)
409                        return; // invalid param
410                if (messageType == null)
411                        return; // invalid param
412 
413                // now look up for link to registered messageType
414                MLink tmp = linkOf(messageType);
415 
416                // check link and insert or create new type link
417                if (tmp != null) { // type is already known!
418 
419                        if (tmp.clients.contains(out)) { // check if already reg'd
420                                return; // already inside
421                        } else { // client is new to this messagetype, so...
422                                tmp.clients.addElement(out); // ...add the client
423                                return; // we're done
424                        }
425 
426                } else { // messageType not registered here, so do it now
427                        // create the new link. New Links are added at first position
428                        _head = new MLink(_head, messageType, true);
429                        _head.clients.addElement(out); // add the output
430                }
431 
432        }
433 
434        /**
435         * Registers a messagereceiver object to receive messages of the given type.
436         * 
437         * @param out
438         *            MessageReceiver : The messagereceiver to be registered
439         * @param className
440         *            java.lang.String : The name of the type of messages the
441         *            messagereceiver is registered with
442         */
443        public void register(MessageReceiver out, String className) {
444 
445                // check parameters
446                if (out == null)
447                        return; // invalid param
448                if ((className == null) || (className.length() == 0))
449                        return; // invalid param
450 
451                // identify the corresponding link
452                Class<?> messageType = null;
453 
454                try {
455                        messageType = Class.forName(className);
456                } catch (ClassNotFoundException cnfx) {
457                        return; // send message that class is not in scope???
458                }
459 
460                // now look up for link to registered messageType
461                MLink tmp = linkOf(messageType);
462 
463                // check link and insert or create new type link
464                if (tmp != null) { // type is already known!
465 
466                        if (tmp.clients.contains(out)) { // check if already reg'd
467                                return; // already inside
468                        } else { // client is new to this messagetype, so...
469                                tmp.clients.addElement(out); // ...add the client
470                                return; // we're done
471                        }
472 
473                } else { // messageType not registered here, so do it now
474                        // create the new link. New Links are added at first position
475                        _head = new MLink(_head, messageType, true);
476                        _head.clients.addElement(out); // add the output
477                }
478 
479        }
480 
481        /**
482         * Skips the transmission of the next tracenote or increases the skipCounter
483         * by one. This is necessary to blend out any activities managed by the
484         * framework that would otherwise confuse the modeller.
485         */
486        public void skip(Class<?> messageType) {
487 
488                if (messageType == null)
489                        return; // no good parameter
490 
491                MLink tmp = linkOf(messageType); // buffer the link to the msgType
492 
493                if (tmp == null)
494                        return; // type not registered, return
495 
496                tmp.skipCount++; // well, just increase by one :-)
497 
498        }
499 
500        /**
501         * Skips the transmission of a number of future messages by increasing the
502         * skipCount by the given number. This is necessary to blend out any
503         * activities managed by the framework that would otherwise confuse the
504         * modeller.
505         * 
506         * @param skipNumber
507         *            int : The number of messages to skip
508         */
509        public void skip(Class<?> messageType, int skipNumber) {
510 
511                if (skipNumber < 1)
512                        return; // check parameters for correctness
513 
514                if (messageType == null)
515                        return;
516 
517                MLink tmp = linkOf(messageType);
518 
519                if (tmp == null)
520                        return;
521 
522                tmp.skipCount += skipNumber; // increase by given number
523 
524        }
525 
526        /**
527         * Disables messages of the given type to be sent to the registered
528         * receivers.
529         * 
530         * @param messageType
531         *            Class : The type of messages to be switched off
532         */
533        public void switchOff(Class<?> messageType) {
534 
535                if (messageType == null)
536                        return; // no good parameter
537 
538                MLink tmp = linkOf(messageType); // buffer the link to the msgType
539 
540                if (tmp == null)
541                        return; // type not registered, return
542 
543                tmp.isOn = false; // well, just stop sending
544 
545        }
546 
547        /**
548         * Enables messages of the given type to be sent to the registered
549         * receivers.
550         * 
551         * @param messageType
552         *            Class : The type of messages to be switched on
553         */
554        public void switchOn(Class<?> messageType) {
555 
556                if (messageType == null)
557                        return; // no good parameter
558 
559                MLink tmp = linkOf(messageType); // buffer the link to the msgType
560 
561                if (tmp == null)
562                        return; // type not registered, return
563 
564                tmp.isOn = true; // well, go on and distribute
565 
566        }
567}

[all classes][desmoj.core.report]
EMMA 2.0.9414 (unsupported private build) (C) Vladimir Roubtsov