SimulatorStateTransceiver.java

  1. package org.opentrafficsim.sim0mq.publisher;

  2. import java.io.Serializable;
  3. import java.rmi.RemoteException;

  4. import org.djutils.event.Event;
  5. import org.djutils.event.EventListener;
  6. import org.djutils.event.EventProducer;
  7. import org.djutils.event.EventType;
  8. import org.djutils.event.LocalEventProducer;
  9. import org.djutils.event.TimedEvent;
  10. import org.djutils.metadata.MetaData;
  11. import org.djutils.metadata.ObjectDescriptor;
  12. import org.djutils.serialization.SerializationException;
  13. import org.opentrafficsim.core.dsol.OtsSimulatorInterface;
  14. import org.sim0mq.Sim0MQException;

  15. import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;

  16. /**
  17.  * Transceiver for simulator state change events.
  18.  * <p>
  19.  * Copyright (c) 2020-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
  20.  * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
  21.  * </p>
  22.  * @author <a href="https://tudelft.nl/staff/p.knoppers-1">Peter Knoppers</a>
  23.  */
  24. public class SimulatorStateTransceiver extends AbstractTransceiver
  25. {
  26.     /** The simulator. */
  27.     private final OtsSimulatorInterface simulator;

  28.     /** Multiplexes SimulatorInterface.START_EVENT and SimulatorInterface.STOP_EVENT. */
  29.     @SuppressWarnings("checkstyle:visibilitymodifier")
  30.     final EventProducer eventMultiplexer;

  31.     /** The event that will be emitted for either the START_EVENT or the STOP_EVENT. */
  32.     public static final EventType SIMULATOR_STATE_CHANGED = new EventType(new MetaData("SIMULATOR_STATE_CHANGED_EVENT",
  33.             "simulator started or stopped", new ObjectDescriptor[] {new ObjectDescriptor("New simulator state",
  34.                     "New simulator state; true if running; false if stopped", Boolean.class)}));

  35.     /**
  36.      * Construct a new SimulatorStateTransceiver.
  37.      * @param simulator OtsSimulatorInterface; the simulator
  38.      * @throws RemoteException on network error
  39.      */
  40.     public SimulatorStateTransceiver(final OtsSimulatorInterface simulator) throws RemoteException
  41.     {
  42.         super("Simulator state transceiver", MetaData.EMPTY,
  43.                 new MetaData("SIMULATOR_STATE_CHANGED_EVENT", "simulator state changed"));
  44.         this.simulator = simulator;
  45.         this.eventMultiplexer = new EventMultiplexer(simulator);
  46.     }

  47.     /** {@inheritDoc} */
  48.     @Override
  49.     public Object[] get(final Object[] address, final ReturnWrapper returnWrapper)
  50.             throws RemoteException, Sim0MQException, SerializationException
  51.     {
  52.         AbstractTransceiver.verifyMetaData(MetaData.EMPTY, address);
  53.         String result = null;
  54.         if (this.simulator.isInitialized())
  55.         {
  56.             if (this.simulator.isStartingOrRunning())
  57.             {
  58.                 result = "Starting or running";
  59.             }
  60.             else
  61.             {
  62.                 result = "Stopping or stopped";
  63.             }
  64.         }
  65.         else
  66.         {
  67.             result = "Not (yet) initialized";
  68.         }
  69.         return new Object[] {result};
  70.     }

  71.     /** Result of the getLookupEventProducer method. */
  72.     private LookupEventProducer lepi = new LookupEventProducer()
  73.     {
  74.         @Override
  75.         public EventProducer lookup(final Object[] address, final ReturnWrapper returnWrapper)
  76.                 throws Sim0MQException, SerializationException
  77.         {
  78.             String bad = AbstractTransceiver.verifyMetaData(MetaData.EMPTY, address);
  79.             if (null != bad)
  80.             {
  81.                 returnWrapper.nack(bad);
  82.                 return null;
  83.             }
  84.             return SimulatorStateTransceiver.this.eventMultiplexer;
  85.         }

  86.         @Override
  87.         public MetaData getAddressMetaData()
  88.         {
  89.             return MetaData.EMPTY;
  90.         }
  91.     };

  92.     /**
  93.      * Retrieve the event LookupEventProducer.
  94.      * @return EventProducerInterface; the event multiplexer
  95.      */
  96.     public LookupEventProducer getLookupEventProducer()
  97.     {
  98.         return this.lepi;
  99.     }

  100. }

  101. /**
  102.  * Create a subscription to SimulatorInterface.START_EVENT and SimulatorInterface.STOP_EVENT and emit a SIMULATOR_STATE_CHANGED
  103.  * event for each.
  104.  */
  105. class EventMultiplexer extends LocalEventProducer implements EventListener
  106. {
  107.     /** ... */
  108.     private static final long serialVersionUID = 20200618L;

  109.     /**
  110.      * @param simulator OtsSimulatorInterface; the simulator
  111.      * @throws RemoteException on network error
  112.      */
  113.     EventMultiplexer(final OtsSimulatorInterface simulator) throws RemoteException
  114.     {
  115.         simulator.addListener(this, SimulatorInterface.START_EVENT);
  116.         simulator.addListener(this, SimulatorInterface.STOP_EVENT);
  117.     }

  118.     /** {@inheritDoc} */
  119.     @Override
  120.     public void notify(final Event event) throws RemoteException
  121.     {
  122.         notifyTimedEvent(event);
  123.     }

  124.     /**
  125.      * Avoid a compilation error with Java 11. Could be bug https://bugs.openjdk.java.net/browse/JDK-8206142 which is
  126.      * unsolved...
  127.      * @param <C> the casting class for the event timestamp
  128.      * @param event the event to be notified of
  129.      */
  130.     private <C extends Serializable & Comparable<C>> void notifyTimedEvent(final Event event)
  131.     {
  132.         @SuppressWarnings("unchecked")
  133.         TimedEvent<C> timedEvent = (TimedEvent<C>) event;
  134.         fireTimedEvent(SimulatorStateTransceiver.SIMULATOR_STATE_CHANGED,
  135.                 event.getType().equals(SimulatorInterface.START_EVENT), timedEvent.getTimeStamp());
  136.     }

  137. }