io.scalecube.cluster.transport.api.Message Maven / Gradle / Ivy
The newest version!
package io.scalecube.cluster.transport.api;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.StringJoiner;
/**
* The Class Message introduces generic protocol used for point to point communication by transport.
*/
public final class Message implements Externalizable {
private static final long serialVersionUID = 1L;
/**
* This header is supposed to be used by application in case if same data type can be reused for
* several messages so it will allow to qualify the specific message type.
*/
public static final String HEADER_QUALIFIER = "q";
/**
* This header is supposed to be used by application in order to correlate request and response
* messages.
*/
public static final String HEADER_CORRELATION_ID = "cid";
/**
* This header represents sender address. It is an address of message originator. This header is
* optional.
*/
public static final String HEADER_SENDER = "sender";
private Map headers = Collections.emptyMap();
private Object data;
public Message() {}
private Message(Builder builder) {
this.data = builder.data;
this.headers = Collections.unmodifiableMap(Objects.requireNonNull(builder.headers));
}
/**
* Instantiates a new message with the given data and without headers.
*
* @param data the data to build a message from
* @return the built message
*/
public static Message fromData(Object data) {
return withData(data).build();
}
/**
* Instantiates a new message builder with the given data and without headers.
*
* @param data the initial data for the builder
* @return a builder with initial data
*/
public static Builder withData(Object data) {
return builder().data(data);
}
/**
* Instantiates a new message with the given headers and with empty data.
*
* @param headers an initial headers to build a message from
* @return the built message
*/
public static Message fromHeaders(Map headers) {
return withHeaders(headers).build();
}
/**
* Instantiates a new message builder with the given headers and with empty data.
*
* @param headers the initial headers for the builder
* @return a builder with initial headers
*/
public static Builder withHeaders(Map headers) {
return builder().headers(headers);
}
/**
* Instantiates a new message with the given qualifier header and with empty data.
*
* @param qualifier the qualifier to build a message from
* @return the built message
*/
public static Message fromQualifier(String qualifier) {
return withQualifier(qualifier).build();
}
/**
* Instantiates a new message builder with the given qualifier header and with empty data.
*
* @param qualifier the initial qualifier for the builder
* @return a builder with initial qualifier
*/
public static Builder withQualifier(String qualifier) {
return builder().qualifier(qualifier);
}
/**
* Instantiates new message with the same data and headers as at given message.
*
* @param message the message to be copied
* @return a new message, with the same data and headers
*/
public static Message from(Message message) {
return with(message).build();
}
/**
* Instantiates new message builder with the same data and headers as at given message.
*
* @param message the message to instantiate the new builder from
* @return a builder with initial data and headers from the message
*/
public static Builder with(Message message) {
return withData(message.data).headers(message.headers);
}
/**
* Instantiates new empty message builder.
*
* @return new builder
*/
public static Builder builder() {
return new Builder();
}
/**
* Returns the message headers.
*
* @return message headers
*/
public Map headers() {
return headers;
}
/**
* Returns header value by given header name.
*
* @param name header name
* @return the message header by given header name
*/
public String header(String name) {
return headers.get(name);
}
/**
* Returns message qualifier.
*
* @return qualifier string
*/
public String qualifier() {
return header(HEADER_QUALIFIER);
}
/**
* Returns message correlation id.
*
* @return correlation id
*/
public String correlationId() {
return header(HEADER_CORRELATION_ID);
}
/**
* Return the message data, which can be byte array, string or any type.
*
* @param data type
* @return payload of the message or null if message is without any payload
*/
public T data() {
// noinspection unchecked
return (T) data;
}
/**
* Returns address of the sender of this message.
*
* @return address, or null
*/
public String sender() {
return Optional.ofNullable(header(HEADER_SENDER)).orElse(null);
}
@Override
public String toString() {
return new StringJoiner(", ", Message.class.getSimpleName() + "[", "]")
.add("headers=" + headers)
.add("data=" + data)
.toString();
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
// headers
out.writeInt(headers.size());
for (Entry header : headers.entrySet()) {
out.writeUTF(header.getKey());
out.writeObject(header.getValue()); // value is nullable
}
// data
out.writeObject(data);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
// headers
int headersSize = in.readInt();
Map headers = new HashMap<>(headersSize);
for (int i = 0; i < headersSize; i++) {
String name = in.readUTF();
String value = (String) in.readObject(); // value is nullable
headers.put(name, value);
}
this.headers = Collections.unmodifiableMap(headers);
// data
data = in.readObject();
}
public static class Builder {
private final Map headers = new HashMap<>();
private Object data;
private Builder() {}
private Object data() {
return this.data;
}
public Builder data(Object data) {
this.data = data;
return this;
}
private Map headers() {
return this.headers;
}
/**
* Bulk setter for headers. Delegates to {@link #header(String, String)}.
*
* @param headers headers
* @return builder
*/
public Builder headers(Map headers) {
headers.forEach(this::header);
return this;
}
/**
* Setter for header.
*
* @param key key (required)
* @param value value (optional)
* @return builder
*/
public Builder header(String key, String value) {
Objects.requireNonNull(key);
headers.put(key, value);
return this;
}
public Builder qualifier(String qualifier) {
return header(HEADER_QUALIFIER, qualifier);
}
public Builder correlationId(String correlationId) {
return header(HEADER_CORRELATION_ID, correlationId);
}
public Builder sender(String sender) {
return header(HEADER_SENDER, sender);
}
public Message build() {
return new Message(this);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy