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 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 #3
0
 def _check_table_compliance(el, ref, warns):
     table = ref[4]
     if table is not None:
         try:
             table_ref = load_reference(table, 'Table', el.version)
         except ChildNotFound:
             pass
         else:
             table_children = table_ref[1]
             if el.to_er7() not in table_children:
                 warns.append(ValidationWarning("Value {} not in table {} in element {}.{}".
                                                format(el.to_er7(), table, el.parent.name,
                                                       el.name)))
Example #4
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