1 package org.sim0mq.message.modelcontroller;
2
3 import org.djutils.exceptions.Throw;
4 import org.djutils.serialization.SerializationException;
5 import org.sim0mq.Sim0MQException;
6 import org.sim0mq.message.MessageStatus;
7 import org.sim0mq.message.Sim0MQReply;
8 import org.sim0mq.message.SimulationMessage;
9
10 /**
11 * StatusMessage, MC.1. The Model sends this message as a response to RequestStatus messages sent by the Federate Starter or the
12 * Federation Manager.
13 * <p>
14 * Copyright (c) 2016-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
15 * BSD-style license. See <a href="http://sim0mq.org/docs/current/license.html">Sim0MQ License</a>.
16 * </p>
17 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
18 */
19 public class MC1StatusMessage extends Sim0MQReply
20 {
21 /** A string that refers to the model status. Four options: "started", "running", "ended", "error". */
22 private final String status;
23
24 /** Optional. If there is an error, the error message is sent as well. Otherwise this field is an empty string. */
25 private final String error;
26
27 /** the unique message id. */
28 private static final String MESSAGETYPE = "MC.1";
29
30 /** */
31 private static final long serialVersionUID = 20170422L;
32
33 /**
34 * @param simulationRunId the Simulation run ids can be provided in different types. Examples are two 64-bit longs
35 * indicating a UUID, or a String with a UUID number, a String with meaningful identification, or a short or an
36 * int with a simulation run number.
37 * @param senderId The sender id can be used to send back a message to the sender at some later time.
38 * @param receiverId The receiver id can be used to check whether the message is meant for us, or should be discarded (or an
39 * error can be sent if we receive a message not meant for us).
40 * @param messageId The unique message number is meant to confirm with a callback that the message has been received
41 * correctly. The number is unique for the sender, so not globally within the federation.
42 * @param uniqueId Id to identify the callback to the message.
43 * @param status A string that refers to the model status. Four options: "started", "running", "ended", "error".
44 * @param error Optional. If there is an error, the error message is sent as well. Otherwise this field is an empty string.
45 * @throws Sim0MQException on unknown data type
46 * @throws NullPointerException when one of the parameters is null
47 */
48 public MC1StatusMessage(final Object simulationRunId, final Object senderId, final Object receiverId, final long messageId,
49 final long uniqueId, final String status, final String error) throws Sim0MQException, NullPointerException
50 {
51 super(simulationRunId, senderId, receiverId, MESSAGETYPE, messageId, MessageStatus.NEW, uniqueId);
52 Throw.whenNull(status, "status cannot be null");
53 Throw.whenNull(error, "error cannot be null");
54
55 Throw.when(status.isEmpty(), Sim0MQException.class, "status cannot be empty");
56 Throw.when(!status.equals("started") && !status.equals("running") && !status.equals("ended") && !status.equals("error"),
57 Sim0MQException.class, "status should be one of 'started', 'running', 'ended', 'error'");
58
59 this.status = status;
60 this.error = error;
61 }
62
63 /**
64 * @return status
65 */
66 public final String getStatus()
67 {
68 return this.status;
69 }
70
71 /**
72 * @return error
73 */
74 public final String getError()
75 {
76 return this.error;
77 }
78
79 /**
80 * @return messagetype
81 */
82 public static final String getMessageType()
83 {
84 return MESSAGETYPE;
85 }
86
87 /** {@inheritDoc} */
88 @Override
89 public short getNumberOfPayloadFields()
90 {
91 return 3;
92 }
93
94 /** {@inheritDoc} */
95 @Override
96 public Object[] createObjectArray()
97 {
98 return new Object[] {getMagicNumber(), getSimulationRunId(), getSenderId(), getReceiverId(), getMessageTypeId(),
99 getMessageId(), getMessageStatus(), getNumberOfPayloadFields(), getReplyToId(), this.status, this.error};
100 }
101
102 /** {@inheritDoc} */
103 @Override
104 public byte[] createByteArray() throws Sim0MQException, SerializationException
105 {
106 return SimulationMessage.encodeUTF8(getSimulationRunId(), getSenderId(), getReceiverId(), getMessageTypeId(),
107 getMessageId(), getMessageStatus(), getReplyToId(), this.status, this.error);
108 }
109
110 /**
111 * Build a message from an Object[] that was received.
112 * @param fields Object[]; the fields in the message
113 * @param intendedReceiverId id of the intended receiver
114 * @return a Sim0MQ message
115 * @throws Sim0MQException when number of fields is not correct
116 */
117 public static MC1StatusMessage createMessage(final Object[] fields, final Object intendedReceiverId) throws Sim0MQException
118 {
119 check(fields, 3, MESSAGETYPE, intendedReceiverId);
120 return new MC1StatusMessage(fields[1], fields[2], fields[3], ((Long) fields[5]).longValue(),
121 ((Long) fields[8]).longValue(), fields[9].toString(), fields[10].toString());
122 }
123
124 /**
125 * Builder for the StartFederate Message. Can string setters together, and call build() at the end to build the actual
126 * message.
127 * <p>
128 * Copyright (c) 2016-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
129 * <br>
130 * BSD-style license. See <a href="http://sim0mq.org/docs/current/license.html">Sim0MQ License</a>.
131 * </p>
132 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
133 */
134 public static class Builder extends Sim0MQReply.Builder<MC1StatusMessage.Builder>
135 {
136 /** A string that refers to the model status. Four options: "started", "running", "ended", "error". */
137 private String status;
138
139 /** Optional. If there is an error, the error message is sent as well. Otherwise this field is an empty string. */
140 private String error;
141
142 /**
143 * Empty constructor.
144 */
145 public Builder()
146 {
147 // nothing to do.
148 }
149
150 /**
151 * @param newStatus set status
152 * @return the original object for chaining
153 */
154 public final Builder setStatus(final String newStatus)
155 {
156 this.status = newStatus;
157 return this;
158 }
159
160 /**
161 * @param newError set error
162 * @return the original object for chaining
163 */
164 public final Builder setError(final String newError)
165 {
166 this.error = newError;
167 return this;
168 }
169
170 /** {@inheritDoc} */
171 @Override
172 public MC1StatusMessage build() throws Sim0MQException, NullPointerException
173 {
174 return new MC1StatusMessage(this.simulationRunId, this.senderId, this.receiverId, this.messageId, this.replyToId,
175 this.status, this.error);
176 }
177
178 }
179 }