Ejemplo n.º 1
0
 def cur_path(self):
     """
     @return: x12 node path
     @rtype: string
     """
     if self.x12_map_node is None:
         raise errors.EngineError('This node has been deleted')
     return self.x12_map_node.get_path()
Ejemplo n.º 2
0
 def id(self):
     """
     @return: x12 node id
     @rtype: string
     """
     if self.x12_map_node is None:
         raise errors.EngineError('This node has been deleted')
     return self.x12_map_node.id
Ejemplo n.º 3
0
 def _get_segment(self, seg_obj):
     """
     Get a pyx12.segment.Segment instance, building one from a string
     """
     if isinstance(seg_obj, pyx12.segment.Segment):
         return seg_obj
     elif isinstance(seg_obj, str):
         (seg_term, ele_term, subele_term) = self._get_terminators()
         assert seg_term is not None, 'seg_term is none, node contains no X12SegmentDataNode children?'
         assert ele_term is not None, 'seg_term is none, node contains no X12SegmentDataNode children?'
         assert subele_term is not None, 'seg_term is none, node contains no X12SegmentDataNode children?'
         return pyx12.segment.Segment(seg_obj, seg_term, ele_term,
                                      subele_term)
     else:
         raise errors.EngineError(
             'Unknown type %s for seg_obj %i.  Expecting a pyx12.segment.Segment or a str'
             % (seg_obj.__class__, seg_obj))
Ejemplo n.º 4
0
def x12n_document(param,
                  src_file,
                  fd_997,
                  fd_html,
                  fd_xmldoc=None,
                  xslt_files=None,
                  map_path=None):
    """
    Primary X12 validation function
    @param param: param instance
    @param src_file: Source document
    @type src_file: string
    @param fd_997: 997/999 output document
    @type fd_997: file descriptor
    @param fd_html: HTML output document
    @type fd_html: file descriptor
    @param fd_xmldoc: XML output document
    @type fd_xmldoc: file descriptor
    @rtype: boolean
    """
    logger = logging.getLogger('pyx12')
    errh = error_handler.err_handler()

    # Get X12 DATA file
    try:
        src = x12file.X12Reader(src_file)
    except errors.X12Error:
        logger.error('"%s" does not look like an X12 data file' % (src_file))
        return False

    #Get Map of Control Segments
    map_file = 'x12.control.00501.xml' if src.icvn == '00501' else 'x12.control.00401.xml'
    logger.debug('X12 control file: %s' % (map_file))
    control_map = map_if.load_map_file(map_file, param, map_path)
    map_index_if = map_index.map_index(map_path)
    node = control_map.getnodebypath('/ISA_LOOP/ISA')
    walker = walk_tree()
    icvn = fic = vriic = tspc = None
    cur_map = None  # we do not initially know the X12 transaction type
    #XXX Generate TA1 if needed.

    if fd_html:
        html = error_html.error_html(errh, fd_html, src.get_term())
        html.header()
        err_iter = error_handler.err_iter(errh)
    if fd_xmldoc:
        xmldoc = x12xml_simple.x12xml_simple(fd_xmldoc,
                                             param.get('simple_dtd'))

    #basedir = os.path.dirname(src_file)
    #erx = errh_xml.err_handler(basedir=basedir)

    valid = True
    for seg in src:
        #find node
        orig_node = node

        if False:
            print('--------------------------------------------')
            print(seg)
            print('--------------------------------------------')
            # reset to control map for ISA and GS loops
            print('------- counters before --------')
            print(walker.counter._dict)
        if seg.get_seg_id() == 'ISA':
            node = control_map.getnodebypath('/ISA_LOOP/ISA')
            walker.forceWalkCounterToLoopStart('/ISA_LOOP', '/ISA_LOOP/ISA')
        elif seg.get_seg_id() == 'GS':
            node = control_map.getnodebypath('/ISA_LOOP/GS_LOOP/GS')
            walker.forceWalkCounterToLoopStart('/ISA_LOOP/GS_LOOP',
                                               '/ISA_LOOP/GS_LOOP/GS')
        else:
            # from the current node, find the map node matching the segment
            # keep track of the loops traversed
            try:
                (node,
                 pop_loops, push_loops) = walker.walk(node, seg, errh,
                                                      src.get_seg_count(),
                                                      src.get_cur_line(),
                                                      src.get_ls_id())
            except errors.EngineError:
                logger.error('Source file line %i' % (src.get_cur_line()))
                raise

        if False:
            print('------- counters after --------')
            print(walker.counter._dict)
        if node is None:
            node = orig_node
        else:
            if seg.get_seg_id() == 'ISA':
                errh.add_isa_loop(seg, src)
                icvn = seg.get_value('ISA12')
                errh.handle_errors(src.pop_errors())
            elif seg.get_seg_id() == 'IEA':
                errh.handle_errors(src.pop_errors())
                errh.close_isa_loop(node, seg, src)
                # Generate 997
                #XXX Generate TA1 if needed.
            elif seg.get_seg_id() == 'GS':
                fic = seg.get_value('GS01')
                vriic = seg.get_value('GS08')
                map_file_new = map_index_if.get_filename(icvn, vriic, fic)
                if map_file != map_file_new:
                    map_file = map_file_new
                    if map_file is None:
                        err_str = "Map not found.  icvn={}, fic={}, vriic={}".format(
                            icvn, fic, vriic)
                        raise errors.EngineError(err_str)
                    cur_map = map_if.load_map_file(map_file, param, map_path)
                    src.check_837_lx = True if cur_map.id == '837' else False
                    logger.debug('Map file: %s' % (map_file))
                    #apply_loop_count(orig_node, cur_map)
                    #reset_isa_counts(cur_map)
                    #_reset_counter_to_isa_counts(walker)  # new counter
                #reset_gs_counts(cur_map)
                #_reset_counter_to_gs_counts(walker)  # new counter
                node = cur_map.getnodebypath('/ISA_LOOP/GS_LOOP/GS')
                errh.add_gs_loop(seg, src)
                errh.handle_errors(src.pop_errors())
            elif seg.get_seg_id() == 'BHT':
                # special case for 4010 837P
                if vriic in ('004010X094', '004010X094A1'):
                    tspc = seg.get_value('BHT02')
                    logger.debug('icvn=%s, fic=%s, vriic=%s, tspc=%s' %
                                 (icvn, fic, vriic, tspc))
                    map_file_new = map_index_if.get_filename(
                        icvn, vriic, fic, tspc)
                    logger.debug('New map file: %s' % (map_file_new))
                    if map_file != map_file_new:
                        map_file = map_file_new
                        if map_file is None:
                            err_str = "Map not found.  icvn={}, fic={}, vriic={}, tspc={}".format(
                                icvn, fic, vriic, tspc)
                            raise errors.EngineError(err_str)
                        cur_map = map_if.load_map_file(map_file, param,
                                                       map_path)
                        src.check_837_lx = True if cur_map.id == '837' else False
                        logger.debug('Map file: %s' % (map_file))
                        #apply_loop_count(node, cur_map)
                        node = cur_map.getnodebypath(
                            '/ISA_LOOP/GS_LOOP/ST_LOOP/HEADER/BHT')
                errh.add_seg(node, seg, src.get_seg_count(),
                             src.get_cur_line(), src.get_ls_id())
                errh.handle_errors(src.pop_errors())
            elif seg.get_seg_id() == 'GE':
                errh.handle_errors(src.pop_errors())
                errh.close_gs_loop(node, seg, src)
            elif seg.get_seg_id() == 'ST':
                errh.add_st_loop(seg, src)
                errh.handle_errors(src.pop_errors())
            elif seg.get_seg_id() == 'SE':
                errh.handle_errors(src.pop_errors())
                errh.close_st_loop(node, seg, src)
            else:
                errh.add_seg(node, seg, src.get_seg_count(),
                             src.get_cur_line(), src.get_ls_id())
                errh.handle_errors(src.pop_errors())

            #errh.set_cur_line(src.get_cur_line())
            valid &= node.is_valid(seg, errh)
            #erx.handleErrors(src.pop_errors())
            #erx.handleErrors(errh.get_errors())
            #errh.reset()

        if fd_html:
            if node is not None and node.is_first_seg_in_loop():
                html.loop(node.get_parent())
            err_node_list = []
            while True:
                try:
                    err_iter.next()
                    err_node = err_iter.get_cur_node()
                    err_node_list.append(err_node)
                except errors.IterOutOfBounds:
                    break
            html.gen_seg(seg, src, err_node_list)

        if fd_xmldoc:
            xmldoc.seg(node, seg)

        if False:
            print('\n\n')
        #erx.Write(src.cur_line)

    #erx.handleErrors(src.pop_errors())
    src.cleanup()  # Catch any skipped loop trailers
    errh.handle_errors(src.pop_errors())
    #erx.handleErrors(src.pop_errors())
    #erx.handleErrors(errh.get_errors())

    if fd_html:
        html.footer()
        del html

    if fd_xmldoc:
        del xmldoc

    #visit_debug = error_debug.error_debug_visitor(sys.stdout)
    #errh.accept(visit_debug)

    #If this transaction is not a 997/999, generate one.
    if fd_997 and fic != 'FA':
        if vriic and vriic[:6] == '004010':
            try:
                visit_997 = error_997.error_997_visitor(fd_997, src.get_term())
                errh.accept(visit_997)
                del visit_997
            except Exception:
                logger.exception('Failed to create 997 response')
        if vriic and vriic[:6] == '005010':
            try:
                visit_999 = error_999.error_999_visitor(fd_997, src.get_term())
                errh.accept(visit_999)
                del visit_999
            except Exception:
                logger.exception('Failed to create 999 response')
    del node
    del src
    del control_map
    try:
        del cur_map
    except UnboundLocalError:
        pass
    try:
        if not valid or errh.get_error_count() > 0:
            return False
        else:
            return True
    except Exception:
        print(errh)
        return False
Ejemplo n.º 5
0
    def iter_segments(self, loop_id=None):
        """
        Simple segment or tree iterator
        @return: X12 Data Node - simple segment or tree
        @rtype: L{node<x12context.X12DataNode>}
        """
        cur_tree = None
        cur_data_node = None
        for seg in self.src:
            #find node
            orig_node = self.x12_map_node
            pop_loops = []
            push_loops = []
            errh = error_handler.errh_list()

            if seg.get_seg_id() == 'ISA':
                tpath = '/ISA_LOOP/ISA'
                self.x12_map_node = self.control_map.getnodebypath(tpath)
            elif seg.get_seg_id() == 'GS':
                tpath = '/ISA_LOOP/GS_LOOP/GS'
                self.x12_map_node = self.control_map.getnodebypath(tpath)
            else:
                try:
                    (seg_node, pop_loops,
                     push_loops) = self.walker.walk(self.x12_map_node, seg,
                                                    errh,
                                                    self.src.get_seg_count(),
                                                    self.src.get_cur_line(),
                                                    self.src.get_ls_id())
                    self.x12_map_node = seg_node
                except errors.EngineError:
                    raise
            if self.x12_map_node is None:
                self.x12_map_node = orig_node
            else:
                seg_id = seg.get_seg_id()
                if seg_id == 'ISA':
                    icvn = seg.get_value('ISA12')
                elif seg_id == 'GS':
                    fic = seg.get_value('GS01')
                    vriic = seg.get_value('GS08')
                    map_file_new = self.map_index_if.get_filename(
                        icvn, vriic, fic)
                    if self.map_file != map_file_new:
                        self.map_file = map_file_new
                        if self.map_file is None:
                            raise pyx12.errors.EngineError(
                                "Map not found.  icvn=%s, fic=%s, vriic=%s" %
                                (icvn, fic, vriic))
                        cur_map = map_if.load_map_file(self.map_file,
                                                       self.param,
                                                       self.map_path)
                        if cur_map.id == '837':
                            self.src.check_837_lx = True
                        else:
                            self.src.check_837_lx = False
                        #self._apply_loop_count(orig_node, cur_map)
                        #self._reset_isa_counts(cur_map)
                        self._reset_counter_to_isa_counts()
                    #self._reset_gs_counts(cur_map)
                    self._reset_counter_to_gs_counts()
                    tpath = '/ISA_LOOP/GS_LOOP/GS'
                    self.x12_map_node = cur_map.getnodebypath(tpath)
                    #self.walker.forceWalkCounterToLoopStart('/ISA_LOOP/GS_LOOP', '/ISA_LOOP/GS_LOOP/GS')
                elif seg_id == 'BHT':
                    if vriic in ('004010X094', '004010X094A1'):
                        tspc = seg.get_value('BHT02')
                        map_file_new = self.map_index_if.get_filename(
                            icvn, vriic, fic, tspc)
                        if self.map_file != map_file_new:
                            self.map_file = map_file_new
                            if self.map_file is None:
                                err_str = "Map not found.  icvn=%s, fic=%s, vriic=%s, tspc=%s" % \
                                    (icvn, fic, vriic, tspc)
                                raise pyx12.errors.EngineError(err_str)
                            cur_map = map_if.load_map_file(
                                self.map_file, self.param, self.map_path)
                            if cur_map.id == '837':
                                self.src.check_837_lx = True
                            else:
                                self.src.check_837_lx = False
                            self._apply_loop_count(self.x12_map_node, cur_map)
                            tpath = '/ISA_LOOP/GS_LOOP/ST_LOOP/HEADER/BHT'
                            self.x12_map_node = cur_map.getnodebypath(tpath)

            node_x12path = self.x12_map_node.x12path
            # If we are in the requested tree, wait until we have the whole thing
            if loop_id is not None and loop_id in node_x12path.loop_list:
                # Are we at the start of the requested tree?
                if node_x12path.loop_list[-1] == loop_id and \
                        self.x12_map_node.is_first_seg_in_loop():
                    if cur_tree is not None:
                        # Found root loop repeat. Yield existing, create new tree
                        yield cur_tree
                    # Make new tree on parent loop
                    #pop_loops = get_pop_loops(cur_data_node.x12_map_node, self.x12_map_node)
                    #pop_loops = [x12_node for x12_node in pop_loops if x12_node.get_path().find(loop_id) == -1]
                    cur_tree = X12LoopDataNode(
                        x12_node=self.x12_map_node.parent,
                        end_loops=pop_loops)  # parent=cur_data_node)
                    cur_data_node = self._add_segment(cur_tree,
                                                      self.x12_map_node, seg,
                                                      pop_loops, push_loops)
                    cur_data_node.seg_count = self.src.get_seg_count()
                    cur_data_node.cur_line_number = self.src.get_cur_line()
                else:
                    if cur_data_node is None or self.x12_map_node is None:
                        raise errors.EngineError(
                            'Either cur_data_node or self.x12_map_node is None'
                        )
                    cur_data_node = self._add_segment(cur_data_node,
                                                      self.x12_map_node, seg,
                                                      pop_loops, push_loops)
                    cur_data_node.seg_count = self.src.get_seg_count()
                    cur_data_node.cur_line_number = self.src.get_cur_line()
            else:
                if cur_tree is not None:
                    # We have completed a tree
                    yield cur_tree
                    cur_tree = None
                if cur_data_node is not None:
                    #push_loops = get_push_loops(cur_data_node.x12_map_node, self.x12_map_node)
                    #pop_loops = get_pop_loops(cur_data_node.x12_map_node, self.x12_map_node)
                    if loop_id:
                        pop_loops = [
                            x12_node for x12_node in pop_loops
                            if x12_node.get_path().find(loop_id) == -1
                        ]
                    assert loop_id not in [
                        x12.id for x12 in push_loops
                    ], 'Loop ID %s should not be in push loops' % (loop_id)
                    assert loop_id not in [
                        x12.id for x12 in pop_loops
                    ], 'Loop ID %s should not be in pop loops' % (loop_id)
                    cur_data_node = X12SegmentDataNode(self.x12_map_node, seg,
                                                       push_loops, pop_loops)
                    cur_data_node.seg_count = self.src.get_seg_count()
                    cur_data_node.cur_line_number = self.src.get_cur_line()
                else:
                    cur_data_node = X12SegmentDataNode(self.x12_map_node, seg)
                    cur_data_node.seg_count = self.src.get_seg_count()
                    cur_data_node.cur_line_number = self.src.get_cur_line()
                # Get errors caught by x12Reader
                errh.handle_errors(self.src.pop_errors())
                # Handle errors captured in errh_list
                cur_data_node.handle_errh_errors(errh)
                if cur_data_node.id != 'ISA' and cur_data_node is not None:
                    assert cur_data_node.parent is not None, 'Node "%s" has no parent' % (
                        cur_data_node.id)
                yield cur_data_node
Ejemplo n.º 6
0
    def _add_segment(self, cur_data_node, segment_x12_node, seg_data,
                     pop_loops, push_loops):
        """
        From the last position in the X12 Data Node Tree, find the correct
        position for the new segment; moving up or down the tree as appropriate.

        G{callgraph}

        @param cur_data_node: Current X12 Data Node
        @type cur_data_node: L{node<x12context.X12DataNode>}
        @param segment_x12_node: Segment Map Node
        @type segment_x12_node: L{node<map_if.x12_node>}
        @return: New X12 Data Node
        @rtype: L{node<x12context.X12DataNode>}
        """
        if not segment_x12_node.is_segment():
            raise errors.EngineError('Node must be a segment')
        # Get enclosing loop
        orig_data_node = cur_data_node
        parent_x12_node = pop_to_parent_loop(segment_x12_node)
        cur_loop_node = cur_data_node
        if cur_loop_node.type == 'seg':
            cur_loop_node = cur_loop_node.parent
        # check path for new loops to be added
        new_path = parent_x12_node.x12path
        last_path = cur_loop_node.x12_map_node.x12path
        if last_path != new_path:
            for x12_loop in pop_loops:
                if cur_loop_node.id != x12_loop.id:
                    raise errors.EngineError('Loop pop: %s != %s' %
                                             (cur_loop_node.id, x12_loop.id))
                cur_loop_node = cur_loop_node.parent
            for x12_loop in push_loops:
                if cur_loop_node is None:
                    raise errors.EngineError(
                        'cur_loop_node is None. x12_loop: %s' % (x12_loop.id))
                # push new loop nodes, if needed
                cur_loop_node = cur_loop_node._add_loop_node(x12_loop)
        else:
            # handle loop repeat
            if cur_loop_node.parent is not None and segment_x12_node.is_first_seg_in_loop(
            ):
                cur_loop_node = cur_loop_node.parent._add_loop_node(
                    segment_x12_node.parent)
        try:
            new_node = X12SegmentDataNode(self.x12_map_node, seg_data)
        except Exception:
            mypath = self.x12_map_node.get_path()
            err_str = 'X12SegmentDataNode failed: x12_path={}, seg_date={}'.format(
                mypath, seg_data)
            raise errors.EngineError(err_str)
        try:
            new_node.parent = cur_loop_node
            cur_loop_node.children.append(new_node)
        except Exception:
            err_str = 'X12SegmentDataNode child append failed:'
            err_str += ' seg_x12_path=%s' % (segment_x12_node.get_path())
            err_str += ', orig_datanode=%s' % (orig_data_node.cur_path)
            err_str += ', cur_datanode=%s' % (cur_data_node.cur_path)
            err_str += ', seg_data=%s' % (seg_data)
            raise errors.EngineError(err_str)
        return new_node