class Message {

	public byte[] getBytes() {
		try (ByteArrayOutputStream headerBaos = new ByteArrayOutputStream();
			 ByteArrayOutputStream dataBaos = new ByteArrayOutputStream()){
			//version
			headerBaos.write(BytesUtil.shortToBytes(VERSION));

			// id
			int len = getLength(getId());
			headerBaos.write((byte) (len & 0xff));
			if (len > 0)
				dataBaos.write(BytesUtil.stringToBytes(getId()));

			// tag
			len = getLength(getTag());
			headerBaos.write(BytesUtil.shortToBytes((short) (len & 0xffff)));
			if (len > 0)
				dataBaos.write(BytesUtil.stringToBytes(getTag()));

			//groupid
			len = getLength(getMessageGroupId());
			headerBaos.write((byte) (len & 0xff));
			if (len > 0)
				dataBaos.write(BytesUtil.stringToBytes(getMessageGroupId()));

			// seq no
			if (getSequenceNumber() == 0)
				headerBaos.write(0);
			else {
				dataBaos.write(BytesUtil.integerToBytes(getSequenceNumber()));
				headerBaos.write(4);
			}

			// seq total
			if (getSequenceTotal() == 0)
				headerBaos.write(0);
			else {
				dataBaos.write(BytesUtil.integerToBytes(getSequenceTotal()));
				headerBaos.write(4);
			}


			// priority
			if (getPriority() == 0)
				headerBaos.write(0);
			else {
				headerBaos.write(1);
				dataBaos.write(getPriority());
			}

			//timestamp
			if (getTimestamp() == 0)
				headerBaos.write(0);
			else {
				headerBaos.write(8);
				dataBaos.write(BytesUtil.longToBytes(getTimestamp()));
			}

			// publisher
			len = getLength(getPublisher());
			headerBaos.write((byte) (len & 0xff));
			if (len > 0)
				dataBaos.write(BytesUtil.stringToBytes(getPublisher()));

			// authIdentifier
			len = getLength(getAuthIdentifier());
			headerBaos.write(BytesUtil.shortToBytes((short) (len & 0xffff)));
			if (len > 0)
				dataBaos.write(BytesUtil.stringToBytes(getAuthIdentifier()));

			// authGroup
			len = getLength(getAuthGroup());
			headerBaos.write(BytesUtil.shortToBytes((short) (len & 0xffff)));
			if (len > 0)
				dataBaos.write(BytesUtil.stringToBytes(getAuthGroup()));

			// chainPosition
			if (getChainPosition() == 0)
				headerBaos.write(0);
			else {
				headerBaos.write(8);
				dataBaos.write(BytesUtil.longToBytes(getChainPosition()));
			}

			// hash
			len = getLength(getHash());
			headerBaos.write(BytesUtil.shortToBytes((short) (len & 0xffff)));
			if (len > 0)
				dataBaos.write(BytesUtil.stringToBytes(getHash()));

			// previousHash
			len = getLength(getPreviousHash());
			headerBaos.write(BytesUtil.shortToBytes((short) (len & 0xffff)));
			if (len > 0)
				dataBaos.write(BytesUtil.stringToBytes(getPreviousHash()));

			// nonce
			len = getLength(getNonce());
			headerBaos.write(BytesUtil.shortToBytes((short) (len & 0xffff)));
			if (len > 0) 
				dataBaos.write(BytesUtil.stringToBytes(getNonce()));

			// difficultyTarget
			if (getDifficultyTarget() == 0)
				headerBaos.write(0);
			else {
				headerBaos.write(4);
				dataBaos.write(BytesUtil.integerToBytes(getDifficultyTarget()));
			}

			// infoType
			len = getLength(getInfoType());
			headerBaos.write((byte) (len & 0xff));
			if (len > 0)
				dataBaos.write(BytesUtil.stringToBytes(getInfoType()));

			// infoFormat
			len = getLength(getInfoFormat());
			headerBaos.write((byte) (len & 0xff));
			if (len > 0)
				dataBaos.write(BytesUtil.stringToBytes(getInfoFormat()));

			// contextData
			if (getContextData() == null)
				headerBaos.write(BytesUtil.integerToBytes(0));
			else {
				headerBaos.write(BytesUtil.integerToBytes(getContextData().length));
				dataBaos.write(getContextData());
			}

			// contentData
			if (getContentData() == null)
				headerBaos.write(BytesUtil.integerToBytes(0));
			else {
				headerBaos.write(BytesUtil.integerToBytes(getContentData().length));
				dataBaos.write(getContentData());
			}

			ByteArrayOutputStream result = new ByteArrayOutputStream();
			headerBaos.writeTo(result);
			dataBaos.writeTo(result);
			return result.toByteArray();
		} catch (IOException exc) {
			logError(MODULE_NAME, "Error in getBytes", new AgentSystemException(exc.getMessage(), exc));
		}

		return new byte[] {};
	}

	public  Message();
	public  Message(String publisher);
	public  Message(JsonObject json);
	public  Message(byte[] rawBytes);
	public  Message(byte[] header, byte[] data);

}