/* * Copyright 2014 Alexey Plotnik * * 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 org.stem.transport; import io.netty.buffer.ByteBuf; import org.stem.transport.ops.*; abstract public class Message { public final Type type; private Connection connection; private volatile int streamId; public enum Direction { REQUEST, RESPONSE } public enum Type { RESULT(0, Direction.RESPONSE, ResultMessage.codec), ERROR(1, Direction.RESPONSE, ErrorMessage.codec), READ_BLOB(2, Direction.REQUEST, ReadBlobMessage.codec), WRITE_BLOB(3, Direction.REQUEST, WriteBlobMessage.codec), DELETE_BLOB(4, Direction.REQUEST, DeleteBlobMessage.codec); public final int opcode; public final Direction direction; public final Codec<?> codec; Type(int opcode, Direction direction, Codec codec) { this.opcode = opcode; this.direction = direction; this.codec = codec; } private static Type[] opcodes; static { int maxOpcode = -1; for (Type type : Type.values()) maxOpcode = Math.max(type.opcode, maxOpcode); opcodes = new Type[maxOpcode + 1]; for (Type type : Type.values()) { opcodes[type.opcode] = type; } } public static Type fromOpcode(int opcode) { return opcodes[opcode]; } } public interface Codec<O extends Message> { ByteBuf encode(O op); O decode(ByteBuf buf); } public static abstract class Request extends Message { protected Request(Type type) { super(type); assert type.direction == Direction.REQUEST; } abstract public Response execute(); } public static abstract class Response extends Message { protected Response(Type type) { super(type); assert type.direction == Direction.RESPONSE; } public boolean isFailed() { return this instanceof ErrorMessage; } public boolean isSuccess() { return !isFailed(); } } protected Message(Type type) { this.type = type; } public void attach(Connection connection) { this.connection = connection; } public Connection connection() { return connection; } public Message setStreamId(int streamId) { this.streamId = streamId; return this; } public int getStreamId() { return streamId; } abstract public ByteBuf encode(); }