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.book;
019    
020    import org.otfeed.command.BookDeleteTypeEnum;
021    import org.otfeed.event.IDataDelegate;
022    import org.otfeed.event.OTBookCancel;
023    import org.otfeed.event.OTBookChange;
024    import org.otfeed.event.OTBookDelete;
025    import org.otfeed.event.OTBookExecute;
026    import org.otfeed.event.OTBookOrder;
027    import org.otfeed.event.OTBookPriceLevel;
028    import org.otfeed.event.OTBookPurge;
029    import org.otfeed.event.OTBookReplace;
030    import org.otfeed.event.TradeSideEnum;
031    
032    import org.otfeed.protocol.DataEnum;
033    import org.otfeed.protocol.request.Header;
034    import org.otfeed.protocol.request.Util;
035    
036    import java.util.Date;
037    import java.nio.ByteBuffer;
038    
039    /**
040     * Class that knows how to de-serialise miscellaneous Book events.
041     */
042    public abstract class BookReader {
043    
044            private BookReader(DataEnum t) {
045                    type = t;
046                    this.mask = 1 << (t.code - 1);
047            }
048    
049            public final DataEnum type;
050            public final int mask;
051    
052            /**
053             * Reads response data frame, parses it and emits events.
054             *
055             * @param header   response header.
056             * @param in       data frame.
057             */
058            public abstract void read(Header header, ByteBuffer in);
059    
060            /**
061             * Creates reader for the BookOrder event.
062             */
063            public static final BookReader orderReader(
064                            final IDataDelegate<OTBookOrder> dataDelegate) {
065                    
066                    return new BookReader(DataEnum.BOOK_ORDER) {
067                            @Override
068                            public void read(Header header, ByteBuffer in) {
069                                    OTBookOrder data = readOrder(in);
070                                    dataDelegate.onData(data);
071                            }
072                    };
073            }
074            
075            private final static OTBookOrder readOrder(ByteBuffer in) {
076                    Date timestamp   = Util.readDate(in);
077                    String reference = Util.readString(in, 21).trim();
078                    double price     = in.getDouble();
079                    int size         = in.getInt();
080                    TradeSideEnum side = Util.readTradeSideEnum(in);
081                    boolean display  = Util.readBoolean(in);
082                    
083                    return new OTBookOrder(timestamp,
084                            reference, price, size, side, display);
085            }
086    
087            /**
088             * Creates reader for the BookExecute event.
089             */
090            public static final BookReader executeReader(
091                            final IDataDelegate<OTBookExecute> dataDelegate) {
092                    
093                    return new BookReader(DataEnum.BOOK_EXECUTE) {
094                            @Override
095                            public void read(Header header, ByteBuffer in) {
096                                    OTBookExecute data = readExecute(in);
097                                    dataDelegate.onData(data);
098                            }
099                    };
100            }
101            
102            private final static OTBookExecute readExecute(ByteBuffer in) {
103                    Date timestamp   = Util.readDate(in);
104                    String reference = Util.readString(in, 21).trim();
105                    int size         = in.getInt();
106                    int matchNumber  = in.getInt();
107    
108                    return new OTBookExecute(timestamp,
109                            reference, size, matchNumber);
110            }
111    
112            /**
113             * Creates reader for the BookDelete event.
114             */
115            public static final BookReader deleteReader(
116                            final IDataDelegate<OTBookDelete> dataDelegate) {
117                    
118                    return new BookReader(DataEnum.BOOK_DELETE) {
119                            @Override
120                            public void read(Header header, ByteBuffer in) {
121                                    OTBookDelete data = readDelete(in);
122                                    dataDelegate.onData(data);
123                            }
124                    };
125            }
126            
127            private final static OTBookDelete readDelete(ByteBuffer in) {
128                    Date timestamp   = Util.readDate(in);
129                    String reference = Util.readString(in,  21).trim();
130                    BookDeleteTypeEnum deleteType = Util.readBookDeleteTypeEnum(in);
131                    TradeSideEnum side = Util.readTradeSideEnum(in);
132                    
133                    return new OTBookDelete(timestamp,
134                            reference, deleteType, side);
135            }
136    
137            /**
138             * Creates reader for the BookCancel event.
139             */
140            public static final BookReader cancelReader(
141                            final IDataDelegate<OTBookCancel> dataDelegate) {
142                    
143                    return new BookReader(DataEnum.BOOK_CANCEL) {
144                            @Override
145                            public void read(Header header, ByteBuffer in) {
146                                    OTBookCancel data = readCancel(in);
147                                    dataDelegate.onData(data);
148                            }
149                    };
150            }
151            
152            private final static OTBookCancel readCancel(ByteBuffer in) {
153                    Date timestamp   = Util.readDate(in);
154                    String reference = Util.readString(in, 21).trim();
155                    int size         = in.getInt();
156    
157                    return new OTBookCancel(timestamp, reference, size);
158            }
159    
160            /**
161             * Creates reader for the BookChange event.
162             */
163            public static final BookReader changeReader(
164                            final IDataDelegate<OTBookChange> dataDelegate) {
165                    
166                    return new BookReader(DataEnum.BOOK_CHANGE) {
167                            @Override
168                            public void read(Header header, ByteBuffer in) {
169                                    OTBookChange data = readChange(in);
170                                    dataDelegate.onData(data);
171                            }
172                    };
173            }
174            
175            private final static OTBookChange readChange(ByteBuffer in) {
176                    Date timestamp   = Util.readDate(in);
177                    String reference = Util.readString(in, 21).trim();
178                    double price     = in.getDouble();
179                    int size         = in.getInt();
180    
181                    return new OTBookChange(timestamp, reference, price, size);
182            }
183    
184            /**
185             * Creates reader for the BookChange event.
186             */
187            public static final BookReader replaceReader(
188                            final IDataDelegate<OTBookReplace> dataDelegate) {
189                    
190                    return new BookReader(DataEnum.BOOK_REPLACE) {
191                            @Override
192                            public void read(Header header, ByteBuffer in) {
193                                    OTBookReplace data = readReplace(in);
194                                    dataDelegate.onData(data);
195                            }
196                    };
197            }
198            
199            private final static OTBookReplace readReplace(ByteBuffer in) {
200                    Date timestamp     = Util.readDate(in);
201                    String reference   = Util.readString(in, 21).trim();
202                    double price       = in.getDouble();
203                    int size           = in.getInt();
204                    TradeSideEnum side = Util.readTradeSideEnum(in);
205    
206                    return new OTBookReplace(timestamp, reference, price, size, side);
207            }
208    
209            /**
210             * Creates reader for the BookPurge event.
211             */
212            public static final BookReader purgeReader(
213                            final IDataDelegate<OTBookPurge> dataDelegate) {
214                    
215                    return new BookReader(DataEnum.BOOK_PURGE) {
216                            @Override
217                            public void read(Header header, ByteBuffer in) {
218                                    OTBookPurge data = readPurge(in);
219                                    dataDelegate.onData(data);
220                            }
221                    };
222            }
223            
224            private final static OTBookPurge readPurge(ByteBuffer in) {
225                    Date timestamp   = Util.readDate(in);
226                    String nameRoot  = Util.readString(in, 3).trim();
227    
228                    return new OTBookPurge(timestamp, nameRoot);
229            }
230    
231            /**
232             * Creates reader for the BookPriceLevel event.
233             */
234            public static final BookReader priceLevelReader(
235                            final IDataDelegate<OTBookPriceLevel> dataDelegate) {
236                    
237                    return new BookReader(DataEnum.BOOK_PRICE_LEVEL) {
238                            @Override
239                            public void read(Header header, ByteBuffer in) {
240                                    OTBookPriceLevel data = readPriceLevel(in);
241                                    dataDelegate.onData(data);
242                            }
243                    };
244            }
245    
246            private final static OTBookPriceLevel readPriceLevel(ByteBuffer in) {
247                    Date timestamp     = Util.readDate(in);
248                    double price       = in.getDouble();
249                    int size           = in.getInt();
250                    TradeSideEnum side = Util.readTradeSideEnum(in);
251                    String levelID     = Util.readString(in, 4).trim();
252    
253                    return new OTBookPriceLevel(timestamp,
254                                            price, size, side, levelID);
255            }
256    }
257    
258