View Javadoc
1   package org.opentrafficsim.sim0mq.publisher;
2   
3   import java.io.Serializable;
4   import java.rmi.RemoteException;
5   
6   import org.djutils.event.EventInterface;
7   import org.djutils.event.EventListenerInterface;
8   import org.djutils.event.EventProducer;
9   import org.djutils.event.EventProducerInterface;
10  import org.djutils.event.TimedEvent;
11  import org.djutils.event.TimedEventType;
12  import org.djutils.metadata.MetaData;
13  import org.djutils.metadata.ObjectDescriptor;
14  import org.djutils.serialization.SerializationException;
15  import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
16  import org.sim0mq.Sim0MQException;
17  
18  import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
19  
20  /**
21   * Transceiver for simulator state change events.
22   * <p>
23   * Copyright (c) 2020-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
24   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
25   * <p>
26   * $LastChangedDate: 2020-02-13 11:08:16 +0100 (Thu, 13 Feb 2020) $, @version $Revision: 6383 $, by $Author: pknoppers $,
27   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
28   */
29  public class SimulatorStateTransceiver extends AbstractTransceiver
30  {
31      /** The simulator. */
32      private final OTSSimulatorInterface simulator;
33  
34      /** Multiplexes SimulatorInterface.START_EVENT and SimulatorInterface.STOP_EVENT. */
35      @SuppressWarnings("checkstyle:visibilitymodifier")
36      final EventProducerInterface eventMultiplexer;
37  
38      /** The event that will be emitted for either the START_EVENT or the STOP_EVENT. */
39      public static final TimedEventType SIMULATOR_STATE_CHANGED =
40              new TimedEventType(new MetaData("SIMULATOR_STATE_CHANGED_EVENT", "simulator started or stopped",
41                      new ObjectDescriptor[] {new ObjectDescriptor("New simulator state",
42                              "New simulator state; true if running; false if stopped", Boolean.class)}));
43  
44      /**
45       * Construct a new SimulatorStateTransceiver.
46       * @param simulator OTSSimulatorInterface; the simulator
47       * @throws RemoteException on network error
48       */
49      public SimulatorStateTransceiver(final OTSSimulatorInterface simulator) throws RemoteException
50      {
51          super("Simulator state transceiver", MetaData.EMPTY,
52                  new MetaData("SIMULATOR_STATE_CHANGED_EVENT", "simulator state changed"));
53          this.simulator = simulator;
54          this.eventMultiplexer = new EventMultiplexer(simulator);
55      }
56  
57      /** {@inheritDoc} */
58      @Override
59      public Object[] get(final Object[] address, final ReturnWrapper returnWrapper)
60              throws RemoteException, Sim0MQException, SerializationException
61      {
62          AbstractTransceiver.verifyMetaData(MetaData.EMPTY, address);
63          String result = null;
64          if (this.simulator.isInitialized())
65          {
66              if (this.simulator.isStartingOrRunning())
67              {
68                  result = "Starting or running";
69              }
70              else
71              {
72                  result = "Stopping or stopped";
73              }
74          }
75          else
76          {
77              result = "Not (yet) initialized";
78          }
79          return new Object[] {result};
80      }
81  
82      /** Result of the getLookupEventProducerInterface method. */
83      private LookupEventProducerInterfaceHandler.html#LookupEventProducerInterface">LookupEventProducerInterface lepi = new LookupEventProducerInterface()
84      {
85          @Override
86          public EventProducerInterface lookup(final Object[] address, final ReturnWrapper returnWrapper)
87                  throws Sim0MQException, SerializationException
88          {
89              String bad = AbstractTransceiver.verifyMetaData(MetaData.EMPTY, address);
90              if (null != bad)
91              {
92                  returnWrapper.nack(bad);
93                  return null;
94              }
95              return SimulatorStateTransceiver.this.eventMultiplexer;
96          }
97  
98          @Override
99          public MetaData getAddressMetaData()
100         {
101             return MetaData.EMPTY;
102         }
103     };
104 
105     /**
106      * Retrieve the event LookupEventProducerInterface.
107      * @return EventProducerInterface; the event multiplexer
108      */
109     public LookupEventProducerInterface getLookupEventProducerInterface()
110     {
111         return this.lepi;
112     }
113 
114 }
115 
116 /**
117  * Create a subscription to SimulatorInterface.START_EVENT and SimulatorInterface.STOP_EVENT and emit a SIMULATOR_STATE_CHANGED
118  * event for each.
119  */
120 class EventMultiplexer extends EventProducer implements EventListenerInterface
121 {
122     /** ... */
123     private static final long serialVersionUID = 20200618L;
124 
125     /**
126      * @param simulator OTSSimulatorInterface; the simulator
127      * @throws RemoteException on network error
128      */
129     EventMultiplexer(final OTSSimulatorInterface simulator) throws RemoteException
130     {
131         simulator.addListener(this, SimulatorInterface.START_EVENT);
132         simulator.addListener(this, SimulatorInterface.STOP_EVENT);
133     }
134 
135     /** {@inheritDoc} */
136     @Override
137     public void notify(final EventInterface event) throws RemoteException
138     {
139         notifyTimedEvent(event);
140     }
141 
142     /**
143      * Avoid a compilation error with Java 11. Could be bug https://bugs.openjdk.java.net/browse/JDK-8206142 which is
144      * unsolved...
145      * @param <C> the casting class for the event timestamp
146      * @param event the event to be notified of
147      */
148     private <C extends Serializable & Comparable<C>> void notifyTimedEvent(final EventInterface event)
149     {
150         @SuppressWarnings("unchecked")
151         TimedEvent<C> timedEvent = (TimedEvent<C>) event;
152         fireTimedEvent(SimulatorStateTransceiver.SIMULATOR_STATE_CHANGED,
153                 event.getType().equals(SimulatorInterface.START_EVENT), timedEvent.getTimeStamp());
154     }
155 
156     /** {@inheritDoc} */
157     @Override
158     public Serializable getSourceId()
159     {
160         // TODO Auto-generated method stub
161         return "EventMultiplexer";
162     }
163 
164 }