package org.smartly.commons.network.socket.messages;
import org.smartly.commons.lang.CharEncoding;
import org.smartly.commons.logging.Level;
import org.smartly.commons.logging.Logger;
import org.smartly.commons.logging.util.LoggingUtils;
import org.smartly.commons.util.ByteUtils;
import org.smartly.commons.util.DateUtils;
import org.smartly.commons.util.StringUtils;
import org.smartly.commons.util.ZipUtils;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.Date;
/**
*
*/
public abstract class AbstractMessage
implements Serializable {
// ------------------------------------------------------------------------
// f i e l d s
// ------------------------------------------------------------------------
private long _creationDate = System.currentTimeMillis();
private String _userToken = "";
private String _charset = CharEncoding.getDefault();
private long _compressionThreshold = 0; // -1 does not use Compression, 0 always, >0 threshold
private byte[] _data = new byte[0];
// ------------------------------------------------------------------------
// o v e r r i d e s
// ------------------------------------------------------------------------
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append(this.getClass().getSimpleName()).append("{");
sb.append("CreationDate: ").append(new Date(this.getCreationDate()));
sb.append(", ");
sb.append("Elapsed: ").append(this.getElapsedTime());
sb.append(", ");
sb.append("UserToken: ").append(this.getUserToken());
sb.append("}");
return sb.toString();
}
// ------------------------------------------------------------------------
// p r o p e r t i e s
// ------------------------------------------------------------------------
/**
* Compression Threshold Supported Values
* <ul>
* <li>-1=no compression</li>
* <li>0=always</li>
* <li>bigger than zero=use this value to check when compress data.</li>
* </ul>
*
* @return Compression Threshold
*/
public long getCompressionThreshold() {
return _compressionThreshold;
}
/**
* Compression Threshold Supported Values
* <ul>
* <li>-1=no compression</li>
* <li>0=always</li>
* <li>bigger than zero=use this value to check when compress data.</li>
* </ul>
*
* @param value Threshold to use as compress limit.
* @return Instance of current Object
*/
public AbstractMessage setCompressionThreshold(final long value) {
_compressionThreshold = value;
return this;
}
public boolean isCompressed() {
return _compressionThreshold > -1;
}
public AbstractMessage setCharset(final String charsetName) {
return this.setCharset(Charset.forName(charsetName));
}
public AbstractMessage setCharset(final Charset charset) {
_charset = charset.name();
return this;
}
public String getCharset() {
return _charset;
}
public long getCreationDate() {
return _creationDate;
}
public double getElapsedTime() {
return DateUtils.dateDiff(new Date(System.currentTimeMillis()), new Date(_creationDate), DateUtils.MILLISECOND);
}
public String getUserToken() {
return _userToken;
}
public AbstractMessage setUserToken(final String value) {
_userToken = value;
return this;
}
public AbstractMessage clearData() {
_data = null;
this.setData(new byte[0]);
return this;
}
public AbstractMessage setData(final byte[] value) {
this.setRawData(value);
return this;
}
public AbstractMessage setData(final String value) {
this.setData(value, _charset);
return this;
}
public AbstractMessage setData(final String value,
final String charset) {
try {
this.setData(StringUtils.hasText(value) ? value.getBytes(charset) : new byte[0]);
} catch (Throwable t) {
this.getLogger().log(Level.SEVERE, null, t);
try {
this.setData(value.getBytes());
} catch (Throwable tt) {
this.getLogger().log(Level.SEVERE, null, tt);
this.setData(new byte[0]);
}
}
return this;
}
public AbstractMessage setData(final Serializable value) {
this.setData(ByteUtils.optBytes(value));
return this;
}
public boolean hasData() {
return this.getRawDataLength() > 0;
}
public int getDataLength() {
return this.getRawDataLength();
}
public byte[] getDataBytes() {
return this.getRawData();
}
public Serializable getData() {
return (Serializable) ByteUtils.optObject(this.getRawData());
}
public String getDataString() {
try {
return new String(this.getRawData(), _charset);
} catch (Throwable t) {
this.getLogger().log(Level.SEVERE, null, t);
return "";
}
}
// ------------------------------------------------------------------------
// p r i v a t e
// ------------------------------------------------------------------------
private Logger getLogger() {
return LoggingUtils.getLogger(this);
}
private void setRawData(final byte[] data) {
_data = isCompressed() ? zip(data) : data;
}
private byte[] getRawData() {
return isCompressed() ? unzip(_data) : _data;
}
private int getRawDataLength() {
return null != _data ? _data.length : 0;
}
private byte[] zip(final byte[] data) {
if (null != data && data.length > 0) {
try {
return ZipUtils.gzip(data);
} catch (Throwable t) {
_compressionThreshold = -1; // disable compression
this.getLogger().warning("Compression disabled: " + t.toString());
return data;
}
}
return new byte[0];
}
private byte[] unzip(final byte[] data) {
if (null != data && data.length > 0) {
try {
return ZipUtils.gunzip(data);
} catch (Throwable t) {
_compressionThreshold = -1; // disable compression
this.getLogger().warning("Compression disabled: " + t.toString());
return data;
}
}
return new byte[0];
}
}