1 /** 2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 * SPDX-License-Identifier: Apache-2.0. 4 */ 5 package software.amazon.awssdk.crt.mqtt5.packets; 6 7 import java.util.ArrayList; 8 import java.util.List; 9 import java.util.Map; 10 import java.util.function.Function; 11 import java.util.stream.Collectors; 12 import java.util.stream.Stream; 13 14 import software.amazon.awssdk.crt.mqtt5.QOS; 15 16 /** 17 * Data model of an <a href="https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901161">MQTT5 SUBSCRIBE</a> packet. 18 */ 19 public class SubscribePacket { 20 21 private List<Subscription> subscriptions; 22 private Long subscriptionIdentifier; 23 private List<UserProperty> userProperties; 24 SubscribePacket(SubscribePacketBuilder builder)25 private SubscribePacket(SubscribePacketBuilder builder) { 26 this.subscriptions = builder.subscriptions; 27 this.subscriptionIdentifier = builder.subscriptionIdentifier; 28 this.userProperties = builder.userProperties; 29 } 30 31 /** 32 * Returns the list of subscriptions that the client wishes to listen to 33 * 34 * See <a href="https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901168">MQTT5 Subscribe Payload</a> 35 * 36 * @return List of subscriptions that the client wishes to listen to 37 */ getSubscriptions()38 public List<Subscription> getSubscriptions() { 39 return this.subscriptions; 40 } 41 42 /** 43 * Returns the positive long to associate with all subscriptions in this request. Publish packets that match 44 * a subscription in this request should include this identifier in the resulting message. 45 * 46 * See <a href="https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901166">MQTT5 Subscription Identifier</a> 47 * 48 * @return A positive long to associate with all subscriptions in this request. 49 */ getSubscriptionIdentifier()50 public Long getSubscriptionIdentifier() { 51 return this.subscriptionIdentifier; 52 } 53 54 /** 55 * Returns the list of MQTT5 user properties included with the packet. 56 * 57 * See <a href="https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901167">MQTT5 User Property</a> 58 * 59 * @return List of MQTT5 user properties included with the packet. 60 */ getUserProperties()61 public List<UserProperty> getUserProperties() { 62 return this.userProperties; 63 } 64 65 /** 66 * Configures how retained messages should be handled when subscribing with a subscription that matches topics with 67 * associated retained messages. 68 * 69 * Enum values match <a href="https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901169">MQTT5 spec</a> encoding values. 70 */ 71 public enum RetainHandlingType { 72 73 /** 74 * The server should always send all retained messages on topics that match a subscription's filter. 75 */ 76 SEND_ON_SUBSCRIBE(0), 77 78 /** 79 * The server should send retained messages on topics that match the subscription's filter, but only for the 80 * first matching subscription, per session. 81 */ 82 SEND_ON_SUBSCRIBE_IF_NEW(1), 83 84 /** 85 * Subscriptions must not trigger any retained message publishes from the server. 86 */ 87 DONT_SEND(2); 88 89 private int type; 90 RetainHandlingType(int code)91 private RetainHandlingType(int code) { 92 type = code; 93 } 94 95 /** 96 * @return The native enum integer value associated with this Java enum value 97 */ getValue()98 public int getValue() { 99 return type; 100 } 101 102 /** 103 * Creates a Java RetainHandlingType enum value from a native integer value. 104 * 105 * @param value native integer value for RetainHandlingType 106 * @return a new RetainHandlingType value 107 */ getEnumValueFromInteger(int value)108 public static RetainHandlingType getEnumValueFromInteger(int value) { 109 RetainHandlingType enumValue = enumMapping.get(value); 110 if (enumValue != null) { 111 return enumValue; 112 } 113 throw new RuntimeException("Illegal RetainHandlingType"); 114 } 115 buildEnumMapping()116 private static Map<Integer, RetainHandlingType> buildEnumMapping() { 117 return Stream.of(RetainHandlingType.values()) 118 .collect(Collectors.toMap(RetainHandlingType::getValue, Function.identity())); 119 } 120 121 private static Map<Integer, RetainHandlingType> enumMapping = buildEnumMapping(); 122 } 123 124 /** 125 * Configures a single subscription within a Subscribe operation 126 * 127 * See <a href="https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901169">MQTT5 Subscription Options</a> 128 */ 129 static final public class Subscription { 130 131 private String topicFilter; 132 private QOS qos; 133 private Boolean noLocal; 134 private Boolean retainAsPublished; 135 private RetainHandlingType retainHandlingType; 136 137 /** 138 * Creates a new subscription within a subscribe operation 139 * 140 * @param topicFilter The topic filter to subscribe to 141 * @param qos The maximum QoS on which the subscriber will accept publish messages 142 * @param noLocal Whether the server will not send publishes to a client when that client was the one who 143 * sent the publish 144 * @param retainAsPublished Whether messages sent due to this subscription keep the retain flag preserved 145 * on the message 146 * @param retainHandlingType Whether retained messages on matching topics be sent in reaction to this subscription 147 */ Subscription(String topicFilter, QOS qos, Boolean noLocal, Boolean retainAsPublished, RetainHandlingType retainHandlingType)148 Subscription(String topicFilter, QOS qos, Boolean noLocal, Boolean retainAsPublished, RetainHandlingType retainHandlingType) { 149 this.topicFilter = topicFilter; 150 this.qos = qos; 151 this.noLocal = noLocal; 152 this.retainAsPublished = retainAsPublished; 153 this.retainHandlingType = retainHandlingType; 154 } 155 156 /** 157 * Creates a new subscription within a subscribe operation 158 * 159 * @param topicFilter The topic filter to subscribe to 160 * @param qos The maximum QoS on which the subscriber will accept publish messages 161 */ Subscription(String topicFilter, QOS qos)162 Subscription(String topicFilter, QOS qos) { 163 this.topicFilter = topicFilter; 164 this.qos = qos; 165 // Defaults: 166 this.noLocal = false; 167 this.retainAsPublished = false; 168 this.retainHandlingType = RetainHandlingType.SEND_ON_SUBSCRIBE; 169 } 170 171 /** 172 * Returns the topic filter to subscribe to 173 * 174 * See <a href="https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901169">MQTT5 Subscription Options</a> 175 * 176 * @return The topic filter to subscribe to 177 */ getTopicFilter()178 public String getTopicFilter() { 179 return this.topicFilter; 180 } 181 182 /** 183 * Returns the maximum QoS on which the subscriber will accept publish messages. Negotiated QoS may be different. 184 * 185 * See <a href="https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901169">MQTT5 Subscription Options</a> 186 * 187 * @return The maximum QoS on which the subscriber will accept publish messages 188 */ getQOS()189 public QOS getQOS() { 190 return this.qos; 191 } 192 193 /** 194 * Returns whether the server should not send publishes to a client when that client was the one who sent the publish. If 195 * null, this is assumed to be false. 196 * 197 * See <a href="https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901169">MQTT5 Subscription Options</a> 198 * 199 * @return Whether the server will not send publishes to a client when that client was the one who sent the publish 200 */ getNoLocal()201 public Boolean getNoLocal() { 202 return this.noLocal; 203 } 204 205 /** 206 * Returns whether messages sent due to this subscription keep the retain flag preserved on the message. If null, 207 * this is assumed to be false. 208 * 209 * See <a href="https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901169">MQTT5 Subscription Options</a> 210 * 211 * @return Whether messages sent due to this subscription keep the retain flag preserved on the message 212 */ getRetainAsPublished()213 public Boolean getRetainAsPublished() { 214 return this.retainAsPublished; 215 } 216 217 /** 218 * Returns whether retained messages on matching topics be sent in reaction to this subscription. If null, 219 * this is assumed to be RetainHandlingType.SendOnSubscribe. 220 * 221 * See <a href="https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901169">MQTT5 Subscription Options</a> 222 * 223 * @return Whether retained messages on matching topics be sent in reaction to this subscription 224 */ getRetainHandlingType()225 public RetainHandlingType getRetainHandlingType() { 226 return this.retainHandlingType; 227 } 228 } 229 230 /** 231 * A class to that allows for the creation of a SubscribePacket. Set all of the settings you want in the 232 * packet and then use the build() function to get a SubscribePacket populated with the settings 233 * defined in the builder. 234 */ 235 static final public class SubscribePacketBuilder { 236 private List<Subscription> subscriptions = new ArrayList<Subscription>(); 237 Long subscriptionIdentifier; 238 private List<UserProperty> userProperties; 239 240 /** 241 * Sets a single subscription within the SubscribePacket. 242 * 243 * @param subscription The subscription to add within the SubscribePacket. 244 * @return The SubscribePacketBuilder after setting the subscription. 245 */ withSubscription(Subscription subscription)246 public SubscribePacketBuilder withSubscription(Subscription subscription) { 247 this.subscriptions.add(subscription); 248 return this; 249 } 250 251 /** 252 * Sets a single subscription within the SubscribePacket. 253 * 254 * @param topicFilter The topic filter to subscribe to 255 * @param qos The maximum QoS on which the subscriber will accept publish messages 256 * @param noLocal Whether the server will not send publishes to a client when that client was the one who 257 * sent the publish 258 * @param retainAsPublished Whether messages sent due to this subscription keep the retain flag preserved 259 * on the message 260 * @param retainHandlingType Whether retained messages on matching topics be sent in reaction to this subscription 261 * @return The SubscribePacketBuilder after setting the subscription. 262 */ withSubscription(String topicFilter, QOS qos, Boolean noLocal, Boolean retainAsPublished, RetainHandlingType retainHandlingType)263 public SubscribePacketBuilder withSubscription(String topicFilter, QOS qos, Boolean noLocal, Boolean retainAsPublished, RetainHandlingType retainHandlingType) { 264 return this.withSubscription(new Subscription(topicFilter, qos, noLocal, retainAsPublished, retainHandlingType)); 265 } 266 267 /** 268 * Sets a single subscription within the SubscribePacket. 269 * 270 * @param topicFilter The topic filter to subscribe to 271 * @param qos The maximum QoS on which the subscriber will accept publish messages 272 * @return The SubscribePacketBuilder after setting the subscription. 273 */ withSubscription(String topicFilter, QOS qos)274 public SubscribePacketBuilder withSubscription(String topicFilter, QOS qos) { 275 return this.withSubscription(new Subscription(topicFilter, qos)); 276 } 277 278 /** 279 * Sets the positive long to associate with all topic filters in this request. Publish packets that match 280 * a subscription in this request should include this identifier in the resulting message. 281 * 282 * See <a href="https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901166">MQTT5 Subscription Identifier</a> 283 * 284 * @param subscriptionIdentifier A positive long to associate with all topic filters in this request. 285 * @return The SubscribePacketBuilder after setting the subscription identifier. 286 */ withSubscriptionIdentifier(long subscriptionIdentifier)287 public SubscribePacketBuilder withSubscriptionIdentifier(long subscriptionIdentifier) { 288 this.subscriptionIdentifier = subscriptionIdentifier; 289 return this; 290 } 291 292 /** 293 * Sets the list of MQTT5 user properties included with the packet. 294 * 295 * See <a href="https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901167">MQTT5 User Property</a> 296 * 297 * @param userProperties List of MQTT5 user properties to be included with the packet. 298 * @return The SubscribePacketBuilder after setting the user properties. 299 */ withUserProperties(List<UserProperty> userProperties)300 public SubscribePacketBuilder withUserProperties(List<UserProperty> userProperties) { 301 this.userProperties = userProperties; 302 return this; 303 } 304 305 /** 306 * Creates a new SubscribePacketBuilder so a SubscribePacket can be created. 307 */ SubscribePacketBuilder()308 public SubscribePacketBuilder() {} 309 310 /** 311 * Creates a new SUBSCRIBE packet using the settings set in the builder. 312 * @return The SubscribePacket created from the builder 313 */ build()314 public SubscribePacket build() { 315 return new SubscribePacket(this); 316 } 317 } 318 319 } 320