com.aoindustries.messaging.MultiMessage Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ao-messaging-api Show documentation
Show all versions of ao-messaging-api Show documentation
Asynchronous bidirectional messaging over various protocols API.
/*
* ao-messaging-api - Asynchronous bidirectional messaging over various protocols API.
* Copyright (C) 2014, 2015, 2016 AO Industries, Inc.
* [email protected]
* 7262 Bull Pen Cir
* Mobile, AL 36695
*
* This file is part of ao-messaging-api.
*
* ao-messaging-api is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ao-messaging-api is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with ao-messaging-api. If not, see .
*/
package com.aoindustries.messaging;
import com.aoindustries.io.AoByteArrayInputStream;
import com.aoindustries.io.AoByteArrayOutputStream;
import com.aoindustries.util.AoCollections;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.List;
/**
* A message that is a combination of multiple messages.
*/
public class MultiMessage implements Message {
private static final char DELIMITER = ',';
public static final MultiMessage EMPTY_MULTI_MESSAGE;
static {
Collection extends Message> empty = Collections.emptyList();
EMPTY_MULTI_MESSAGE = new MultiMessage(empty);
}
/**
* Decodes the messages.
*/
public static MultiMessage decode(String encodedMessages) throws IOException {
if(encodedMessages.isEmpty()) return EMPTY_MULTI_MESSAGE;
int pos = encodedMessages.indexOf(DELIMITER);
if(pos == -1) throw new IllegalArgumentException("Delimiter not found");
final int size = Integer.parseInt(encodedMessages.substring(0, pos++));
List decodedMessages = new ArrayList(size);
for(int i=0; i decodedMessages = new ArrayList(size);
for(int i=0; i messages;
public MultiMessage(Collection extends Message> messages) {
this.messages = messages;
}
@Override
public String toString() {
return "MultiMessage(" + messages.size() + ")";
}
@Override
public boolean equals(Object o) {
if(this == o) return true;
if(!(o instanceof MultiMessage)) return false;
MultiMessage other = (MultiMessage)o;
return AoCollections.equals(messages, other.messages);
}
@Override
public int hashCode() {
return AoCollections.hashCode(messages);
}
@Override
public MessageType getMessageType() {
return MessageType.MULTI;
}
/**
* Encodes the messages into a single string.
*/
@Override
public String encodeAsString() throws IOException {
final int size = messages.size();
if(size == 0) return "";
StringBuilder sb = new StringBuilder();
sb.append(size).append(DELIMITER);
int count = 0;
for(Message message : messages) {
count++;
String str = message.encodeAsString();
sb
.append(message.getMessageType().getTypeChar())
.append(str.length())
.append(DELIMITER)
.append(str)
;
}
if(count != size) throw new ConcurrentModificationException();
return sb.toString();
}
/**
* Encodes the messages into a single ByteArray.
* There is likely a more efficient implementation that reads-through, but this
* is a simple implementation.
*/
@Override
public ByteArray encodeAsByteArray() throws IOException {
final int size = messages.size();
if(size == 0) return ByteArray.EMPTY_BYTE_ARRAY;
AoByteArrayOutputStream bout = new AoByteArrayOutputStream();
try {
DataOutputStream out = new DataOutputStream(bout);
try {
out.writeInt(size);
int count = 0;
for(Message message : messages) {
count++;
ByteArray byteArray = message.encodeAsByteArray();
final int capacity = byteArray.size;
out.writeByte(message.getMessageType().getTypeByte());
out.writeInt(capacity);
out.write(byteArray.array, 0, capacity);
}
if(count != size) throw new ConcurrentModificationException();
} finally {
out.close();
}
} finally {
bout.close();
}
return new ByteArray(bout.getInternalByteArray(), bout.size());
}
/**
* Closes each of the underlying messages.
*/
@Override
public void close() throws IOException {
for(Message message : messages) {
message.close();
}
}
public Collection extends Message> getMessages() {
return messages;
}
}