From e2c4c0d607295068ed7413e781e58d88c8a9beb8 Mon Sep 17 00:00:00 2001 From: Pascal Christoph Date: Fri, 19 Apr 2024 11:55:40 +0200 Subject: [PATCH] Encode "leader" also if it's passed as one literal (#454) "leader" can be given aa top-level literal or as literal in an entity. This makes the claim "The stream expected by the encoder is compatible to the streams emitted by the {@link Marc21Decoder} and the {@link MarcXmlHandler}." true again. --- .../biblio/iso2709/Iso2709Constants.java | 15 ++++----- .../biblio/marc21/Marc21Encoder.java | 32 +++++++++++++++++-- .../biblio/marc21/Marc21EncoderTest.java | 22 +++++++++++++ 3 files changed, 57 insertions(+), 12 deletions(-) diff --git a/metafacture-biblio/src/main/java/org/metafacture/biblio/iso2709/Iso2709Constants.java b/metafacture-biblio/src/main/java/org/metafacture/biblio/iso2709/Iso2709Constants.java index ebe9475c8..02a7ec3f7 100644 --- a/metafacture-biblio/src/main/java/org/metafacture/biblio/iso2709/Iso2709Constants.java +++ b/metafacture-biblio/src/main/java/org/metafacture/biblio/iso2709/Iso2709Constants.java @@ -23,9 +23,13 @@ * @author Christoph Böhme * */ -final class Iso2709Constants { +public final class Iso2709Constants { - static final int RECORD_LABEL_LENGTH = 24; + public static final int IMPL_CODES_START = 6; + public static final int IMPL_CODES_LENGTH = 4; + public static final int RECORD_LABEL_LENGTH = 24; + public static final int RECORD_STATUS_POS = 5; + public static final int SYSTEM_CHARS_START = 17; static final int MIN_RECORD_LENGTH = RECORD_LABEL_LENGTH + 2; static final int MAX_RECORD_LENGTH = 99_999; @@ -38,18 +42,11 @@ final class Iso2709Constants { static final int RECORD_LENGTH_START = 0; static final int RECORD_LENGTH_LENGTH = 5; - static final int RECORD_STATUS_POS = 5; - - static final int IMPL_CODES_START = 6; - static final int IMPL_CODES_LENGTH = 4; - static final int INDICATOR_LENGTH_POS = 10; static final int IDENTIFIER_LENGTH_POS = 11; static final int BASE_ADDRESS_START = 12; static final int BASE_ADDRESS_LENGTH = 5; - - static final int SYSTEM_CHARS_START = 17; static final int SYSTEM_CHARS_LENGTH = 3; static final int FIELD_LENGTH_LENGTH_POS = 20; diff --git a/metafacture-biblio/src/main/java/org/metafacture/biblio/marc21/Marc21Encoder.java b/metafacture-biblio/src/main/java/org/metafacture/biblio/marc21/Marc21Encoder.java index 876f85203..6be0a0d08 100644 --- a/metafacture-biblio/src/main/java/org/metafacture/biblio/marc21/Marc21Encoder.java +++ b/metafacture-biblio/src/main/java/org/metafacture/biblio/marc21/Marc21Encoder.java @@ -16,6 +16,7 @@ package org.metafacture.biblio.marc21; +import org.metafacture.biblio.iso2709.Iso2709Constants; import org.metafacture.biblio.iso2709.RecordBuilder; import org.metafacture.biblio.iso2709.RecordFormat; import org.metafacture.framework.FluxCommand; @@ -180,7 +181,12 @@ public void literal(final String name, final String value) { builder.appendSubfield(name.toCharArray(), value); break; case IN_LEADER_ENTITY: - processLiteralInLeader(name, value); + if (name == Marc21EventNames.LEADER_ENTITY) { + processLeaderAsOneLiteral(value); + } + else { + processLeaderAsSubfields(name, value); + } break; case IN_RECORD: processTopLevelLiteral(name, value); @@ -190,7 +196,22 @@ public void literal(final String name, final String value) { } } - private void processLiteralInLeader(final String name, final String value) { + private void processLeaderAsOneLiteral(final String value) { + if (value.length() != Iso2709Constants.RECORD_LABEL_LENGTH) { + throw new FormatException( + "leader literal must contain " + Iso2709Constants.RECORD_LABEL_LENGTH + " characters:" + value); + } + processLeaderAsSubfields(Marc21EventNames.RECORD_STATUS_LITERAL, String.valueOf(value.charAt(Iso2709Constants.RECORD_STATUS_POS))); + processLeaderAsSubfields(Marc21EventNames.RECORD_TYPE_LITERAL, String.valueOf(value.charAt(Iso2709Constants.IMPL_CODES_START))); + processLeaderAsSubfields(Marc21EventNames.BIBLIOGRAPHIC_LEVEL_LITERAL, String.valueOf(value.charAt(Iso2709Constants.IMPL_CODES_START + 1))); + processLeaderAsSubfields(Marc21EventNames.TYPE_OF_CONTROL_LITERAL, String.valueOf(value.charAt(Iso2709Constants.IMPL_CODES_START + 2))); + processLeaderAsSubfields(Marc21EventNames.CHARACTER_CODING_LITERAL, String.valueOf(value.charAt(Iso2709Constants.RECORD_STATUS_POS + Iso2709Constants.IMPL_CODES_LENGTH))); + processLeaderAsSubfields(Marc21EventNames.ENCODING_LEVEL_LITERAL, String.valueOf(value.charAt(Iso2709Constants.SYSTEM_CHARS_START))); + processLeaderAsSubfields(Marc21EventNames.CATALOGING_FORM_LITERAL, String.valueOf(value.charAt(Iso2709Constants.SYSTEM_CHARS_START + 1))); + processLeaderAsSubfields(Marc21EventNames.MULTIPART_LEVEL_LITERAL, String.valueOf(value.charAt(Iso2709Constants.SYSTEM_CHARS_START + 2))); + } + + private void processLeaderAsSubfields(final String name, final String value) { if (value.length() != 1) { throw new FormatException( "literal must only contain a single character:" + name); @@ -251,7 +272,12 @@ private void processTopLevelLiteral(final String name, final String value) { // these literals here. return; } - builder.appendReferenceField(name.toCharArray(), value); + if (Marc21EventNames.LEADER_ENTITY.equals(name)) { + processLeaderAsOneLiteral(value); + } + else { + builder.appendReferenceField(name.toCharArray(), value); + } } @Override diff --git a/metafacture-biblio/src/test/java/org/metafacture/biblio/marc21/Marc21EncoderTest.java b/metafacture-biblio/src/test/java/org/metafacture/biblio/marc21/Marc21EncoderTest.java index 41e8d2b6c..b766104a2 100644 --- a/metafacture-biblio/src/test/java/org/metafacture/biblio/marc21/Marc21EncoderTest.java +++ b/metafacture-biblio/src/test/java/org/metafacture/biblio/marc21/Marc21EncoderTest.java @@ -114,4 +114,26 @@ public void issue278ShouldNotFailWhenProcessingLeaderEntity() { verify(receiver).process(any(String.class)); } + @Test + public void issue454ShouldNotFailWhenProcessingEntityLeaderAsOneString() { + marc21Encoder.startRecord(""); + marc21Encoder.startEntity(LEADER_ENTITY); + marc21Encoder.literal(LEADER_ENTITY, "02602pam a2200529 c 4500"); + marc21Encoder.endEntity(); + marc21Encoder.endEntity(); + marc21Encoder.endRecord(); + + verify(receiver).process(matches("00026pam a2200025 c 4500\u001e\u001d")); + } + + @Test + public void issue454ShouldNotFailWhenProcessingLeaderAsOneString() { + marc21Encoder.startRecord(""); + marc21Encoder.literal(LEADER_ENTITY, "02602pam a2200529 c 4500"); + marc21Encoder.endEntity(); + marc21Encoder.endRecord(); + + verify(receiver).process(matches("00026pam a2200025 c 4500\u001e\u001d")); + } + }