diff options
| author | Ralph Amissah <ralph.amissah@gmail.com> | 2026-09-08 08:28:24 -0400 |
|---|---|---|
| committer | Ralph Amissah <ralph.amissah@gmail.com> | 2026-09-09 17:56:14 -0400 |
| commit | 9af1dda9b03f745aa2b7700419574e2e3e59fde2 (patch) | |
| tree | 62ebe97f85a6bac96aeede065c9137c087296c84 /src/sisudoc | |
| parent | a reader for the ocda db, and its round trip (diff) | |
ocda db: built from the .ssp, (tethered)
The ocda database is now built from the .ssp itself: the writer's
lines are emitted, read straight back by ssp_in, and the objects
that come out populate the database. Anything the .ssp does not
carry, the database will not have either, by construction (rather
than by test).
[instead of as previously through a second walk over the in-memory
abstraction]
- spineAbstractionTxt is split: sspDocumentLines(doc) returns the
whole .ssp as lines, and the file writer emits them. Output
neutral, the reference test confirms.
- spineAbstractionDb takes the abstraction as an argument rather
than taking doc.abstraction.
- sspRoundTripAbstraction(doc) in ssp_in is the join: lines out,
lines in, abstraction returned. Both call sites in spine.d use
it.
- the header blocks and the image blobs still come from
doc_matters (as: the .ssp does not carry image bytes).
All (35) markup sample sourced databases built through the .ssp
have byte identical SQL dumps to the one built directly before the
change.
That comparison also found one reader inaccuracy, which the .ssp
round trip could not see because the writer omits the field either
way: an absent identifier was restored as the ocn in every case,
but for an object with no ocn it was empty ("a"~N identifiers are
always written). Fixed; the two artefacts checking each other is
what caught it.
(assisted by Claude-Code)
Diffstat (limited to 'src/sisudoc')
| -rw-r--r-- | src/sisudoc/ocda/abstraction/ssp.d | 11 | ||||
| -rw-r--r-- | src/sisudoc/ocda/abstraction/ssp_in.d | 19 | ||||
| -rw-r--r-- | src/sisudoc/outputs/io_out/create_abstraction_db.d | 9 | ||||
| -rw-r--r-- | src/sisudoc/spine.d | 20 |
4 files changed, 49 insertions, 10 deletions
diff --git a/src/sisudoc/ocda/abstraction/ssp.d b/src/sisudoc/ocda/abstraction/ssp.d index 6aa55c2..3e80956 100644 --- a/src/sisudoc/ocda/abstraction/ssp.d +++ b/src/sisudoc/ocda/abstraction/ssp.d @@ -414,7 +414,11 @@ template spineAbstractionTxt() { import std.string; import std.array; mixin sspObjectRecord; - void spineAbstractionTxt(D)(D doc) { + /+ ↓ the whole .ssp for a document, as lines. the file writer below emits + these, and the abstraction db is built by reading them back, so the + database cannot carry anything the .ssp does not + +/ + string[] sspDocumentLines(D)(D doc) { auto doc_abstraction = doc.abstraction; auto doc_matters = doc.matters; string[] output; @@ -556,6 +560,11 @@ template spineAbstractionTxt() { output ~= "}"; output ~= ""; } + return output; + } + void spineAbstractionTxt(D)(D doc) { + auto doc_matters = doc.matters; + string[] output = sspDocumentLines(doc); /+ ↓ write to file +/ /+ path: <output_path>/<language>/abstraction/<doc_uid_out>.ssp +/ string out_root = (doc_matters.output_path.length > 0) diff --git a/src/sisudoc/ocda/abstraction/ssp_in.d b/src/sisudoc/ocda/abstraction/ssp_in.d index f0fb963..220bfe3 100644 --- a/src/sisudoc/ocda/abstraction/ssp_in.d +++ b/src/sisudoc/ocda/abstraction/ssp_in.d @@ -198,11 +198,16 @@ template spineAbstractionRead() { obj.metainfo.identifier = _tail[_sp + 1 .. $]; } else { obj.metainfo.heading_lev_markup = _levOfMarkedUp(_tail); - obj.metainfo.identifier = obj.metainfo.ocn.to!string; + /+ ↓ omitted means it equals the ocn, and for an object with no ocn + it was empty: "a"~N identifiers are always written + +/ + obj.metainfo.identifier = (obj.metainfo.ocn != 0) + ? obj.metainfo.ocn.to!string : ""; } } else { obj.metainfo.is_a = _rest; - obj.metainfo.identifier = obj.metainfo.ocn.to!string; + obj.metainfo.identifier = (obj.metainfo.ocn != 0) + ? obj.metainfo.ocn.to!string : ""; } obj.metainfo.is_of_section = section; continue; @@ -327,6 +332,16 @@ template spineAbstractionRead() { } return doc; } + /+ ↓ the abstraction as it survives a trip through the .ssp text: emitted + as lines by the writer, read straight back. what a consumer built + from this cannot see, the .ssp does not carry, which is what makes a + second artefact built from it unable to drift + +/ + auto sspRoundTripAbstraction(D)(D doc) { + import sisudoc.ocda.abstraction.ssp; + mixin spineAbstractionTxt; + return sspRead(sspDocumentLines(doc)).abstraction; + } SSPdocument sspReadFile(string file_path) { string[] _lines; try { diff --git a/src/sisudoc/outputs/io_out/create_abstraction_db.d b/src/sisudoc/outputs/io_out/create_abstraction_db.d index 3a6a85e..cc90cb3 100644 --- a/src/sisudoc/outputs/io_out/create_abstraction_db.d +++ b/src/sisudoc/outputs/io_out/create_abstraction_db.d @@ -60,9 +60,12 @@ template spineAbstractionDb() { import std.array; import d2sqlite3; import sisudoc.outputs.io_out.paths_output; - - void spineAbstractionDb(D)(D doc) { - auto doc_abstraction = doc.abstraction; + /+ ↓ the abstraction is passed in rather than taken from doc, because the + caller hands over one that has been through the .ssp: written as text + and read back. so the database is a function of the .ssp and cannot + carry anything the .ssp does not + +/ + void spineAbstractionDb(D,A)(D doc, A doc_abstraction) { auto doc_matters = doc.matters; /+ ↓ determine output path +/ diff --git a/src/sisudoc/spine.d b/src/sisudoc/spine.d index 4bf714d..4695c60 100644 --- a/src/sisudoc/spine.d +++ b/src/sisudoc/spine.d @@ -1417,10 +1417,16 @@ string program_name = "spine"; import sisudoc.ocda.abstraction.ssp; spineAbstractionTxt!()(doc); } - /+ ↓ document abstraction sqlite database +/ + /+ ↓ document abstraction sqlite database, built from the .ssp: the + lines are emitted and read straight back, and the objects that + come out are what is written, so the database cannot carry + anything the .ssp does not + +/ if (doc.matters.opt.action.show_abstraction_db) { + import sisudoc.ocda.abstraction.ssp_in; import sisudoc.outputs.io_out.create_abstraction_db; - spineAbstractionDb!()(doc); + mixin spineAbstractionRead; + spineAbstractionDb!()(doc, sspRoundTripAbstraction(doc)); } if (doc.matters.opt.action.curate) { auto _hvst = spineMetaDocCurate!()(doc.matters, hvst); @@ -1526,10 +1532,16 @@ string program_name = "spine"; import sisudoc.ocda.abstraction.ssp; spineAbstractionTxt!()(doc); } - /+ ↓ document abstraction sqlite database +/ + /+ ↓ document abstraction sqlite database, built from the .ssp: the + lines are emitted and read straight back, and the objects that + come out are what is written, so the database cannot carry + anything the .ssp does not + +/ if (doc.matters.opt.action.show_abstraction_db) { + import sisudoc.ocda.abstraction.ssp_in; import sisudoc.outputs.io_out.create_abstraction_db; - spineAbstractionDb!()(doc); + mixin spineAbstractionRead; + spineAbstractionDb!()(doc, sspRoundTripAbstraction(doc)); } if (doc.matters.opt.action.curate) { auto _hvst = spineMetaDocCurate!()(doc.matters, hvst); |
