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.command.AggregationSpan;
021    import org.otfeed.event.ICompletionDelegate;
022    import org.otfeed.event.IDataDelegate;
023    import org.otfeed.event.OTOHLC;
024    import org.otfeed.protocol.CommandEnum;
025    import org.otfeed.protocol.DataEnum;
026    import org.otfeed.protocol.ProtocolException;
027    
028    import java.nio.ByteBuffer;
029    import java.util.Date;
030    
031    /**
032     * Request to receive aggregated historical data.
033     */
034    public final class HistDataRequest extends AbstractSessionRequest {
035    
036            private final String           exchangeCode;
037            private final String           symbolCode;
038            private final Date             startDate;
039            private final Date             endDate;
040            private final AggregationSpan  aggregationSpan;
041    
042            private final IDataDelegate<OTOHLC> dataDelegate;
043    
044            public String            getExchangeCode()  { return exchangeCode; }
045            public String            getSymbolCode()    { return symbolCode; }
046            public Date              getStartDate()     { return startDate; }
047            public Date              getEndDate()       { return endDate; }
048            public AggregationSpan   getAggregationSpan() { return aggregationSpan; }
049    
050            public HistDataRequest(int requestId, 
051                            String exchangeCode,
052                            String symbolCode,
053                            Date startDate,
054                            Date endDate,
055                            AggregationSpan aggregationSpan,
056                            final IDataDelegate<OTOHLC> dataDelegate,
057                            ICompletionDelegate completionDelegate) {
058    
059                    super(CommandEnum.REQUEST_HIST_DATA, 
060                                    requestId, completionDelegate);
061    
062                    Check.notNull(exchangeCode,  "exchangeCode");
063                    Check.notNull(symbolCode,  "symbolCode");
064                    Check.notNull(startDate, "startDate");
065                    Check.notNull(endDate, "endDate");
066                    Check.notNull(aggregationSpan, "aggreagationSpan");
067    
068                    Check.notNull(dataDelegate,  "dataDelegate");
069    
070                    this.exchangeCode    = exchangeCode;
071                    this.symbolCode      = symbolCode;
072                    this.startDate       = startDate;
073                    this.endDate         = endDate;
074                    this.aggregationSpan = aggregationSpan;
075                    this.dataDelegate    = dataDelegate;
076    
077            }
078    
079            @Override
080            public void writeRequest(ByteBuffer out) {
081                    super.writeRequest(out);
082    
083                    Util.writeString(out, exchangeCode, 15);
084                    Util.writeString(out, symbolCode, 15);
085                    out.put((byte) 0);
086                    out.put((byte) 0);
087                    Util.writeDate(out, startDate);
088                    Util.writeDate(out, endDate);
089                    Util.writeAggreagationSpan(out, aggregationSpan);
090            }
091    
092            private final static OTOHLC readOHLC(ByteBuffer in) {
093                    Date ohlc_timestamp    = Util.readDate(in);
094                    double ohlc_openPrice  = in.getDouble();
095                    double ohlc_highPrice  = in.getDouble();
096                    double ohlc_lowPrice   = in.getDouble();
097                    double ohlc_closePrice = in.getDouble();
098                    long ohlc_volume       = in.getLong();
099    
100                    return new OTOHLC(ohlc_timestamp,
101                            ohlc_openPrice, ohlc_highPrice, ohlc_lowPrice,
102                            ohlc_closePrice, ohlc_volume);
103            }
104    
105            @Override
106            public JobStatus handleMessage(Header header, ByteBuffer in) {
107                    super.handleMessage(header, in);
108    
109                    int count = in.getInt();
110    
111                    while( count-- > 0) {
112    
113                            int typeCode = in.get();
114    
115                            if(typeCode == DataEnum.EOD.code) {
116                                    return JobStatus.FINISHED;
117                            }
118                            
119                            if(typeCode != DataEnum.OHLC.code) {
120                                    throw new ProtocolException("unexpected historical data code: " + typeCode, in);
121                            }
122    
123                            OTOHLC ohlc = readOHLC(in);
124                            dataDelegate.onData(ohlc);
125                    }
126    
127                    return JobStatus.ACTIVE;
128            }
129    
130            @Override
131            public final CommandEnum getCancelCommand() {
132                    return CommandEnum.CANCEL_HIST_DATA; // fixme??
133            }
134    }