Esempio n. 1
0
def copy_coding(source: message.Message, target: message.Message):
    """Copies all fields from source to target "Coding" messages.

  Args:
    source: The FHIR coding instance to copy from.
    target: The FHIR coding instance to copy to.

  Raises:
    InvalidFhirError: In the event that source or target is not a type/profile
    of Coding.
  """
    if not fhir_types.is_type_or_profile_of_coding(source.DESCRIPTOR):
        raise fhir_errors.InvalidFhirError(
            f'Source: {source.DESCRIPTOR.full_name} '
            'is not a type or profile of Coding.')

    if not fhir_types.is_type_or_profile_of_coding(target.DESCRIPTOR):
        raise fhir_errors.InvalidFhirError(
            f'Target: {target.DESCRIPTOR.full_name} '
            'is not a type or profile of Coding.')

    if proto_utils.are_same_message_type(source.DESCRIPTOR, target.DESCRIPTOR):
        target.CopyFrom(source)
        return

    # Copy fields present in both profiled and unprofiled codings.
    proto_utils.copy_common_field(source, target, 'id')
    proto_utils.copy_common_field(source, target, 'extension')
    proto_utils.copy_common_field(source, target, 'version')
    proto_utils.copy_common_field(source, target, 'display')
    proto_utils.copy_common_field(source, target, 'user_selected')

    # Copy the "code" field from source to target
    source_code = proto_utils.get_value_at_field(source, 'code')
    copy_code(source_code, proto_utils.set_in_parent_or_add(target, 'code'))

    target_system_field = target.DESCRIPTOR.fields_by_name.get('system')

    # TODO: This will fail if there is a target system field,
    # *and* a source system field, since in this case the source code will not
    # contain the system information, the containing Coding would.  In general,
    # it's not quite right to get the system from Code, since unprofiled codes
    # don't contain system information.  In practice, this isn't a problem,
    # because the only kind of profiled Codings we currently support are
    # Codings with typed Codes (which contain source information) but this is
    # not neccessary according to FHIR spec.
    if target_system_field is not None:
        source_system_str = get_system_for_code(source_code)
        target_system_uri = proto_utils.set_in_parent_or_add(
            target, target_system_field)
        proto_utils.set_value_at_field(target_system_uri, 'value',
                                       source_system_str)
Esempio n. 2
0
def copy_coding(source: message.Message, target: message.Message):
    """Copies all fields from source to target "Coding" messages.

  Args:
    source: The FHIR coding instance to copy from.
    target: The FHIR coding instance to copy to.

  Raises:
    InvalidFhirError: In the event that source or target is not a type/profile
    of Coding.
  """
    if not fhir_types.is_type_or_profile_of_coding(source.DESCRIPTOR):
        raise fhir_errors.InvalidFhirError(
            f'Source: {source.DESCRIPTOR.full_name} '
            'is not a type or profile of Coding.')

    if not fhir_types.is_type_or_profile_of_coding(target.DESCRIPTOR):
        raise fhir_errors.InvalidFhirError(
            f'Target: {target.DESCRIPTOR.full_name} '
            'is not a type or profile of Coding.')

    if proto_utils.are_same_message_type(source.DESCRIPTOR, target.DESCRIPTOR):
        target.CopyFrom(source)
        return

    # Copy fields present in both profiled and unprofiled codings.
    proto_utils.copy_common_field(source, target, 'id')
    proto_utils.copy_common_field(source, target, 'extension')
    proto_utils.copy_common_field(source, target, 'version')
    proto_utils.copy_common_field(source, target, 'display')
    proto_utils.copy_common_field(source, target, 'user_selected')

    # Copy the "code" field from source to target
    source_code = proto_utils.get_value_at_field(source, 'code')
    copy_code(source_code, proto_utils.set_in_parent_or_add(target, 'code'))

    target_system_field = target.DESCRIPTOR.fields_by_name.get('system')
    if target_system_field is not None:
        source_system_str = get_system_for_code(source_code)
        target_system_uri = proto_utils.set_in_parent_or_add(
            target, target_system_field)
        proto_utils.set_value_at_field(target_system_uri, 'value',
                                       source_system_str)
Esempio n. 3
0
def copy_code(source: message.Message, target: message.Message):
    """Adds all fields from source to target.

  Args:
    source: The FHIR Code instance to copy from.
    target: The target FHIR Code instance to copy to.
  """
    if not fhir_types.is_type_or_profile_of_code(source.DESCRIPTOR):
        raise fhir_errors.InvalidFhirError(
            f'Source: {source.DESCRIPTOR.full_name} '
            'is not type or profile of Code.')

    if not fhir_types.is_type_or_profile_of_code(target.DESCRIPTOR):
        raise fhir_errors.InvalidFhirError(
            f'Target: {target.DESCRIPTOR.full_name} '
            'is not type or profile of Code.')

    if proto_utils.are_same_message_type(source.DESCRIPTOR, target.DESCRIPTOR):
        target.CopyFrom(source)
        return

    source_value_field = source.DESCRIPTOR.fields_by_name.get('value')
    target_value_field = target.DESCRIPTOR.fields_by_name.get('value')
    if source_value_field is None or target_value_field is None:
        raise fhir_errors.InvalidFhirError(
            'Unable to copy code from '
            f'{source.DESCRIPTOR.full_name} '
            f'to {target.DESCRIPTOR.full_name}.')

    proto_utils.copy_common_field(source, target, 'id')
    proto_utils.copy_common_field(source, target, 'extension')

    # Handle specialized codes
    if (source_value_field.type not in _CODE_TYPES
            or target_value_field.type not in _CODE_TYPES):
        raise ValueError(
            f'Unable to copy from {source.DESCRIPTOR.full_name} '
            f'to {target.DESCRIPTOR.full_name}. Must have a field '
            'of TYPE_ENUM or TYPE_STRING.')

    source_value = proto_utils.get_value_at_field(source, source_value_field)
    if source_value_field.type == target_value_field.type:
        # Perform a simple assignment if value_field types are equivalent
        proto_utils.set_value_at_field(target, target_value_field,
                                       source_value)
    else:
        # Otherwise, we need to transform the value prior to assignment...
        if source_value_field.type == descriptor.FieldDescriptor.TYPE_STRING:
            source_enum_value = code_string_to_enum_value_descriptor(
                source_value, target_value_field.enum_type)
            proto_utils.set_value_at_field(target, target_value_field,
                                           source_enum_value.number)
        elif source_value_field.type == descriptor.FieldDescriptor.TYPE_ENUM:
            source_string_value = enum_value_descriptor_to_code_string(
                source_value_field.enum_type.values_by_number[source_value])
            proto_utils.set_value_at_field(target, target_value_field,
                                           source_string_value)
        else:  # Should never hit
            raise ValueError('Unexpected generic value field type: '
                             f'{source_value_field.type}. Must be a field of '
                             'TYPE_ENUM or TYPE_STRING in order to copy.')