001 /**
002 * Copyright 2007 Mike Kroutikov.
003 *
004 * This program is free software; you can redistribute it and/or modify
005 * it under the terms of the Lesser GNU General Public License as
006 * published by the Free Software Foundation; either version 3 of
007 * the License, or (at your option) any later version.
008 *
009 * This program is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012 * Lesser GNU General Public License for more details.
013 *
014 * You should have received a copy of the Lesser GNU General Public License
015 * along with this program. If not, see <http://www.gnu.org/licenses/>.
016 */
017
018 package org.otfeed.protocol.request;
019
020 import org.otfeed.event.ICompletionDelegate;
021 import org.otfeed.protocol.MessageEnum;
022 import org.otfeed.protocol.CommandEnum;
023 import org.otfeed.protocol.StatusEnum;
024 import org.otfeed.protocol.ProtocolException;
025
026 import java.nio.ByteBuffer;
027
028 /**
029 * Common base for all OpenTick requests.
030 */
031 public abstract class AbstractRequest extends RequestJob {
032
033 /**
034 * Request status. Returned by <code>handleMessage</code> to
035 * indicate whether more messages are expected.
036 */
037 public enum JobStatus {
038 /**
039 * Request active, more messages may follow.
040 */
041 ACTIVE,
042
043 /**
044 * Request finished. No more messages expected.
045 */
046 FINISHED
047 }
048
049 private final CommandEnum command;
050 private final int requestId;
051
052 /**
053 * Returns command type of this request.
054 */
055 public final CommandEnum getCommand() { return command; }
056
057 /**
058 * Returns request id number.
059 */
060 public final int getRequestId() { return requestId; }
061
062 /**
063 * Creates request.
064 *
065 * @param command command type.
066 * @param requestId request id number.
067 */
068 AbstractRequest(CommandEnum command,
069 int requestId,
070 ICompletionDelegate completionDelegate) {
071 super(completionDelegate);
072
073 Check.notNull(command, "command");
074
075 this.command = command;
076 this.requestId = requestId;
077 }
078
079 /**
080 * Abstract method that writes out request body.
081 *
082 * This implementation only writes the request header.
083 * It is meant to be overwritten by concrete request implementation.
084 * Concrete implementation must call <code>super.writeRequest</code>
085 * at the top of its method body.
086 *
087 * @param out output buffer.
088 */
089 public void writeRequest(ByteBuffer out) {
090 Header header = new Header(
091 MessageEnum.REQUEST,
092 StatusEnum.OK,
093 command,
094 requestId);
095
096 header.writeOut(out);
097 }
098
099 /**
100 * Abstract method to handle response message.
101 *
102 * This implementation only validates request and command.
103 * Must be overwritten by concrete implementation.
104 * Some concrete implementations may call this one at the beginning to
105 * check the sanity of the response.
106 *
107 * @param header parsed response header.
108 * @param in input buffer with the rest of the
109 * data (after header has been parsed).
110 */
111 public JobStatus handleMessage(Header header, ByteBuffer in) {
112
113 if(header.getCommand() != command) {
114 throw new ProtocolException("mismatch in command type: "
115 + header.getCommand() + ", expected: " + command,
116 in);
117 }
118
119 if(header.getRequestId() != requestId) {
120 throw new ProtocolException("mismatch in requestId: "
121 + header.getRequestId() + ", expected: " + requestId,
122 in);
123 }
124
125 return JobStatus.FINISHED;
126 }
127
128 @Override
129 public String toString() {
130 return "Request: requestId=" + requestId + ", command=" + command;
131 }
132 }