Example #1
0
        def _check_known_element(el, ref, errs, warns):
            if ref is None:
                is_profile = False
                try:
                    ref = load_reference(el.name, el.classname, el.version)
                except ChildNotFound:
                    errs.append(ValidationError("Invalid element found: {}".format(el)))
            else:
                is_profile = ref[0] == 'mp'

            if is_profile:  # it is a message profile
                ref = ref[1:]  # ref[0] is 'mp'

            if ref[0] in ('sequence', 'choice'):
                element_children = {c.name for c in el.children if not c.is_z_element()}
                valid_children, valid_children_refs = _get_valid_children_info(ref, is_profile)
                z_children = [c for c in el.children if c.is_z_element()]

                # check that the children are all allowed children
                if not element_children <= valid_children:
                    errs.append(ValidationError("Invalid children detected for {}: {}".
                                                format(el, list(element_children - valid_children))))

                # iterates the valid children
                for child_ref in valid_children_refs:
                    # it gets the structure of the children to check
                    child_name, cardinality = _get_child_reference_info(child_ref, is_profile)

                    try:
                        # it gets all the occurrences of the children of a type
                        children = el.children.get(child_name)
                    except Exception:
                        # TODO: it is due to the lack of element in the official reference files...  should
                        # we raise an exception here?
                        pass
                    else:
                        _check_repetitions(el, children, cardinality, child_name, errs)
                        # calls validation for every children
                        for c in children:
                            ref = child_ref if is_profile else None
                            _is_valid(c, ref, errs, warns)

                # finally calls validation for z_elements
                for c in z_children:
                    _is_valid(c, None, errs, warns)
            else:
                _check_table_compliance(el, ref, is_profile, warns)

                _check_length(el, ref, is_profile, warns)

                if el.datatype == 'varies':  # TODO: it should check the real rule
                    return True
                _check_datatype(el, ref, is_profile, errs)

                # For complex datatypes element, the reference is the one of the datatype
                if not is_base_datatype(el.datatype, el.version):
                    # Component just to search in the datatypes....
                    ref = load_reference(el.datatype, 'Component', el.version)
                    _is_valid(el, ref, errs, warns)
Example #2
0
def parse_subcomponents(text, component_datatype='ST', version=None, encoding_chars=None,
                        validation_level=None):
    """
    Parse the given ER7-encoded subcomponents and return a list of
    :class:`SubComponent <hl7apy.core.SubComponent>` instances.

    :type text: ``str``
    :param text: the ER7-encoded string containing the components to be parsed

    :type component_datatype: ``str``
    :param component_datatype: the datatype of the subcomponents (e.g. ST)

    :type version: ``str``
    :param version: the HL7 version (e.g. "2.5"), or ``None`` to use the default
        (see :func:`set_default_version <hl7apy.set_default_version>`)

    :type encoding_chars: ``dict``
    :param encoding_chars: a dictionary containing the encoding chars or None to use the default
        (see :func:`set_default_encoding_chars <hl7apy.set_default_encoding_chars>`)

    :type validation_level: ``int``
    :param validation_level: the validation level. Possible values are those defined in
        :class:`VALIDATION_LEVEL <hl7apy.consts.VALIDATION_LEVEL>` class or ``None`` to use the default
        validation level (see :func:`set_default_validation_level <hl7apy.set_default_validation_level>`)

    :return: a list of :class:`SubComponent <hl7apy.core.SubComponent>` instances

    >>> subcomponents= "ID&TEST&&AHAH"
    >>> cwe = parse_subcomponents(subcomponents, component_datatype="CWE")
    >>> print(cwe)
    [<SubComponent CWE_1>, <SubComponent CWE_2>, <SubComponent CWE_4>]
    >>> c = Component(datatype='CWE')
    >>> c.children = cwe
    >>> print(c.to_er7())
    ID&TEST&&AHAH
    >>> subs = parse_subcomponents(subcomponents)
    >>> print(subs)
    [<SubComponent ST>, <SubComponent ST>, <SubComponent ST>, <SubComponent ST>]
    >>> c.children = subs
    >>> print(c.to_er7())
    &&&&&&&&&ID&TEST&&AHAH
    """
    version = _get_version(version)
    encoding_chars = _get_encoding_chars(encoding_chars, version)
    validation_level = _get_validation_level(validation_level)

    subcomp_sep = encoding_chars['SUBCOMPONENT']
    subcomponents = []
    for index, subcomponent in enumerate(text.split(subcomp_sep)):
        if is_base_datatype(component_datatype, version) or component_datatype is None:
            subcomponent_name = None
            subcomponent_datatype = component_datatype if component_datatype is not None else 'ST'
        else:
            subcomponent_name = "{0}_{1}".format(component_datatype, index+1)
            subcomponent_datatype = None
        if subcomponent.strip() or subcomponent_name is None:
            subcomponents.append(parse_subcomponent(subcomponent, subcomponent_name, subcomponent_datatype,
                                                    version, validation_level))
    return subcomponents
Example #3
0
def parse_subcomponents(text, component_datatype='ST', version=None, encoding_chars=None,
                        validation_level=None):
    """
    Parse the given ER7-encoded subcomponents and return a list of
    :class:`SubComponent <hl7apy.core.SubComponent>` instances.

    :type text: ``str``
    :param text: the ER7-encoded string containing the components to be parsed

    :type component_datatype: ``str``
    :param component_datatype: the datatype of the subcomponents (e.g. ST)

    :type version: ``str``
    :param version: the HL7 version (e.g. "2.5"), or ``None`` to use the default
        (see :func:`set_default_version <hl7apy.set_default_version>`)

    :type encoding_chars: ``dict``
    :param encoding_chars: a dictionary containing the encoding chars or None to use the default
        (see :func:`set_default_encoding_chars <hl7apy.set_default_encoding_chars>`)

    :type validation_level: ``int``
    :param validation_level: the validation level. Possible values are those defined in
        :class:`VALIDATION_LEVEL <hl7apy.consts.VALIDATION_LEVEL>` class or ``None`` to use the default
        validation level (see :func:`set_default_validation_level <hl7apy.set_default_validation_level>`)

    :return: a list of :class:`SubComponent <hl7apy.core.SubComponent>` instances

    >>> subcomponents= "ID&TEST&&AHAH"
    >>> cwe = parse_subcomponents(subcomponents, component_datatype="CWE")
    >>> print(cwe)
    [<SubComponent CWE_1>, <SubComponent CWE_2>, <SubComponent CWE_4>]
    >>> c = Component(datatype='CWE')
    >>> c.children = cwe
    >>> print(c.to_er7())
    ID&TEST&&AHAH
    >>> subs = parse_subcomponents(subcomponents)
    >>> print(subs)
    [<SubComponent ST>, <SubComponent ST>, <SubComponent ST>, <SubComponent ST>]
    >>> c.children = subs
    >>> print(c.to_er7())
    &&&&&&&&&ID&TEST&&AHAH
    """
    version = _get_version(version)
    encoding_chars = _get_encoding_chars(encoding_chars)
    validation_level = _get_validation_level(validation_level)

    subcomp_sep = encoding_chars['SUBCOMPONENT']
    subcomponents = []
    for index, subcomponent in enumerate(text.split(subcomp_sep)):
        if is_base_datatype(component_datatype, version) or component_datatype is None:
            subcomponent_name = None
            subcomponent_datatype = component_datatype if component_datatype is not None else 'ST'
        else:
            subcomponent_name = "{0}_{1}".format(component_datatype, index+1)
            subcomponent_datatype = None
        if subcomponent.strip() or subcomponent_name is None:
            subcomponents.append(parse_subcomponent(subcomponent, subcomponent_name, subcomponent_datatype,
                                                    version, validation_level))
    return subcomponents
Example #4
0
    def validate(element):
        """
        Checks if the :class:`hl7apy.core.Element` is a valid HL7 message according to the official structures.
        It checks if it follows the max and min number of occurrences for every child and if it
        doesn't contain children not allowed.

        :param element: :class:`hl7apy.core.Element`
        :return: The element to be validated
        """

        from hl7apy.core import is_base_datatype

        def _is_valid(ref, element):
            children = set([ child.name for child in element.children ])
            valid_children = set([ child[0] for child in ref[1] ])
            if not children <= valid_children:
                return False
            for child in ref[1]:
                child_name, cardinality = child
                min, max = cardinality

                children = element.children.get(child_name)
                num_children = len(children)
                if max != -1:
                    if num_children < min or num_children > max:
                        return False
                else:
                    if num_children < min:
                        return False
                for el in children:
                    if not Validator.validate(el):
                        return False
            return True

        if element.is_unknown():
            return False
        ref = load_reference(element.name, element.classname, element.version)
        if ref[0] in ('sequence', 'choice'):
            return _is_valid(ref, element)
        else: # it's an element that has a datatype
            if element.datatype != ref[1]:
                return False
            if element.is_unknown():
                return False
            if element.datatype == 'varies': #TODO: it should check the real rule
                return True
            if not is_base_datatype(element.datatype, element.version):
                # Component just to search in the datatypes....
                ref = load_reference(element.datatype, 'Component', element.version)
                return _is_valid(ref, element)

        return True
Example #5
0
 def _check_z_element(el, errs, warns):
     if el.classname == 'Field':
         if is_base_datatype(el.datatype, el.version) or \
                 el.datatype == 'varies':
             return True
         elif el.datatype is not None:
             # if the datatype the is a complex datatype, the z element must follow the correct
             # structure of that datatype
             # Component just to search in the datatypes....
             ref = load_reference(el.datatype, 'Component', el.version)
             _check_known_element(el, ref, errs, warns)
     for c in el.children:
         _is_valid(c, None, errs, warns)
     return True
Example #6
0
def parse_field(text, name=None, version=None, encoding_chars=None, validation_level=None, reference=None, force_varies=False):
    """
    Parse the given ER7-encoded field and return an instance of :class:`hl7apy.core.Field`.

    :type text: ``basestring``
    :param text: the ER7-encoded string containing the fields to be parsed
    :type name: ``basestring``
    :param name: the field name (e.g. MSH_7)
    :type version: ``basestring``
    :param version: the HL7 version (e.g. "2.5"), or ``None`` to use the default (see :func:`hl7apy.set_default_version`)
    :type encoding_chars: ``dict``
    :param encoding_chars: a dictionary containing the encoding chars or None to use the default (see :func:`hl7apy.set_default_encoding_chars`)
    :param validation_level: the validation level. Possible values are those defined in :class:`hl7apy.consts.VALIDATION_LEVEL` class or ``None`` to use the default validation level (see :func:`hl7apy.set_default_validation_level`)
    :type reference: ``dict``
    :param reference: a dictionary containing the element structure returned by :func:`hl7apy.load_reference` or :func:`hl7apy.find_reference`
    :return: an instance of :class:`hl7apy.core.Field`

    >>> field = "NUCLEAR^NELDA^W"
    >>> nk1_2 = parse_field(field, name="NK1_2")
    >>> print nk1_2
    <Field NK1_2 (NAME) of type XPN>
    >>> print nk1_2.to_er7()
    NUCLEAR^NELDA^W
    >>> unknown = parse_field(field)
    >>> print unknown
    <Field of type None>
    >>> print unknown.to_er7()
    NUCLEAR^NELDA^W
    """
    version = _get_version(version)
    encoding_chars = _get_encoding_chars(encoding_chars)

    if force_varies:
        reference = ('leaf', 'varies', None, None)
    try:
        field = Field(name, version=version, validation_level=validation_level, reference=reference)
    except InvalidName:
        field = Field(version=version, validation_level=validation_level, reference=reference)
    if name in ('MSH_1', 'MSH_2'):
        s = SubComponent(datatype='ST', value=text)
        c = Component(datatype='ST')
        c.add(s)
        field.add(c)
    else:
        children = parse_components(text, field.datatype, version, encoding_chars, validation_level)
        if Validator.is_quiet(validation_level) and is_base_datatype(field.datatype, version) and \
                len(children) > 1:
            field.datatype = None
        field.children = children
    return field
Example #7
0
def parse_component(text, name=None, datatype='ST', version=None, encoding_chars=None, validation_level=None, reference=None):
    """
    Parse the given ER7-encoded component and return an instance of :class:`hl7apy.core.Component`.

    :type text: ``basestring``
    :param text: the ER7-encoded string containing the components to be parsed
    :type name: ``basestring``
    :param name: the component's name (e.g. XPN_2)
    :type datatype: ``basestring``
    :param datatype: the datatype of the component (e.g. ST)
    :type version: ``basestring``
    :param version: the HL7 version (e.g. "2.5"), or ``None`` to use the default (see :func:`hl7apy.set_default_version`)
    :type encoding_chars: ``dict``
    :param encoding_chars: a dictionary containing the encoding chars or None to use the default (see :func:`hl7apy.set_default_encoding_chars`)
    :param validation_level: the validation level. Possible values are those defined in :class:`hl7apy.consts.VALIDATION_LEVEL` class or ``None`` to use the default validation level (see :func:`hl7apy.set_default_validation_level`)
    :type reference: ``dict``
    :param reference: a dictionary containing the element structure returned by :func:`hl7apy.load_reference` or :func:`hl7apy.find_reference`
    :return: an instance of :class:`hl7apy.core.Component`

    >>> component = "GATEWAY&1.3.6.1.4.1.21367.2011.2.5.17"
    >>> cx_4 = parse_component(component, name="CX_4")
    >>> print cx_4
    <Component CX_4 (ASSIGNING_AUTHORITY) of type None>
    >>> print cx_4.to_er7()
    GATEWAY&1.3.6.1.4.1.21367.2011.2.5.17
    >>> print parse_component(component)
    <Component ST (None) of type None>
    """
    version = _get_version(version)
    encoding_chars = _get_encoding_chars(encoding_chars)

    try:
        component = Component(name, datatype, version=version, validation_level=validation_level, reference=reference)
    except InvalidName as e:
        if Validator.is_strict(validation_level):
            raise e
        component = Component(datatype, version=version, validation_level=validation_level, reference=reference)
    children = parse_subcomponents(text, component.datatype, version, encoding_chars, validation_level)
    if Validator.is_quiet(component.validation_level) and is_base_datatype(component.datatype, version) and \
            len(children) > 1:
        component.datatype = None
    component.children = children
    return component
Example #8
0
def parse_components(text, field_datatype='ST', version=None, encoding_chars=None, validation_level=None):
    """
    Parse the given ER7-encoded components and return a list of :class:`hl7apy.core.Component` instances.

    :type text: ``basestring``
    :param text: the ER7-encoded string containing the components to be parsed
    :type field_datatype: ``basestring``
    :param field_datatype: the datatype of the components (e.g. ST)
    :type version: ``basestring``
    :param version: the HL7 version (e.g. "2.5"), or ``None`` to use the default (see :func:`hl7apy.set_default_version`)
    :type encoding_chars: ``dict``
    :param encoding_chars: a dictionary containing the encoding chars or None to use the default (see :func:`hl7apy.set_default_encoding_chars`)
    :param validation_level: the validation level. Possible values are those defined in :class:`hl7apy.consts.VALIDATION_LEVEL` class or ``None`` to use the default validation level (see :func:`hl7apy.set_default_validation_level`)
    :return: a list of :class:`hl7apy.core.Component` instances

    >>> components = "NUCLEAR^NELDA^W^^TEST"
    >>> xpn = parse_components(components, field_datatype="XPN")
    >>> print xpn
    [<Component XPN_1 (FAMILY_NAME) of type FN>, <Component XPN_2 (GIVEN_NAME) of type ST>, <Component XPN_3 (SECOND_AND_FURTHER_GIVEN_NAMES_OR_INITIALS_THEREOF) of type ST>, <Component XPN_5 (PREFIX_E_G_DR_) of type ST>]
    >>> print parse_components(components)
    [<Component ST (None) of type ST>, <Component ST (None) of type ST>, <Component ST (None) of type ST>, <Component ST (None) of type ST>, <Component ST (None) of type ST>]
    """
    version = _get_version(version)
    encoding_chars = _get_encoding_chars(encoding_chars)

    component_sep = encoding_chars['COMPONENT']
    components = []
    for index, component in enumerate(text.split(component_sep)):
        if is_base_datatype(field_datatype, version):
            component_datatype = field_datatype
            component_name = None
        elif field_datatype is None or field_datatype == 'varies':
            component_datatype = None
            component_name = 'VARIES_{0}'.format(index+1)
        else:
            component_name = "{0}_{1}".format(field_datatype, index+1)
            component_datatype = None
        if component.strip() or component_name is None or component_name.startswith("VARIES_"):
            components.append(parse_component(component, component_name, component_datatype,
                                              version, encoding_chars, validation_level))
    return components
Example #9
0
def parse_component(text, name=None, datatype='ST', version=None, encoding_chars=None,
                    validation_level=None, reference=None):
    """
    Parse the given ER7-encoded component and return an instance of
    :class:`Component <hl7apy.core.Component>`.

    :type text: ``str``
    :param text: the ER7-encoded string containing the components to be parsed

    :type name: ``str``
    :param name: the component's name (e.g. XPN_2)

    :type datatype: ``str``
    :param datatype: the datatype of the component (e.g. ST)

    :type version: ``str``
    :param version: the HL7 version (e.g. "2.5"), or ``None`` to use the default
        (see :func:`set_default_version <hl7apy.set_default_version>`)

    :type encoding_chars: ``dict``
    :param encoding_chars: a dictionary containing the encoding chars or None to use the default
        (see :func:`set_default_encoding_chars <hl7apy.set_default_encoding_chars>`)

    :type validation_level: ``int``
    :param validation_level: the validation level. Possible values are those defined in
        :class:`VALIDATION_LEVEL <hl7apy.consts.VALIDATION_LEVEL>` class or ``None`` to use the default
        validation level (see :func:`set_default_validation_level <hl7apy.set_default_validation_level>`)

    :type reference: ``dict``
    :param reference: a dictionary containing the element structure returned by
        :func:`load_reference <hl7apy.load_reference>` or :func:`find_reference <hl7apy.find_reference>`
        or belonging to a message profile

    :return: an instance of :class:`Component <hl7apy.core.Component>`

    >>> component = "GATEWAY&1.3.6.1.4.1.21367.2011.2.5.17"
    >>> cx_4 = parse_component(component, name="CX_4")
    >>> print(cx_4)
    <Component CX_4 (ASSIGNING_AUTHORITY) of type None>
    >>> print(cx_4.to_er7())
    GATEWAY&1.3.6.1.4.1.21367.2011.2.5.17
    >>> print(parse_component(component))
    <Component ST (None) of type None>
    """
    version = _get_version(version)
    encoding_chars = _get_encoding_chars(encoding_chars)
    validation_level = _get_validation_level(validation_level)

    try:
        component = Component(name, datatype, version=version, validation_level=validation_level,
                              reference=reference)
    except InvalidName as e:
        if Validator.is_strict(validation_level):
            raise e
        component = Component(datatype, version=version, validation_level=validation_level,
                              reference=reference)
    children = parse_subcomponents(text, component.datatype, version, encoding_chars, validation_level)
    if Validator.is_tolerant(component.validation_level) and is_base_datatype(component.datatype, version) and \
            len(children) > 1:
        component.datatype = None
    component.children = children
    return component
Example #10
0
def parse_components(text, field_datatype='ST', version=None, encoding_chars=None,
                     validation_level=None, references=None):
    """
    Parse the given ER7-encoded components and return a list of :class:`Component <hl7apy.core.Component>`
    instances.

    :type text: ``str``
    :param text: the ER7-encoded string containing the components to be parsed

    :type field_datatype: ``str``
    :param field_datatype: the datatype of the components (e.g. ST)

    :type version: ``str``
    :param version: the HL7 version (e.g. "2.5"), or ``None`` to use the default
        (see :func:`set_default_version <hl7apy.set_default_version>`)

    :type encoding_chars: ``dict``
    :param encoding_chars: a dictionary containing the encoding chars or None to use the default
        (see :func:`set_default_encoding_chars <hl7apy.set_default_encoding_chars>`)

    :type validation_level: ``int``
    :param validation_level: the validation level. Possible values are those defined in
        :class:`VALIDATION_LEVEL <hl7apy.consts.VALIDATION_LEVEL>` class or ``None`` to use the default
        validation level (see :func:`set_default_validation_level <hl7apy.set_default_validation_level>`)

    :type references: ``list``
    :param references: A list of the references of the :class:`Component <hl7apy.core.Component>`'s children

    :return: a list of :class:`Component <hl7apy.core.Component>` instances

    >>> components = "NUCLEAR^NELDA^W^^TEST"
    >>> xpn = parse_components(components, field_datatype="XPN")
    >>> print(xpn)
    [<Component XPN_1 (FAMILY_NAME) of type FN>, <Component XPN_2 (GIVEN_NAME) of type ST>, \
<Component XPN_3 (SECOND_AND_FURTHER_GIVEN_NAMES_OR_INITIALS_THEREOF) of type ST>, \
<Component XPN_5 (PREFIX_E_G_DR) of type ST>]
    >>> print(parse_components(components))
    [<Component ST (None) of type ST>, <Component ST (None) of type ST>, <Component ST (None) of type ST>, \
<Component ST (None) of type ST>, <Component ST (None) of type ST>]
    """
    version = _get_version(version)
    encoding_chars = _get_encoding_chars(encoding_chars)
    validation_level = _get_validation_level(validation_level)

    component_sep = encoding_chars['COMPONENT']
    components = []
    for index, component in enumerate(text.split(component_sep)):
        if is_base_datatype(field_datatype, version):
            component_datatype = field_datatype
            component_name = None
        elif field_datatype is None or field_datatype == 'varies':
            component_datatype = None
            component_name = 'VARIES_{0}'.format(index+1)
        else:
            component_name = "{0}_{1}".format(field_datatype, index+1)
            component_datatype = None

        try:
            reference = references[component_name]['ref'] \
                if None not in (references, component_name) else None
        except KeyError:
            reference = None

        if component.strip() or component_name is None or component_name.startswith("VARIES_"):
            components.append(parse_component(component, component_name, component_datatype,
                                              version, encoding_chars, validation_level, reference))
    return components
Example #11
0
def parse_field(text, name=None, version=None, encoding_chars=None, validation_level=None,
                reference=None, force_varies=False):
    """
    Parse the given ER7-encoded field and return an instance of :class:`Field <hl7apy.core.Field>`.

    :type text: ``str``
    :param text: the ER7-encoded string containing the fields to be parsed

    :type name: ``str``
    :param name: the field name (e.g. MSH_7)

    :type version: ``str``
    :param version: the HL7 version (e.g. "2.5"), or ``None`` to use the default
        (see :func:`set_default_version <hl7apy.set_default_version>`)

    :type encoding_chars: ``dict``
    :param encoding_chars: a dictionary containing the encoding chars or None to use the default
        (see :func:`set_default_encoding_chars <hl7apy.set_default_encoding_chars>`)

    :type validation_level: ``int``
    :param validation_level: the validation level. Possible values are those defined in
        :class:`VALIDATION_LEVEL <hl7apy.consts.VALIDATION_LEVEL>` class or ``None`` to use the default
        validation level (see :func:`set_default_validation_level <hl7apy.set_default_validation_level>`)

    :type reference: ``dict``
    :param reference: a dictionary containing the element structure returned by
        :func:`load_reference <hl7apy.load_reference>` or :func:`find_reference <hl7apy.find_reference>`
        or belonging to a message profile

    :type force_varies: ``boolean``
    :param force_varies: flag that force the fields to use a varies structure when no reference is found.
        It is used when a segment ends with a field of type varies that thus support infinite children

    :return: an instance of :class:`Field <hl7apy.core.Field>`

    >>> field = "NUCLEAR^NELDA^W"
    >>> nk1_2 = parse_field(field, name="NK1_2")
    >>> print(nk1_2)
    <Field NK1_2 (NAME) of type XPN>
    >>> print(nk1_2.to_er7())
    NUCLEAR^NELDA^W
    >>> unknown = parse_field(field)
    >>> print(unknown)
    <Field of type None>
    >>> print(unknown.to_er7())
    NUCLEAR^NELDA^W
    """
    version = _get_version(version)
    encoding_chars = _get_encoding_chars(encoding_chars)
    validation_level = _get_validation_level(validation_level)

    try:
        field = Field(name, version=version, validation_level=validation_level, reference=reference)
    except InvalidName:
        if force_varies:
            reference = ('leaf', 'varies', None, None)
            field = Field(name, version=version, validation_level=validation_level, reference=reference)
        else:
            field = Field(version=version, validation_level=validation_level, reference=reference)

    if name in ('MSH_1', 'MSH_2'):
        s = SubComponent(datatype='ST', value=text, validation_level=validation_level, version=version)
        c = Component(datatype='ST', validation_level=validation_level, version=version)
        c.add(s)
        field.add(c)
    else:
        children = parse_components(text, field.datatype, version, encoding_chars, validation_level,
                                    field.structure_by_name)
        if Validator.is_tolerant(validation_level) and is_base_datatype(field.datatype, version) and \
                len(children) > 1:
            field.datatype = None
        field.children = children
    return field
Example #12
0
def parse_field(text, name=None, version=None, encoding_chars=None, validation_level=None,
                reference=None, force_varies=False):
    """
    Parse the given ER7-encoded field and return an instance of :class:`Field <hl7apy.core.Field>`.

    :type text: ``str``
    :param text: the ER7-encoded string containing the fields to be parsed

    :type name: ``str``
    :param name: the field name (e.g. MSH_7)

    :type version: ``str``
    :param version: the HL7 version (e.g. "2.5"), or ``None`` to use the default
        (see :func:`set_default_version <hl7apy.set_default_version>`)

    :type encoding_chars: ``dict``
    :param encoding_chars: a dictionary containing the encoding chars or None to use the default
        (see :func:`set_default_encoding_chars <hl7apy.set_default_encoding_chars>`)

    :type validation_level: ``int``
    :param validation_level: the validation level. Possible values are those defined in
        :class:`VALIDATION_LEVEL <hl7apy.consts.VALIDATION_LEVEL>` class or ``None`` to use the default
        validation level (see :func:`set_default_validation_level <hl7apy.set_default_validation_level>`)

    :type reference: ``dict``
    :param reference: a dictionary containing the element structure returned by
        :func:`load_reference <hl7apy.load_reference>` or :func:`find_reference <hl7apy.find_reference>`
        or belonging to a message profile

    :type force_varies: ``boolean``
    :param force_varies: flag that force the fields to use a varies structure when no reference is found.
        It is used when a segment ends with a field of type varies that thus support infinite children

    :return: an instance of :class:`Field <hl7apy.core.Field>`

    >>> field = "NUCLEAR^NELDA^W"
    >>> nk1_2 = parse_field(field, name="NK1_2")
    >>> print(nk1_2)
    <Field NK1_2 (NAME) of type XPN>
    >>> print(nk1_2.to_er7())
    NUCLEAR^NELDA^W
    >>> unknown = parse_field(field)
    >>> print(unknown)
    <Field of type None>
    >>> print(unknown.to_er7())
    NUCLEAR^NELDA^W
    """
    version = _get_version(version)
    encoding_chars = _get_encoding_chars(encoding_chars, version)
    validation_level = _get_validation_level(validation_level)

    try:
        field = Field(name, version=version, validation_level=validation_level, reference=reference)
    except InvalidName:
        if force_varies:
            reference = ('leaf', None, 'varies', None, None, -1)
            field = Field(name, version=version, validation_level=validation_level, reference=reference)
        else:
            field = Field(version=version, validation_level=validation_level, reference=reference)

    if name in ('MSH_1', 'MSH_2'):
        s = SubComponent(datatype='ST', value=text, validation_level=validation_level, version=version)
        c = Component(datatype='ST', validation_level=validation_level, version=version)
        c.add(s)
        field.add(c)
    else:
        children = parse_components(text, field.datatype, version, encoding_chars, validation_level,
                                    field.structure_by_name)
        if Validator.is_tolerant(validation_level) and is_base_datatype(field.datatype, version) and \
                len(children) > 1:
            field.datatype = None
        field.children = children
    return field