1 package org.sim0mq.message; 2 3 import org.djutils.exceptions.Throw; 4 import org.sim0mq.Sim0MQException; 5 6 /** 7 * The abstract body of a reply message with the first fields of every Sim0MQ reply message. 8 * <p> 9 * Copyright (c) 2016-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br> 10 * BSD-style license. See <a href="http://sim0mq.org/docs/current/license.html">Sim0MQ License</a>. 11 * </p> 12 * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $, 13 * initial version Apr 22, 2017 <br> 14 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a> 15 */ 16 public abstract class Sim0MQReply extends Sim0MQMessage 17 { 18 /** */ 19 private static final long serialVersionUID = 20170422L; 20 21 /** The unique message id (Frame 5) of the sender for which this is the reply. */ 22 private final Object replyToId; 23 24 /** 25 * Encode the object array into a message. 26 * @param bigEndian boolean; Indicates whether this message using little endian or big endian encoding. Big endian is 27 * encoded as true, and little endian as false. 28 * @param federationId the federation id can be coded using different types. Examples are two 64-bit longs indicating a 29 * UUID, or a String with a UUID number, a String with meaningful identification, or a short or an int with a 30 * simulation run number. 31 * @param senderId The sender id can be used to send back a message to the sender at some later time. 32 * @param receiverId The receiver id can be used to check whether the message is meant for us, or should be discarded (or an 33 * error can be sent if we receive a message not meant for us). 34 * @param messageTypeId Message type ids can be defined per type of simulation, and can be provided in different types. 35 * Examples are a String with a meaningful identification, or a short or an int with a message type number. 36 * @param messageId The unique message number is meant to confirm with a callback that the message has been received 37 * correctly. The number is unique for the sender, so not globally within the federation. 38 * @param payload Object[]; Payload as an Object array 39 * @throws Sim0MQException on unknown data type 40 * @throws NullPointerException when one of the parameters is null 41 */ 42 public Sim0MQReply(final boolean bigEndian, final Object federationId, final Object senderId, final Object receiverId, 43 final Object messageTypeId, final Object messageId, final Object[] payload) 44 throws Sim0MQException, NullPointerException 45 { 46 super(bigEndian, federationId, senderId, receiverId, messageTypeId, messageId, payload); 47 Throw.when(payload.length < 1, Sim0MQException.class, "payload for a reply should start with the replyToId"); 48 this.replyToId = payload[0]; 49 } 50 51 /** 52 * Encode the object array into a message. <br> 53 * 0 = magic number, equal to the String "SIM##" where ## stands for the version number of the protocol.<br> 54 * 1 = endianness, boolean indicating the endianness for the message. True is Big Endian, false is Little Endian.<br> 55 * 2 = federation id, could be String, int, Object, ...<br> 56 * 3 = sender id, could be String, int, Object, ...<br> 57 * 4 = receiver id, could be String, int, Object, ...<br> 58 * 5 = message type id, could be String, int, Object, ...<br> 59 * 6 = message id, could be long, Object, String, ....<br> 60 * 7 = number of fields that follow, as a Number (byte, short, int, long).<br> 61 * 8-n = payload, where the number of fields was defined by message[7]. The first payload field should be the replyToId. 62 * @param objectArray Object[]; Full message object array 63 * @param expectedNumberOfPayloadFields int; the expected number of fields in the message (field 8 and further). The payload 64 * fields should include the replyToId, so the number should be 1 or higher. 65 * @param expectedMessageTypeId the expected message type id 66 * @throws Sim0MQException on unknown data type 67 * @throws NullPointerException when one of the parameters is null 68 */ 69 public Sim0MQReply(final Object[] objectArray, final int expectedNumberOfPayloadFields, final Object expectedMessageTypeId) 70 throws Sim0MQException, NullPointerException 71 { 72 super(objectArray, expectedNumberOfPayloadFields, expectedMessageTypeId); 73 Throw.when(objectArray.length < 9, Sim0MQException.class, "payload for a reply should start with the replyToId"); 74 this.replyToId = objectArray[8]; 75 } 76 77 /** 78 * @return replyToId 79 */ 80 public final Object getReplyToId() 81 { 82 return this.replyToId; 83 } 84 85 /** 86 * Builder for the Sim0MQReply. Can string setters together, and call build() at the end to build the actual message. 87 * <p> 88 * Copyright (c) 2016-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. 89 * <br> 90 * BSD-style license. See <a href="http://sim0mq.org/docs/current/license.html">Sim0MQ License</a>. 91 * </p> 92 * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $, 93 * initial version Apr 22, 2017 <br> 94 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a> 95 * @param <B> the actual inherited builder for the return types. 96 */ 97 public abstract static class Builder<B extends Sim0MQMessage.Builder<B>> extends Sim0MQMessage.Builder<B> 98 { 99 /** The unique message id (Frame 5) of the sender for which this is the reply. */ 100 @SuppressWarnings("checkstyle:visibilitymodifier") 101 protected Object replyToId; 102 103 /** 104 * Empty constructor. 105 */ 106 public Builder() 107 { 108 // nothing to do. 109 } 110 111 /** 112 * @param newReplyToId set replyToId 113 * @return the original object for chaining 114 */ 115 @SuppressWarnings("unchecked") 116 public final B setReplyToId(final Object newReplyToId) 117 { 118 this.replyToId = newReplyToId; 119 return (B) this; 120 } 121 122 /** 123 * @param message set replyToId and receiver based on the message to which this is a reply 124 * @return the original object for chaining 125 */ 126 @SuppressWarnings("unchecked") 127 public final B setReplyTo(final Sim0MQMessage message) 128 { 129 this.replyToId = message.getMessageId(); 130 this.receiverId = message.getSenderId(); 131 return (B) this; 132 } 133 134 @Override 135 public abstract Sim0MQReply build() throws Sim0MQException, NullPointerException; 136 137 } 138 }