View Javadoc
1   package org.sim0mq.message.federatestarter;
2   
3   import org.sim0mq.Sim0MQException;
4   import org.sim0mq.message.MessageStatus;
5   import org.sim0mq.message.Sim0MQMessage;
6   import org.sim0mq.message.SimulationMessage;
7   
8   import nl.tudelft.simulation.language.Throw;
9   
10  /**
11   * FederateStarted, FS.2. Message sent by the Federate Starter to the Federation Manager in response to message FM.1.
12   * <p>
13   * Copyright (c) 2016-2017 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
14   * BSD-style license. See <a href="http://sim0mq.org/docs/current/license.html">Sim0MQ License</a>.
15   * </p>
16   * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $,
17   * initial version Apr 22, 2017 <br>
18   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
19   */
20  public class FederateStartedMessage extends Sim0MQMessage
21  {
22      /** */
23      private static final long serialVersionUID = 20170422L;
24  
25      /**
26       * The sender id of the model that was started or had an error while starting. This is exactly the same as the instanceId
27       * sent by the Federation Manager in the StartFederate message.
28       */
29      private final String instanceId;
30  
31      /** A string that refers to the model status. Four options: "started", "running", "ended", "error". */
32      private final String status;
33  
34      /** The model port number. We use an int in Java due to the fact there is no unsigned short. */
35      private final int modelPort;
36  
37      /** Optional. If there is an error, the error message is sent as well. Otherwise this field is an empty string. */
38      private final String error;
39  
40      /** the unique message id. */
41      private static final String MESSAGETYPE = "FS.2";
42  
43      /**
44       * @param simulationRunId the Simulation run ids can be provided in different types. Examples are two 64-bit longs
45       *            indicating a UUID, or a String with a UUID number, a String with meaningful identification, or a short or an
46       *            int with a simulation run number.
47       * @param senderId The sender id can be used to send back a message to the sender at some later time.
48       * @param receiverId The receiver id can be used to check whether the message is meant for us, or should be discarded (or an
49       *            error can be sent if we receive a message not meant for us).
50       * @param messageId The unique message number is meant to confirm with a callback that the message has been received
51       *            correctly. The number is unique for the sender, so not globally within the federation.
52       * @param instanceId The sender id of the model that was started or had an error while starting. This is exactly the same as
53       *            the instanceId sent by the Federation Manager in the StartFederate message.
54       * @param status A string that refers to the model status. Four options: "started", "running", "ended", "error".
55       * @param modelPort The model port number. We use an int in Java due to the fact there is no unsigned short.
56       * @param error Optional. If there is an error, the error message is sent as well. Otherwise this field is an empty string.
57       * @throws Sim0MQException on unknown data type
58       * @throws NullPointerException when one of the parameters is null
59       */
60      @SuppressWarnings("checkstyle:parameternumber")
61      public FederateStartedMessage(final Object simulationRunId, final Object senderId, final Object receiverId,
62              final long messageId, final String instanceId, final String status, final int modelPort, final String error)
63              throws Sim0MQException, NullPointerException
64      {
65          super(simulationRunId, senderId, receiverId, MESSAGETYPE, messageId, MessageStatus.NEW);
66  
67          Throw.whenNull(instanceId, "instanceId cannot be null");
68          Throw.whenNull(status, "status cannot be null");
69          Throw.whenNull(error, "error cannot be null");
70  
71          Throw.when(status.isEmpty(), Sim0MQException.class, "status cannot be empty");
72          Throw.when(!status.equals("started") && !status.equals("running") && !status.equals("ended") && !status.equals("error"),
73                  Sim0MQException.class, "status should be one of 'started', 'running', 'ended', 'error'");
74          Throw.when(modelPort < 0 || modelPort > 65535, Sim0MQException.class, "modelPort should be between 0 and 65535");
75  
76          this.instanceId = instanceId;
77          this.status = status;
78          this.modelPort = modelPort;
79          this.error = error;
80      }
81  
82      /**
83       * @return messagetype
84       */
85      public static final String getMessageType()
86      {
87          return MESSAGETYPE;
88      }
89  
90      /** {@inheritDoc} */
91      @Override
92      public Object[] createObjectArray()
93      {
94          return new Object[] { getSimulationRunId(), getSenderId(), getReceiverId(), getMessageTypeId(), getMessageId(),
95                  getMessageStatus(), this.instanceId, this.status, this.modelPort, this.error };
96      }
97  
98      /** {@inheritDoc} */
99      @Override
100     public byte[] createByteArray() throws Sim0MQException
101     {
102         return SimulationMessage.encodeUTF8(getSimulationRunId(), getSenderId(), getReceiverId(), getMessageTypeId(),
103                 getMessageId(), getMessageStatus(), this.instanceId, this.status, this.modelPort, this.error);
104     }
105 
106     /**
107      * Build a message from an Object[] that was received.
108      * @param fields Object[]; the fields in the message
109      * @param intendedReceiverId id of the intended receiver
110      * @return a Sim0MQ message
111      * @throws Sim0MQException when number of fields is not correct
112      */
113     public static FederateStartedMessage createMessage(final Object[] fields, final Object intendedReceiverId)
114             throws Sim0MQException
115     {
116         check(fields, 4, MESSAGETYPE, intendedReceiverId);
117         return new FederateStartedMessage(fields[1], fields[2], fields[3], ((Long) fields[5]).longValue(), fields[8].toString(),
118                 fields[9].toString(), ((Short) fields[10]).intValue(), fields[11].toString());
119     }
120 
121     /**
122      * Builder for the FederateStarted Message. Can string setters together, and call build() at the end to build the actual
123      * message.
124      * <p>
125      * Copyright (c) 2016-2017 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
126      * <br>
127      * BSD-style license. See <a href="http://sim0mq.org/docs/current/license.html">Sim0MQ License</a>.
128      * </p>
129      * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $,
130      * initial version Apr 22, 2017 <br>
131      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
132      */
133     public static class Builder extends Sim0MQMessage.Builder<FederateStartedMessage.Builder>
134     {
135         /**
136          * The sender id of the model that was started or had an error while starting. This is exactly the same as the
137          * instanceId sent by the Federation Manager in the StartFederate message.
138          */
139         private String instanceId;
140 
141         /** A string that refers to the model status. Four options: "started", "running", "ended", "error". */
142         private String status;
143 
144         /** The model port number. We use an int in Java due to the fact there is no unsigned short. */
145         private int modelPort;
146 
147         /** Optional. If there is an error, the error message is sent as well. Otherwise this field is an empty string. */
148         private String error;
149 
150         /**
151          * Empty constructor.
152          */
153         public Builder()
154         {
155             // nothing to do.
156         }
157 
158         /**
159          * @param newInstanceId set instanceId
160          * @return the original object for chaining
161          */
162         public final Builder setInstanceId(final String newInstanceId)
163         {
164             this.instanceId = newInstanceId;
165             return this;
166         }
167 
168         /**
169          * @param newStatus set status
170          * @return the original object for chaining
171          */
172         public final Builder setStatus(final String newStatus)
173         {
174             this.status = newStatus;
175             return this;
176         }
177 
178         /**
179          * @param newModelPort set modelPort (int instead of short because of signed short in Java)
180          * @return the original object for chaining
181          */
182         public final Builder setModelPort(final int newModelPort)
183         {
184             this.modelPort = newModelPort;
185             return this;
186         }
187 
188         /**
189          * @param newError set error
190          * @return the original object for chaining
191          */
192         public final Builder setError(final String newError)
193         {
194             this.error = newError;
195             return this;
196         }
197 
198         /** {@inheritDoc} */
199         @Override
200         public Sim0MQMessage build() throws Sim0MQException, NullPointerException
201         {
202             return new FederateStartedMessage(this.simulationRunId, this.senderId, this.receiverId, this.messageId,
203                     this.instanceId, this.status, this.modelPort, this.error);
204         }
205 
206     }
207 }