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
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
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
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()