diff --git a/backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/output/LoadNormPort.java b/backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/output/LoadNormPort.java index 33fb724dc..53e974d9e 100644 --- a/backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/output/LoadNormPort.java +++ b/backend/src/main/java/de/bund/digitalservice/ris/norms/application/port/output/LoadNormPort.java @@ -1,7 +1,6 @@ package de.bund.digitalservice.ris.norms.application.port.output; import de.bund.digitalservice.ris.norms.domain.entity.Norm; -import de.bund.digitalservice.ris.norms.domain.entity.eli.DokumentEli; import de.bund.digitalservice.ris.norms.domain.entity.eli.NormEli; import java.util.Optional; @@ -25,16 +24,5 @@ public interface LoadNormPort { * * @param eli The ELI (European Legislation Identifier) used to identify the norm in the command. */ - record Command(NormEli eli) { - /** - * Old way to call the load norm port with using a dokument eli. As a norm is loaded and not just - * a Dokument a NormEli should be used instead - * @param eli the eli of a dokument of the norm - * @deprecated - */ - @Deprecated(forRemoval = true) - public Command(DokumentEli eli) { - this(eli.asNormEli()); - } - } + record Command(NormEli eli) {} } diff --git a/backend/src/main/java/de/bund/digitalservice/ris/norms/application/service/SingleModValidator.java b/backend/src/main/java/de/bund/digitalservice/ris/norms/application/service/SingleModValidator.java deleted file mode 100644 index e45881226..000000000 --- a/backend/src/main/java/de/bund/digitalservice/ris/norms/application/service/SingleModValidator.java +++ /dev/null @@ -1,155 +0,0 @@ -package de.bund.digitalservice.ris.norms.application.service; - -import de.bund.digitalservice.ris.norms.application.exception.ValidationException; -import de.bund.digitalservice.ris.norms.domain.entity.*; -import de.bund.digitalservice.ris.norms.domain.entity.eli.DokumentExpressionEli; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.tuple.Pair; -import org.springframework.stereotype.Service; -import org.w3c.dom.Node; - -/** - * A custom validator for validating single mods that are being updated on the amending law. This - * validator uses the ZF0 version of the target law targeted by the mod - */ -@Service -public class SingleModValidator { - - /** - * Validates the given ZF0 regelungstext using the one mod of the amending law being modified. - * - * @param zf0Norm - the ZF0 {@link Regelungstext} - * @param activeMod - the {@link Mod} that is being modified. - * @throws ValidationException if a validation step fails - */ - public void validate(final Regelungstext zf0Norm, final Mod activeMod) - throws ValidationException { - final String modEId = activeMod.getEid(); - final DokumentExpressionEli zf0NormEli = zf0Norm.getExpressionEli(); - - final TextualMod affectedPassiveMod = zf0Norm - .getMeta() - .getOrCreateAnalysis() - .getPassiveModifications() - .stream() - .filter(f -> f.getSourceHref().orElseThrow().getEId().orElseThrow().equals(modEId)) - .findFirst() - .orElseThrow(); - - final String targetNodeEid = affectedPassiveMod - .getDestinationHref() - .orElseThrow() - .getEId() - .orElseThrow(); - final Node zf0TargetedNode = zf0Norm - .getElementByEId(targetNodeEid) - .orElseThrow(() -> - new ValidationException( - ValidationException.ErrorType.TARGET_NODE_NOT_PRESENT, - Pair.of(ValidationException.FieldName.EID, targetNodeEid), - Pair.of(ValidationException.FieldName.ELI, zf0NormEli.toString()) - ) - ); - if (activeMod.usesQuotedText()) { - validateQuotedText( - zf0NormEli, - affectedPassiveMod, - StringUtils.normalizeSpace(activeMod.getMandatoryOldText()), - zf0TargetedNode - ); - } - if (activeMod.usesQuotedStructure()) { - validateQuotedStructure(affectedPassiveMod, zf0Norm, targetNodeEid, zf0TargetedNode); - } - } - - private void validateQuotedText( - final DokumentExpressionEli zf0NormEli, - final TextualMod passivemod, - String amendingNormOldText, - Node targetNode - ) throws ValidationException { - final Href destinationHref = passivemod.getDestinationHref().orElseThrow(); - final String passiveModEid = passivemod.getEid(); - final CharacterRange characterRange = destinationHref - .getCharacterRange() - .orElseThrow(() -> - new ValidationException( - ValidationException.ErrorType.CHARACTER_RANGE_NOT_PRESENT, - Pair.of(ValidationException.FieldName.DESTINATION_HREF, destinationHref.value()), - Pair.of(ValidationException.FieldName.EID, passiveModEid), - Pair.of(ValidationException.FieldName.ELI, zf0NormEli.toString()) - ) - ); - - if (!characterRange.isValidCharacterRange()) throw new ValidationException( - ValidationException.ErrorType.CHARACTER_RANGE_INVALID_FORMAT, - Pair.of(ValidationException.FieldName.CHARACTER_RANGE, characterRange.characterRange()), - Pair.of(ValidationException.FieldName.EID, passiveModEid), - Pair.of(ValidationException.FieldName.ELI, zf0NormEli.toString()) - ); - - try { - if ( - !characterRange.findTextInNode(targetNode).equals(amendingNormOldText) - ) throw new ValidationException( - ValidationException.ErrorType.CHARACTER_RANGE_NOT_RESOLVE_TARGET, - Pair.of(ValidationException.FieldName.CHARACTER_RANGE, characterRange.characterRange()), - Pair.of(ValidationException.FieldName.EID, passiveModEid), - Pair.of(ValidationException.FieldName.ELI, zf0NormEli.toString()) - ); - } catch (IndexOutOfBoundsException exception) { - throw new ValidationException( - ValidationException.ErrorType.CHARACTER_RANGE_NOT_WITHIN_NODE_RANGE, - Pair.of(ValidationException.FieldName.CHARACTER_RANGE, characterRange.characterRange()), - Pair.of(ValidationException.FieldName.EID, passiveModEid), - Pair.of(ValidationException.FieldName.ELI, zf0NormEli.toString()) - ); - } - } - - private void validateQuotedStructure( - final TextualMod affectedPassiveMod, - final Regelungstext zf0Norm, - final String targetNodeEid, - final Node targetNode - ) throws ValidationException { - affectedPassiveMod - .getDestinationUpTo() - .ifPresent(upToHref -> { - final String targetUpToNodeEid = upToHref.getEId().orElseThrow(); - - final Node zf0TargetedUpToNode = zf0Norm - .getElementByEId(targetUpToNodeEid) - .orElseThrow(() -> - new ValidationException( - ValidationException.ErrorType.TARGET_UPTO_NODE_NOT_PRESENT, - Pair.of(ValidationException.FieldName.EID, targetUpToNodeEid), - Pair.of(ValidationException.FieldName.ELI, zf0Norm.getExpressionEli().toString()) - ) - ); - - if (targetNode.getParentNode() != zf0TargetedUpToNode.getParentNode()) { - throw new ValidationException( - ValidationException.ErrorType.TARGET_AND_UPTO_NODES_NOT_SIBLINGS, - Pair.of(ValidationException.FieldName.TARGET_NODE_EID, targetNodeEid), - Pair.of(ValidationException.FieldName.TARGET_UPTO_NODE_EID, targetUpToNodeEid), - Pair.of(ValidationException.FieldName.ELI, zf0Norm.getExpressionEli().toString()) - ); - } - - if ( - (targetNode.compareDocumentPosition(zf0TargetedUpToNode) & - Node.DOCUMENT_POSITION_FOLLOWING) == - 0 - ) { - throw new ValidationException( - ValidationException.ErrorType.TARGET_NODE_AFTER_UPTO_NODE, - Pair.of(ValidationException.FieldName.TARGET_NODE_EID, targetNodeEid), - Pair.of(ValidationException.FieldName.TARGET_UPTO_NODE_EID, targetUpToNodeEid), - Pair.of(ValidationException.FieldName.ELI, zf0Norm.getExpressionEli().toString()) - ); - } - }); - } -} diff --git a/backend/src/main/java/de/bund/digitalservice/ris/norms/domain/entity/Norm.java b/backend/src/main/java/de/bund/digitalservice/ris/norms/domain/entity/Norm.java index 12e165f6a..cc5f488b0 100644 --- a/backend/src/main/java/de/bund/digitalservice/ris/norms/domain/entity/Norm.java +++ b/backend/src/main/java/de/bund/digitalservice/ris/norms/domain/entity/Norm.java @@ -123,11 +123,6 @@ public Optional getRegelungstextByEli(DokumentEli dokumentEli) { .findFirst(); } - @Deprecated(forRemoval = true) - public Document getDocument() { - return getRegelungstext1().getDocument(); - } - /** * Returns the work Eli of the {@link Norm}. * diff --git a/backend/src/test/java/de/bund/digitalservice/ris/norms/application/service/SingleModValidatorTest.java b/backend/src/test/java/de/bund/digitalservice/ris/norms/application/service/SingleModValidatorTest.java deleted file mode 100644 index e2add4562..000000000 --- a/backend/src/test/java/de/bund/digitalservice/ris/norms/application/service/SingleModValidatorTest.java +++ /dev/null @@ -1,504 +0,0 @@ -package de.bund.digitalservice.ris.norms.application.service; - -import static org.assertj.core.api.Assertions.*; -import static org.assertj.core.api.AssertionsForClassTypes.catchThrowable; - -import de.bund.digitalservice.ris.norms.application.exception.ValidationException; -import de.bund.digitalservice.ris.norms.domain.entity.Analysis; -import de.bund.digitalservice.ris.norms.domain.entity.CharacterRange; -import de.bund.digitalservice.ris.norms.domain.entity.Fixtures; -import de.bund.digitalservice.ris.norms.domain.entity.Href; -import de.bund.digitalservice.ris.norms.domain.entity.Mod; -import de.bund.digitalservice.ris.norms.domain.entity.Regelungstext; -import de.bund.digitalservice.ris.norms.domain.entity.TextualMod; -import de.bund.digitalservice.ris.norms.domain.entity.eli.DokumentExpressionEli; -import de.bund.digitalservice.ris.norms.utils.exceptions.MandatoryNodeNotFoundException; -import java.util.Collections; -import java.util.stream.Stream; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.w3c.dom.Element; - -class SingleModValidatorTest { - - private final SingleModValidator underTest = new SingleModValidator(); - - @Nested - class quotedText { - - @Test - void oldTextIsEmpty() { - // given - final Regelungstext amendingNorm = Fixtures.loadRegelungstextFromDisk("NormWithMods.xml"); - final Element modNode = amendingNorm - .getElementByEId( - "hauptteil-1_art-1_abs-1_untergl-1_listenelem-1_inhalt-1_text-1_ändbefehl-1" - ) - .orElseThrow(); - final Mod mod = new Mod(modNode); - mod.setOldText(""); - - final Regelungstext zf0Norm = Fixtures.loadRegelungstextFromDisk( - "NormWithPassiveModifications.xml" - ); - - // when - Throwable thrown = catchThrowable(() -> underTest.validate(zf0Norm, mod)); - - // then - assertThat(thrown) - .isInstanceOf(MandatoryNodeNotFoundException.class) - .hasMessageContaining( - "Element with xpath 'normalize-space(./quotedText[1])' not found in 'akn:mod' of norm 'eli/bund/bgbl-1/2017/s419/2017-03-15/1/deu/regelungstext-1'" - ); - } - - @Test - void oldTextNotTheSameInZf0Norm() { - // given - final Regelungstext amendingNorm = Fixtures.loadRegelungstextFromDisk("NormWithMods.xml"); - final Element modNode = amendingNorm - .getElementByEId( - "hauptteil-1_art-1_abs-1_untergl-1_listenelem-1_inhalt-1_text-1_ändbefehl-1" - ) - .orElseThrow(); - final Mod mod = new Mod(modNode); - mod.setOldText("not the same text as in target law"); - - final Regelungstext zf0Norm = Fixtures.loadRegelungstextFromDisk( - "NormWithPassiveModifications.xml" - ); - - // when - Throwable thrown = catchThrowable(() -> underTest.validate(zf0Norm, mod)); - - // then - assertThat(thrown) - .isInstanceOf(ValidationException.class) - .hasMessageContaining( - "The character range 9-34 of passive mod with eId meta-1_analysis-1_pasmod-1_textualmod-1 within ZF0 norm with eli eli/bund/bgbl-1/1964/s593/1964-08-05/1/deu/regelungstext-1 does not resolve to the targeted text to be replaced." - ); - } - - @Test - void nodeWithGivenDestEidDoesNotExists() { - // given - final Regelungstext amendingNorm = Fixtures.loadRegelungstextFromDisk("NormWithMods.xml"); - final Element modNode = amendingNorm - .getElementByEId( - "hauptteil-1_art-1_abs-1_untergl-1_listenelem-1_inhalt-1_text-1_ändbefehl-1" - ) - .orElseThrow(); - final Mod mod = new Mod(modNode); - final Regelungstext zf0Norm = Fixtures.loadRegelungstextFromDisk( - "NormWithPassiveModifications.xml" - ); - final TextualMod passiveMod = zf0Norm - .getMeta() - .getAnalysis() - .orElseThrow() - .getPassiveModifications() - .getFirst(); - passiveMod.setDestinationHref( - new Href("#hauptteil-1_art-1_abs-1_untergl-1_listenelem-1_inhalt-1_text-1_ändbefehl-1") - ); - - // when - Throwable thrown = catchThrowable(() -> underTest.validate(zf0Norm, mod)); - - // then - assertThat(thrown) - .isInstanceOf(ValidationException.class) - .hasMessageContaining( - "Target node with eid hauptteil-1_art-1_abs-1_untergl-1_listenelem-1_inhalt-1_text-1_ändbefehl-1 not present" - ); - } - - @Test - void validationSuccessful() { - // given - final Regelungstext amendingNorm = Fixtures.loadRegelungstextFromDisk("NormWithMods.xml"); - final Element modNode = amendingNorm - .getElementByEId( - "hauptteil-1_art-1_abs-1_untergl-1_listenelem-1_inhalt-1_text-1_ändbefehl-1" - ) - .orElseThrow(); - final Mod mod = new Mod(modNode); - final Regelungstext zf0Norm = Fixtures.loadRegelungstextFromDisk( - "NormWithPassiveModifications.xml" - ); - - // when/then - assertThatCode(() -> underTest.validate(zf0Norm, mod)).doesNotThrowAnyException(); - } - - @Test - void validationSuccessfulUntilEndOfParagraph() { - // given - final Regelungstext amendingNorm = Fixtures.loadRegelungstextFromDisk("NormWithMods.xml"); - final Element modNode = amendingNorm - .getElementByEId( - "hauptteil-1_art-1_abs-1_untergl-1_listenelem-1_inhalt-1_text-1_ändbefehl-1" - ) - .orElseThrow(); - final Mod mod = new Mod(modNode); - final DokumentExpressionEli amendingNormEli = amendingNorm.getExpressionEli(); - final Href href = new Href.Builder() - .setEli(amendingNormEli) - .setEId("hauptteil-1_art-20_abs-1_untergl-1_listenelem-2_inhalt-1_text-1") - .setCharacterRange(new CharacterRange("9-112")) - .buildAbsolute(); - - // 112 paragraph length - amendingNorm - .getMeta() - .getAnalysis() - .map(Analysis::getActiveModifications) - .orElse(Collections.emptyList()) - .getFirst() - .setDestinationHref(href); - - mod.setTargetRefHref(href); - mod.setOldText("§ 9 Abs. 1 Satz 2, Abs. 2"); - - final Regelungstext zf0Norm = Fixtures.loadRegelungstextFromDisk( - "NormWithPassiveModifications.xml" - ); - - // when/then - assertThatCode(() -> underTest.validate(zf0Norm, mod)).doesNotThrowAnyException(); - } - - @Test - void validationSuccessfulStartingAt0() { - // given - final Regelungstext amendingNorm = Fixtures.loadRegelungstextFromDisk("NormWithMods.xml"); - final Element modNode = amendingNorm - .getElementByEId( - "hauptteil-1_art-1_abs-1_untergl-1_listenelem-1_inhalt-1_text-1_ändbefehl-1" - ) - .orElseThrow(); - final Mod mod = new Mod(modNode); - final DokumentExpressionEli amendingNormEli = amendingNorm.getExpressionEli(); - final Href href = new Href.Builder() - .setEli(amendingNormEli) - .setEId("hauptteil-1_art-20_abs-1_untergl-1_listenelem-2_inhalt-1_text-1") - .setCharacterRange(new CharacterRange("0-34")) - .buildAbsolute(); - - // 112 paragraph length - amendingNorm - .getMeta() - .getAnalysis() - .map(Analysis::getActiveModifications) - .orElse(Collections.emptyList()) - .getFirst() - .setDestinationHref(href); - - mod.setTargetRefHref(href); - mod.setOldText("§ 9 Abs. 1 Satz 2, Abs. 2"); - - final Regelungstext zf0Norm = Fixtures.loadRegelungstextFromDisk( - "NormWithPassiveModifications.xml" - ); - - // when/then - assertThatCode(() -> underTest.validate(zf0Norm, mod)).doesNotThrowAnyException(); - } - - @Test - void throwsExceptionWhenCharacterRangeIsNotSet() { - // given - final Regelungstext amendingNorm = Fixtures.loadRegelungstextFromDisk("NormWithMods.xml"); - final DokumentExpressionEli amendingNormEli = amendingNorm.getExpressionEli(); - final Element modNode = amendingNorm - .getElementByEId( - "hauptteil-1_art-1_abs-1_untergl-1_listenelem-1_inhalt-1_text-1_ändbefehl-1" - ) - .orElseThrow(); - final Mod mod = new Mod(modNode); - mod.setTargetRefHref( - new Href.Builder() - .setEli(amendingNormEli) - .setEId("hauptteil-1_art-1_abs-1_untergl-1_listenelem-2_inhalt-1_text-1") - .setCharacterRange(new CharacterRange("")) - .buildInternalReference() - ); - - final Regelungstext zf0Norm = Fixtures.loadRegelungstextFromDisk( - "NormWithPassiveModifications.xml" - ); - final TextualMod passiveMod = zf0Norm - .getMeta() - .getAnalysis() - .orElseThrow() - .getPassiveModifications() - .getFirst(); - passiveMod.setDestinationHref( - new Href.Builder() - .setEId("hauptteil-1_art-1_abs-1_untergl-1_listenelem-2_inhalt-1_text-1") - .setCharacterRange(new CharacterRange("")) - .buildInternalReference() - ); - - // when - Throwable thrown = catchThrowable(() -> underTest.validate(zf0Norm, mod)); - - // then - assertThat(thrown) - .isInstanceOf(ValidationException.class) - .hasMessageContaining( - "In the destination href with value #hauptteil-1_art-1_abs-1_untergl-1_listenelem-2_inhalt-1_text-1/ of passive mod with eId meta-1_analysis-1_pasmod-1_textualmod-1 within ZF0 norm with eli eli/bund/bgbl-1/1964/s593/1964-08-05/1/deu/regelungstext-1, the character range not present." - ); - } - - private static Stream provideParametersForThrowsExceptionWhenCharacterRange() { - return Stream.of( - Arguments.of( - "20-20.xml", - "The character range 20-20.xml of passive mod with eId meta-1_analysis-1_pasmod-1_textualmod-1 within ZF0 norm with eli eli/bund/bgbl-1/1964/s593/1964-08-05/1/deu/regelungstext-1 has invalid format." - ), - Arguments.of( - "-20.xml", - "The character range -20.xml of passive mod with eId meta-1_analysis-1_pasmod-1_textualmod-1 within ZF0 norm with eli eli/bund/bgbl-1/1964/s593/1964-08-05/1/deu/regelungstext-1 has invalid format." - ), - Arguments.of( - "0-.xml", - "The character range 0-.xml of passive mod with eId meta-1_analysis-1_pasmod-1_textualmod-1 within ZF0 norm with eli eli/bund/bgbl-1/1964/s593/1964-08-05/1/deu/regelungstext-1 has invalid format." - ), - Arguments.of( - "", - "In the destination href with value #hauptteil-1_art-1_abs-1_untergl-1_listenelem-2_inhalt-1_text-1/ of passive mod with eId meta-1_analysis-1_pasmod-1_textualmod-1 within ZF0 norm with eli eli/bund/bgbl-1/1964/s593/1964-08-05/1/deu/regelungstext-1, the character range not present." - ) - ); - } - - @ParameterizedTest - @MethodSource("provideParametersForThrowsExceptionWhenCharacterRange") - void throwsExceptionWhenCharacterRangeIsMalformed(String cr, String message) { - // given - final Regelungstext amendingNorm = Fixtures.loadRegelungstextFromDisk("NormWithMods.xml"); - final Element modNode = amendingNorm - .getElementByEId( - "hauptteil-1_art-1_abs-1_untergl-1_listenelem-1_inhalt-1_text-1_ändbefehl-1" - ) - .orElseThrow(); - final Mod mod = new Mod(modNode); - - final Regelungstext zf0Norm = Fixtures.loadRegelungstextFromDisk( - "NormWithPassiveModifications.xml" - ); - final TextualMod passiveMod = zf0Norm - .getMeta() - .getAnalysis() - .orElseThrow() - .getPassiveModifications() - .getFirst(); - passiveMod.setDestinationHref( - new Href.Builder() - .setEId("hauptteil-1_art-1_abs-1_untergl-1_listenelem-2_inhalt-1_text-1") - .setCharacterRange(new CharacterRange(cr)) - .buildInternalReference() - ); - - // when - Throwable thrown = catchThrowable(() -> underTest.validate(zf0Norm, mod)); - - // then - assertThat(thrown).isInstanceOf(ValidationException.class).hasMessageContaining(message); - } - - @Test - void ThrowsExceptionWhenCharacterRangeEndIsTooHigh() { - // given - final Regelungstext amendingNorm = Fixtures.loadRegelungstextFromDisk("NormWithMods.xml"); - final Element modNode = amendingNorm - .getElementByEId( - "hauptteil-1_art-1_abs-1_untergl-1_listenelem-1_inhalt-1_text-1_ändbefehl-1" - ) - .orElseThrow(); - final Mod mod = new Mod(modNode); - - final Regelungstext zf0Norm = Fixtures.loadRegelungstextFromDisk( - "NormWithPassiveModifications.xml" - ); - final TextualMod passiveMod = zf0Norm - .getMeta() - .getAnalysis() - .orElseThrow() - .getPassiveModifications() - .getFirst(); - passiveMod.setDestinationHref( - new Href.Builder() - .setEId("hauptteil-1_art-1_abs-1_untergl-1_listenelem-2_inhalt-1_text-1") - .setCharacterRange(new CharacterRange("9-1113")) - .buildInternalReference() - ); - - // when - Throwable thrown = catchThrowable(() -> underTest.validate(zf0Norm, mod)); - - // then - assertThat(thrown) - .isInstanceOf(ValidationException.class) - .hasMessageContaining( - "The character range 9-1113 of passive mod with eId meta-1_analysis-1_pasmod-1_textualmod-1 within ZF0 norm with eli eli/bund/bgbl-1/1964/s593/1964-08-05/1/deu/regelungstext-1 is not within the target node." - ); - } - } - - @Nested - class quotedStructure { - - @Test - void validationSuccessNoUpTo() { - // given - final Regelungstext amendingNorm = Fixtures.loadRegelungstextFromDisk( - "NormWithQuotedStructureMods.xml" - ); - final Element modNode = amendingNorm - .getElementByEId( - "hauptteil-1_art-1_abs-1_untergl-1_listenelem-1_inhalt-1_text-1_ändbefehl-1" - ) - .orElseThrow(); - final Mod mod = new Mod(modNode); - final Regelungstext zf0Norm = Fixtures.loadRegelungstextFromDisk( - "NormWithPassiveModsQuotedStructure.xml" - ); - - // when then - assertThatCode(() -> underTest.validate(zf0Norm, mod)).doesNotThrowAnyException(); - } - - @Test - void validationSuccessWithUpTo() { - // given - final Regelungstext amendingNorm = Fixtures.loadRegelungstextFromDisk( - "NormWithQuotedStructureModsAndUpTo.xml" - ); - final Element modNode = amendingNorm - .getElementByEId( - "hauptteil-1_art-1_abs-1_untergl-1_listenelem-1_inhalt-1_text-1_ändbefehl-1" - ) - .orElseThrow(); - final Mod mod = new Mod(modNode); - final Regelungstext zf0Norm = Fixtures.loadRegelungstextFromDisk( - "NormWithPassiveModsQuotedStructureAndUpTo.xml" - ); - - // when then - assertThatCode(() -> underTest.validate(zf0Norm, mod)).doesNotThrowAnyException(); - } - - @Test - void upToNodeNotPresent() { - // given - final Regelungstext amendingNorm = Fixtures.loadRegelungstextFromDisk( - "NormWithQuotedStructureModsAndUpTo.xml" - ); - final Element modNode = amendingNorm - .getElementByEId( - "hauptteil-1_art-1_abs-1_untergl-1_listenelem-1_inhalt-1_text-1_ändbefehl-1" - ) - .orElseThrow(); - final Mod mod = new Mod(modNode); - final Regelungstext zf0Norm = Fixtures.loadRegelungstextFromDisk( - "NormWithPassiveModsQuotedStructureAndUpTo.xml" - ); - - final TextualMod passiveMod = zf0Norm - .getMeta() - .getAnalysis() - .orElseThrow() - .getPassiveModifications() - .getFirst(); - passiveMod.setDestinationUpTo(new Href("#not-present-href")); - - // when - Throwable thrown = catchThrowable(() -> underTest.validate(zf0Norm, mod)); - - // then - assertThat(thrown) - .isInstanceOf(ValidationException.class) - .hasMessageContaining( - "Target upTo node with eid not-present-href not present in ZF0 norm with eli eli/bund/bgbl-1/1999/66/2002-02-20/1/deu/regelungstext-1." - ); - } - - @Test - void upToNodeAndTargetNodeNotSiblings() { - // given - final Regelungstext amendingNorm = Fixtures.loadRegelungstextFromDisk( - "NormWithQuotedStructureModsAndUpTo.xml" - ); - final Element modNode = amendingNorm - .getElementByEId( - "hauptteil-1_art-1_abs-1_untergl-1_listenelem-1_inhalt-1_text-1_ändbefehl-1" - ) - .orElseThrow(); - final Mod mod = new Mod(modNode); - final Regelungstext zf0Norm = Fixtures.loadRegelungstextFromDisk( - "NormWithPassiveModsQuotedStructureAndUpTo.xml" - ); - - final TextualMod passiveMod = zf0Norm - .getMeta() - .getAnalysis() - .orElseThrow() - .getPassiveModifications() - .getFirst(); - passiveMod.setDestinationUpTo( - new Href("#hauptteil-1_art-2_abs-3_untergl-1_listenelem-1_untergl-1_listenelem-2") - ); - - // when - Throwable thrown = catchThrowable(() -> underTest.validate(zf0Norm, mod)); - - // then - assertThat(thrown) - .isInstanceOf(ValidationException.class) - .hasMessageContaining( - "Target node with eid hauptteil-1_art-2_abs-1 and target upTo node with eid hauptteil-1_art-2_abs-3_untergl-1_listenelem-1_untergl-1_listenelem-2 are not siblings in ZF0 norm with eli eli/bund/bgbl-1/1999/66/2002-02-20/1/deu/regelungstext-1." - ); - } - - @Test - void upToNodeBeforeTargetNode() { - // given - final Regelungstext amendingNorm = Fixtures.loadRegelungstextFromDisk( - "NormWithQuotedStructureModsAndUpTo.xml" - ); - final Element modNode = amendingNorm - .getElementByEId( - "hauptteil-1_art-1_abs-1_untergl-1_listenelem-1_inhalt-1_text-1_ändbefehl-1" - ) - .orElseThrow(); - final Mod mod = new Mod(modNode); - final Regelungstext zf0Norm = Fixtures.loadRegelungstextFromDisk( - "NormWithPassiveModsQuotedStructureAndUpTo.xml" - ); - - final TextualMod passiveMod = zf0Norm - .getMeta() - .getAnalysis() - .orElseThrow() - .getPassiveModifications() - .getFirst(); - passiveMod.setDestinationHref(new Href("#hauptteil-1_art-2_abs-3")); - passiveMod.setDestinationUpTo(new Href("#hauptteil-1_art-2_abs-1")); - - // when - Throwable thrown = catchThrowable(() -> underTest.validate(zf0Norm, mod)); - - // then - assertThat(thrown) - .isInstanceOf(ValidationException.class) - .hasMessageContaining( - "Target node with eid hauptteil-1_art-2_abs-3 does not appear before target upTo node with eid hauptteil-1_art-2_abs-1 in ZF0 norm with eli eli/bund/bgbl-1/1999/66/2002-02-20/1/deu/regelungstext-1." - ); - } - } -}