Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: mas_gui/Parser.java


1   /* Copyright 1998 - 2003: Jim Cochrane - see file forum.txt */
2   
3   package mas_gui;
4   
5   import java.lang.*;
6   import java.util.*;
7   import graph.*;
8   
9   /** Market Analysis Parser - parses market and indicator data sent from
10  the Market Analysis server */
11  class Parser {
12    public static final int Date = 1, Open = 2, High = 3, Low = 4, Close = 5,
13      Volume = 6, Open_interest = 7, Not_set = 0;
14  
15    // Constructor - fieldspecs specifies the fields format of each tuple -
16    // e.g., date, high, low, close, volume.
17    Parser(int fieldspecs[], String record_sep, String field_sep) {
18      parsetype = fieldspecs;
19      _record_separator = record_sep;
20      _field_separator = field_sep;
21  
22      dates = new Vector();
23      times = new Vector();
24      float_field_count = float_fields(fieldspecs);
25    }
26  
27    // Set the tuple field specifications.
28    // Precondition: fs != null
29    // Postcondition: field_specifications() == fs
30    void set_field_specifications(int[] fs) {
31      parsetype = fs;
32    }
33  
34    // Set the drawer for drawing volume.
35    void set_volume_drawer(BasicDrawer d) {
36      volume_drawer = d;
37    }
38  
39    // Set the drawer for open interest.
40    void set_open_interest_drawer(BasicDrawer d) {
41      open_interest_drawer = d;
42    }
43  
44    // Specifications of the type (date, open, etc.) and order of each field
45    // in a tuple.
46    int[] field_specifications() {
47      return parsetype;
48    }
49  
50    // Parse `s' into a DataSet according to record_separator and
51    // field_separator.  `drawer' is the tuple drawer to use for the
52    // DataSet.  result() gives the new DataSet.
53    public void parse(String s, BasicDrawer drawer) throws Exception {
54      int rec_count;
55      volumes = null;
56      open_interests = null;
57      is_intraday = contains_time_field(s);
58      StringTokenizer recs = new StringTokenizer(s, _record_separator, false);
59      rec_count = recs.countTokens();
60      clear_vectors();
61      if (has_field_type(Volume)) {
62        volumes = new double[rec_count];
63      }
64      if (has_field_type(Open_interest)) {
65        open_interests = new double[rec_count];
66      }
67      // If there is no open field
68      if (! has_field_type(Open) && has_field_type(High) &&
69          has_field_type(Low)) {
70        // Add 1 to make room for the "fake" open field.
71        value_data = new double[rec_count * (float_field_count + 1)];
72        parse_with_no_open(recs);
73      } else {
74        value_data = new double[rec_count * float_field_count];
75        parse_default(recs);
76      }
77      process_data(drawer);
78    }
79  
80    // Parse fields - default routine
81    private void parse_default(StringTokenizer recs) throws Exception {
82      int float_index = 0, volume_index = 0, oi_index = 0;
83      while (recs.hasMoreTokens()) {
84        String s = recs.nextToken();
85        StringTokenizer fields = new StringTokenizer(s,
86          _field_separator, false);
87        for (int j = 0; fields.hasMoreTokens(); ++j) {
88          try {
89          switch (parsetype[j]) {
90            case Date:
91              dates.addElement(fields.nextToken());
92              if (is_intraday) {
93                times.addElement(fields.nextToken());
94              }
95              break;
96            case Open:
97              value_data[float_index++] =
98                parse_double(fields.nextToken());
99              break;
100           case High:
101             value_data[float_index++] =
102               parse_double(fields.nextToken());
103             break;
104           case Low:
105             value_data[float_index++] =
106               parse_double(fields.nextToken());
107             break;
108           case Close:
109             value_data[float_index++] =
110               parse_double(fields.nextToken());
111             break;
112           case Volume:
113             volumes[volume_index++] =
114               parse_double(fields.nextToken());
115             break;
116           case Open_interest:
117             open_interests[oi_index++] =
118               parse_double(fields.nextToken());
119             break;
120         }
121         }
122         catch (Exception e) {
123           System.err.println("Last record processed was dated " +
124             dates.elementAt(dates.size() - 1));
125           throw e;
126         }
127       }
128     }
129   }
130 
131   // Parse fields - expecting high, low, and close fields (in that order),
132   // but NO open field.
133   private void parse_with_no_open(StringTokenizer recs) throws Exception {
134     int float_index = 0, volume_index = 0, oi_index = 0;
135     while (recs.hasMoreTokens()) {
136       StringTokenizer fields = new StringTokenizer(recs.nextToken(),
137                           _field_separator, false);
138       int open_field_index = -1;
139       for (int j = 0; fields.hasMoreTokens(); ++j) {
140         try {
141         switch (parsetype[j]) {
142           case Date:
143             dates.addElement(fields.nextToken());
144             if (is_intraday) {
145               times.addElement(fields.nextToken());
146             }
147             // Save a place for the open field:
148             value_data[float_index] = 0;
149             open_field_index = float_index;
150             ++float_index;
151             break;
152           case High:
153             value_data[float_index++] =
154               parse_double(fields.nextToken());
155             break;
156           case Low:
157             value_data[float_index++] =
158               parse_double(fields.nextToken());
159             break;
160           case Close:
161             value_data[float_index++] =
162               parse_double(fields.nextToken());
163             if (open_field_index != -1) {
164               // Store the close value into the open field.
165               value_data[open_field_index] =
166                 value_data[float_index - 1];
167             }
168             break;
169           case Volume:
170             volumes[volume_index++] =
171               parse_double(fields.nextToken());
172             break;
173           case Open_interest:
174             open_interests[oi_index++] =
175               parse_double(fields.nextToken());
176             break;
177         }
178         }
179         catch (Exception e) {
180           System.err.println("Last record processed was dated " +
181             dates.elementAt(dates.size() - 1));
182           throw e;
183         }
184       }
185     }
186   }
187 
188   // Parsed data set result
189   DataSet result() {
190     return processed_data;
191   }
192 
193   // Parsed volume
194   DataSet volume_result() {
195     return volume_data;
196   }
197 
198   // Parsed open interest
199   DataSet open_interest_result() {
200     return oi_data;
201   }
202 
203   public String record_separator() {
204     return _record_separator;
205   }
206 
207   public String field_separator() {
208     return _field_separator;
209   }
210 
211 // Implementation
212 
213   double parse_double(String s) throws Exception {
214     double result;
215     try {
216       result = Float.valueOf(s).floatValue();
217     }
218     catch (Exception e) {
219       if (s.equals("NaN") || s.equals("nan")) {
220         System.err.println("NaN encountered - substituting 0.");
221         result = 0;
222       }
223       else {
224         System.err.println("Error occurred in formatting value " + s +
225           " (" + e + ")");
226         throw e;
227       }
228     }
229     return result;
230   }
231 
232   Integer parse_int(String s) {
233     return Integer.valueOf(s);
234   }
235 
236   // Put the parsed data into a data set.
237   // Postcondition: result() != null && result().drawer() == drawer
238   private void process_data(BasicDrawer drawer) throws Exception {
239     String[] date_array = null;
240     String[] time_array = null;
241     boolean has_dates = false;
242     boolean has_times = false;
243 
244     volume_data = null;
245     oi_data = null;
246 
247     try {
248       has_dates = dates != null && ! dates.isEmpty();
249       has_times = times != null && ! times.isEmpty();
250       int length = value_data.length / float_field_count;
251       if (length > 0) {
252         processed_data = new DataSet(value_data, length, drawer);
253       }
254       else {
255         processed_data = new DataSet(drawer);
256       }
257       if (has_dates) {
258         date_array = new String[dates.size()];
259         dates.copyInto(date_array);
260         processed_data.set_dates(date_array);
261       }
262       if (has_times) {
263         time_array = new String[times.size()];
264         times.copyInto(time_array);
265         processed_data.set_times(time_array);
266       }
267       if (volume_drawer != null && volumes != null &&
268           volumes.length > 0) {
269         volume_data = new DataSet(volumes, volumes.length,
270                       volume_drawer);
271         if (has_dates) volume_data.set_dates(date_array);
272         if (has_times) volume_data.set_times(time_array);
273       }
274       if (open_interest_drawer != null && open_interests != null &&
275           open_interests.length > 0) {
276         oi_data = new DataSet(open_interests,
277           open_interests.length, open_interest_drawer);
278         if (has_dates) oi_data.set_dates(date_array);
279         if (has_times) oi_data.set_times(time_array);
280       }
281     }
282     catch (Exception e) {
283       System.err.println("DataSet constructor failed - " + e);
284       e.printStackTrace();
285     }
286   }
287 
288   // Remove all elements from data vectors - set their sizes to 0.
289   private void clear_vectors() {
290     dates.removeAllElements();
291     times.removeAllElements();
292   }
293 
294   // The number of fields in `fieldspecs' that will be of type float
295   private int float_fields(int fieldspecs[]) {
296     int result = 0;
297 
298     for (int i = 0; i < fieldspecs.length; ++i) {
299       if (fieldspecs[i] == Open ||
300         fieldspecs[i] == Close ||
301         fieldspecs[i] == High ||
302         fieldspecs[i] == Low) {
303         result = result + 1;
304       }
305     }
306 
307     return result;
308   }
309 
310   // Does `parsetype' have the specified field type?
311   private boolean has_field_type(int ftype) {
312     boolean result = false;
313     for (int i = 0; i < parsetype.length; ++i) {
314       if (parsetype[i] == ftype) result = true;
315     }
316 
317     return result;
318   }
319 
320   // Does `s' contain a time field?
321   boolean contains_time_field(String s) {
322     boolean result = false;
323     int valid_parse_fields;
324     StringTokenizer recs = new StringTokenizer(s, _record_separator, false);
325     if (recs.countTokens() > 0) {
326       StringTokenizer fields = new StringTokenizer(recs.nextToken(),
327         _field_separator, false);
328 
329       valid_parse_fields = 0;
330       for (int i = 0; i < parsetype.length && parsetype[i] != Not_set;
331           ++i) {
332         ++valid_parse_fields;
333       }
334       // If the number of fields in a record is greater than the number of
335       // parse types, a time field is included.
336       result = fields.countTokens() > valid_parse_fields;
337     }
338     return result;
339   }
340 
341   int parsetype[];
342   int float_field_count;
343 
344   // Date, time, open, high, low, close, volume, and open interest values -
345   // Some fields may not be used - for those that are, lengths should all
346   // be equal to the number of records in the input.
347   protected Vector dates;  // String
348   protected Vector times;  // String
349   // Holds open, high, low, close data or, for indicator data, holds
350   // the main value data.
351   protected double[] value_data;
352   protected double[] volumes, open_interests;
353 
354   String _record_separator, _field_separator;
355   DataSet processed_data;    // the parsed data
356   DataSet volume_data;    // the parsed volume data
357   DataSet oi_data;      // the parsed open interest data
358   boolean is_intraday;
359   BasicDrawer volume_drawer;
360   BasicDrawer open_interest_drawer;
361 }