1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.gscg.singleuser.interactionlayer;
15
16 import java.io.IOException;
17 import java.io.ObjectOutputStream;
18 import java.rmi.RemoteException;
19 import java.rmi.server.UnicastRemoteObject;
20 import java.util.ArrayList;
21 import java.util.HashMap;
22 import java.util.HashSet;
23 import java.util.Map;
24 import java.util.Set;
25 import java.util.TreeSet;
26
27 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
28 import nl.tudelft.simulation.event.Event;
29 import nl.tudelft.simulation.event.EventInterface;
30 import nl.tudelft.simulation.event.EventListenerInterface;
31 import nl.tudelft.simulation.event.EventType;
32 import nl.tudelft.simulation.event.remote.RemoteEventListener;
33 import nl.tudelft.simulation.event.remote.RemoteEventListenerInterface;
34 import nl.tudelft.simulation.event.remote.RemoteEventProducerInterface;
35 import nl.tudelft.simulation.logger.Logger;
36 import nl.tudelft.simulation.naming.InitialEventContext;
37 import nl.tudelft.simulation.supplychain.actor.SupplyChainActor;
38 import nl.tudelft.simulation.supplychain.actor.Trader;
39 import nl.tudelft.simulation.supplychain.stock.StockInterface;
40
41 import org.gscg.common.gui.ClientInterface;
42 import org.gscg.common.gui.exceptions.ReceivedUnknownEventException;
43 import org.gscg.common.interactionlayer.AnnounceInterface;
44 import org.gscg.common.interactionlayer.ThreadedEventProducer;
45 import org.gscg.common.interactionlayer.location.YellowPage;
46 import org.gscg.common.interactionlayer.messaging.ScenarioText;
47 import org.gscg.common.interactionlayer.messaging.SocialMessaging;
48 import org.gscg.common.interactionlayer.timecontrol.CurrentRowOrColumnNumber;
49 import org.gscg.common.interactionlayer.timecontrol.GlobalRowOrColumnNumber;
50 import org.gscg.common.interactionlayer.timecontrol.ProgressDateAndTime;
51 import org.gscg.game.GameActorContentStore;
52 import org.gscg.game.GameGlobalData;
53 import org.gscg.gameactors.GameActorInteractiveInterface;
54 import org.gscg.gameactors.GameManufacturer;
55 import org.gscg.gameleader.interactionlayer.util.EventTypeComparator;
56 import org.gscg.singleuser.handlers.CommittedOrderHandler;
57 import org.gscg.singleuser.handlers.ConfirmedOrderHandler;
58 import org.gscg.singleuser.handlers.ConfirmedProductionHandler;
59 import org.gscg.singleuser.interactionlayer.business.BusinessProduction;
60 import org.gscg.singleuser.interactionlayer.business.BusinessPurchase;
61 import org.gscg.singleuser.interactionlayer.business.BusinessSales;
62 import org.gscg.singleuser.interactionlayer.business.BusinessStock;
63 import org.gscg.singleuser.interactionlayer.business.statistics.BankStatistics;
64 import org.gscg.singleuser.interactionlayer.business.statistics.StockStatistics;
65 import org.gscg.singleuser.interactionlayer.dataobjects.content.RFQDataSuppliers;
66 import org.gscg.singleuser.interactionlayer.economics.Economics;
67
68 /***
69 * The ManufacturerSingleUserInteractionLayer takes care of the communication
70 * between the simulation server side and a client side application for a
71 * manufacturer.
72 *
73 * <p>
74 * Copyright (c) 2003-2005 Delft University of Technology, Jaffalaan 5, 2628 BX
75 * Delft, the Netherlands. All rights reserved.
76 *
77 * See for project information <a href="http://www.simulation.tudelft.nl/">
78 * www.simulation.tudelft.nl </a>.
79 *
80 * The source code and binary code of this software is proprietary information
81 * of Delft University of Technology.
82 *
83 * @author <a
84 * href="http://www.tbm.tudelft.nl/webstaf/stijnh/index.htm">Stijn-Pieter
85 * van Houten </a>
86 * @version $Revision: 1.2 $ $Date: 2005/08/09 20:49:45 $
87 * @since 1.0.0
88 */
89 public class ManufacturerSingleUserInteractionLayer extends
90 ThreadedEventProducer implements RemoteInteractionLayerInterface,
91 SingleUserInteractionLayerInterface
92 {
93 /*** the serial version uid */
94 private static final long serialVersionUID = 13L;
95
96 /*** the static list of ids in this game for identification mapping */
97 protected static Map idMap = new HashMap();
98
99 /*** the remote event listener */
100 private transient RemoteEventListener remoteEventListener = null;
101
102 /*** the id is used by a client to perform a lookup in de remote context */
103 private String id = "";
104
105 /*** the simulator */
106 private SimulatorInterface simulator = null;
107
108 /*** the owner of the interaction layer */
109 private SupplyChainActor owner = null;
110
111 /*** the event types this layer is subscribed to */
112 private Set eventTypes = new HashSet();
113
114 /*** the event types this layer is subscribed to */
115 private Set eventsSentByClient = new HashSet();
116
117 /*** the semaphore to use for the announce calls */
118 private transient Object semaphore = new Object();
119
120 /*** indicates if all announce events have been processed client side */
121 private boolean clientIsReady = false;
122
123 /*** the event types this layer is subscribed to */
124 private Set statisticEventTypes = new TreeSet(new EventTypeComparator());
125
126 /*** the overall game data */
127 private GameGlobalData globalSupplyChainData;
128
129 /*** the yellowpage */
130 private YellowPage yellowPage = null;
131
132 /*** maps event types and corresponding announce objects */
133 private HashMap announceObjects = new HashMap();
134
135 /***
136 * indicates whether caching is necessary (during initialization of a
137 * client)
138 */
139 private boolean shouldBeCaching = false;
140
141 /*** the cache to store mesages during intialization of a client */
142 private ArrayList cache = new ArrayList();
143
144 /***
145 * constructs a new DistributorSingleUserInteractionLayer
146 *
147 * @param simulator the simulator
148 * @param id the id of the single user interaction layer
149 * @param owner the owner of the interaction layer
150 * @param globalSupplyChainData the global supply chain data
151 */
152 public ManufacturerSingleUserInteractionLayer(
153 final SimulatorInterface simulator, final String id,
154 final SupplyChainActor owner,
155 final GameGlobalData globalSupplyChainData)
156 {
157 super();
158 try
159 {
160 UnicastRemoteObject.exportObject(this);
161 } catch (RemoteException remoteException)
162 {
163 Logger.severe(this, "<init>", remoteException);
164 }
165 try
166 {
167 this.globalSupplyChainData = globalSupplyChainData;
168 this.remoteEventListener = new RemoteEventListener(this);
169
170 this.simulator = simulator;
171 this.simulator.addListener(this, SimulatorInterface.START_EVENT);
172 this.eventTypes.add(SimulatorInterface.START_EVENT);
173 this.simulator.addListener(this, SimulatorInterface.STOP_EVENT);
174 this.eventTypes.add(SimulatorInterface.STOP_EVENT);
175
176 this.id = id;
177 this.owner = owner;
178 this.yellowPage = this.globalSupplyChainData.getYellowPage();
179
180
181 this.globalSupplyChainData.getYellowPage().addListener(this,
182 YellowPage.UPDATE_ACTORS, false);
183 this.globalSupplyChainData.getYellowPage().addListener(this,
184 YellowPage.UPDATE_INTERACTIVE_PLAYER_STATUS, false);
185
186
187
188
189 new ProgressDateAndTime(this);
190 new CurrentRowOrColumnNumber(this);
191
192 new SocialMessaging(this, this.yellowPage);
193 new Economics(this);
194 new BusinessStock(this);
195 new BusinessPurchase(this);
196 new BusinessProduction(this);
197 new BusinessSales(this);
198 new BankStatistics(this, (Trader) this.owner,
199 GlobalRowOrColumnNumber.getNumberOfDays());
200 new StockStatistics(this, (Trader) this.owner,
201 GlobalRowOrColumnNumber.getNumberOfDays());
202
203
204
205
206
207
208 ((Trader) this.owner).getStock().addListener(this,
209 StockInterface.STOCK_CHANGE_EVENT);
210 this.eventTypes.add(StockInterface.STOCK_CHANGE_EVENT);
211
212
213 new ConfirmedOrderHandler(this);
214 new CommittedOrderHandler(this);
215 new ConfirmedProductionHandler(this);
216
217
218
219
220 new InitialEventContext().bind("manufacturer_" + this.id, this);
221
222
223 ((GameActorInteractiveInterface) this.owner)
224 .setSingleUserInteractionLayer(this);
225 } catch (Exception exception)
226 {
227 Logger.severe(this, "ManufacturerSingleUserInteractionLayer",
228 exception);
229 }
230 }
231
232 /***
233 * @see org.gscg.singleuser.interactionlayer.SingleUserInteractionLayerInterface#addEventType(nl.tudelft.simulation.event.EventType)
234 */
235 public void addEventType(final EventType eventType)
236 {
237 if (!this.eventTypes.contains(eventType))
238 {
239 this.eventTypes.add((eventType));
240 }
241 }
242
243 /***
244 * @see org.gscg.common.interactionlayer.GlobalInteractionLayerInterface#addEventTypeSentByClient(nl.tudelft.simulation.event.EventType)
245 */
246 public void addEventTypeSentByClient(final EventType eventType)
247 {
248 if (!this.eventsSentByClient.contains(eventType))
249 {
250 this.eventsSentByClient.add((eventType));
251 }
252 }
253
254 /***
255 * @see org.gscg.common.interactionlayer.GlobalInteractionLayerInterface#addEventTypeToAnnounceList(nl.tudelft.simulation.event.EventType,
256 * org.gscg.common.interactionlayer.AnnounceInterface)
257 */
258 public void addEventTypeToAnnounceList(final EventType eventType,
259 final AnnounceInterface announceObject)
260 {
261 String key = eventType.toString();
262 this.announceObjects.put(key, announceObject);
263 }
264
265 /***
266 * @see org.gscg.singleuser.interactionlayer.SingleUserInteractionLayerInterface#addStatisticEventType(nl.tudelft.simulation.event.EventType)
267 */
268 public void addStatisticEventType(final EventType eventType)
269 {
270 if (!this.statisticEventTypes.contains(eventType))
271 {
272 this.statisticEventTypes.add(eventType);
273 }
274 }
275
276 /***
277 * @see org.gscg.common.interactionlayer.GlobalInteractionLayerInterface#getCache(java.lang.Object,
278 * nl.tudelft.simulation.event.EventType, boolean)
279 */
280 public synchronized void getCache(final Object remoteEventProducer,
281 final EventType eventType, final boolean cache)
282 throws RemoteException
283 {
284 if (cache)
285 {
286
287
288
289
290 if (!this.clientIsReady)
291 {
292
293 this.shouldBeCaching = true;
294
295 synchronized (this.semaphore)
296 {
297 if (eventType
298 .equals(ScenarioText.CACHE_LARGE_NEWS_MESSAGE_EVENT))
299 {
300 ScenarioText.getScenarioText().announce(eventType,
301 true, this);
302 return;
303 }
304 if (this.announceObjects.containsKey(eventType.toString()))
305 {
306 AnnounceInterface object = (AnnounceInterface) this.announceObjects
307 .get(eventType.toString());
308 object.announce(eventType, true);
309 return;
310 }
311 if (eventType.equals(YellowPage.UPDATE_ACTORS))
312 {
313
314 this.globalSupplyChainData.getYellowPage().update(true,
315 this);
316
317
318 this.eventTypes.add(YellowPage.UPDATE_ACTORS);
319 this.eventTypes
320 .add(YellowPage.UPDATE_INTERACTIVE_PLAYER_STATUS);
321 return;
322 }
323
324
325 if (eventType
326 .equals(GameActorContentStore.UPDATE_ALL_NUMBER_DATA_EVENT))
327 {
328 this.fireAllNumberData();
329 return;
330 }
331
332
333 if (eventType
334 .equals(ClientInterface.INITIALIZATION_COMPLETED_EVENT))
335 {
336 if (this.simulator.isRunning())
337 {
338 this
339 .notifyAnnounced(new Event(
340 SimulatorInterface.START_EVENT,
341 this, null));
342 }
343
344
345
346
347
348 this.isReady(true);
349
350 try
351 {
352
353
354
355 while (this.cache.size() > 0)
356 {
357 this.notify((EventInterface) this.cache
358 .remove(0));
359 }
360 } catch (RemoteException remoteException)
361 {
362
363
364 this.removeListener(null,
365 SimulatorInterface.TIME_CHANGED_EVENT);
366 }
367
368 this.shouldBeCaching = false;
369
370 Logger.info(this, "getCache",
371 "ManufacturerSingleUserInteractionLayer: last cache event fired. Player: \""
372 + this.owner.getName()
373 + "\" is ready to play.");
374 return;
375 }
376 new ReceivedUnknownEventException(this, "getCache1",
377 eventType);
378 }
379 }
380 } else
381 {
382
383 if (this.announceObjects.containsKey(eventType.toString()))
384 {
385 AnnounceInterface object = (AnnounceInterface) this.announceObjects
386 .get(eventType.toString());
387 object.announce(eventType, false);
388 return;
389 }
390
391
392 if (this.eventsSentByClient.contains(eventType))
393 {
394 if (remoteEventProducer != null)
395 {
396 ((RemoteEventProducerInterface) remoteEventProducer)
397 .addListener(this.remoteEventListener, eventType,
398 false);
399 System.out.println("eveny sent by client event: "
400 + eventType);
401 }
402 return;
403 }
404 new ReceivedUnknownEventException(this, "getCache2", eventType);
405 }
406 }
407
408 /***
409 * @see nl.tudelft.simulation.event.EventListenerInterface#notify(nl.tudelft.simulation.event.EventInterface)
410 */
411 public void notify(final EventInterface event) throws RemoteException
412 {
413
414 if (this.clientIsReady)
415 {
416
417
418 super.fireEvent(event);
419
420
421
422
423
424
425
426
427 } else
428 {
429
430 if (event.getType().equals(SocialMessaging.RECEIVE_SOCIAL_MESSAGE)
431 || event.getType().equals(
432 SocialMessaging.SOCIAL_MESSAGE_SENT)
433 || event.getType().equals(
434 SocialMessaging.UPDATE_SENT_SOCIAL_MESSAGE)
435 || event.getType().equals(
436 SocialMessaging.UPDATE_RECEIVED_SOCIAL_MESSAGE))
437 {
438 this.fireEvent(new Event(event.getType(), this, event
439 .getContent()));
440 return;
441 }
442 if (this.shouldBeCaching)
443 {
444 Logger.info(this, "notify",
445 "ManufacturerSingleUserInteractionLayer: player: "
446 + this.owner.getName() + " is caching");
447
448 if (!event.getType().equals(
449 SimulatorInterface.TIME_CHANGED_EVENT))
450 {
451
452
453
454
455
456
457 this.cache.add(event);
458 }
459 return;
460 }
461 }
462 }
463
464 /***
465 * @see org.gscg.singleuser.interactionlayer.SingleUserInteractionLayerInterface#notifyAnnounced(nl.tudelft.simulation.event.EventInterface)
466 */
467 public void notifyAnnounced(final EventInterface event)
468 {
469 this.fireEvent(event);
470 }
471
472
473 /***
474 * @see org.gscg.common.interactionlayer.GlobalInteractionLayerInterface#login(nl.tudelft.simulation.event.remote.RemoteEventListenerInterface)
475 */
476 public synchronized boolean login(final RemoteEventListenerInterface client)
477 throws RemoteException
478 {
479
480
481 if (this.clientIsReady)
482 {
483
484 return true;
485 }
486 if (this.shouldBeCaching)
487 {
488
489 return true;
490 }
491 return false;
492 }
493
494 /***
495 * Method publicFireEvent.
496 *
497 * @param event the event to fire
498 */
499 public void publicFireEvent(final EventInterface event)
500 {
501 super.fireEvent(event);
502 }
503
504 /***
505 * Method fireAllNumberData.
506 */
507 public void fireAllNumberData()
508 {
509 ((GameManufacturer) this.owner).fireAllNumberData();
510 }
511
512 /***
513 * @see nl.tudelft.simulation.event.EventProducerInterface#removeListener(nl.tudelft.simulation.event.EventListenerInterface,
514 * nl.tudelft.simulation.event.EventType)
515 */
516 public synchronized boolean removeListener(
517 final EventListenerInterface listener, final EventType eventType)
518 {
519
520
521 if (eventType.equals(SimulatorInterface.TIME_CHANGED_EVENT))
522 {
523
524 this.shouldBeCaching = false;
525 this.cache.clear();
526
527 this.isReady(false);
528 Logger.info(this, "removeListener",
529 "ManufacturerSingleUserInteractionLayer: status of player: \""
530 + this.owner.getName() + "" + "\" set to "
531 + this.clientIsReady);
532 }
533 boolean result = super.removeListener(listener, eventType);
534 return result;
535 }
536
537
538
539
540
541 /***
542 * @see org.gscg.singleuser.interactionlayer.RemoteInteractionLayerInterface#getContentList(java.lang.Class,
543 * boolean, java.lang.String)
544 */
545 public void getContentList(final Class contentClass, final boolean sent,
546 final String productName) throws RemoteException
547 {
548 ((GameManufacturer) this.owner).fireAllContentData(contentClass, sent,
549 productName);
550 }
551
552 /***
553 * @see org.gscg.singleuser.interactionlayer.SingleUserInteractionLayerInterface#getGlobalSupplyChainData()
554 */
555 public GameGlobalData getGlobalSupplyChainData()
556 {
557 return this.globalSupplyChainData;
558 }
559
560 /***
561 * @see org.gscg.common.interactionlayer.GlobalInteractionLayerInterface#getStatisticEventTypes()
562 */
563 public EventType[] getStatisticEventTypes()
564 {
565 return (EventType[]) this.statisticEventTypes
566 .toArray(new EventType[this.statisticEventTypes.size()]);
567 }
568
569 /***
570 * @see org.gscg.singleuser.interactionlayer.RemoteInteractionLayerInterface#getSuppliers(java.lang.String)
571 */
572 public RFQDataSuppliers getSuppliers(final String productName)
573 throws RemoteException
574 {
575 return ((GameManufacturer) this.owner).getInitialRFQData(productName);
576 }
577
578 /***
579 * @see org.gscg.common.interactionlayer.GlobalInteractionLayerInterface#getTotalNumberOfDays()
580 */
581 public int getTotalNumberOfDays() throws RemoteException
582 {
583 return GlobalRowOrColumnNumber.getNumberOfDays();
584 }
585
586 /***
587 * @see org.gscg.singleuser.interactionlayer.SingleUserInteractionLayerInterface#getOwner()
588 */
589 public SupplyChainActor getOwner()
590 {
591 return this.owner;
592 }
593
594 /***
595 * @see org.gscg.singleuser.interactionlayer.SingleUserInteractionLayerInterface#getSimulator()
596 */
597 public SimulatorInterface getSimulator()
598 {
599 return this.simulator;
600 }
601
602
603
604
605 /***
606 * Method isReady.
607 *
608 * @param ready true if the client is connected, false otherwise
609 */
610 private void isReady(final boolean ready)
611 {
612 this.clientIsReady = ready;
613 this.yellowPage.updateInteractiveOnlineStatus(this.owner, ready, false);
614 }
615
616 /***
617 * writes a serializable method to stream
618 *
619 * @param out the outputstream
620 * @throws IOException on IOException
621 */
622 private synchronized void writeObject(final ObjectOutputStream out)
623 throws IOException
624 {
625
626 this.yellowPage.updateInteractiveOnlineStatus(this.owner, false, true);
627
628 out.defaultWriteObject();
629 out.writeObject(this.simulator.getReplication().getRunControl()
630 .getTreatment().getProperties());
631
632
633 this.yellowPage.updateInteractiveOnlineStatus(this.owner,
634 this.clientIsReady, true);
635 }
636
637 /***
638 * reads a serializable method from stream
639 *
640 * @param in the inputstream
641 */
642 private synchronized void readObject(final java.io.ObjectInputStream in)
643 {
644 try
645 {
646 in.defaultReadObject();
647 try
648 {
649 UnicastRemoteObject.exportObject(this);
650 } catch (RemoteException remoteException)
651 {
652 Logger.severe(this, "<init>", remoteException);
653 }
654
655 this.remoteEventListener = new RemoteEventListener(this);
656 this.semaphore = new Object();
657 new InitialEventContext().bind(this.id, this);
658
659 this.clientIsReady = false;
660
661 } catch (Exception exception)
662 {
663 Logger.severe(this, "readObject", exception);
664 }
665 }
666 }