1
2
3
4
5
6
7
8
9
10
11
12
13 """
14 Interface to X12 Errors
15 """
16
17 import logging
18 from types import *
19
20
21
22 from errors import *
23
24
25
26
27 logger = logging.getLogger('pyx12.error_handler')
28
29
30
33 """
34 @param errh: Error_handler instance
35 @type errh: L{error_handler.err_handler}
36 """
37 self.errh = errh
38 self.cur_node = errh
39
40 self.visit_stack = []
41
43 self.cur_node = self.errh
44
46
47
48
49
50 if self.cur_node in self.visit_stack:
51 node = None
52 else:
53 node = self.cur_node.get_first_child()
54 if node is not None:
55 self.visit_stack.append(self.cur_node)
56 self.cur_node = node
57 else:
58 node = self.cur_node.get_next_sibling()
59 if node is not None:
60 self.cur_node = node
61 else:
62 if not self.cur_node.is_closed():
63 raise IterOutOfBounds
64
65 node = self.cur_node.get_parent()
66 if node is None:
67 raise IterOutOfBounds
68
69 if not node.is_closed():
70 raise IterOutOfBounds
71 if self.cur_node in self.visit_stack:
72 del self.visit_stack[-1]
73 self.cur_node = node
74
75 if node.id == 'ROOT':
76 raise IterOutOfBounds
77
78
101
104
105
106
107
108
109
111 """
112 The interface to the error handling structures.
113 """
115 """
116 """
117
118 self.id = 'ROOT'
119
120 self.children = []
121 self.cur_node = self
122 self.cur_isa_node = None
123 self.cur_gs_node = None
124 self.cur_st_node = None
125 self.cur_seg_node = None
126 self.seg_node_added = False
127 self.cur_ele_node = None
128 self.cur_line = 0
129
131 """
132 Params: visitor - ref to visitor class
133 """
134 visitor.visit_root_pre(self)
135 for child in self.children:
136 child.accept(visitor)
137 visitor.visit_root_post(self)
138
140 """
141 @param err_list: list of errors to apply
142 """
143 for (err_type, err_cde, err_str, err_val, src_line) in err_list:
144 if err_type == 'isa':
145 self.isa_error(err_cde, err_str)
146 elif err_type == 'gs':
147 self.gs_error(err_cde, err_str)
148 elif err_type == 'st':
149 self.st_error(err_cde, err_str)
150 elif err_type == 'seg':
151 self.seg_error(err_cde, err_str, err_val, src_line)
152
154 """
155 @return: Current file line number
156 @rtype: int
157 """
158 return self.cur_line
159
161 """
162 """
163 return self.id
164
166 """
167 @param seg_data: Segment object
168 @type seg_data: L{segment<segment.Segment>}
169 """
170
171 self.children.append(err_isa(self, seg_data, src))
172 self.cur_isa_node = self.children[-1]
173 self.cur_seg_node = self.cur_isa_node
174 self.seg_node_added = True
175
177 """
178 @param seg_data: Segment object
179 @type seg_data: L{segment<segment.Segment>}
180 """
181
182 parent = self.cur_isa_node
183 parent.children.append(err_gs(parent, seg_data, src))
184 self.cur_gs_node = parent.children[-1]
185 self.cur_seg_node = self.cur_gs_node
186 self.seg_node_added = True
187
189 """
190 @param seg_data: Segment object
191 @type seg_data: L{segment<segment.Segment>}
192 """
193
194 parent = self.cur_gs_node
195 parent.children.append(err_st(parent, seg_data, src))
196 self.cur_st_node = parent.children[-1]
197 self.cur_seg_node = self.cur_st_node
198 self.seg_node_added = True
199
200 - def add_seg(self, map_node, seg_data, seg_count, cur_line, ls_id):
201 """
202 @param map_node: current segment node
203 @type map_node: L{node<map_if.segment_if>}
204 @param seg_data: Segment object
205 @type seg_data: L{segment<segment.Segment>}
206 @param seg_count: Count of current segment in the ST Loop
207 @type seg_count: int
208 @param cur_line: Current line number in the file
209 @type cur_line: int
210 @param ls_id: The current LS loop identifier
211 @type ls_id: string
212 """
213 parent = self.cur_st_node
214 self.cur_seg_node = err_seg(parent, map_node, seg_data, seg_count, cur_line, ls_id)
215 self.seg_node_added = False
216
217
218
219
220
221
222
224 """
225 """
226
227 if not self.seg_node_added:
228 self.cur_st_node.children.append(self.cur_seg_node)
229 self.seg_node_added = True
230
232 """
233 """
234 if self.cur_seg_node.id == 'ISA':
235 self.cur_ele_node = err_ele(self.cur_isa_node, map_node)
236 elif self.cur_seg_node.id == 'GS':
237 self.cur_ele_node = err_ele(self.cur_gs_node, map_node)
238 elif self.cur_seg_node.id == 'ST':
239 self.cur_ele_node = err_ele(self.cur_st_node, map_node)
240 else:
241 self.cur_ele_node = err_ele(self.cur_seg_node, map_node)
242 self.ele_node_added = False
243
245 """
246 """
247 self._add_cur_seg()
248 if not self.ele_node_added and self.cur_seg_node is not None:
249 self.cur_seg_node.elements.append(self.cur_ele_node)
250 self.ele_node_added = True
251
252
254 """
255 @param err_cde: ISA level error code
256 @type err_cde: string
257 @param err_str: Description of the error
258 @type err_str: string
259 """
260 sout = ''
261 sout += 'Line:%i ' % (self.cur_isa_node.get_cur_line())
262 sout += 'ISA:%s - %s' % (err_cde, err_str)
263 logger.error(sout)
264 self.cur_isa_node.add_error(err_cde, err_str)
265
267 """
268 @param err_cde: GS level error code
269 @type err_cde: string
270 @param err_str: Description of the error
271 @type err_str: string
272 """
273 sout = ''
274 sout += 'Line:%i ' % (self.cur_gs_node.get_cur_line())
275 sout += 'GS:%s - %s' % (err_cde, err_str)
276 logger.error(sout)
277 self.cur_gs_node.add_error(err_cde, err_str)
278
280 """
281 @param err_cde: Segment level error code
282 @type err_cde: string
283 @param err_str: Description of the error
284 @type err_str: string
285 """
286 sout = ''
287 sout += 'Line:%i ' % (self.cur_st_node.get_cur_line())
288 sout += 'ST:%s - %s' % (err_cde, err_str)
289 logger.error(sout)
290 self.cur_st_node.add_error(err_cde, err_str)
291
292 - def seg_error(self, err_cde, err_str, err_value=None, src_line=None):
293 """
294 @param err_cde: Segment level error code
295 @type err_cde: string
296 @param err_str: Description of the error
297 @type err_str: string
298 """
299 self._add_cur_seg()
300 self.cur_seg_node.add_error(err_cde, err_str, err_value)
301 sout = ''
302 if src_line:
303 sout += 'Line:%i ' % (src_line)
304 else:
305 sout += 'Line:%i ' % (self.cur_seg_node.get_cur_line())
306 sout += 'SEG:%s - %s' % (err_cde, err_str)
307 if err_value:
308 sout += ' (%s)' % err_value
309 logger.error(sout)
310
311 - def ele_error(self, err_cde, err_str, bad_value):
312 """
313 @param err_cde: Element level error code
314 @type err_cde: string
315 @param err_str: Description of the error
316 @type err_str: string
317 """
318 self._add_cur_ele()
319 self.cur_ele_node.add_error(err_cde, err_str, bad_value)
320 sout = ''
321 sout += 'Line:%i ' % (self.cur_seg_node.get_cur_line())
322 sout += 'ELE:%s - %s' % (err_cde, err_str)
323 if bad_value:
324 sout += ' (%s)' % (bad_value)
325 logger.error(sout)
326
327
329 """
330 """
331 self.cur_isa_node.close(node, seg, src)
332 self.cur_seg_node = self.cur_isa_node
333 self.seg_node_added = True
334
336 """
337 """
338 self.cur_gs_node.close(node, seg, src)
339 self.cur_seg_node = self.cur_gs_node
340 self.seg_node_added = True
341
343 """
344 """
345 self.cur_st_node.close(node, seg, src)
346 self.cur_seg_node = self.cur_st_node
347 self.seg_node_added = True
348
350 """
351 Find the last node of a type
352 """
353 new_node = self.cur_node
354 node_order = {'ROOT': 1, 'ISA': 2, 'GS': 3, 'ST': 4, 'SEG': 5, 'ELE': 6}
355 while node_order[type] > new_node[new_node.get_id()]:
356 new_node = new_node.get_parent()
357
358
359
360
361
362
363
365 """
366 """
367 if len(self.children) != 0:
368 return self.children[-1]
369 else:
370 return None
371
374
376 """
377 """
378 count = 0
379 for child in self.children:
380 count += child.get_error_count()
381 return count
382
384 """
385 """
386 if len(self.children) > 0:
387 return self.children[0]
388 else:
389 return None
390
392 """
393 """
394 return None
395
396
398 """
399 Return the next error node
400 """
401 for child in self.children:
402 yield child
403
405 """
406 @rtype: boolean
407 """
408 return True
409
411 """
412 """
413 return '%i: %s' % (-1, self.id)
414
415
418 """
419 """
420 self.parent = parent
421 self.id = None
422 self.children = []
423 self.cur_line = -1
424 self.errors = []
425
430
431
432
433
435 """
436 @return: Current file line number
437 @rtype: int
438 """
439 return self.cur_line
440
442 """
443 """
444 return self.id
445
447 """
448 """
449 return self.parent
450
452 """
453 """
454 if len(self.children) != 0:
455 return self.children[-1]
456 else:
457 return None
458
460 """
461 """
462
463 bFound = False
464 for sibling in self.parent.children:
465 if bFound:
466 return sibling
467 if sibling is self:
468 bFound = True
469 return None
470
471
473 """
474 """
475 if len(self.children) > 0:
476 return self.children[0]
477 else:
478 return None
479
481 """
482 """
483 count = 0
484 for child in self.children:
485 count += child.get_error_count()
486 return count
487
489 """
490 """
491 return self.errors
492
494 """
495 @rtype: boolean
496 """
497 return True
498
500 """
501 Holds source ISA loop errors
502 """
503
504 - def __init__(self, parent, seg_data, src):
505 """
506 @param seg_data: Segment object
507 @type seg_data: L{segment<segment.Segment>}
508 @param src: X12file source
509 @type src: L{X12file<x12file.X12file>}
510 """
511 self.seg_data = seg_data
512 self.isa_id = src.get_isa_id()
513 self.cur_line_isa = src.get_cur_line()
514 self.cur_line_iea = None
515
516 self.isa_trn_set_id = seg_data.get_value('ISA13')
517 self.ta1_req = seg_data.get_value('ISA14')
518 self.orig_date = seg_data.get_value('ISA09')
519 self.orig_time = seg_data.get_value('ISA10')
520 self.id = 'ISA'
521
522 self.parent = parent
523 self.children = []
524 self.errors = []
525 self.elements = []
526
528 """
529 @rtype: boolean
530 """
531 if self.cur_line_iea:
532 return True
533 else:
534 return False
535
537 """
538 Params: visitor - ref to visitor class
539 """
540 visitor.visit_isa_pre(self)
541 for child in self.children:
542 child.accept(visitor)
543 visitor.visit_isa_post(self)
544
546 """
547 @param err_cde: Error code
548 @type err_cde: string
549 @param err_str: Description of the error
550 @type err_str: string
551 """
552 self.errors.append((err_cde, err_str))
553
554 - def close(self, node, seg, src):
556
558 """
559 @return: Current file line number
560 @rtype: int
561 """
562 if self.cur_line_iea:
563 return self.cur_line_iea
564 else:
565 return self.cur_line_isa
566
568 """
569 """
570 count = 0
571 for ele in self.elements:
572 count += ele.get_error_count()
573 for child in self.children:
574 count += child.get_error_count()
575 return count + len(self.errors)
576
578 """
579 """
580 if seg_id == 'ISA':
581 return filter(lambda err: 'ISA' in err[0], self.errors)
582 elif seg_id == 'IEA':
583 return filter(lambda err: 'IEA' in err[0], self.errors)
584 else:
585 return []
586
587
588
589
590
591
593 """
594 Return the next error node
595 """
596 for child in self.children:
597 yield child
598 self.parent.next()
599
602
603
605 """
606 Holds source GS loop information
607 """
608
609 - def __init__(self, parent, seg_data, src):
610 """
611 @param seg_data: Segment object
612 @type seg_data: L{segment<segment.Segment>}
613 @param src: X12file source
614 @type src: L{X12file<x12file.X12file>}
615
616 """
617 self.seg_data = seg_data
618 self.isa_id = src.get_isa_id()
619 self.cur_line_gs = src.get_cur_line()
620 self.cur_line_ge = None
621 self.gs_control_num = src.get_gs_id()
622 self.fic = self.seg_data.get_value('GS01')
623 self.id = 'GS'
624
625 self.st_loops = []
626
627
628 self.ack_code = None
629 self.st_count_orig = 0
630 self.st_count_recv = 0
631
632
633 self.parent = parent
634 self.children = []
635 self.errors = []
636 self.elements = []
637
639 """
640 Params: visitor - ref to visitor class
641 """
642 visitor.visit_gs_pre(self)
643 for child in self.children:
644 child.accept(visitor)
645 visitor.visit_gs_post(self)
646
648 """
649 @param err_cde: Error code
650 @type err_cde: string
651 @param err_str: Description of the error
652 @type err_str: string
653 """
654 self.errors.append((err_cde, err_str))
655
656 - def close(self, node, seg_data, src):
657 """
658 """
659
660 self.cur_line_ge = src.get_cur_line()
661
662 self.ack_code = self._get_ack_code()
663
664 if seg_data is None:
665 self.st_count_orig = 0
666 else:
667 self.st_count_orig = int(seg_data.get_value('GE01'))
668 self.st_count_recv = src.st_count
669
670
672 for child in self.children:
673 if child.get_error_count() > 0:
674 return 'R'
675
676
677
678
679
680
681
682 if len(self.errors) > 0:
683 return 'R'
684 return 'A'
685
687 ct = 0
688 for child in self.children:
689 if child.ack_code not in ['A', 'E']:
690 ct += 1
691 return ct
692
694 """
695 @return: Current file line number
696 @rtype: int
697 """
698 if self.cur_line_ge:
699 return self.cur_line_ge
700 else:
701 return self.cur_line_gs
702
704 """
705 """
706 count = 0
707 for ele in self.elements:
708 count += ele.get_error_count()
709 for child in self.children:
710 count += child.get_error_count()
711 return count + len(self.errors)
712
714 """
715 """
716 if seg_id == 'GS':
717 return filter(lambda err: err[0] in ('6'), self.errors)
718 elif seg_id == 'GE':
719 return filter(lambda err: err[0] not in ('6'), self.errors)
720 else:
721 return []
722
724 """
725 @rtype: boolean
726 """
727 if self.cur_line_ge:
728 return True
729 else:
730 return False
731
733 """
734 Return the next error node
735 """
736 for child in self.children:
737 yield child
738 self.parent.next()
739
742
743
745 """
746 ST loops
747
748 Needs:
749 1. Transaction set id code (837, 834)
750 2. Transaction set control number
751 3. trn set error codes
752 4. At SE, Determine final ack code
753 """
754
755 - def __init__(self, parent, seg_data, src):
756 """
757 @param seg_data: Segment object
758 @type seg_data: L{segment<segment.Segment>}
759 @param src: X12file source
760 @type src: L{X12file<x12file.X12file>}
761 """
762 self.seg_data = seg_data
763 self.trn_set_control_num = src.get_st_id()
764 self.cur_line_st = src.get_cur_line()
765 self.cur_line_se = None
766 self.trn_set_id = seg_data.get_value('ST01')
767 self.id = 'ST'
768
769 self.ack_code = 'R'
770 self.parent = parent
771 self.children = []
772 self.errors = []
773 self.elements = []
774
775
777 """
778 Params: visitor - ref to visitor class
779 """
780 visitor.visit_st_pre(self)
781 for child in self.children:
782 child.accept(visitor)
783 visitor.visit_st_post(self)
784
786 """
787 @param err_cde: Error code
788 @type err_cde: string
789 @param err_str: Description of the error
790 @type err_str: string
791 """
792 self.errors.append((err_cde, err_str))
793
794 - def close(self, node, seg_data, src):
795 """
796 Close ST loop
797
798 @param node: SE node
799 @type node: L{node<map_if.x12_node>}
800 @param seg_data: Segment object
801 @type seg_data: L{segment<segment.Segment>}
802 @param src: X12file source
803 @type src: L{X12file<x12file.X12file>}
804 """
805 self.cur_line_se = src.get_cur_line()
806
807 if self.err_count() > 0:
808 self.ack_code = 'R'
809 else:
810 self.ack_code = 'A'
811
813 """
814 @return: Count of ST/SE loop errors
815 @rtype: int
816 """
817 seg_err_ct = 0
818 if self.child_err_count() > 0:
819 seg_err_ct = 1
820 return len(self.errors) + seg_err_ct
821
824
826 """
827 """
828 if seg_id == 'ST':
829 return filter(lambda err: err[0] in ('1', '6', '7', '23'), self.errors)
830 elif seg_id == 'SE':
831 return filter(lambda err: err[0] not in ('1', '6', '7', '23'), self.errors)
832 else:
833 return []
834
836 ct = 0
837 for child in self.children:
838 if child.err_count() > 0:
839 ct += 1
840 return ct
841
843 """
844 @return: Current file line number
845 @rtype: int
846 """
847 if self.cur_line_se:
848 return self.cur_line_se
849 else:
850 return self.cur_line_st
851
853 """
854 @rtype: boolean
855 """
856 if self.cur_line_se:
857 return True
858 else:
859 return False
860
862 """
863 Return the next error node
864 """
865 for child in self.children:
866 yield child
867 return
868
869
872
873
875 """
876 Segment Errors
877 """
878 - def __init__(self, parent, map_node, seg_data, seg_count, cur_line, ls_id):
879 """
880 Needs:
881 1. seg_id_code
882 2. seg_pos - pos in ST loop
883 3, loop_id - LS loop id
884 4. seg_count - in parent
885 """
886 self.parent = parent
887 if map_node is None:
888 self.name = 'Unknown'
889 self.pos = -1
890 else:
891 self.name = map_node.name
892 self.pos = map_node.pos
893 self.seg_id = seg_data.get_seg_id()
894 self.seg_count = seg_count
895 self.cur_line = cur_line
896 self.ls_id = ls_id
897
898 self.id = 'SEG'
899
900 self.elements= []
901 self.errors = []
902
904 """
905 Params: visitor - ref to visitor class
906 """
907 visitor.visit_seg(self)
908 for elem in self.elements:
909 elem.accept(visitor)
910
911 - def add_error(self, err_cde, err_str, err_value=None):
912 """
913 @param err_cde: Error code
914 @type err_cde: string
915 @param err_str: Description of the error
916 @type err_str: string
917 """
918 self.errors.append((err_cde, err_str, err_value))
919
921 """
922 Returns: count of errors
923 """
924 ele_err_ct = 0
925 if self.child_err_count() > 0:
926 ele_err_ct = 1
927 return len(self.errors) + ele_err_ct
928
931
933 ct = 0
934 for ele in self.elements:
935 if ele.err_count() > 0:
936 ct += 1
937 return ct
938
940 """
941 Desc: Return the next error node
942 """
943
944
945
946 return self
947
948
950 return '%i: %s %s' % (self.get_cur_line(), self.id, self.seg_id)
951
954
955
957 """
958 Element Errors - Holds and generates output for element and
959 composite/sub-element errors
960
961 Each element with an error creates a new err_ele instance.
962 """
964 """
965 """
966
967 self.ele_ref_num = map_node.data_ele
968 self.name = map_node.name
969 if map_node.parent.is_composite():
970 self.ele_pos = map_node.parent.seq
971 self.subele_pos = map_node.seq
972 else:
973 self.ele_pos = map_node.seq
974 self.subele_pos = None
975
976
977 self.id = 'ELE'
978
979 self.parent = parent
980
981 self.errors = []
982
984 """
985 Params: visitor - ref to visitor class
986 """
987 visitor.visit_ele(self)
988
989 - def add_error(self, err_cde, err_str, bad_value):
990 """
991 @param err_cde: Error code
992 @type err_cde: string
993 @param err_str: Description of the error
994 @type err_str: string
995 """
996
997 self.errors.append((err_cde, err_str, bad_value))
998
1001
1004
1006 """Class for errh_null errors."""
1007
1009 """
1010 A null error object - used for testing.
1011 Stores the current error in simple variables.
1012 """
1014 self.id = 'ROOT'
1015
1016 self.cur_node = self
1017
1018
1019
1020
1021
1022
1023 self.cur_line = 0
1024 self.err_cde = None
1025 self.err_str = None
1026
1028 """
1029 @return: Current file line number
1030 @rtype: int
1031 """
1032 return self.cur_line
1033
1035 """
1036 @return: Error node type
1037 @rtype: string
1038 """
1039 return self.id
1040
1045
1047 """
1048 """
1049 pass
1050
1052 """
1053 """
1054 pass
1055
1056 - def add_seg(self, map_node, seg, seg_count, cur_line, ls_id):
1057 """
1058 """
1059 pass
1060
1062 """
1063 """
1064 pass
1065
1067 """
1068 @param err_cde: ISA level error code
1069 @type err_cde: string
1070 @param err_str: Description of the error
1071 @type err_str: string
1072 """
1073 self.err_cde = err_cde
1074 self.err_str = err_str
1075
1077 """
1078 @param err_cde: GS level error code
1079 @type err_cde: string
1080 @param err_str: Description of the error
1081 @type err_str: string
1082 """
1083 self.err_cde = err_cde
1084 self.err_str = err_str
1085
1087 """
1088 @param err_cde: Segment level error code
1089 @type err_cde: string
1090 @param err_str: Description of the error
1091 @type err_str: string
1092 """
1093 self.err_cde = err_cde
1094 self.err_str = err_str
1095
1096 - def seg_error(self, err_cde, err_str, err_value=None, src_line=None):
1097 """
1098 @param err_cde: Segment level error code
1099 @type err_cde: string
1100 @param err_str: Description of the error
1101 @type err_str: string
1102 """
1103 self.err_cde = err_cde
1104 self.err_str = err_str
1105
1106 - def ele_error(self, err_cde, err_str, bad_value):
1107 """
1108 @param err_cde: Element level error code
1109 @type err_cde: string
1110 @param err_str: Description of the error
1111 @type err_str: string
1112 """
1113 self.err_cde = err_cde
1114 self.err_str = err_str
1115
1117 """
1118 """
1119 pass
1120
1122 """
1123 """
1124 pass
1125
1127 """
1128 """
1129 pass
1130
1132 """
1133 Find the last node of a type
1134 """
1135 pass
1136
1139
1140
1141
1142
1143
1144
1145
1146
1147
1149 """
1150 """
1151 return None
1152
1154 """
1155 """
1156 if self.err_cde is not None:
1157 return 1
1158 else:
1159 return 0
1160
1162 """
1163 @rtype: boolean
1164 """
1165 return True
1166
1168 """
1169 """
1170 return '%i: %s' % (-1, self.id)
1171