Source code for pyx12.map_if._root
######################################################################
# Copyright (c)
# All rights reserved.
#
# This software is licensed as described in the file LICENSE.txt, which
# you should have received as part of this distribution.
#
######################################################################
"""
Map root - the X12N IG transaction-level interface.
"""
from __future__ import annotations
import os.path
import sys
from collections.abc import Iterator
from xml.etree.ElementTree import Element
from .. import codes, dataele
from ..errors import EngineError
from ..params import ParamsBase
from ..path import X12Path
from ._base import x12_node
from ._element import element_if
from ._loop import loop_if
from ._segment import segment_if
############################################################
[docs]
class map_if(x12_node):
"""
Map file interface
"""
pos_map: dict[int, list[x12_node]]
cur_path: str
param: ParamsBase
ext_codes: codes.ExternalCodes
data_elements: dataele.DataElements
base_name: str
icvn: str | None
def __init__(self, eroot: Element, param: ParamsBase, base_path: str | None = None) -> None:
"""
:param eroot: ElementTree root
:param param: map of parameters
"""
x12_node.__init__(self)
self.children = None # type: ignore[assignment]
self.pos_map = {}
self.cur_path = "/transaction"
self.path = "/"
# self.cur_iter_node = self
self.param = param
# global codes
self.ext_codes = codes.ExternalCodes(base_path, param.get("exclude_external_codes"))
self.data_elements = dataele.DataElements(base_path)
self.id = eroot.get("xid")
self.name = eroot.get("name") if eroot.get("name") else eroot.findtext("name")
self.base_name = "transaction"
for e in eroot.findall("loop"):
loop_node = loop_if(self, self, e)
try:
self.pos_map[loop_node.pos].append(loop_node)
except KeyError:
self.pos_map[loop_node.pos] = [loop_node]
for e in eroot.findall("segment"):
seg_node = segment_if(self, self, e)
try:
self.pos_map[seg_node.pos].append(seg_node)
except KeyError:
self.pos_map[seg_node.pos] = [seg_node]
self.icvn = self._get_icvn()
def _get_icvn(self) -> str | None:
"""
Get the Interchange version of this map
Map must have a first ISA segment
ISA12
"""
ipath = "/ISA_LOOP/ISA"
try:
isa = self.getnodebypath(ipath)
assert isinstance(isa, segment_if)
node = isa.children[11]
assert isinstance(node, element_if)
return node.valid_codes[0]
except Exception:
return None
[docs]
def debug_print(self) -> None:
sys.stdout.write(self.__repr__())
for ord1 in sorted(self.pos_map):
for node in self.pos_map[ord1]:
node.debug_print()
def __eq__(self, other: object) -> bool:
if not isinstance(other, map_if):
return NotImplemented
return self.id == other.id
def __hash__(self) -> int:
return (self.id or "").__hash__()
def __len__(self) -> int:
i = 0
for ord1 in sorted(self.pos_map):
i += len(self.pos_map[ord1])
return i
[docs]
def get_child_count(self) -> int:
return self.__len__()
[docs]
def get_first_node(self) -> x12_node | None:
pos_keys = sorted(self.pos_map)
if len(pos_keys) > 0:
return self.pos_map[pos_keys[0]][0]
else:
return None
[docs]
def get_first_seg(self) -> segment_if | None:
first = self.get_first_node()
if isinstance(first, segment_if):
return first
else:
return None
def __repr__(self) -> str:
"""
:rtype: string
"""
return "%s\n" % (self.id)
def _path_parent(self) -> str:
"""
:rtype: string
"""
return os.path.basename(os.path.dirname(self.cur_path))
[docs]
def get_path(self) -> str:
"""
:rtype: string
"""
return self.path
[docs]
def get_child_node_by_idx(self, idx: int) -> x12_node | None:
"""
:param idx: zero based
"""
raise EngineError("map_if.get_child_node_by_idx is not a valid call")
[docs]
def getnodebypath(self, spath: str) -> x12_node | None:
"""
:param spath: Path string; /1000/2000/2000A/NM102-3
:type spath: string
"""
pathl = spath.split("/")[1:]
if len(pathl) == 0:
return None
for ord1 in sorted(self.pos_map):
for child in self.pos_map[ord1]:
assert child.id is not None
if child.id.lower() == pathl[0].lower():
if len(pathl) == 1:
return child
else:
return child.getnodebypath("/".join(pathl[1:]))
raise EngineError('getnodebypath failed. Path "%s" not found' % spath)
[docs]
def getnodebypath2(self, path_str: str) -> x12_node | None:
"""
:param path: Path string; /1000/2000/2000A/NM102-3
:type path: string
"""
x12path = X12Path(path_str)
if x12path.empty():
return None
for ord1 in sorted(self.pos_map):
for child in self.pos_map[ord1]:
assert child.id is not None
if child.id.upper() == x12path.loop_list[0]:
if len(x12path.loop_list) == 1:
return child
else:
del x12path.loop_list[0]
if isinstance(child, loop_if):
return child.getnodebypath2(x12path.format())
return None
raise EngineError('getnodebypath2 failed. Path "%s" not found' % path_str)
[docs]
def is_map_root(self) -> bool:
"""
:rtype: boolean
"""
return True
[docs]
def reset_child_count(self) -> None:
"""
Set cur_count of child nodes to zero
"""
raise DeprecationWarning("Moved to nodeCounter")
[docs]
def reset_cur_count(self) -> None:
"""
Set cur_count of child nodes to zero
"""
raise DeprecationWarning("Moved to nodeCounter")
def __iter__(self) -> map_if:
return self
[docs]
def loop_segment_iterator(self) -> Iterator[x12_node]:
yield self
for ord1 in sorted(self.pos_map):
for child in self.pos_map[ord1]:
if isinstance(child, loop_if):
yield from child.loop_segment_iterator()
elif isinstance(child, segment_if):
yield child