1
2
24
25
43
44 import org.omus.data.TableDefinition;
45 import org.omus.data.Table;
46 import org.omus.data.TableBackup;
47 import org.omus.data.UpdateSequence;
48 import org.omus.data.ClearTable;
49 import org.omus.data.RemoveRow;
50 import org.omus.data.AddRow;
51 import org.omus.data.UpdateRow;
52
53 import org.omus.util._Class;
54
55
64 class org.omus.data.DataParser
65 {
66
67
68
69
72 public var data:String;
73
74
77 public var idx:Number;
78
79
82 public var error:String;
83
84
94 private var categories:Object;
95
96
99 private var len:Number;
100
101
102
103
104
110 public function DataParser(str:String, index:Number)
111 {
112 categories = {u:1,t:1,o:1,a:1,p:2,s:3,b:4,c:4,i:4,l:4,f:4,d:4,x:5,y:5,z:6};
113
114 reset(str, index);
115
116
117
118
119
120
121
122
123 }
124
125
126
127
128
132 public function toString():String
133 {
134 return "[Object DataParser]";
135 }
136
137
143 public function reset (str:String, index:Number):Void
144 {
145 data = str;
146 len = str.length;
147 idx = index;
148 error = null;
149 }
150
151
159 public function nextValue (includeBackup:Boolean):Object
160 {
161 var type = nextType();
162 var cat = categories[type];
163 var bd = (cat == 1) ? "z" : (cat == 3) ? "y" : (cat == 4) ? "x" : "0";
164 if (bd == "0")
165 {
166 if (error == null) error = "illegal field type: " + type;
167 return null;
168 }
169
170
171 if (type == "o" || type == "a")
172 {
173 var startIdx = idx - 1;
174 var val:Object;
175 if (type == "o") val = nextObject(false);
176 if (type == "a") val = nextArray(false);
177 if (includeBackup) return getSplittedValue(val, startIdx);
178 else return val;
179 }
180 if (type == "t") return nextTable(false, includeBackup);
181 if (type == "u") return nextUpdateSequence(false);
182
183 var b = nextBoundary(bd);
184 var i = idx + 1;
185 var l = b - idx - 2;
186 idx = b;
187
188 if (type == "s")
189 {
190 return unescape(data.substr(i-1, l));
191 }
192
193 if (type == "b")
194 {
195 if (l != 1)
196 {
197 if (error == null) error = "illegal format for boolean field";
198 return null;
199 }
200 var c = data.substr(i-1, 1);
201 return (c == "1");
202 }
203
204 if (type == "d")
205 {
206 var tm = parseInt(data.substr(i-1, l));
207 if (isNaN(tm)) {
208 if (error == null) error = "error parsing number: " + data.substr(i-1, l);
209 return null;
210 }
211 var dt = new Date();
212 dt.setTime(tm);
213 if (includeBackup) return {value:dt, backup:tm};
214 else return dt;
215 }
216
217 if (categories[type] != 4) {
218 if (error == null) error = "illegal field type: " + type;
219 return null;
220 }
221
222 var s = data.substr(i-1, l);
223 var n = (type == "f") ? parseFloat(s) : parseInt(s) ;
224 if (isNaN(n)) {
225 if (error == null) error = "error parsing number: " + s;
226 return null;
227 }
228 return n;
229 }
230
231
232
239 public function nextObject (check:Boolean):Object
240 {
241 if (check)
242 {
243 if (nextType() != "o")
244 {
245 if (error == null) error = "next value not an object";
246 return null;
247 }
248 }
249
250
251 var _class = nextString();
252 if (error != null) return null;
253 var obj:Object;
254
255 if (_class.length != 0 && _class != "PropertySet")
256 {
257
258 var clazz = _Class.getInstance();
259 var constr = clazz.getConstructor(_class);
260 if (typeof(constr) != "function")
261 {
262
263 _global.oregano.iLog.error("clj-015","class name = " + _class);
264 obj = new Object();
265 } else
266 {
267 obj = new Function(constr) ();
268 }
269 } else
270 {
271 obj = new Object();
272 }
273
274 var cnt = nextInt();
275 var name:String;
276 var value:Object;
277 for (var i = 0; i < cnt; i++)
278 {
279 name = nextString ();
280 value = nextValue (_class == "PropertySet");
281 obj[name] = value;
282 if (error != null) return null;
283 }
284 nextDelimiter("z");
285 if (check) finish();
286 if (error != null) return null;
287 return obj;
288 }
289
290
297 public function nextArray (check:Boolean):Object
298 {
299 if (check)
300 {
301 if (nextType() != "a")
302 {
303 if (error == null) error = "next value not an array";
304 return null;
305 }
306 }
307 var arr = new Array();
308 var cnt = nextInt();
309 for (var i = 0; i < cnt; i++) {
310 var elem = nextValue(false);
311 arr.push(elem);
312 }
313 nextDelimiter("z");
314 if (check) finish();
315 return arr;
316 }
317
318
319
320
321
327 private function nextDelimiter (char:String):Void
328 {
329 var delim = nextType();
330 if (delim == null)
331 if (error == null) error = "unexpected or illegal delimiter: " + data.substr(idx, 2);
332 if (delim != char)
333 if (error == null) error = "unexpected or illegal delimiter: " + data.substr(idx-2, 2);
334 }
335
336
343 private function nextType ():String
344 {
345 if (idx + 2 > len)
346 {
347 if (error == null) error = "unexpected end of string";
348 return null;
349 }
350 if (data.substr(idx, 1) != "#")
351 {
352 if (error == null) error = "illegal type definition" + data.substr(idx, 2);
353 return null;
354 }
355 idx += 2;
356 return data.substr(idx-1, 1);
357 }
358
359
366 private function nextInt ():Number
367 {
368 var b = nextBoundary("x");
369 var val = parseInt(data.substr(idx, b - idx - 2));
370 if (isNaN(val))
371 {
372 if (error == null) error = "error parsing number: " + data.substr(idx, b - idx -2);
373 return null;
374 }
375 idx = b;
376 return val;
377 }
378
379
386 private function nextString ():String
387 {
388 var b = nextBoundary("y");
389 var val = unescape(data.substr(idx, b - idx-2));
390 idx = b;
391 return val;
392 }
393
394
401 private function nextBoundary (b:String):Number
402 {
403 if (b != "x" && b != "y" && b != "z")
404 {
405 if (error == null) error = "illegal boundary: " + b;
406 return null;
407 }
408 var l = len;
409 var d = data;
410
411 var lvl = 1;
412 var esc = false;
413 var cat = categories;
414 var i:Number;
415
416
417 for (i = idx + 1; i <= l; i++) {
418 var c = d.substr(i-1, 1);
419 if (esc) {
420 if (b == "x") {
421
422 if (c == "x") return i;
423 if (error == null) error = "illegal escape sequence(1): #" + c;
424 return null;
425 }
426 if (b == "y") {
427
428 if (c == "y") return i;
429 if (c != "#" && c != "e") {
430 if (error == null) error = "illegal escape sequence(2): #" + c;
431 return null;
432 }
433 }
434 if (b == "z") {
435
436 if (c == "z") {
437 lvl--;
438 } else {
439 var g = cat[c];
440 if (g == 1 || g == 2) {
441 lvl++;
442 } else {
443 if (c != "#" && g == undefined) {
444 if (error == null) error = "illegal escape sequence(3): #" + c;
445 return null;
446 }
447 }
448 }
449
450 if (lvl == 0) return i;
451 }
452 esc = false;
453
454 } else {
455 if (c == "#") esc = true;
456 }
457 }
458 if (error == null) error = "unexpected end of data";
459 return null;
460 }
461
462
470 private function getSplittedValue (val:Object, startIdx:Number):Object
471 {
472 var obj = new Object();
473 obj.value = val;
474 var len = idx - startIdx + 1;
475 obj.backup = data.substr(startIdx-1, len);
476 return obj;
477 }
478
479
485 private function unescape (orig:String):String
486 {
487 if (orig.substr(0, 2) != "#e") return orig;
488 var len = orig.length;
489 var esc = false;
490 var s = "";
491 for (var i = 3; i <= len; i++)
492 {
493 var c = orig.substr(i-1, 1);
494 if (c == "#")
495 {
496 if (esc)
497 {
498 esc = false;
499 s += "#";
500 } else
501 {
502 esc = true;
503 }
504 } else
505 {
506 if (esc)
507 {
508 if (error == null) error = "illegal escape sequence4: #" + c;
509 return null;
510 }
511 s += c;
512 }
513 }
514 return s;
515 }
516
517
518
531 private function nextTable (check:Boolean, includeBackup:Boolean):Object
532 {
533 if (check)
534 {
535 if (nextType() != "t")
536 {
537 if (error == null) error = "next value not a org.omus.Table object";
538 return null;
539 }
540 }
541 var rowCnt = nextInt();
542 var nextRowID = nextInt();
543 var cols = new Array();
544
545
546 var fieldCnt = nextInt();
547 var def = new TableDefinition();
548 var type:String;
549 var name:String;
550 for (var i = 0; i < fieldCnt; i++)
551 {
552
553 var clazz = _Class.getInstance();
554 type = clazz.charToCellType(nextType());
555 name = nextString();
556 def.addColumn(name,type);
557 cols.push(name);
558 }
559 if (error != null) return null;
560 def.lock();
561
562
563 var table = new Table(def);
564 table.nextRowID = nextRowID;
565 var backup:TableBackup;
566 if (includeBackup) backup = new TableBackup();
567 for (var j = 0; j < rowCnt; j++)
568 {
569
570 nextDelimiter("r");
571 var rowID = nextInt();
572 var row = new Object();
573 row.__rowID = rowID;
574 var startIdx = idx + 1;
575 for (var k = 0; k < fieldCnt; k++)
576 {
577
578 var cell = this.nextValue(false);
579 row[cols[k]] = cell;
580 }
581
582 _global.ASSetPropFlags(row, ["__rowID"], 7);
583 table.addExistingRow(rowID, row);
584
585 if (includeBackup)
586 {
587 var len = idx - startIdx + 1;
588 var arr = "#a" + fieldCnt + "#x" + data.substr(startIdx-1, len) + "#z";
589 backup.addRow(rowID, arr);
590 }
591 if (error != null) return null;
592 }
593
594 nextDelimiter("z");
595 if (check) finish();
596 if (error != null) return null;
597
598 if (includeBackup)
599 {
600 table.enableRecording(true);
601 return { value: table, backup: backup };
602 } else
603 {
604 return table;
605 }
606 }
607
608
618 private function nextUpdateSequence (check:Boolean):Object
619 {
620 if (check)
621 {
622 if (nextType() != "u")
623 {
624 if (error == null) error = "next value not a org.omus.UpdateSequence object";
625 return null;
626 }
627 }
628
629 var cnt = nextInt();
630 var rowID:Number;
631
632 var us = new UpdateSequence();
633 var aor = us.addOrRemove;
634 var upd = us.updates;
635 var backup = new TableBackup();
636 backup.clear = false;
637
638 for (var i = 0; i < cnt; i++)
639 {
640 nextDelimiter("p");
641 var type = nextInt();
642 var up = null;
643 if (type == org.omus.data.UpdateSequence.CLEAR_TABLE)
644 {
645 aor.push(new ClearTable());
646 backup.clear = true;
647 } else if (type == org.omus.data.UpdateSequence.REMOVE_ROW)
648 {
649 rowID = nextInt();
650 aor.push(new RemoveRow(rowID));
651 backup.addRemoveRow(rowID);
652 } else if (type == org.omus.data.UpdateSequence.ADD_ROW || type == org.omus.data.UpdateSequence.UPDATE_ROW)
653 {
654 rowID = nextInt();
655 var startIdx = idx + 1;
656 nextDelimiter("a");
657 var arr = nextArray(false);
658 if (type == org.omus.data.UpdateSequence.ADD_ROW) aor.push(new AddRow(rowID,arr));
659 if (type == org.omus.data.UpdateSequence.UPDATE_ROW) upd["r" + rowID] = new UpdateRow(rowID,arr);
660 var len = this.idx - startIdx + 1;
661 backup.addRow(rowID, data.substr(startIdx-1, len));
662 } else if (error == null)
663 {
664 error = "error unmarshalling: illegal identifier for UpdatePart: " + type;
665 }
666 nextDelimiter("z");
667 if (error != null) return null;
668 }
669 nextDelimiter("z");
670 if (check) finish();
671 if (error != null) return null;
672 return { value: us, backup: backup };
673 }
674
675
678 private function finish ():Void
679 {
680 if (idx != len) error = "marshalled data not correctly terminated";
681 }
682
683
684
685
686
690 public static function toLog():String
691 {
692 return "[Object DataParser]";
693 }
694
695
704 public static function arrayToRow (arr:Object, colNames:Array):Object
705 {
706 if (arr.length != colNames.length)
707 {
708
709 _global.oregano.iLog.error("clj-014","column names = " + colNames.toString());
710 return null;
711 }
712
713 var row = new Object();
714 var l = colNames.length;
715 for (var i = 0; i < l; i++)
716 {
717 row[colNames[i]] = arr[i];
718 }
719 return row;
720 }
721 }
722