/* Copyright (c) 2011 Danish Maritime Authority.
*
* 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 net.maritimecloud.internal.mms.messages.spi;
import static java.util.Objects.requireNonNull;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import net.maritimecloud.internal.mms.messages.Close;
import net.maritimecloud.internal.mms.messages.Connected;
import net.maritimecloud.internal.mms.messages.Hello;
import net.maritimecloud.internal.mms.messages.PositionReport;
import net.maritimecloud.internal.mms.messages.Welcome;
import net.maritimecloud.internal.net.messages.Broadcast;
import net.maritimecloud.internal.net.messages.BroadcastAck;
import net.maritimecloud.internal.net.messages.MethodInvoke;
import net.maritimecloud.internal.net.messages.MethodInvokeResult;
import net.maritimecloud.message.Message;
import net.maritimecloud.message.MessageSerializer;
/**
* The type of messages that can be sent around in the system.
*
* @author Kasper Nielsen
*/
enum MmsMessageType {
/* ***************** Auxiliary messages ******** */
// 0 - 7 : lifecycle, connect/reconnect/disconnect.. keep/alive
/** This is the first message sent by the server to client. Whenever a Websocket connection has been created. */
WELCOME(1, Welcome.class, Welcome.SERIALIZER), // 1. message from server 2 client
/** This is the first message from the client to server. Contains an optional reconnect token. */
HELLO(2, Hello.class, Hello.SERIALIZER), // 1. message from client 2 server
/** The final handshake massage from the server, contains the connection id */
CONNECTED(3, Connected.class, Connected.SERIALIZER), // 2. message from server 2 client
/** The final handshake massage from the server, contains the connection id */
CLOSE(4, Close.class, Close.SERIALIZER), // 2. message from server 2 client
/** A keep alive message sent periodically. Contains current position/time. */
POSITION_REPORT(8, PositionReport.class, PositionReport.SERIALIZER),
// Channel Switched + men er jo naesten det samme som reconnect
// nej lige saa snart man er connected, starter man med at sende beskeder der
// Client maa saa vente til den har receivet faerdigt paa den anden hvorefter den
// lukker den gamle kanal
// Man kunne ogsaa receive beskeder over begge kanaller.
// Hvis de har et fortloebende id kan man jo bare smide dublikater vaek
/* ******************** Communication client<->server ******************* */
/** Invokes a remote service. */
METHOD_INVOKE(10, MethodInvoke.class, MethodInvoke.SERIALIZER), //
/** The result of invoking a remote service. */
METHOD_INVOKE_RESULT(11, MethodInvokeResult.class, MethodInvokeResult.SERIALIZER), //
/** Broadcasts a message. */
BROADCAST(12, Broadcast.class, Broadcast.SERIALIZER), // client->server
/** Acknowledgment of a received broadcast by a remote client. */
BROADCAST_ACK(13, BroadcastAck.class, BroadcastAck.SERIALIZER),
/** The standard error message sent for an invalid request from the client */
// REQUEST_ERROR(15, ServerRequestError.class), // <- requestId, int error_code, String message
;
final Class<? extends Message> cl;
final int type;
final MessageSerializer<? extends Message> p;
MmsMessageType(int type, Class<? extends Message> cl, MessageSerializer<? extends Message> p) {
if (type < 1 || type > 15) {
throw new IllegalArgumentException("type must be 1>= type <=15");
}
this.type = type;
this.cl = requireNonNull(cl);
this.p = p;
}
public static MessageSerializer<? extends Message> getParser(int type) {
return HelperHolder.TYPES[type].p;
}
public static MmsMessageType getTypeOf(Class<? extends Message> c) {
requireNonNull(c);
return HelperHolder.MAP.get(c);
}
public boolean isConnectionMessage() {
return type > 7;
}
/** A little initialization-on-demand holder idiom helper class */
private static class HelperHolder {
static MmsMessageType[] TYPES;
static final Map<Class<? extends Message>, MmsMessageType> MAP = new HashMap<>();
static {
TreeMap<Integer, MmsMessageType> m = new TreeMap<>();
for (MmsMessageType mt : MmsMessageType.values()) {
m.put(mt.type, mt);
MAP.put(mt.cl, mt);
}
TYPES = new MmsMessageType[m.lastKey() + 1];
for (Entry<Integer, MmsMessageType> e : m.entrySet()) {
TYPES[e.getKey()] = e.getValue();
}
}
}
}