Retrieve tree of SectionTA from articles CONTEXTE.TEXTE.TM instead of using the SectionTA dates

This commit is contained in:
Emmanuel 2024-12-12 08:03:48 +01:00
parent 6837dff057
commit c5777427f8

View file

@ -7,19 +7,24 @@ import sade from "sade"
import type {
JorfArticle,
JorfArticleTm,
JorfSectionTa,
JorfSectionTaLienArt,
JorfSectionTaLienSectionTa,
JorfSectionTaStructure,
JorfTextelr,
JorfTextelrLienArt,
JorfTexteVersion,
} from "$lib/legal/jorf"
import type {
LegiArticle,
LegiArticleTm,
LegiSectionTa,
LegiSectionTaLienArt,
LegiSectionTaLienSectionTa,
LegiSectionTaStructure,
LegiTextelr,
LegiTextelrLienArt,
LegiTexteVersion,
} from "$lib/legal/legi"
import type { ArticleLienDb, TexteVersionLienDb } from "$lib/legal/shared"
@ -57,10 +62,101 @@ interface Context {
texteVersionById: Record<string, JorfTexteVersion | LegiTexteVersion | null>
}
interface NodeBase {
children?: SectionTaNode[]
}
interface SectionTaNode extends NodeBase {
liensArticles?: Array<JorfSectionTaLienArt | LegiSectionTaLienArt>
titreTm: {
"#text"?: string
"@debut": string
"@fin": string
"@id": string // ID of a SectionTa
}
}
interface TextelrNode extends NodeBase {
liensArticles?: Array<JorfTextelrLienArt | LegiTextelrLienArt>
}
interface TexteManquant {
date: string
}
async function addArticleToTree(
context: Context,
tree: TextelrNode,
encounteredArticlesIds: Set<string>,
lienArticle:
| JorfTextelrLienArt
| LegiTextelrLienArt
| JorfSectionTaLienArt
| LegiSectionTaLienArt,
): Promise<void> {
if (encounteredArticlesIds.has(lienArticle["@id"])) {
return
}
encounteredArticlesIds.add(lienArticle["@id"])
const article = await getOrLoadArticle(context, lienArticle["@id"])
await addArticleToTreeNode(
context,
tree,
article.CONTEXTE.TEXTE.TM,
lienArticle,
article,
)
}
async function addArticleToTreeNode(
context: Context,
node: SectionTaNode | TextelrNode,
tm: JorfArticleTm | LegiArticleTm | undefined,
lienArticle:
| JorfTextelrLienArt
| LegiTextelrLienArt
| JorfSectionTaLienArt
| LegiSectionTaLienArt,
article: JorfArticle | LegiArticle,
): Promise<void> {
if (tm === undefined) {
// Article is directly in textelr.
const liensArticles = (node.liensArticles ??= [])
liensArticles.push(lienArticle as JorfTextelrLienArt | LegiTextelrLienArt)
} else {
let foundTitreTm: SectionTaNode["titreTm"]
if (Array.isArray(tm.TITRE_TM)) {
// LegiArticleTm
const sortedTitreTmArray = tm.TITRE_TM.toSorted((titreTm1, titreTm2) =>
titreTm1["@debut"].localeCompare(titreTm2["@debut"]),
)
if (lienArticle["@debut"] < sortedTitreTmArray[0]["@debut"]) {
// Assume that the @debut of the first TITRE_TM is wrong.
foundTitreTm = sortedTitreTmArray[0]
} else if (lienArticle["@debut"] >= sortedTitreTmArray.at(-1)!["@fin"]) {
// Assume that the @fin of the last TITRE_TM is wrong.
foundTitreTm = sortedTitreTmArray.at(-1)!
} else {
foundTitreTm = sortedTitreTmArray.find(
(titreTm) => lienArticle["@debut"] < titreTm["@fin"],
)!
}
} else {
// JorfArticleTm
foundTitreTm = tm.TITRE_TM
}
const children = (node.children ??= [])
const lastChild = children.at(-1)
if (foundTitreTm["@id"] === lastChild?.titreTm["@id"]) {
addArticleToTreeNode(context, lastChild, tm.TM, lienArticle, article)
} else {
const newChild: SectionTaNode = { titreTm: foundTitreTm }
children.push(newChild)
addArticleToTreeNode(context, newChild, tm.TM, lienArticle, article)
}
}
}
async function addModifyingArticleId(
context: Context,
modifyingArticleId: string,
@ -79,6 +175,7 @@ async function addModifyingArticleId(
}
if (
action === "CREATE" &&
modifyingArticleDateSignature !== "2999-01-01" &&
modifyingArticleDateSignature > modifiedDateDebut
) {
console.warn(
@ -86,7 +183,11 @@ async function addModifyingArticleId(
)
return
}
if (action === "DELETE" && modifyingArticleDateSignature > modifiedDateFin) {
if (
action === "DELETE" &&
modifyingArticleDateSignature !== "2999-01-01" &&
modifyingArticleDateSignature > modifiedDateFin
) {
console.warn(
`Ignoring article suppresseur ${modifyingArticleId} because its date signature ${modifyingArticleDateSignature} doesn't match date fin ${modifiedDateFin} of ${modifiedId}`,
)
@ -162,13 +263,21 @@ async function addModifyingTextId(
(consolidatedTextModifyingTextsIdsByAction[action] ??= new Set())
consolidatedTextModifyingTextsIds.add(modifyingTextId)
} else {
if (action === "CREATE" && modifyingTextDateSignature > modifiedDateDebut) {
if (
action === "CREATE" &&
modifyingTextDateSignature !== "2999-01-01" &&
modifyingTextDateSignature > modifiedDateDebut
) {
console.warn(
`Ignoring creating text ${modifyingTextId} because its date signature ${modifyingTextDateSignature} doesn't match date début ${modifiedDateDebut} of ${modifiedId}`,
)
return
}
if (action === "DELETE" && modifyingTextDateSignature > modifiedDateFin) {
if (
action === "DELETE" &&
modifyingTextDateSignature !== "2999-01-01" &&
modifyingTextDateSignature > modifiedDateFin
) {
console.warn(
`Ignoring texte suppresseur ${modifyingTextId} because its date signature ${modifyingTextDateSignature} doesn't match date fin ${modifiedDateFin} of ${modifiedId}`,
)
@ -358,23 +467,10 @@ async function exportConsolidatedTextToGit(
}
}
for await (const {
lienSectionTa,
liensSectionTa,
parentsSectionTa,
sectionTa,
} of walkStructureTree(
for await (const { parentsSectionTa, sectionTa } of walkStructureTree(
context,
consolidatedTextelrStructure as LegiSectionTaStructure,
)) {
await registerLegiSectionTaModifiers(
context,
parentsSectionTa.length + 1,
liensSectionTa,
lienSectionTa,
sectionTa as LegiSectionTa,
)
const liensArticles = sectionTa?.STRUCTURE_TA?.LIEN_ART
if (liensArticles !== undefined) {
for (const lienArticle of liensArticles) {
@ -542,7 +638,8 @@ async function exportConsolidatedTextToGit(
).toSorted(([date1], [date2]) => date1.localeCompare(date2))) {
console.log(date)
for (const modifyingTextId of modifyingTextsId.toSorted()) {
const t1 = performance.now()
// Generate tree of SectionTa & articles at this date
const t0 = performance.now()
let modifyingTexteVersion:
| JorfTexteVersion
| LegiTexteVersion
@ -580,17 +677,91 @@ async function exportConsolidatedTextToGit(
` CREATE: ${[...idsByAction.CREATE].toSorted().join(", ")}`,
)
}
const t2 = performance.now()
const t1 = performance.now()
const encounteredArticlesIds = new Set<string>()
const tree: TextelrNode = {}
if (liensArticles !== undefined) {
for (const action of ["DELETE", "CREATE"] as Action[]) {
for (const lienArticle of liensArticles) {
const articleId = lienArticle["@id"]
const modifyingTextIdByAction =
context.modifyingTextIdByActionById[articleId]
if (context.currentInternalIds.has(articleId)) {
if (modifyingTextIdByAction.DELETE === modifyingTextId) {
if (action === "DELETE") {
context.currentInternalIds.delete(articleId)
}
continue
}
} else if (modifyingTextIdByAction.CREATE === modifyingTextId) {
if (action === "CREATE") {
context.currentInternalIds.add(articleId)
}
} else {
continue
}
if (action === "DELETE") {
continue
}
await addArticleToTree(
context,
tree,
encounteredArticlesIds,
lienArticle,
)
}
}
}
for await (const { sectionTa } of walkStructureTree(
context,
consolidatedTextelrStructure as LegiSectionTaStructure,
)) {
const liensArticles = sectionTa?.STRUCTURE_TA?.LIEN_ART
if (liensArticles !== undefined) {
for (const action of ["DELETE", "CREATE"] as Action[]) {
for (const lienArticle of liensArticles) {
const articleId = lienArticle["@id"]
const modifyingTextIdByAction =
context.modifyingTextIdByActionById[articleId]
if (context.currentInternalIds.has(articleId)) {
if (modifyingTextIdByAction.DELETE === modifyingTextId) {
if (action === "DELETE") {
context.currentInternalIds.delete(articleId)
}
continue
}
} else if (modifyingTextIdByAction.CREATE === modifyingTextId) {
if (action === "CREATE") {
context.currentInternalIds.add(articleId)
}
} else {
continue
}
if (action === "DELETE") {
continue
}
await addArticleToTree(
context,
tree,
encounteredArticlesIds,
lienArticle,
)
}
}
}
}
const t2 = performance.now()
await generateTextGitDirectory(
context,
2,
consolidatedTextelr as LegiTextelr,
tree,
consolidatedTexteVersion as LegiTexteVersion,
modifyingTextId,
)
const t3 = performance.now()
const t3 = performance.now()
let messageLines: string | undefined = undefined
let summary: string | undefined = undefined
if (modifyingTextId.startsWith("JORFTEXT")) {
@ -680,8 +851,9 @@ async function exportConsolidatedTextToGit(
.filter((block) => block !== undefined)
.join("\n\n"),
})
const t4 = performance.now()
console.log(`Durations: ${t2 - t1} ${t3 - t2} ${t4 - t3}`)
console.log(`Durations: ${t1 - t0} ${t2 - t1} ${t3 - t2} ${t4 - t3}`)
}
}
}
@ -689,7 +861,7 @@ async function exportConsolidatedTextToGit(
async function generateSectionTaGitDirectory(
context: Context,
depth: number,
lienSectionTa: LegiSectionTaLienSectionTa,
sectionTaNode: SectionTaNode,
sectionTa: LegiSectionTa,
parentRepositoryRelativeDir: string,
modifyingTextId: string,
@ -710,10 +882,8 @@ async function generateSectionTaGitDirectory(
await fs.ensureDir(path.join(context.targetDir, repositoryRelativeDir))
const readmeLinks: Array<{ href: string; title: string }> = []
const liensArticles = sectionTa.STRUCTURE_TA?.LIEN_ART
if (liensArticles !== undefined) {
for (const action of ["DELETE", "CREATE"] as Action[]) {
for (const lienArticle of liensArticles) {
if (sectionTaNode.liensArticles !== undefined) {
for (const lienArticle of sectionTaNode.liensArticles) {
const articleId = lienArticle["@id"]
const article = (await getOrLoadArticle(
context,
@ -732,33 +902,6 @@ async function generateSectionTaGitDirectory(
repositoryRelativeDir,
articleFilename,
)
const modifyingTextIdByAction =
context.modifyingTextIdByActionById[articleId]
if (context.currentInternalIds.has(articleId)) {
if (modifyingTextIdByAction.DELETE === modifyingTextId) {
if (action === "DELETE") {
await git.remove({
dir: context.targetDir,
filepath: articleRepositoryRelativeFilePath,
fs,
})
await fs.remove(
path.join(context.targetDir, articleRepositoryRelativeFilePath),
)
context.currentInternalIds.delete(articleId)
}
continue
}
} else if (modifyingTextIdByAction.CREATE === modifyingTextId) {
if (action === "CREATE") {
context.currentInternalIds.add(articleId)
}
} else {
continue
}
if (action === "DELETE") {
continue
}
await fs.writeFile(
path.join(context.targetDir, articleRepositoryRelativeFilePath),
dedent`
@ -790,13 +933,10 @@ async function generateSectionTaGitDirectory(
readmeLinks.push({ href: articleFilename, title: articleTitle })
}
}
}
const liensSectionTa = sectionTa.STRUCTURE_TA?.LIEN_SECTION_TA
if (liensSectionTa !== undefined) {
for (const action of ["DELETE", "CREATE"] as Action[]) {
for (const lienSectionTa of liensSectionTa) {
const sectionTaId = lienSectionTa["@id"]
if (sectionTaNode.children !== undefined) {
for (const child of sectionTaNode.children) {
const sectionTaId = child.titreTm["@id"]
const sectionTa = (await getOrLoadSectionTa(
context,
sectionTaId,
@ -810,50 +950,16 @@ async function generateSectionTaGitDirectory(
}
}
const sectionTaDirName = sectionTaSlug
const sectionTaRepositoryRelativeDir = path.join(
repositoryRelativeDir,
sectionTaDirName,
)
const modifyingTextIdByAction =
context.modifyingTextIdByActionById[sectionTaId]
if (context.currentInternalIds.has(sectionTaId)) {
if (modifyingTextIdByAction.DELETE === modifyingTextId) {
if (action === "DELETE") {
for (const repositoryRelativeFilePath of await git.listFiles({
dir: context.targetDir,
fs,
})) {
if (
repositoryRelativeFilePath.startsWith(
sectionTaRepositoryRelativeDir + path.sep,
)
) {
await git.remove({
dir: context.targetDir,
filepath: repositoryRelativeFilePath,
fs,
})
}
}
await fs.remove(
path.join(context.targetDir, sectionTaRepositoryRelativeDir),
)
context.currentInternalIds.delete(sectionTaId)
}
continue
}
} else if (modifyingTextIdByAction.CREATE === modifyingTextId) {
if (action === "CREATE") {
context.currentInternalIds.add(sectionTaId)
}
} else {
continue
}
if (action === "DELETE") {
continue
}
readmeLinks.push({ href: sectionTaDirName, title: sectionTaTitle })
}
await generateSectionTaGitDirectory(
context,
depth + 1,
child,
sectionTa,
repositoryRelativeDir,
modifyingTextId,
)
}
}
@ -867,12 +973,12 @@ async function generateSectionTaGitDirectory(
---
${[
["Commentaire", sectionTa.COMMENTAIRE],
["État", lienSectionTa["@etat"]],
["Date de début", lienSectionTa["@debut"]],
["Date de fin", lienSectionTa["@fin"]],
// ["État", lienSectionTa["@etat"]],
["Date de début", sectionTaNode.titreTm["@debut"]],
["Date de fin", sectionTaNode.titreTm["@fin"]],
["Identifiant", sectionTa.ID],
// TODO: Mettre l'URL dans le Git Tricoteuses
["URL", lienSectionTa["@url"]],
// ["URL", lienSectionTa["@url"]],
]
.filter(([, value]) => value !== undefined)
.map(([key, value]) => `${key}: ${value}`)
@ -889,32 +995,12 @@ async function generateSectionTaGitDirectory(
filepath: readmeRepositoryRelativeFilePath,
fs,
})
if (liensSectionTa !== undefined) {
for (const lienSectionTa of liensSectionTa) {
const sectionTaId = lienSectionTa["@id"]
if (context.currentInternalIds.has(sectionTaId)) {
const sectionTa = (await getOrLoadSectionTa(
context,
sectionTaId,
)) as LegiSectionTa
await generateSectionTaGitDirectory(
context,
depth + 1,
lienSectionTa,
sectionTa,
repositoryRelativeDir,
modifyingTextId,
)
}
}
}
}
async function generateTextGitDirectory(
context: Context,
depth: number,
textelr: LegiTextelr,
tree: TextelrNode,
texteVersion: LegiTexteVersion,
modifyingTextId: string,
) {
@ -927,14 +1013,13 @@ async function generateTextGitDirectory(
.trim()
const texteDirName = slugify(texteTitle, "_")
const repositoryRelativeDir = texteDirName
await fs.ensureDir(path.join(context.targetDir, repositoryRelativeDir))
const repositoryDir = path.join(context.targetDir, repositoryRelativeDir)
await fs.remove(repositoryDir)
await fs.ensureDir(repositoryDir)
const readmeLinks: Array<{ href: string; title: string }> = []
const { STRUCT: textelrStructure } = textelr
const liensArticles = textelrStructure?.LIEN_ART
if (liensArticles !== undefined) {
for (const action of ["DELETE", "CREATE"] as Action[]) {
for (const lienArticle of liensArticles) {
if (tree.liensArticles !== undefined) {
for (const lienArticle of tree.liensArticles) {
const articleId = lienArticle["@id"]
const article = (await getOrLoadArticle(
context,
@ -953,33 +1038,6 @@ async function generateTextGitDirectory(
repositoryRelativeDir,
articleFilename,
)
const modifyingTextIdByAction =
context.modifyingTextIdByActionById[articleId]
if (context.currentInternalIds.has(articleId)) {
if (modifyingTextIdByAction.DELETE === modifyingTextId) {
if (action === "DELETE") {
await git.remove({
dir: context.targetDir,
filepath: articleRepositoryRelativeFilePath,
fs,
})
await fs.remove(
path.join(context.targetDir, articleRepositoryRelativeFilePath),
)
context.currentInternalIds.delete(articleId)
}
continue
}
} else if (modifyingTextIdByAction.CREATE === modifyingTextId) {
if (action === "CREATE") {
context.currentInternalIds.add(articleId)
}
} else {
continue
}
if (action === "DELETE") {
continue
}
await fs.writeFile(
path.join(context.targetDir, articleRepositoryRelativeFilePath),
dedent`
@ -1011,13 +1069,10 @@ async function generateTextGitDirectory(
readmeLinks.push({ href: articleFilename, title: articleTitle })
}
}
}
const liensSectionTa = textelrStructure?.LIEN_SECTION_TA
if (liensSectionTa !== undefined) {
for (const action of ["DELETE", "CREATE"] as Action[]) {
for (const lienSectionTa of liensSectionTa) {
const sectionTaId = lienSectionTa["@id"]
if (tree.children !== undefined) {
for (const child of tree.children) {
const sectionTaId = child.titreTm["@id"]
const sectionTa = (await getOrLoadSectionTa(
context,
sectionTaId,
@ -1031,50 +1086,16 @@ async function generateTextGitDirectory(
}
}
const sectionTaDirName = sectionTaSlug
const sectionTaRepositoryRelativeDir = path.join(
repositoryRelativeDir,
sectionTaDirName,
)
const modifyingTextIdByAction =
context.modifyingTextIdByActionById[sectionTaId]
if (context.currentInternalIds.has(sectionTaId)) {
if (modifyingTextIdByAction.DELETE === modifyingTextId) {
if (action === "DELETE") {
for (const repositoryRelativeFilePath of await git.listFiles({
dir: context.targetDir,
fs,
})) {
if (
repositoryRelativeFilePath.startsWith(
sectionTaRepositoryRelativeDir + path.sep,
)
) {
await git.remove({
dir: context.targetDir,
filepath: repositoryRelativeFilePath,
fs,
})
}
}
await fs.remove(
path.join(context.targetDir, sectionTaRepositoryRelativeDir),
)
context.currentInternalIds.delete(sectionTaId)
}
continue
}
} else if (modifyingTextIdByAction.CREATE === modifyingTextId) {
if (action === "CREATE") {
context.currentInternalIds.add(sectionTaId)
}
} else {
continue
}
if (action === "DELETE") {
continue
}
readmeLinks.push({ href: sectionTaDirName, title: sectionTaTitle })
}
await generateSectionTaGitDirectory(
context,
depth + 1,
child,
sectionTa,
repositoryRelativeDir,
modifyingTextId,
)
}
}
@ -1122,26 +1143,6 @@ async function generateTextGitDirectory(
filepath: readmeRepositoryRelativeFilePath,
fs,
})
if (liensSectionTa !== undefined) {
for (const lienSectionTa of liensSectionTa) {
const sectionTaId = lienSectionTa["@id"]
if (context.currentInternalIds.has(sectionTaId)) {
const sectionTa = (await getOrLoadSectionTa(
context,
sectionTaId,
)) as LegiSectionTa
await generateSectionTaGitDirectory(
context,
depth + 1,
lienSectionTa,
sectionTa,
repositoryRelativeDir,
modifyingTextId,
)
}
}
}
}
async function getOrLoadArticle(
@ -1642,324 +1643,6 @@ async function registerLegiArticleModifiers(
}
}
async function registerLegiSectionTaModifiers(
context: Context,
depth: number,
liensSectionTa: LegiSectionTaLienSectionTa[],
lienSectionTa: LegiSectionTaLienSectionTa,
sectionTa: LegiSectionTa,
): Promise<void> {
const sectionTaId = sectionTa.ID
const sectionTaIds = [
sectionTaId,
context.jorfCreatorIdById[sectionTaId],
].filter((id) => id !== undefined)
const sectionTaDateDebut = lienSectionTa["@debut"]
const sectionTaDateFin = lienSectionTa["@fin"]
console.log(
`${sectionTa.ID} ${" ".repeat(depth)}${sectionTa.TITRE_TA?.replace(/\s+/g, " ") ?? sectionTa.ID} (${sectionTaDateDebut}${sectionTaDateFin === "2999-01-01" ? "…" : lienSectionTa["@fin"]}, ${lienSectionTa["@etat"]})`,
)
for (const articleLien of await db<ArticleLienDb[]>`
SELECT * FROM article_lien WHERE id IN ${db(sectionTaIds)}
`) {
if (articleLien.article_id in context.consolidatedTextInternalIds) {
// Ignore internal links because a LEGI texte can't modify itself.
continue
}
console.log(
`${" ".repeat(20)} ${" ".repeat(depth + 1)}${articleLien.article_id} cible: ${articleLien.cible} typelien: ${articleLien.typelien}`,
)
assert.strictEqual(articleLien.cidtexte, context.consolidatedTextCid)
assert(articleLien.article_id.startsWith("LEGIARTI"))
if (
(articleLien.typelien === "ABROGATION" && articleLien.cible) ||
(articleLien.typelien === "ABROGE" && !articleLien.cible) ||
(articleLien.typelien === "TRANSFERE" && !articleLien.cible)
) {
await addModifyingArticleId(
context,
articleLien.article_id,
"DELETE",
sectionTaId,
sectionTaDateDebut,
sectionTaDateFin,
)
} else if (
(articleLien.typelien === "CITATION" && !articleLien.cible) ||
(articleLien.typelien === "PEREMPTION" && articleLien.cible)
) {
// Ignore link.
} else if (
(articleLien.typelien === "CREATION" && articleLien.cible) ||
(articleLien.typelien === "CREE" && !articleLien.cible) ||
(articleLien.typelien === "DEPLACE" && !articleLien.cible) ||
(articleLien.typelien === "MODIFICATION" && articleLien.cible) ||
(articleLien.typelien === "MODIFIE" && !articleLien.cible)
) {
await addModifyingArticleId(
context,
articleLien.article_id,
"CREATE",
sectionTaId,
sectionTaDateDebut,
sectionTaDateFin,
)
// Delete another version of the same article that existed before the newly created one.
for (const otherLienSectionTa of liensSectionTa) {
if (otherLienSectionTa["@id"] === sectionTaId) {
continue
}
if (
otherLienSectionTa["@cid"] === lienSectionTa["@cid"] &&
otherLienSectionTa["@fin"] === sectionTaDateDebut
) {
// The other sectionTa is the old version of the sectionTa.
await addModifyingArticleId(
context,
articleLien.article_id,
"DELETE",
otherLienSectionTa["@id"],
otherLienSectionTa["@debut"],
otherLienSectionTa["@fin"],
)
}
}
} else {
throw new Error(
`Unexpected article_lien to Section Texte Article ${articleLien.id}: typelien=${articleLien.typelien}, cible=${articleLien.cible}`,
)
}
}
for (const texteVersionLien of await db<TexteVersionLienDb[]>`
SELECT * FROM texte_version_lien WHERE id IN ${db(sectionTaIds)}
`) {
if (
texteVersionLien.texte_version_id in context.consolidatedTextInternalIds
) {
// Ignore internal links because a LEGI texte can't modify itself.
continue
}
console.log(
`${" ".repeat(20)} ${" ".repeat(depth + 1)}${texteVersionLien.texte_version_id} cible: ${texteVersionLien.cible} typelien: ${texteVersionLien.typelien}`,
)
assert.strictEqual(texteVersionLien.cidtexte, context.consolidatedTextCid)
assert(
texteVersionLien.texte_version_id.startsWith("JORFTEXT") ||
texteVersionLien.texte_version_id.startsWith("LEGITEXT"),
)
if (texteVersionLien.typelien === "ANNULATION" && texteVersionLien.cible) {
await addModifyingTextId(
context,
texteVersionLien.texte_version_id,
"DELETE",
sectionTaId,
sectionTaDateDebut,
sectionTaDateFin,
)
} else if (
texteVersionLien.typelien === "CITATION" &&
!texteVersionLien.cible
) {
// Ignore link.
} else if (
texteVersionLien.typelien === "RECTIFICATION" &&
texteVersionLien.cible
) {
await addModifyingTextId(
context,
texteVersionLien.texte_version_id,
"CREATE",
sectionTaId,
sectionTaDateDebut,
sectionTaDateFin,
)
// Delete another version of the same article that existed before the newly created one.
for (const otherLienSectionTa of liensSectionTa) {
if (otherLienSectionTa["@id"] === sectionTaId) {
continue
}
if (
otherLienSectionTa["@cid"] === lienSectionTa["@cid"] &&
otherLienSectionTa["@fin"] === sectionTaDateDebut
) {
// The other sectionTa is the old version of the sectionTa.
await addModifyingTextId(
context,
texteVersionLien.texte_version_id,
"DELETE",
otherLienSectionTa["@id"],
otherLienSectionTa["@debut"],
otherLienSectionTa["@fin"],
)
}
}
} else {
throw new Error(
`Unexpected texte_version_lien to Section Texte Article ${texteVersionLien.id}: typelien=${texteVersionLien.typelien}, cible=${texteVersionLien.cible}`,
)
}
}
// If Section Texte Article belongs directly to a text published in JORF then this JORF text is its creating text.
if (
sectionTa.CONTEXTE.TEXTE["@cid"].startsWith("JORFTEXT") &&
sectionTaDateDebut === sectionTa.CONTEXTE.TEXTE["@date_publi"]
) {
await addModifyingTextId(
context,
sectionTa.CONTEXTE.TEXTE["@cid"],
"CREATE",
sectionTaId,
sectionTaDateDebut,
sectionTaDateFin,
)
// Delete another version of the same article that existed before the newly created one.
for (const otherLienSectionTa of liensSectionTa) {
if (otherLienSectionTa["@id"] === sectionTaId) {
continue
}
if (
otherLienSectionTa["@cid"] === lienSectionTa["@cid"] &&
otherLienSectionTa["@fin"] === sectionTaDateDebut
) {
// The other sectionTa is the old version of the sectionTa.
await addModifyingTextId(
context,
sectionTa.CONTEXTE.TEXTE["@cid"],
"DELETE",
otherLienSectionTa["@id"],
otherLienSectionTa["@debut"],
otherLienSectionTa["@fin"],
)
}
}
}
if (sectionTa.CONTEXTE.TEXTE["@cid"].startsWith("JORFTEXT")) {
if (sectionTaDateDebut === sectionTa.CONTEXTE.TEXTE["@date_publi"]) {
// If Section Texte Article belongs directly to a text published in JORF at the same date, then this JORF text is its creating text.
await addModifyingTextId(
context,
sectionTa.CONTEXTE.TEXTE["@cid"],
"CREATE",
sectionTaId,
sectionTaDateDebut,
sectionTaDateFin,
)
// Delete another version of the same sectionTa that existed before the newly created one.
for (const otherLienSectionTa of liensSectionTa) {
if (otherLienSectionTa["@id"] === sectionTaId) {
continue
}
if (
otherLienSectionTa["@cid"] === lienSectionTa["@cid"] &&
otherLienSectionTa["@fin"] === sectionTaDateDebut
) {
// The other sectionTa is the old version of the sectionTa.
await addModifyingTextId(
context,
sectionTa.CONTEXTE.TEXTE["@cid"],
"DELETE",
otherLienSectionTa["@id"],
otherLienSectionTa["@debut"],
otherLienSectionTa["@fin"],
)
}
}
} else {
// If Section Texte Article belongs directly to a text published in JORF but at a later date than the JORF text,
// then if it has no creating text, consider that it has been created by a modifying text having the same start
// date as the Section Texte Article when such a text exists.
const modifyingTextIdByAction = (context.modifyingTextIdByActionById[
sectionTaId
] ??= {})
if (modifyingTextIdByAction.CREATE === undefined) {
const consolidatedTextModifyingTextsIds =
context.consolidatedTextModifyingTextsIdsByActionByDate[
sectionTaDateDebut
]?.CREATE
if (consolidatedTextModifyingTextsIds !== undefined) {
if (consolidatedTextModifyingTextsIds.size === 1) {
const modifyingTextId = [...consolidatedTextModifyingTextsIds][0]
await addModifyingTextId(
context,
modifyingTextId,
"CREATE",
sectionTaId,
sectionTaDateDebut,
sectionTaDateFin,
)
// Delete another version of the same sectionTa that existed before the newly created one.
for (const otherLienSectionTa of liensSectionTa) {
if (otherLienSectionTa["@id"] === sectionTaId) {
continue
}
if (
otherLienSectionTa["@cid"] === lienSectionTa["@cid"] &&
otherLienSectionTa["@fin"] === sectionTaDateDebut
) {
// The other sectionTa is the old version of the sectionTa.
await addModifyingTextId(
context,
sectionTa.CONTEXTE.TEXTE["@cid"],
"DELETE",
otherLienSectionTa["@id"],
otherLienSectionTa["@debut"],
otherLienSectionTa["@fin"],
)
}
}
} else {
console.log(
`Can't attach modifying article ${sectionTaId} to a modifying text`,
`because there are several possibilities at the date ${sectionTaDateDebut}:`,
`${[...consolidatedTextModifyingTextsIds].join(", ")}`,
)
}
}
}
}
}
// If Section Texte Article has no creating text at all, then use a fake one.
const modifyingTextIdByAction = (context.modifyingTextIdByActionById[
sectionTaId
] ??= {})
if (modifyingTextIdByAction.CREATE === undefined) {
const texteManquantId = `ZZZZ TEXTE MANQUANT ${sectionTaDateDebut}`
context.texteManquantById[texteManquantId] ??= {
date: sectionTaDateDebut,
}
modifyingTextIdByAction.CREATE = texteManquantId
;((context.idsByActionByTexteMoficateurId[texteManquantId] ??=
{}).CREATE ??= new Set()).add(sectionTaId)
// Delete another version of the same article that existed before the newly created one.
for (const otherLienSectionTa of liensSectionTa) {
if (otherLienSectionTa["@id"] === sectionTaId) {
continue
}
if (
otherLienSectionTa["@cid"] === lienSectionTa["@cid"] &&
otherLienSectionTa["@fin"] === sectionTaDateDebut
) {
// The other sectionTa is the old version of the sectionTa.
const modifyingTextIdByAction = (context.modifyingTextIdByActionById[
otherLienSectionTa["@id"]
] ??= {})
if (modifyingTextIdByAction.DELETE === undefined) {
modifyingTextIdByAction.DELETE = texteManquantId
;((context.idsByActionByTexteMoficateurId[texteManquantId] ??=
{}).DELETE ??= new Set()).add(otherLienSectionTa["@id"])
}
}
}
}
}
async function registerLegiTextModifiers(
context: Context,
depth: number,