feat(import): pass generation from JSON in PersonTreeImporter (#689)

Reads the optional `generation` integer from the canonical tree JSON and
routes it into PersonUpsertCommand. Out-of-range values are skip-and-
warned with the same policy as the register importer.

Tree imports run after register (per CanonicalImportOrchestrator); a
tree-confirmed integer overwrites a register-parsed value — both sides
are "canonical" in preferHuman terms (neither is a human edit).

Refs #689

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-05-28 15:32:27 +02:00
parent df0037cba2
commit a68a822c13
2 changed files with 79 additions and 0 deletions

View File

@@ -79,12 +79,32 @@ public class PersonTreeImporter {
.notes(blankToNull(text(node, "notes")))
.birthYear(intOrNull(node, "birthYear"))
.deathYear(intOrNull(node, "deathYear"))
.generation(generationOrNull(node, personId))
.familyMember(node.path("familyMember").asBoolean(false))
.personType(PersonType.PERSON)
.provisional(false)
.build();
}
/**
* Returns the JSON {@code generation} value if present and in
* {@value #GENERATION_MIN}..{@value #GENERATION_MAX}; null otherwise. Out-of-range
* values log a WARN but never abort the batch — mirrors the register-importer
* skip-and-warn policy.
*/
private static Integer generationOrNull(JsonNode node, String personId) {
Integer raw = intOrNull(node, "generation");
if (raw == null) return null;
if (raw < GENERATION_MIN || raw > GENERATION_MAX) {
log.warn("Skipping out-of-range generation '{}' for person {}", raw, personId);
return null;
}
return raw;
}
private static final int GENERATION_MIN = 0;
private static final int GENERATION_MAX = 10;
private int createRelationships(JsonNode relationships, Map<String, UUID> idByRowId) {
int created = 0;
for (JsonNode node : relationships) {