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.event.IDataDelegate;
022    import org.otfeed.event.OTTodaysOHL;
023    import org.otfeed.protocol.CommandEnum;
024    import org.otfeed.protocol.DataEnum;
025    import org.otfeed.protocol.ProtocolException;
026    
027    import java.nio.ByteBuffer;
028    
029    /**
030     * Request to receive current OHL (open-high-low) data.
031     */
032    public class TodaysOHLRequest extends AbstractSessionRequest {
033    
034            private final String exchangeCode;
035            private final String symbolCode;
036    
037            private final IDataDelegate<OTTodaysOHL> dataDelegate;
038    
039            public String getExchangeCode()  { return exchangeCode; }
040            public String getSymbolCode()    { return symbolCode; }
041    
042            public TodaysOHLRequest(int requestId, 
043                            String exchangeCode,
044                            String symbolCode,
045                            IDataDelegate<OTTodaysOHL> dataDelegate,
046                            ICompletionDelegate completionDelegate) {
047    
048                    super(CommandEnum.REQUEST_HIST_DATA, 
049                                    requestId, completionDelegate);
050    
051                    Check.notNull(exchangeCode,  "exchangeCode");
052                    Check.notNull(symbolCode,  "symbolCode");
053                    Check.notNull(dataDelegate,  "dataDelegate");
054    
055                    this.exchangeCode  = exchangeCode;
056                    this.symbolCode    = symbolCode;
057                    this.dataDelegate  = dataDelegate;
058            }
059    
060            @Override
061            public void writeRequest(ByteBuffer out) {
062                    super.writeRequest(out);
063    
064                    Util.writeString(out, exchangeCode, 15);
065                    Util.writeString(out, symbolCode, 15);
066                    out.put((byte) 0);
067                    out.put((byte) 0);
068                    out.putInt(0);
069                    out.putInt(0);
070                    out.put((byte) 9); // special code, meaning "get ohlc"
071                    out.put((byte) 0);
072                    out.putShort((short) 0);
073            }
074    
075            private static OTTodaysOHL readTodaysOHL(ByteBuffer in) {
076                    double ohl_openPrice = in.getDouble();
077                    double ohl_highPrice = in.getDouble();
078                    double ohl_lowPrice  = in.getDouble();
079    
080                    return new OTTodaysOHL(ohl_openPrice,
081                            ohl_highPrice, ohl_lowPrice);
082            }
083    
084            @Override
085            public JobStatus handleMessage(Header header, ByteBuffer in) {
086                    super.handleMessage(header, in);
087    
088                    int count = in.getInt();
089    
090                    // to the best of my knowledge, TodaysOHL request returns only
091                    // one event. Therefore, we have to return end-of data
092                    // right away... Note that this is exactly what CPP driver from Opentick
093                    // Corp. does (but not .NET one).
094                    if(count < 0 || count > 1) {
095                            throw new ProtocolException("unexpected number of todaysOHL events", in);
096                    }
097    
098                    while(count -- > 0) {
099                            int typeCode = in.get();
100    
101                            if(typeCode == DataEnum.EOD.code) {
102                                    return JobStatus.FINISHED;
103                            }
104                            
105                            if(typeCode != DataEnum.OHL_TODAY.code) {
106                                    throw new ProtocolException("unexpected OHL data code: " + typeCode, in);
107                            }
108    
109                            OTTodaysOHL ohl = readTodaysOHL(in);
110                            dataDelegate.onData(ohl);
111                    }
112    
113                    return JobStatus.FINISHED; // ???
114            }
115    }