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    }