MetamodelVersionRowMapper

Translate metamodel versions to and from the property maps the Neo4j graph store reads and writes.

Neo4j properties are scalars and flat arrays, while a version's content is lists, a map of label sets, and a map of property signature sets, so all four structural fields are serialized to JSON strings. JSON also handles names containing pipes, tabs, newlines and quotes, which these names routinely do: they come out of LLM extraction.

The save instant is informational, and is written twice. savedAt is the ISO-8601 string, which is what you want when you're looking at a node and wondering when it landed. savedAtEpochMillis is the same instant as a number, for filtering or grouping by time in an ad-hoc query; the string is no use for that, since Instant.toString() drops the fraction entirely at a whole second and 'Z' sorts above '.', making "…T00:00:00Z" compare greater than "…T00:00:00.500Z".

Neither field orders the history. The sequence property does that; see DrivineMetamodelVersionStore for why a clock can't express write order. Nothing here writes or reads sequence: Cypher assigns it off a per-schema counter, and it is storage bookkeeping, so it stays out of the strict round-trip below.

Reads are strict. A property this mapper wrote must be present when it is read again; a node missing one is corrupt, so the accessor throws and the store's surrounding guard skips the row with a warning. An empty string is corrupt too: an empty collection is written as [] or {}, so "" never comes from this mapper, and it fails the read like any other bad JSON.

Two things are optional, and absent means "no former names were declared": the version-level entityTypeAliases property, and the aliases field inside a stored property signature. Writing them only when they hold something means an alias-free stamp stores exactly the properties this mapper stored before either existed, and a node written by that older build reads back here as a stamp declaring neither. Aliases feed the content hash, so a stamp carrying them and failing to store them would fail its own integrity check on the way back in and be unreadable for good.

Functions

Link copied to clipboard
fun bindMap(version: <Error class: unknown class>, savedAt: Instant): Map<String, Any?>

Bind values for a write. The natural key is (schemaName, contentHash).

Link copied to clipboard
fun fromRow(row: Map<*, *>): <Error class: unknown class>

Rebuild a MetamodelVersion from a returned node's property map, and check its integrity on the way.