Beispiel #1
0
def get_external_ids_from_entity(entity: DatabaseEntity):
    external_ids = []
    if isinstance(entity, schema.StatePerson):
        for external_id in entity.external_ids:
            if external_id:
                external_ids.append(external_id.external_id)
    else:
        if entity.get_external_id():
            external_ids.append(entity.get_external_id())
    return external_ids
def get_or_create_placeholder_child(parent_entity: DatabaseEntity,
                                    child_field_name: str,
                                    child_class: Type[DatabaseEntity],
                                    **child_kwargs):
    """Checks all the entities in the |parent_entity|'s field |child_field_name|. If there is a placeholder entity,
    returns that. Otherwise creates a new placeholder entity of type |child_class| on the parent's |child_field_name|
    using |child_kw_args|.
    """
    children = parent_entity.get_field_as_list(child_field_name)
    placeholder_children = [c for c in children if is_placeholder(c)]

    if placeholder_children:
        return placeholder_children[0]

    logging.info(
        'No placeholder children on entity with id [%s] of type [%s] exist on field [%s]. Have to create one.',
        parent_entity.get_external_id(), parent_entity.get_entity_name(),
        child_field_name)
    new_child = child_class(**child_kwargs)
    if not is_placeholder(new_child):
        raise EntityMatchingError(
            f'Child created with kwargs is not a placeholder [{child_kwargs}]',
            parent_entity.get_entity_name())

    children.append(new_child)
    parent_entity.set_field_from_list(child_field_name, children)
    return new_child
Beispiel #3
0
def _base_entity_match(
        a: DatabaseEntity,
        b: DatabaseEntity,
        skip_fields: Set[str],
        allow_null_mismatch: bool = False
) -> bool:
    """Returns whether two objects of the same type are an entity match.

    Args:
        a: The first entity to match
        b: The second entity to match
        skip_fields: A list of names of fields that should be ignored when determining if two objects match based on
            flat fields.
        allow_null_mismatch: Allow for two objects to still match if one has a null value in a field where the other's
            is nonnull.
    """

    # Placeholders never match
    if is_placeholder(a) or is_placeholder(b):
        return False

    # Compare external ids if one is present
    if a.get_external_id() or b.get_external_id():
        return a.get_external_id() == b.get_external_id()

    # Compare all flat fields of the two entities
    all_set_flat_field_names = \
        get_set_entity_field_names(a, EntityFieldType.FLAT_FIELD) | \
        get_set_entity_field_names(b, EntityFieldType.FLAT_FIELD)
    for field_name in all_set_flat_field_names:
        # Skip primary key
        if field_name == a.get_class_id_name() or field_name in skip_fields:
            continue
        a_field = a.get_field(field_name)
        b_field = b.get_field(field_name)

        if allow_null_mismatch and (a_field is None or b_field is None):
            # Do not disqualify a match if one of the fields is null
            continue

        if a_field != b_field:
            return False

    return True
Beispiel #4
0
def _base_entity_match(a: DatabaseEntity, b: DatabaseEntity) -> bool:
    # Placeholders never match
    if is_placeholder(a) or is_placeholder(b):
        return False

    # Compare external ids if one is present
    if a.get_external_id() or b.get_external_id():
        return a.get_external_id() == b.get_external_id()

    # Compare all flat fields of the two entities
    all_set_flat_field_names = \
        get_set_entity_field_names(a, EntityFieldType.FLAT_FIELD) | \
        get_set_entity_field_names(b, EntityFieldType.FLAT_FIELD)
    for field_name in all_set_flat_field_names:
        # Skip primary key
        if field_name == a.get_class_id_name():
            continue
        a_field = a.get_field(field_name)
        b_field = b.get_field(field_name)
        if a_field != b_field:
            return False

    return True
Beispiel #5
0
def _is_match(*,
              ingested_entity: DatabaseEntity,
              db_entity: DatabaseEntity) -> bool:
    """Returns true if the provided |ingested_entity| matches the provided
    |db_entity|. Otherwise returns False.
    """
    if not ingested_entity or not db_entity:
        return ingested_entity == db_entity

    if ingested_entity.__class__ != db_entity.__class__:
        raise EntityMatchingError(
            f"is_match received entities of two different classes: "
            f"ingested entity {ingested_entity.__class__.__name__} and "
            f"db_entity {db_entity.__class__.__name__}",
            ingested_entity.get_entity_name())

    if not isinstance(ingested_entity, DatabaseEntity):
        raise EntityMatchingError(
            f"Unexpected type for ingested entity[{type(ingested_entity)}]",
            'unknown')
    if not isinstance(db_entity, DatabaseEntity):
        raise EntityMatchingError(
            f"Unexpected type for db entity[{type(db_entity)}]",
            'unknown')

    if isinstance(ingested_entity, schema.StatePerson):
        db_entity = cast(schema.StatePerson, db_entity)
        for ingested_external_id in ingested_entity.external_ids:
            for db_external_id in db_entity.external_ids:
                if _is_match(ingested_entity=ingested_external_id,
                             db_entity=db_external_id):
                    return True
        return False

    # Aside from people, all entities are state specific.
    if ingested_entity.get_field('state_code') \
            != db_entity.get_field('state_code'):
        return False

    # TODO(2671): Update all person attributes below to use complete entity
    # equality instead of just comparing individual fields.
    if isinstance(ingested_entity, schema.StatePersonExternalId):
        db_entity = cast(schema.StatePersonExternalId, db_entity)
        return ingested_entity.external_id == db_entity.external_id \
            and ingested_entity.id_type == db_entity.id_type

    # As person has already been matched, assume that any of these 'person
    # attribute' entities are matches if specific attributes match.
    if isinstance(ingested_entity, schema.StatePersonAlias):
        db_entity = cast(schema.StatePersonAlias, db_entity)
        return ingested_entity.full_name == db_entity.full_name
    if isinstance(ingested_entity, schema.StatePersonRace):
        db_entity = cast(schema.StatePersonRace, db_entity)
        return ingested_entity.race == db_entity.race
    if isinstance(ingested_entity, schema.StatePersonEthnicity):
        db_entity = cast(schema.StatePersonEthnicity, db_entity)
        return ingested_entity.ethnicity == db_entity.ethnicity

    if isinstance(ingested_entity,
                  (schema.StateSupervisionViolationResponseDecisionEntry,
                   schema.StateSupervisionViolatedConditionEntry,
                   schema.StateSupervisionViolationTypeEntry,
                   schema.StateSupervisionCaseTypeEntry)):
        return _base_entity_match(ingested_entity, db_entity)

    # Placeholders entities are considered equal
    if ingested_entity.get_external_id() is None \
            and db_entity.get_external_id() is None:
        return is_placeholder(ingested_entity) and is_placeholder(db_entity)
    return ingested_entity.get_external_id() == db_entity.get_external_id()