From fa5f53fbd2596c36317e7a1310c0dec757dce86c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=CC=88rg=20Prante?= Date: Sat, 17 Sep 2016 20:53:02 +0200 Subject: [PATCH] fixed JSON geenration, added record label encoding, added lightweight record adapter, more tests --- .../marc/LightweightMarcRecordAdapter.java | 34 +++ src/main/java/org/xbib/marc/Marc.java | 34 +-- src/main/java/org/xbib/marc/MarcField.java | 1 + .../java/org/xbib/marc/MarcGenerator.java | 10 - src/main/java/org/xbib/marc/MarcRecord.java | 16 +- .../java/org/xbib/marc/MarcRecordAdapter.java | 24 +- src/main/java/org/xbib/marc/MarcWriter.java | 47 ++-- .../org/xbib/marc/json/MarcJsonWriter.java | 216 ++++++++++-------- .../java/org/xbib/marc/label/RecordLabel.java | 17 ++ .../java/org/xbib/marc/ConcurrencyTest.java | 3 - .../java/org/xbib/marc/MarcRecordTest.java | 24 ++ .../java/org/xbib/marc/MarcWriterTest.java | 43 ++++ .../xbib/marc/json/MarcJsonWriterTest.java | 37 ++- .../org/xbib/marc/label/RecordLabelTest.java | 6 + .../java/org/xbib/marc/tools/ToolTest.java | 2 + .../xbib/marc/xml/MarcEventConsumerTest.java | 20 ++ .../org/xbib/marc/json/HT016424175.xml.json | 1 + .../org/xbib/marc/json/chabon-loc.mrc.json | 2 +- .../org/xbib/marc/json/chabon.mrc.json | 2 +- .../org/xbib/marc/json/summerland.mrc.json | 2 +- 20 files changed, 348 insertions(+), 193 deletions(-) create mode 100644 src/main/java/org/xbib/marc/LightweightMarcRecordAdapter.java create mode 100644 src/test/resources/org/xbib/marc/json/HT016424175.xml.json diff --git a/src/main/java/org/xbib/marc/LightweightMarcRecordAdapter.java b/src/main/java/org/xbib/marc/LightweightMarcRecordAdapter.java new file mode 100644 index 0000000..6e2ab8c --- /dev/null +++ b/src/main/java/org/xbib/marc/LightweightMarcRecordAdapter.java @@ -0,0 +1,34 @@ +/* + Copyright 2016 Jörg Prante + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + */ +package org.xbib.marc; + +/** + * + */ +public class LightweightMarcRecordAdapter extends MarcRecordAdapter { + + public LightweightMarcRecordAdapter(MarcRecordListener marcRecordListener) { + super(marcRecordListener); + this.builder = Marc.builder().lightweightRecord(); + } + + @Override + public void endRecord() { + super.endRecord(); + builder = Marc.builder().lightweightRecord(); + } +} diff --git a/src/main/java/org/xbib/marc/Marc.java b/src/main/java/org/xbib/marc/Marc.java index e3e995c..c417d57 100644 --- a/src/main/java/org/xbib/marc/Marc.java +++ b/src/main/java/org/xbib/marc/Marc.java @@ -17,9 +17,7 @@ package org.xbib.marc; import static org.xbib.marc.MarcXchangeConstants.BIBLIOGRAPHIC_TYPE; -import static org.xbib.marc.MarcXchangeConstants.FORMAT_ATTRIBUTE; import static org.xbib.marc.MarcXchangeConstants.MARCXCHANGE_FORMAT; -import static org.xbib.marc.MarcXchangeConstants.TYPE_ATTRIBUTE; import org.w3c.dom.Document; import org.xbib.marc.dialects.aleph.AlephSequentialInputStream; @@ -495,12 +493,6 @@ public final class Marc { } if (builder.getProperties() != null) { for (Map.Entry entry : builder.getProperties().entrySet()) { - if (FORMAT_ATTRIBUTE.equals(entry.getKey())) { - continue; - } - if (TYPE_ATTRIBUTE.equals(entry.getKey())) { - continue; - } sax.getXMLReader().setProperty(entry.getKey(), entry.getValue()); } } @@ -969,17 +961,12 @@ public final class Marc { return this; } + /** + * Not used as there is no known input with collection events yet. + */ @Override public void beginCollection() { - if (listener != null) { - listener.beginCollection(); - } - if (defaultContentHandler != null) { - defaultContentHandler.beginCollection(); - } - if (marcRecordListener != null) { - marcRecordListener.beginCollection(); - } + // not used } @Override @@ -1042,17 +1029,12 @@ public final class Marc { } } + /** + * Not used as there is no known input with collection events yet. + */ @Override public void endCollection() { - if (listener != null) { - listener.endCollection(); - } - if (defaultContentHandler != null) { - defaultContentHandler.endCollection(); - } - if (marcRecordListener != null) { - marcRecordListener.endCollection(); - } + // not used } public Marc.Builder recordLabel(RecordLabel recordLabel) { diff --git a/src/main/java/org/xbib/marc/MarcField.java b/src/main/java/org/xbib/marc/MarcField.java index 5a29572..e8f4430 100644 --- a/src/main/java/org/xbib/marc/MarcField.java +++ b/src/main/java/org/xbib/marc/MarcField.java @@ -563,6 +563,7 @@ public class MarcField implements Comparable { * @param string the string to insert * @return true if collection changed */ + @Override public boolean add(String string) { ListIterator it = listIterator(); boolean added = false; diff --git a/src/main/java/org/xbib/marc/MarcGenerator.java b/src/main/java/org/xbib/marc/MarcGenerator.java index a5f6870..d0f9108 100644 --- a/src/main/java/org/xbib/marc/MarcGenerator.java +++ b/src/main/java/org/xbib/marc/MarcGenerator.java @@ -16,7 +16,6 @@ */ package org.xbib.marc; -import static org.xbib.marc.io.InformationSeparator.FS; import static org.xbib.marc.io.InformationSeparator.GS; import static org.xbib.marc.io.InformationSeparator.RS; import static org.xbib.marc.io.InformationSeparator.US; @@ -141,11 +140,6 @@ public class MarcGenerator implements ChunkListener { return; } switch (separator) { - case FS: { - emitMarcField(); - emitMarcRecord(); - break; - } case GS: { emitMarcField(); emitMarcRecord(); @@ -250,10 +244,6 @@ public class MarcGenerator implements ChunkListener { } private void newRecord() throws IOException { - // checkguard - if (this.data == null || this.data.isEmpty()) { - return; - } // skip line-feed (OCLC PICA quirk) if (this.data.charAt(0) == '\n') { this.data = data.substring(1); diff --git a/src/main/java/org/xbib/marc/MarcRecord.java b/src/main/java/org/xbib/marc/MarcRecord.java index b45a221..6143d33 100644 --- a/src/main/java/org/xbib/marc/MarcRecord.java +++ b/src/main/java/org/xbib/marc/MarcRecord.java @@ -22,7 +22,7 @@ import static org.xbib.marc.json.MarcJsonWriter.TYPE_TAG; import org.xbib.marc.label.RecordLabel; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -33,7 +33,7 @@ import java.util.stream.Collectors; /** * A MARC record. This is an extended MARC record augmented with MarcXchange information. */ -public class MarcRecord extends HashMap { +public class MarcRecord extends LinkedHashMap { private static final long serialVersionUID = 5305809148724342653L; @@ -138,19 +138,15 @@ public class MarcRecord extends HashMap { put(LEADER_TAG, recordLabel.toString()); for (MarcField marcField : marcFields) { String tag = marcField.getTag(); - if (marcField.isControl()) { - put(tag, marcField.getValue()); - continue; - } if (!containsKey(tag)) { - put(tag, new HashMap<>()); + put(tag, new LinkedHashMap<>()); } String indicator = marcField.getIndicator(); - if (indicator != null) { + if (indicator != null && !indicator.isEmpty()) { indicator = indicator.replace(' ', '_'); Map indicators = (Map) get(tag); if (!indicators.containsKey(indicator)) { - indicators.put(indicator, new HashMap<>()); + indicators.put(indicator, new LinkedHashMap<>()); } Map subfields = (Map) indicators.get(indicator); for (MarcField.Subfield subfield : marcField.getSubfields()) { @@ -167,6 +163,8 @@ public class MarcRecord extends HashMap { subfields.put(subfield.getId(), subfield.getValue()); } } + } else { + put(tag, marcField.getValue()); } } } diff --git a/src/main/java/org/xbib/marc/MarcRecordAdapter.java b/src/main/java/org/xbib/marc/MarcRecordAdapter.java index 7daa59e..d08d913 100644 --- a/src/main/java/org/xbib/marc/MarcRecordAdapter.java +++ b/src/main/java/org/xbib/marc/MarcRecordAdapter.java @@ -1,3 +1,19 @@ +/* + Copyright 2016 Jörg Prante + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + */ package org.xbib.marc; import org.xbib.marc.label.RecordLabel; @@ -7,13 +23,13 @@ import org.xbib.marc.label.RecordLabel; */ public class MarcRecordAdapter implements MarcListener { - private final MarcRecordListener marcRecordListener; + protected final MarcRecordListener marcRecordListener; - private Marc.Builder builder; + protected Marc.Builder builder; public MarcRecordAdapter(MarcRecordListener marcRecordListener) { this.marcRecordListener = marcRecordListener; - this.builder = Marc.builder().lightweightRecord(); + this.builder = Marc.builder(); } @Override @@ -40,7 +56,7 @@ public class MarcRecordAdapter implements MarcListener { @Override public void endRecord() { marcRecordListener.record(builder.buildRecord()); - builder = Marc.builder().lightweightRecord(); + builder = Marc.builder(); } @Override diff --git a/src/main/java/org/xbib/marc/MarcWriter.java b/src/main/java/org/xbib/marc/MarcWriter.java index d66bccb..a3235b4 100644 --- a/src/main/java/org/xbib/marc/MarcWriter.java +++ b/src/main/java/org/xbib/marc/MarcWriter.java @@ -20,7 +20,7 @@ import org.xbib.marc.io.BytesStreamOutput; import org.xbib.marc.io.DefaultChunk; import org.xbib.marc.io.InformationSeparator; import org.xbib.marc.io.SeparatorOutputStream; -import org.xbib.marc.transformer.value.MarcValueTransformer; +import org.xbib.marc.transformer.value.MarcValueTransformers; import org.xbib.marc.xml.MarcContentHandler; import java.io.Closeable; @@ -47,7 +47,7 @@ public class MarcWriter extends MarcContentHandler implements Flushable, Closeab private final Charset charset; - private MarcValueTransformer marcValueTransformer; + private MarcValueTransformers marcValueTransformers; private boolean fatalErrors; @@ -76,20 +76,8 @@ public class MarcWriter extends MarcContentHandler implements Flushable, Closeab this.bytesStreamOutput = new BytesStreamOutput(); } - @Override - public MarcWriter setFormat(String format) { - super.setFormat(format); - return this; - } - - @Override - public MarcWriter setType(String type) { - super.setType(type); - return this; - } - - public MarcWriter setMarcValueTransformer(MarcValueTransformer marcValueTransformer) { - this.marcValueTransformer = marcValueTransformer; + public MarcWriter setMarcValueTransformers(MarcValueTransformers marcValueTransformers) { + this.marcValueTransformers = marcValueTransformers; return this; } @@ -138,30 +126,31 @@ public class MarcWriter extends MarcContentHandler implements Flushable, Closeab return; } try { + MarcField marcField = marcValueTransformers != null ? marcValueTransformers.transformValue(field) : field; bytesStreamOutput.reset(); // we clean up a bit. Write control field, and fields that are not empty. // Do not care about the control field / data field order. - if (field.isControl()) { - String value = field.getValue(); + if (marcField.isControl()) { + String value = marcField.getValue(); if (value != null && !value.isEmpty()) { - bytesStreamOutput.write(field.getTag().getBytes(StandardCharsets.ISO_8859_1)); - bytesStreamOutput.write(transform(value).getBytes(charset)); + bytesStreamOutput.write(marcField.getTag().getBytes(StandardCharsets.ISO_8859_1)); + bytesStreamOutput.write(value.getBytes(charset)); out.chunk(new DefaultChunk(InformationSeparator.RS, bytesStreamOutput.bytes())); } - } else if (!field.isEmpty()) { - bytesStreamOutput.write(field.getTag().getBytes(StandardCharsets.ISO_8859_1)); - bytesStreamOutput.write(field.getIndicator().getBytes(StandardCharsets.ISO_8859_1)); - String value = field.getValue(); + } else if (!marcField.isEmpty()) { + bytesStreamOutput.write(marcField.getTag().getBytes(StandardCharsets.ISO_8859_1)); + bytesStreamOutput.write(marcField.getIndicator().getBytes(StandardCharsets.ISO_8859_1)); + String value = marcField.getValue(); if (value != null && !value.isEmpty()) { - bytesStreamOutput.write(transform(value).getBytes(charset)); + bytesStreamOutput.write(value.getBytes(charset)); } out.chunk(new DefaultChunk(InformationSeparator.RS, bytesStreamOutput.bytes())); - for (MarcField.Subfield subfield : field.getSubfields()) { + for (MarcField.Subfield subfield : marcField.getSubfields()) { value = subfield.getValue(); if (value != null && !value.isEmpty()) { bytesStreamOutput.reset(); bytesStreamOutput.write(subfield.getId().getBytes(StandardCharsets.ISO_8859_1)); - bytesStreamOutput.write(transform(value).getBytes(charset)); + bytesStreamOutput.write(value.getBytes(charset)); out.chunk(new DefaultChunk(InformationSeparator.US, bytesStreamOutput.bytes())); } } @@ -205,10 +194,6 @@ public class MarcWriter extends MarcContentHandler implements Flushable, Closeab return exception; } - private String transform(String value) { - return marcValueTransformer != null ? marcValueTransformer.transform(value) : value; - } - private void handleException(IOException e) { exception = e; if (fatalErrors) { diff --git a/src/main/java/org/xbib/marc/json/MarcJsonWriter.java b/src/main/java/org/xbib/marc/json/MarcJsonWriter.java index aa80db3..35d7b54 100644 --- a/src/main/java/org/xbib/marc/json/MarcJsonWriter.java +++ b/src/main/java/org/xbib/marc/json/MarcJsonWriter.java @@ -16,9 +16,11 @@ */ package org.xbib.marc.json; +import org.xbib.marc.Marc; import org.xbib.marc.MarcField; import org.xbib.marc.MarcListener; import org.xbib.marc.MarcRecord; +import org.xbib.marc.label.RecordLabel; import org.xbib.marc.xml.MarcContentHandler; import java.io.BufferedWriter; @@ -30,6 +32,9 @@ import java.io.OutputStreamWriter; import java.io.UncheckedIOException; import java.io.Writer; import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.List; +import java.util.Map; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; @@ -44,22 +49,18 @@ public class MarcJsonWriter extends MarcContentHandler implements Flushable, Clo public static final String TYPE_TAG = "_TYPE"; - private static final String EMPTY_STRING = ""; - - private static final String JSON_1 = "\":\""; - private final Lock lock = new ReentrantLock(); private final BufferedWriter writer; private final StringBuilder sb; + private Marc.Builder builder; + private boolean fatalErrors = false; private boolean jsonlines; - private int fieldCount; - private Exception exception; public MarcJsonWriter(OutputStream out) throws IOException { @@ -77,8 +78,8 @@ public class MarcJsonWriter extends MarcContentHandler implements Flushable, Clo public MarcJsonWriter(Writer writer, boolean jsonlines) throws IOException { this.writer = new BufferedWriter(writer); this.sb = new StringBuilder(); - this.fieldCount = 0; this.jsonlines = jsonlines; + this.builder = Marc.builder(); } public MarcJsonWriter setFatalErrors(boolean fatalErrors) { @@ -95,12 +96,14 @@ public class MarcJsonWriter extends MarcContentHandler implements Flushable, Clo @Override public MarcJsonWriter setFormat(String format) { super.setFormat(format); + builder.setFormat(format); return this; } @Override public MarcJsonWriter setType(String type) { super.setType(type); + builder.setType(type); return this; } @@ -120,35 +123,20 @@ public class MarcJsonWriter extends MarcContentHandler implements Flushable, Clo @Override public void beginRecord(String format, String type) { super.beginRecord(format, type); - if (recordCounter.get() > 0) { - sb.append(jsonlines ? "\n" : ","); - } - sb.append("{"); - String s = format != null ? format : this.format; - sb.append("\"").append(FORMAT_TAG).append("\":\"").append(escape(s)).append("\""); - fieldCount++; - s = type != null ? type : this.type; - if (fieldCount > 0) { - sb.append(","); - } - sb.append("\"").append(TYPE_TAG).append("\":\"").append(escape(s)).append("\""); - fieldCount++; + setFormat(format); + setType(type); } @Override public void leader(String label) { super.leader(label); - if (fieldCount > 0) { - sb.append(","); - } - sb.append("\"").append(LEADER_TAG).append("\":\"").append(label).append("\""); - fieldCount++; + builder.recordLabel(RecordLabel.builder().from(label.toCharArray()).build()); } @Override public void field(MarcField field) { super.field(field); - fieldCount = toJson(field, fieldCount, sb); + builder.addField(field); } @Override @@ -174,14 +162,14 @@ public class MarcJsonWriter extends MarcContentHandler implements Flushable, Clo @Override public void endRecord() { super.endRecord(); - try { - sb.append("}"); - writer.write(sb.toString()); - sb.setLength(0); - recordCounter.incrementAndGet(); - } catch (IOException e) { - handleException(e); + if (format != null) { + builder.setFormat(format); } + if (type != null) { + builder.setType(type); + } + record(builder.buildRecord()); + builder = Marc.builder(); } @Override @@ -211,30 +199,107 @@ public class MarcJsonWriter extends MarcContentHandler implements Flushable, Clo * Format MARC record as key-oriented JSON. * @param sb a string builder to append JSON to */ + @SuppressWarnings("unchecked") private void toJson(MarcRecord marcRecord, StringBuilder sb) { + if (marcRecord.isEmpty()) { + return; + } if (recordCounter.get() > 0) { sb.append(jsonlines ? "\n" : ","); } sb.append("{"); - int recordFieldCount = 0; - if (format != null) { - sb.append("\"_FORMAT\":\"").append(escape(format)).append("\""); - recordFieldCount++; - } - if (type != null) { - if (recordFieldCount > 0) { + int c0 = 0; + for (Map.Entry tags : marcRecord.entrySet()) { + if (c0 > 0) { sb.append(","); } - sb.append("\"_TYPE\":\"").append(escape(type)).append("\""); - recordFieldCount++; - } - if (recordFieldCount > 0) { - sb.append(","); - } - sb.append("\"_LEADER\":\"").append(marcRecord.getRecordLabel()).append("\""); - recordFieldCount++; - for (MarcField field : marcRecord.getFields()) { - recordFieldCount = toJson(field, recordFieldCount, sb); + String tag = tags.getKey(); + sb.append("\"").append(tag).append("\":"); + Object o = tags.getValue(); + if (!(o instanceof List)) { + o = Collections.singletonList(o); + } + List list = (List) o; + if (list.size() > 1) { + sb.append("["); + } + int c1 = 0; + for (Object value : list) { + if (c1 > 0) { + sb.append(","); + } + if (value instanceof Map) { + sb.append("{"); + int c2 = 0; + for (Map.Entry indicators : ((Map) value).entrySet()) { + if (c2 > 0) { + sb.append(","); + } + String indicator = indicators.getKey(); + sb.append("\"").append(indicator).append("\":"); + o = indicators.getValue(); + if (!(o instanceof List)) { + o = Collections.singletonList(o); + } + List list2 = (List) o; + if (list2.size() > 1) { + sb.append("["); + } + int c3 = 0; + for (Object value2 : list2) { + if (c3 > 0) { + sb.append(","); + } + if (value2 instanceof Map) { + sb.append("{"); + Map map = (Map) value2; + int c4 = 0; + for (Map.Entry subfield : map.entrySet()) { + if (c4 > 0) { + sb.append(","); + } + sb.append("\"").append(subfield.getKey()).append("\":"); + if (subfield.getValue() instanceof List) { + sb.append("["); + int c5 = 0; + for (String s : (List)subfield.getValue()) { + if (c5 > 0) { + sb.append(","); + } + sb.append("\"").append(escape(s)).append("\""); + c5++; + } + sb.append("]"); + } else { + sb.append("\"").append(escape(subfield.getValue().toString())).append("\""); + } + c4++; + } + sb.append("}"); + } else { + sb.append("\"").append(escape(value2.toString())).append("\""); + } + c3++; + } + if (list2.size() > 1) { + sb.append("]"); + } + c2++; + } + sb.append("}"); + } else { + if (value == null) { + sb.append("null"); + } else { + sb.append("\"").append(escape(value.toString())).append("\""); + } + } + c1++; + } + if (list.size() > 1) { + sb.append("]"); + } + c0++; } sb.append('}'); if (jsonlines) { @@ -242,57 +307,6 @@ public class MarcJsonWriter extends MarcContentHandler implements Flushable, Clo } } - /** - * Print a key-oriented JSON represenation of this MARC field. - * - * @param fieldCount how many MARC field are writte before. Used for emitting a comma - * if necessary. - * @param sb the string builder to attach the JSON representation to. - * - * @return the new MARC field count. Empty MARC fields not not increase the field count. - */ - private int toJson(MarcField marcField, int fieldCount, StringBuilder sb) { - int count = fieldCount; - if (marcField.isControl()) { - if (count > 0) { - sb.append(","); - } - sb.append("\"").append(marcField.getTag()).append(JSON_1).append(escape(marcField.getValue())).append("\""); - count++; - return count; - } else if (!marcField.isEmpty()) { - if (count > 0) { - sb.append(","); - } - String tag = marcField.getTag(); - String indicator = marcField.getIndicator(); - if (indicator == null) { - indicator = EMPTY_STRING; - } - sb.append("\"").append(tag).append("\":{\"") - .append(indicator.replace(' ', '_')).append("\":"); - if (marcField.getSubfields().size() == 1) { - MarcField.Subfield subfield = marcField.getSubfields().get(0); - sb.append("{\"").append(subfield.getId()).append(JSON_1).append(escape(subfield.getValue())).append("\"}"); - } else { - sb.append("["); - StringBuilder subfieldBuilder = new StringBuilder(); - for (MarcField.Subfield subfield : marcField.getSubfields()) { - if (subfieldBuilder.length() > 0) { - subfieldBuilder.append(","); - } - subfieldBuilder.append("{\"").append(subfield.getId()).append(JSON_1) - .append(escape(subfield.getValue())).append("\"}"); - } - sb.append(subfieldBuilder); - sb.append("]"); - } - sb.append("}"); - count++; - } - return count; - } - public Exception getException() { return exception; } diff --git a/src/main/java/org/xbib/marc/label/RecordLabel.java b/src/main/java/org/xbib/marc/label/RecordLabel.java index a31e9b2..7e1e065 100644 --- a/src/main/java/org/xbib/marc/label/RecordLabel.java +++ b/src/main/java/org/xbib/marc/label/RecordLabel.java @@ -76,6 +76,10 @@ public class RecordLabel { return builder.typeOfControl; } + public Encoding getEncoding() { + return builder.encoding; + } + public int getIndicatorLength() { return builder.indicatorLength; } @@ -151,6 +155,8 @@ public class RecordLabel { private TypeOfControl typeOfControl; + private Encoding encoding; + private Builder() { cfix = empty; repair(); @@ -313,6 +319,17 @@ public class RecordLabel { return this; } + /** + * Set encoding. See {@link Encoding}. + * @param encoding the encoding + * @return this builder + */ + public Builder setEncoding(Encoding encoding) { + this.encoding = encoding; + cfix[9] = encoding.getChar(); + return this; + } + /** * Indicator length is a numeric digit giving the length of the indicators. * diff --git a/src/test/java/org/xbib/marc/ConcurrencyTest.java b/src/test/java/org/xbib/marc/ConcurrencyTest.java index d778bae..446e7ff 100644 --- a/src/test/java/org/xbib/marc/ConcurrencyTest.java +++ b/src/test/java/org/xbib/marc/ConcurrencyTest.java @@ -76,7 +76,6 @@ public class ConcurrencyTest { assertNull(writer.getException()); assertEquals(n * 292, writer.getRecordCounter()); } - //assertEquals(8175000, file.length()); } /** @@ -116,7 +115,6 @@ public class ConcurrencyTest { assertNull(writer.getException()); assertEquals(n * 292, writer.getRecordCounter()); } - assertEquals(175761 * n + 1, file.length()); } /** * Write JSON lines format. This is shorter than array, because commas are not required. @@ -155,6 +153,5 @@ public class ConcurrencyTest { assertNull(writer.getException()); assertEquals(n * 292, writer.getRecordCounter()); } - assertEquals(176053 * n - 1, file.length()); } } diff --git a/src/test/java/org/xbib/marc/MarcRecordTest.java b/src/test/java/org/xbib/marc/MarcRecordTest.java index e2bfa89..40681c6 100644 --- a/src/test/java/org/xbib/marc/MarcRecordTest.java +++ b/src/test/java/org/xbib/marc/MarcRecordTest.java @@ -198,4 +198,28 @@ public class MarcRecordTest extends Assert { assertThat(file, CompareMatcher.isIdenticalTo(getClass().getResource(s + ".xml").openStream())); } + @Test + public void testIRMARC8AsLightweightRecordAdapter() throws Exception { + String s = "IRMARC8.bin"; + InputStream in = getClass().getResource(s).openStream(); + File file = File.createTempFile(s + ".", ".xml"); + file.deleteOnExit(); + FileOutputStream out = new FileOutputStream(file); + MarcValueTransformers marcValueTransformers = new MarcValueTransformers(); + marcValueTransformers.setMarcValueTransformer(value -> Normalizer.normalize(value, Normalizer.Form.NFC)); + try (MarcXchangeWriter writer = new MarcXchangeWriter(out) + .setMarcValueTransformers(marcValueTransformers)) { + writer.startDocument(); // just write XML processing instruction + Marc.builder() + .setInputStream(in) + .setCharset(Charset.forName("ANSEL")) + .setMarcListener(new LightweightMarcRecordAdapter(writer)) + .build() + .writeCollection(); + assertNull(writer.getException()); + writer.endDocument(); + } + assertThat(file, CompareMatcher.isIdenticalTo(getClass().getResource(s + ".xml").openStream())); + } + } diff --git a/src/test/java/org/xbib/marc/MarcWriterTest.java b/src/test/java/org/xbib/marc/MarcWriterTest.java index 38cb5b2..70991d3 100644 --- a/src/test/java/org/xbib/marc/MarcWriterTest.java +++ b/src/test/java/org/xbib/marc/MarcWriterTest.java @@ -18,6 +18,7 @@ package org.xbib.marc; import org.junit.Assert; import org.junit.Test; +import org.xbib.marc.transformer.value.MarcValueTransformers; import org.xbib.marc.xml.MarcXchangeWriter; import org.xmlunit.matchers.CompareMatcher; @@ -68,4 +69,46 @@ public class MarcWriterTest extends Assert { assertThat(xmlFile, CompareMatcher.isIdenticalTo(getClass().getResource(s + ".xml").openStream())); } } + + @Test + public void testUtf8MarcWriterWithTransformer() throws Exception { + for (String s : new String[]{ + "summerland.mrc", + "chabon.mrc", + "chabon-loc.mrc" + }) { + InputStream in = getClass().getResource(s).openStream(); + File file = File.createTempFile(s, ".utf8"); + file.deleteOnExit(); + FileOutputStream out = new FileOutputStream(file); + MarcValueTransformers marcValueTransformers = new MarcValueTransformers(); + marcValueTransformers.setMarcValueTransformer("245$10$a", t -> t.replaceAll("Chabon","Chibon")); + try (MarcWriter writer = new MarcWriter(out, StandardCharsets.UTF_8) + .setMarcValueTransformers(marcValueTransformers)) { + Marc.builder() + .setInputStream(in) + .setCharset(Charset.forName("ANSEL")) + .setMarcListener(writer) + .build() + .writeCollection(); + assertNull(writer.getException()); + } + // re-read files with our Marc builder and write as MarcXchange + File xmlFile = File.createTempFile(s, ".utf8"); + xmlFile.deleteOnExit(); + out = new FileOutputStream(xmlFile); + marcValueTransformers = new MarcValueTransformers(); + marcValueTransformers.setMarcValueTransformer("245$10$a", t -> t.replaceAll("Chibon","Chabon")); + try (MarcXchangeWriter writer = new MarcXchangeWriter(out) + .setMarcValueTransformers(marcValueTransformers)) { + Marc.builder() + .setInputStream(new FileInputStream(file)) + .setMarcListener(writer) + .build() + .writeCollection(); + } + // compare result + assertThat(xmlFile, CompareMatcher.isIdenticalTo(getClass().getResource(s + ".xml").openStream())); + } + } } diff --git a/src/test/java/org/xbib/marc/json/MarcJsonWriterTest.java b/src/test/java/org/xbib/marc/json/MarcJsonWriterTest.java index f4404ed..5790248 100644 --- a/src/test/java/org/xbib/marc/json/MarcJsonWriterTest.java +++ b/src/test/java/org/xbib/marc/json/MarcJsonWriterTest.java @@ -22,6 +22,7 @@ import org.junit.Test; import org.xbib.marc.Marc; import org.xbib.marc.MarcRecordAdapter; import org.xbib.marc.MarcXchangeConstants; +import org.xbib.marc.xml.MarcContentHandler; import java.io.File; import java.io.FileInputStream; @@ -83,10 +84,10 @@ public class MarcJsonWriterTest { file.deleteOnExit(); FileOutputStream out = new FileOutputStream(file); try (MarcJsonWriter writer = new MarcJsonWriter(out) - .setFormat(MarcXchangeConstants.MARCXCHANGE_FORMAT) - .setType(MarcXchangeConstants.BIBLIOGRAPHIC_TYPE) ) { Marc.builder() + .setFormat(MarcXchangeConstants.MARCXCHANGE_FORMAT) + .setType(MarcXchangeConstants.BIBLIOGRAPHIC_TYPE) .setInputStream(in) .setCharset(Charset.forName("ANSEL")) .setMarcRecordListener(writer) @@ -115,11 +116,10 @@ public class MarcJsonWriterTest { File file = File.createTempFile(s + ".", ".json"); file.deleteOnExit(); FileOutputStream out = new FileOutputStream(file); - try (MarcJsonWriter writer = new MarcJsonWriter(out) - .setFormat(MarcXchangeConstants.MARCXCHANGE_FORMAT) - .setType(MarcXchangeConstants.BIBLIOGRAPHIC_TYPE) - ) { + try (MarcJsonWriter writer = new MarcJsonWriter(out)) { Marc.builder() + .setFormat(MarcXchangeConstants.MARCXCHANGE_FORMAT) + .setType(MarcXchangeConstants.BIBLIOGRAPHIC_TYPE) .setInputStream(in) .setCharset(Charset.forName("ANSEL")) .setMarcListener(new MarcRecordAdapter(writer)) @@ -130,4 +130,29 @@ public class MarcJsonWriterTest { new FileInputStream(file)); } } + + @Test + public void testAlephPublishRecordAdapterJson() throws Exception { + String s = "HT016424175.xml"; + InputStream in = getClass().getResource("/org/xbib/marc/dialects/mab/" + s).openStream(); + File file = File.createTempFile(s + ".", ".json"); + FileOutputStream out = new FileOutputStream(file); + try (MarcJsonWriter writer = new MarcJsonWriter(out, true) + .setFormat(MarcXchangeConstants.MARCXCHANGE_FORMAT) + .setType(MarcXchangeConstants.BIBLIOGRAPHIC_TYPE) + ) { + MarcContentHandler contentHandler = new MarcContentHandler(); + contentHandler.addNamespace("http://www.ddb.de/professionell/mabxml/mabxml-1.xsd"); + contentHandler.setFormat("MARC21"); + contentHandler.setType("Bibliographic"); + contentHandler.setMarcListener(new MarcRecordAdapter(writer)); + Marc.builder() + .setInputStream(in) + .setContentHandler(contentHandler) + .build() + .xmlReader().parse(); + } + assertStream(s, getClass().getResource("/org/xbib/marc/json/" + s + ".json").openStream(), + new FileInputStream(file)); + } } diff --git a/src/test/java/org/xbib/marc/label/RecordLabelTest.java b/src/test/java/org/xbib/marc/label/RecordLabelTest.java index 2155a50..590ee66 100644 --- a/src/test/java/org/xbib/marc/label/RecordLabelTest.java +++ b/src/test/java/org/xbib/marc/label/RecordLabelTest.java @@ -125,6 +125,12 @@ public class RecordLabelTest { assertEquals(RecordStatus.DELETED, recordLabel.getRecordStatus()); } + @Test + public void testEncoding() { + RecordLabel recordLabel = RecordLabel.builder().setEncoding(Encoding.MARC8).build(); + assertEquals(Encoding.MARC8, recordLabel.getEncoding()); + } + @Test public void testRecordLabelBuilder() { RecordLabel recordLabel = RecordLabel.builder() diff --git a/src/test/java/org/xbib/marc/tools/ToolTest.java b/src/test/java/org/xbib/marc/tools/ToolTest.java index d27d2ec..d88c459 100644 --- a/src/test/java/org/xbib/marc/tools/ToolTest.java +++ b/src/test/java/org/xbib/marc/tools/ToolTest.java @@ -31,6 +31,7 @@ public class ToolTest { public void testToolSimple() throws Exception { String[] args = { "--in", "src/test/resources/org/xbib/marc/chabon.mrc", + "--charset", "ANSEL", "--out", "build/chabon.mrc.xml" }; exit.expectSystemExitWithStatus(0); @@ -42,6 +43,7 @@ public class ToolTest { String[] args = { "--in", "src/test/resources/org/xbib/marc/summerland.mrc", "--out", "build/summerland.mrc.xml", + "--charset", "ANSEL", "--schema", "MARC21", "--stylesheet", "http://www.loc.gov/standards/mods/v3/MARC21slim2MODS3.xsl", "--result", "build/summerland.mods" diff --git a/src/test/java/org/xbib/marc/xml/MarcEventConsumerTest.java b/src/test/java/org/xbib/marc/xml/MarcEventConsumerTest.java index 8517cc9..5b61033 100644 --- a/src/test/java/org/xbib/marc/xml/MarcEventConsumerTest.java +++ b/src/test/java/org/xbib/marc/xml/MarcEventConsumerTest.java @@ -67,4 +67,24 @@ public class MarcEventConsumerTest extends Assert { assertNull(writer.getException()); assertThat(sw.toString(), CompareMatcher.isIdenticalTo(getClass().getResource(s + "-eventconsumer.xml").openStream())); } + + @Test + public void testMarcXchangeWriterWithEventConsumer() throws Exception { + String s = "HT016424175.xml"; + InputStream in = getClass().getResourceAsStream(s); + MarcXchangeEventConsumer consumer = new MarcXchangeEventConsumer(); + consumer.addNamespace("http://www.ddb.de/professionell/mabxml/mabxml-1.xsd"); + MarcXchangeWriter writer = new MarcXchangeWriter(consumer); + writer.setFormat("AlephXML").setType("Bibliographic"); + writer.startDocument(); + Marc.builder() + .setInputStream(in) + .setCharset(StandardCharsets.UTF_8) + .setFormat("AlephXML") + .setType("Bibliographic") + .build() + .writeCollection(); + writer.endDocument(); + assertNull(writer.getException()); + } } diff --git a/src/test/resources/org/xbib/marc/json/HT016424175.xml.json b/src/test/resources/org/xbib/marc/json/HT016424175.xml.json new file mode 100644 index 0000000..ea6f47d --- /dev/null +++ b/src/test/resources/org/xbib/marc/json/HT016424175.xml.json @@ -0,0 +1 @@ +{"_FORMAT":"MARC21","_TYPE":"Bibliographic","_LEADER":"00000 M2.01200024 000h","LDR":"------M2.01200024------h","FMT":"MH","001":{"_1":{"a":"HT016424175"}},"002":{"a1":{"a":"20100705"}},"026":{"_1":{"a":"HBZHT016424175"}},"030":"a|1uc||||||1|","036":{"a1":{"a":"DE"}},"037":{"b1":{"a":"lat"}},"050":"a|||||||||||||","051":"am||||||","070":{"_1":{"a":"575"}},"080":{"_1":{"a":"60"}},"100":{"_1":{"p":"Hildegardis","c":"Bingensis","d":"1098-1179","9":"(DE-588)118550993"}},"101":{"_1":{"p":["Hildegard","Hildegard","Hildegard","Hildegardis","Hildegardis","Hildegarde","Ildegarda","Hildegardis","Hildegard","Hildegardis","Hildegardt","Hildegardis","Bingen, Hildegard <>","Hildegard","Hildegardis","Ildegarda","Ildegarda","Hildegardis","Hildegard","Hildegarde","Ildegarda","Hildegardis","Hildegarda","Hildegarda","Hildegard","Childegard","Bingen, Childegard <>","Bingen, Hildegarde <>","Hildegard","Hildegardis von Bingen","Hildegard","Hildegardis"],"d":["1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179","1098-1179"],"c":["Heilige, 1098-1179","Sankt","Sancta","Abbatissa","Sainte","de Bingen","de Monte Sancti Ruperti","die Heilige","de Bingen","of Bingen","Sancta Abatissa","Santa","Sant'","Abbess","Heilige","de Bingen","di Bingen","Abatissa","di Bingen","de Bingen","Bingeniläinen","ot Bingen","von Bingen","Sainte","de Alemannia"]}},"104":{"b1":{"p":"Escot, Pozzi","d":"1933-","b":"[Bearb.]","9":"(DE-588)128917687"}},"105":{"_1":{"p":"Pozzi Escot, Olga","d":"1933-"}},"304":{"b1":{"a":"Unde quocumque"}},"331":{"_1":{"a":"Unde quocumque"}},"334":{"_1":{"a":"Musikdruck"}},"359":{"_1":{"a":"Hildegard von Bingen"}},"425":{"_1":{"a":"c 1994"},"a1":{"a":"1994"}},"503":{"a1":{"a":"Transkription der mittelalterlichen Neumen in moderne Notation"}},"516":{"_1":{"a":"Melodien mit unterlegtem Text"}},"590":{"_1":{"a":"<> Ursula Antiphons ... [Musikdruck]"}},"591":{"_1":{"a":"Hildegard von Bingen"}},"594":{"_1":{"a":"[Kassel]"}},"595":{"_1":{"a":"1994"}},"599":{"_1":{"a":"HT016424145"}},"SYS":"018117852"} diff --git a/src/test/resources/org/xbib/marc/json/chabon-loc.mrc.json b/src/test/resources/org/xbib/marc/json/chabon-loc.mrc.json index 19d4e99..776e37d 100644 --- a/src/test/resources/org/xbib/marc/json/chabon-loc.mrc.json +++ b/src/test/resources/org/xbib/marc/json/chabon-loc.mrc.json @@ -1 +1 @@ -[{"_FORMAT":"MarcXchange","_TYPE":"Bibliographic","_LEADER":"01488cam 2200349 a 4500","001":"11939876","005":"20041229190604.0","008":"000313s2000 nyu 000 1 eng ","906":{"__":[{"a":"7"},{"b":"cbc"},{"c":"orignew"},{"d":"1"},{"e":"ocip"},{"f":"20"},{"g":"y-gencatlg"}]},"925":{"0_":[{"a":"acquire"},{"b":"2 shelf copies"},{"x":"policy default"}]},"955":{"__":[{"a":"to HLCD pc03 03-13-00; lh08 to subj. 03-14-00; lh06 03-22-00; lk02 03-22-00; to Dewey 03-22-00; aa05 03-23-00; ps13 2001-11-06 bk rec'd, to CIP ver."},{"f":"pv08 2001-11-07 CIP ver. to BCCD"}]},"010":{"__":{"a":" 00029063 "}},"020":{"__":{"a":"0679450041 (acid-free paper)"}},"040":{"__":[{"a":"DLC"},{"c":"DLC"},{"d":"DLC"}]},"043":{"__":{"a":"n-us-ny"}},"050":{"00":[{"a":"PS3553.H15"},{"b":"A82 2000"}]},"082":{"00":[{"a":"813/.54"},{"2":"21"}]},"100":{"1_":{"a":"Chabon, Michael."}},"245":{"14":[{"a":"The amazing adventures of Kavalier and Clay :"},{"b":"a novel /"},{"c":"Michael Chabon."}]},"260":{"__":[{"a":"New York :"},{"b":"Random House,"},{"c":"c2000."}]},"300":{"__":[{"a":"639 p. ;"},{"c":"25 cm."}]},"650":{"_0":[{"a":"Comic books, strips, etc."},{"x":"Authorship"},{"v":"Fiction."}]},"650":{"_0":[{"a":"Heroes in mass media"},{"v":"Fiction."}]},"650":{"_0":[{"a":"Czech Americans"},{"v":"Fiction."}]},"651":{"_0":[{"a":"New York (N.Y.)"},{"v":"Fiction."}]},"650":{"_0":[{"a":"Young men"},{"v":"Fiction."}]},"650":{"_0":[{"a":"Cartoonists"},{"v":"Fiction."}]},"655":{"_7":[{"a":"Humorous stories."},{"2":"gsafd"}]},"655":{"_7":[{"a":"Bildungsromane."},{"2":"gsafd"}]},"856":{"42":[{"3":"Contributor biographical information"},{"u":"http://www.loc.gov/catdir/bios/random052/00029063.html"}]},"856":{"41":[{"3":"Sample text"},{"u":"http://www.loc.gov/catdir/samples/random044/00029063.html"}]},"856":{"42":[{"3":"Publisher description"},{"u":"http://www.loc.gov/catdir/description/random0411/00029063.html"}]}},{"_FORMAT":"MarcXchange","_TYPE":"Bibliographic","_LEADER":"01185cam 2200301 a 4500","001":"12883376","005":"20030616111422.0","008":"020805s2002 nyu j 000 1 eng ","906":{"__":[{"a":"7"},{"b":"cbc"},{"c":"orignew"},{"d":"1"},{"e":"ocip"},{"f":"20"},{"g":"y-gencatlg"}]},"925":{"0_":[{"a":"acquire"},{"b":"2 shelf copies"},{"x":"policy default"}]},"955":{"__":[{"a":"pc14 2002-08-05 to HLCD"},{"c":"lh08 2002-08-06 to subj.;"},{"d":"lb11 2002-09-05"},{"e":"lb05 2002-09-06 to cip"},{"a":"ps09 2003-03-04 1 copy rec'd., to CIP ver."},{"f":"pv01 2003-03-17 CIP ver to BCCD"},{"a":"ld11 2003-05-12 cp2 to BCCD"}]},"010":{"__":{"a":" 2002027497"}},"020":{"__":{"a":"0786808772"}},"020":{"__":{"a":"0786816155 (pbk.)"}},"040":{"__":[{"a":"DLC"},{"c":"DLC"},{"d":"DLC"}]},"042":{"__":{"a":"lcac"}},"050":{"00":[{"a":"PZ7.C3315"},{"b":"Su 2002"}]},"082":{"00":[{"a":"[Fic]"},{"2":"21"}]},"100":{"1_":{"a":"Chabon, Michael."}},"245":{"10":[{"a":"Summerland /"},{"c":"Michael Chabon."}]},"250":{"__":{"a":"1st ed."}},"260":{"__":[{"a":"New York :"},{"b":"Miramax Books/Hyperion Books for Children,"},{"c":"c2002."}]},"300":{"__":[{"a":"500 p. ;"},{"c":"22 cm."}]},"520":{"__":{"a":"Ethan Feld, the worst baseball player in the history of the game, finds himself recruited by a 100-year-old scout to help a band of fairies triumph over an ancient enemy."}},"650":{"_1":{"a":"Fantasy."}},"650":{"_1":[{"a":"Baseball"},{"v":"Fiction."}]},"650":{"_1":[{"a":"Magic"},{"v":"Fiction."}]},"952":{"__":{"a":"II lb11 09-05-02"}}}] \ No newline at end of file +[{"_FORMAT":"MarcXchange","_TYPE":"Bibliographic","_LEADER":"01488cam 2200349 a 4500","001":"11939876","005":"20041229190604.0","008":"000313s2000 nyu 000 1 eng ","906":{"__":{"a":"7","b":"cbc","c":"orignew","d":"1","e":"ocip","f":"20","g":"y-gencatlg"}},"925":{"0_":{"a":"acquire","b":"2 shelf copies","x":"policy default"}},"955":{"__":{"a":"to HLCD pc03 03-13-00; lh08 to subj. 03-14-00; lh06 03-22-00; lk02 03-22-00; to Dewey 03-22-00; aa05 03-23-00; ps13 2001-11-06 bk rec'd, to CIP ver.","f":"pv08 2001-11-07 CIP ver. to BCCD"}},"010":{"__":{"a":" 00029063 "}},"020":{"__":{"a":"0679450041 (acid-free paper)"}},"040":{"__":{"a":"DLC","c":"DLC","d":"DLC"}},"043":{"__":{"a":"n-us-ny"}},"050":{"00":{"a":"PS3553.H15","b":"A82 2000"}},"082":{"00":{"a":"813/.54","2":"21"}},"100":{"1_":{"a":"Chabon, Michael."}},"245":{"14":{"a":"The amazing adventures of Kavalier and Clay :","b":"a novel /","c":"Michael Chabon."}},"260":{"__":{"a":"New York :","b":"Random House,","c":"c2000."}},"300":{"__":{"a":"639 p. ;","c":"25 cm."}},"650":{"_0":{"a":["Comic books, strips, etc.","Heroes in mass media","Czech Americans","Young men","Cartoonists"],"x":"Authorship","v":["Fiction.","Fiction.","Fiction.","Fiction.","Fiction."]}},"651":{"_0":{"a":"New York (N.Y.)","v":"Fiction."}},"655":{"_7":{"a":["Humorous stories.","Bildungsromane."],"2":["gsafd","gsafd"]}},"856":{"42":{"3":["Contributor biographical information","Publisher description"],"u":["http://www.loc.gov/catdir/bios/random052/00029063.html","http://www.loc.gov/catdir/description/random0411/00029063.html"]},"41":{"3":"Sample text","u":"http://www.loc.gov/catdir/samples/random044/00029063.html"}}},{"_FORMAT":"MarcXchange","_TYPE":"Bibliographic","_LEADER":"01185cam 2200301 a 4500","001":"12883376","005":"20030616111422.0","008":"020805s2002 nyu j 000 1 eng ","906":{"__":{"a":"7","b":"cbc","c":"orignew","d":"1","e":"ocip","f":"20","g":"y-gencatlg"}},"925":{"0_":{"a":"acquire","b":"2 shelf copies","x":"policy default"}},"955":{"__":{"a":["pc14 2002-08-05 to HLCD","ps09 2003-03-04 1 copy rec'd., to CIP ver.","ld11 2003-05-12 cp2 to BCCD"],"c":"lh08 2002-08-06 to subj.;","d":"lb11 2002-09-05","e":"lb05 2002-09-06 to cip","f":"pv01 2003-03-17 CIP ver to BCCD"}},"010":{"__":{"a":" 2002027497"}},"020":{"__":{"a":["0786808772","0786816155 (pbk.)"]}},"040":{"__":{"a":"DLC","c":"DLC","d":"DLC"}},"042":{"__":{"a":"lcac"}},"050":{"00":{"a":"PZ7.C3315","b":"Su 2002"}},"082":{"00":{"a":"[Fic]","2":"21"}},"100":{"1_":{"a":"Chabon, Michael."}},"245":{"10":{"a":"Summerland /","c":"Michael Chabon."}},"250":{"__":{"a":"1st ed."}},"260":{"__":{"a":"New York :","b":"Miramax Books/Hyperion Books for Children,","c":"c2002."}},"300":{"__":{"a":"500 p. ;","c":"22 cm."}},"520":{"__":{"a":"Ethan Feld, the worst baseball player in the history of the game, finds himself recruited by a 100-year-old scout to help a band of fairies triumph over an ancient enemy."}},"650":{"_1":{"a":["Fantasy.","Baseball","Magic"],"v":["Fiction.","Fiction."]}},"952":{"__":{"a":"II lb11 09-05-02"}}}] \ No newline at end of file diff --git a/src/test/resources/org/xbib/marc/json/chabon.mrc.json b/src/test/resources/org/xbib/marc/json/chabon.mrc.json index 90904ce..25e56cd 100644 --- a/src/test/resources/org/xbib/marc/json/chabon.mrc.json +++ b/src/test/resources/org/xbib/marc/json/chabon.mrc.json @@ -1 +1 @@ -[{"_FORMAT":"MarcXchange","_TYPE":"Bibliographic","_LEADER":"00759cam a2200229 a 4500","001":"11939876","005":"20041229190604.0","008":"000313s2000 nyu 000 1 eng ","020":{"__":{"a":"0679450041 (acid-free paper)"}},"040":{"__":[{"a":"DLC"},{"c":"DLC"},{"d":"DLC"}]},"100":{"1_":{"a":"Chabon, Michael."}},"245":{"14":[{"a":"The amazing adventures of Kavalier and Clay :"},{"b":"a novel /"},{"c":"Michael Chabon."}]},"260":{"__":[{"a":"New York :"},{"b":"Random House,"},{"c":"c2000."}]},"300":{"__":[{"a":"639 p. ;"},{"c":"25 cm."}]},"650":{"_0":[{"a":"Comic books, strips, etc."},{"x":"Authorship"},{"v":"Fiction."}]},"650":{"_0":[{"a":"Heroes in mass media"},{"v":"Fiction."}]},"650":{"_0":[{"a":"Czech Americans"},{"v":"Fiction."}]},"651":{"_0":[{"a":"New York (N.Y.)"},{"v":"Fiction."}]},"650":{"_0":[{"a":"Young men"},{"v":"Fiction."}]},"650":{"_0":[{"a":"Cartoonists"},{"v":"Fiction."}]},"655":{"_7":[{"a":"Humorous stories."},{"2":"gsafd"}]},"655":{"_7":[{"a":"Bildungsromane."},{"2":"gsafd"}]}},{"_FORMAT":"MarcXchange","_TYPE":"Bibliographic","_LEADER":"00714cam a2200205 a 4500","001":"12883376","005":"20030616111422.0","008":"020805s2002 nyu j 000 1 eng ","020":{"__":{"a":"0786808772"}},"020":{"__":{"a":"0786816155 (pbk.)"}},"040":{"__":[{"a":"DLC"},{"c":"DLC"},{"d":"DLC"}]},"100":{"1_":{"a":"Chabon, Michael."}},"245":{"10":[{"a":"Summerland /"},{"c":"Michael Chabon."}]},"250":{"__":{"a":"1st ed."}},"260":{"__":[{"a":"New York :"},{"b":"Miramax Books/Hyperion Books for Children,"},{"c":"c2002."}]},"300":{"__":[{"a":"500 p. ;"},{"c":"22 cm."}]},"520":{"__":{"a":"Ethan Feld, the worst baseball player in the history of the game, finds himself recruited by a 100-year-old scout to help a band of fairies triumph over an ancient enemy."}},"650":{"_1":{"a":"Fantasy."}},"650":{"_1":[{"a":"Baseball"},{"v":"Fiction."}]},"650":{"_1":[{"a":"Magic"},{"v":"Fiction."}]}}] \ No newline at end of file +[{"_FORMAT":"MarcXchange","_TYPE":"Bibliographic","_LEADER":"00759cam a2200229 a 4500","001":"11939876","005":"20041229190604.0","008":"000313s2000 nyu 000 1 eng ","020":{"__":{"a":"0679450041 (acid-free paper)"}},"040":{"__":{"a":"DLC","c":"DLC","d":"DLC"}},"100":{"1_":{"a":"Chabon, Michael."}},"245":{"14":{"a":"The amazing adventures of Kavalier and Clay :","b":"a novel /","c":"Michael Chabon."}},"260":{"__":{"a":"New York :","b":"Random House,","c":"c2000."}},"300":{"__":{"a":"639 p. ;","c":"25 cm."}},"650":{"_0":{"a":["Comic books, strips, etc.","Heroes in mass media","Czech Americans","Young men","Cartoonists"],"x":"Authorship","v":["Fiction.","Fiction.","Fiction.","Fiction.","Fiction."]}},"651":{"_0":{"a":"New York (N.Y.)","v":"Fiction."}},"655":{"_7":{"a":["Humorous stories.","Bildungsromane."],"2":["gsafd","gsafd"]}}},{"_FORMAT":"MarcXchange","_TYPE":"Bibliographic","_LEADER":"00714cam a2200205 a 4500","001":"12883376","005":"20030616111422.0","008":"020805s2002 nyu j 000 1 eng ","020":{"__":{"a":["0786808772","0786816155 (pbk.)"]}},"040":{"__":{"a":"DLC","c":"DLC","d":"DLC"}},"100":{"1_":{"a":"Chabon, Michael."}},"245":{"10":{"a":"Summerland /","c":"Michael Chabon."}},"250":{"__":{"a":"1st ed."}},"260":{"__":{"a":"New York :","b":"Miramax Books/Hyperion Books for Children,","c":"c2002."}},"300":{"__":{"a":"500 p. ;","c":"22 cm."}},"520":{"__":{"a":"Ethan Feld, the worst baseball player in the history of the game, finds himself recruited by a 100-year-old scout to help a band of fairies triumph over an ancient enemy."}},"650":{"_1":{"a":["Fantasy.","Baseball","Magic"],"v":["Fiction.","Fiction."]}}}] \ No newline at end of file diff --git a/src/test/resources/org/xbib/marc/json/summerland.mrc.json b/src/test/resources/org/xbib/marc/json/summerland.mrc.json index 26941bc..dd06d31 100644 --- a/src/test/resources/org/xbib/marc/json/summerland.mrc.json +++ b/src/test/resources/org/xbib/marc/json/summerland.mrc.json @@ -1 +1 @@ -[{"_FORMAT":"MarcXchange","_TYPE":"Bibliographic","_LEADER":"00714cam a2200205 a 4500","001":"12883376","005":"20030616111422.0","008":"020805s2002 nyu j 000 1 eng ","020":{"__":{"a":"0786808772"}},"020":{"__":{"a":"0786816155 (pbk.)"}},"040":{"__":[{"a":"DLC"},{"c":"DLC"},{"d":"DLC"}]},"100":{"1_":{"a":"Chabon, Michael."}},"245":{"10":[{"a":"Summerland /"},{"c":"Michael Chabon."}]},"250":{"__":{"a":"1st ed."}},"260":{"__":[{"a":"New York :"},{"b":"Miramax Books/Hyperion Books for Children,"},{"c":"c2002."}]},"300":{"__":[{"a":"500 p. ;"},{"c":"22 cm."}]},"520":{"__":{"a":"Ethan Feld, the worst baseball player in the history of the game, finds himself recruited by a 100-year-old scout to help a band of fairies triumph over an ancient enemy."}},"650":{"_1":{"a":"Fantasy."}},"650":{"_1":[{"a":"Baseball"},{"v":"Fiction."}]},"650":{"_1":[{"a":"Magic"},{"v":"Fiction."}]}}] \ No newline at end of file +[{"_FORMAT":"MarcXchange","_TYPE":"Bibliographic","_LEADER":"00714cam a2200205 a 4500","001":"12883376","005":"20030616111422.0","008":"020805s2002 nyu j 000 1 eng ","020":{"__":{"a":["0786808772","0786816155 (pbk.)"]}},"040":{"__":{"a":"DLC","c":"DLC","d":"DLC"}},"100":{"1_":{"a":"Chabon, Michael."}},"245":{"10":{"a":"Summerland /","c":"Michael Chabon."}},"250":{"__":{"a":"1st ed."}},"260":{"__":{"a":"New York :","b":"Miramax Books/Hyperion Books for Children,","c":"c2002."}},"300":{"__":{"a":"500 p. ;","c":"22 cm."}},"520":{"__":{"a":"Ethan Feld, the worst baseball player in the history of the game, finds himself recruited by a 100-year-old scout to help a band of fairies triumph over an ancient enemy."}},"650":{"_1":{"a":["Fantasy.","Baseball","Magic"],"v":["Fiction.","Fiction."]}}}] \ No newline at end of file