/*
* Copyright 2014-2015 JKOOL, LLC.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jkoolcloud.tnt4j.core;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.codec.binary.Base64;
import com.jkoolcloud.tnt4j.utils.Utils;
/**
* <p>Implements a Message entity.</p>
*
* <p>A {@code Message} represents a logical entity represented by: payload, mime type, encoding (e.g. base64) and character set see{@code Charset}.
* Messages are exchanged between a set of software entities (applications). Message has tracking id, size, tag and content with a set of arguments
* and age. Content is always represented as text and binary data encoded with base64.
* </p>
*
* @see Activity
* @see Operation
* @see Trackable
*
* @version $Revision: 7 $
*/
public class Message {
public static final String ENCODING_BASE64 = "base64";
public static final String ENCODING_NONE = "none";
public static final String CHARSET_DEFAULT = Charset.defaultCharset().displayName();
public static final String MIME_TYPE_BINARY = "application/octet-stream";
public static final String MIME_TYPE_TEXT_PLAIN = "text/plain";
private String signature;
private int size;
private String strData;
private Object[] argList;
private long messageAge;
private String mimeType = MIME_TYPE_TEXT_PLAIN;
private String encoding = ENCODING_NONE;
private String charset = CHARSET_DEFAULT;
private HashSet<String> tags = new HashSet<String>(89);
/**
* Creates a message object with empty signature.
*
*/
public Message() {
}
/**
* Creates a message object with the specified properties.
*
* @param signature unique signature identifying message
* @throws NullPointerException if any arguments are <code>null</code>
* @throws IllegalArgumentException if signature is empty or too long
*/
public Message(String signature) {
setTrackingId(signature);
}
/**
* Creates a message object with the specified properties.
*
* @param signature unique signature identifying message
* @param msg actual string message associated with this instance
* @param args argument list passed along the message
* @throws NullPointerException if any arguments are <code>null</code>
* @throws IllegalArgumentException if signature is empty or too long
*/
public Message(String signature, String msg, Object...args) {
setTrackingId(signature);
setMessage(msg, args);
}
/**
* Creates a message object with the specified properties.
*
* @param signature unique signature identifying message
* @param msg actual byte message associated with this instance
* @param args argument list passed along the message
* @throws NullPointerException if any arguments are <code>null</code>
* @throws IllegalArgumentException if signature is empty or too long
*/
public Message(String signature, byte[] msg, Object...args) {
setTrackingId(signature);
setMessage(msg, args);
}
/**
* Gets message encoding
*
* @return message encoding
*/
public String getEncoding() {
return encoding;
}
/**
* Sets message encoding e.g. "base64"
*
* @param encoding message content encoding type such as "base64" see {@code Message.ENCODING_BASE64}
*/
public void setEncoding(String encoding) {
this.encoding = encoding;
}
/**
* Gets message character as defined by {@code Charset}
*
* @return message encoding
*/
public String getCharset() {
return charset;
}
/**
* Sets message character set see {@code Charset}
*
* @param charset character set of the body of the message see {@code Charset}
*/
public void setCharset(String charset) {
this.charset = charset;
}
/**
* Gets message mime type
*
* @return message encoding
*/
public String getMimeType() {
return mimeType;
}
/**
* Sets message mime type
*
* @param mimeType mime type of the message (default <code>text/plain</code>)
*
*/
public void setMimeType(String mimeType) {
this.mimeType = mimeType;
}
/**
* Gets the message signature, which is the unique identifier for the message.
*
* @return message signature
*/
public String getTrackingId() {
return signature;
}
/**
* Sets the message tracking signature, which is the unique identifier for the message.
* Could be any string that will uniquely identify this message.
*
* @param signature unique signature identifying message
*/
public void setTrackingId(String signature) {
this.signature = signature;
}
/**
* Gets the age of the message that the operation applies to.
* This value represents the time between when the message was sent/created
* and time is was consumed.
*
* @return age of message, in microseconds
*/
public long getMessageAge() {
return messageAge;
}
/**
* Sets the age of the message in microseconds. Age represents the relative
* time that the message was idle. Typically this applies to messages that
* are sent or received.
*
* @param messageAge age of message, in microseconds
* @throws IllegalArgumentException if messageAge is negative
*/
public void setMessageAge(long messageAge) {
if (messageAge < 0)
throw new IllegalArgumentException("messageAge must be non-negative");
this.messageAge = messageAge;
}
/**
* Gets message tags, which are user-defined values associated with the message.
*
* @return user-defined set of message tags
*/
public Set<String> getTag() {
return tags;
}
/**
* Sets message tags, which are user-defined values associated with the message
*
* @param tlist user-defined list of message tags
*/
public void setTag(String...tlist) {
for (int i=0; (tlist != null) && (i < tlist.length); i++) {
if (tlist[i] != null) {
this.tags.add(tlist[i]);
}
}
}
/**
* Sets message tags, which are user-defined values associated with the message.
*
* @param tlist user-defined list of message tags
*/
public void setTag(Collection<String> tlist) {
if (tlist != null)
this.tags.addAll(tlist);
}
/**
* Remove all tags from this message
*
*/
public void clearTags() {
this.tags.clear();
}
/**
* Get the size of the message.
*
* @return message size, in bytes
*/
public int getSize() {
return size;
}
/**
* Set the size of the message.
*
* @param size message size, in bytes
* @throws IllegalArgumentException if size is negative
*/
public void setSize(int size) {
if (size < 0)
throw new IllegalArgumentException("size must be non-negative");
this.size = size;
}
/**
* Gets the current formatted message with formatted arguments
*
* @return string message data, or <code>null</code> if there is no data
*/
public String getMessage() {
return Utils.format(strData, argList);
}
/**
* Gets the current non formatted message
*
* @return string non formatted message, or <code>null</code> if there is no data
*/
public String getMessagePattern() {
return strData;
}
/**
* Gets the current message argument list
*
* @return message argument list
*/
public Object[] getMessageArgs() {
return argList;
}
/**
* Sets the data for the message. This is usually the message body.
*
* @param pattern message pattern
* @param args list of arguments
*/
public void setMessage(String pattern, Object...args) {
strData = pattern;
if (strData != null) {
setSize(strData.length());
} else setSize(0);
argList = args;
}
/**
* Sets binary data for the message. Binary message will be base64 encoded
* and message encoding set to "base64".
*
* @param bytes binary message content
* @param args list of arguments associated with this message
*/
public void setMessage(byte[] bytes, Object...args) {
strData = new String(Base64.encodeBase64(bytes));
setEncoding(ENCODING_BASE64);
setMimeType(MIME_TYPE_BINARY);
if (strData != null) {
setSize(strData.length());
} else setSize(0);
argList = args;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return 31 + ((signature == null) ? 0 : signature.hashCode());
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Message))
return false;
final Message other = (Message) obj;
if (signature == null) {
if (other.signature != null)
return false;
}
else if (!signature.equals(other.signature)) {
return false;
}
return true;
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
StringBuilder str = new StringBuilder();
str.append(getClass().getSimpleName()).append("(")
.append("TrackId:").append(getTrackingId()).append(",")
.append("Tag:").append(getTag()).append(",")
.append("Encoding:").append(getEncoding()).append(",")
.append("MimeType:").append(getMimeType()).append(",")
.append("Size:").append(getSize()).append(")");
return str.toString();
}
}