Skip to content

Commit b8f5ad5

Browse files
committed
Merge branch '107-passDataThroughMetamorphElse' of https://github.com/metafacture/metafacture-core
See #333.
2 parents 62ab1cd + 113ce50 commit b8f5ad5

File tree

6 files changed

+132
-18
lines changed

6 files changed

+132
-18
lines changed

metafacture-biblio/src/main/java/org/metafacture/biblio/marc21/MarcXmlEncoder.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,8 @@ public void literal(final String name, final String value) {
175175
if (currentEntity.equals("")) {
176176
prettyPrintIndentation();
177177
writeRaw(String.format(CONTROLFIELD_OPEN_TEMPLATE, name));
178-
writeEscaped(value.trim());
178+
if (value != null)
179+
writeEscaped(value.trim());
179180
writeRaw(CONTROLFIELD_CLOSE);
180181
prettyPrintNewLine();
181182
} else if (!currentEntity.equals(Marc21EventNames.LEADER_ENTITY)) {

metafacture-biblio/src/test/java/org/metafacture/biblio/marc21/MarcXmlEncoderTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,4 +204,17 @@ public void sendAndClearDataWhenOnResetStream() {
204204
String actual = resultCollector.toString();
205205
assertEquals(expected, actual);
206206
}
207+
208+
@Test
209+
public void shouldIgnoreNullValueOfLiteral() {
210+
encoder.startRecord(RECORD_ID);
211+
encoder.literal("type", null);
212+
encoder.endRecord();
213+
encoder.closeStream();
214+
String expected = XML_DECLARATION + XML_ROOT_OPEN
215+
+ "<marc:record><marc:controlfield tag=\"type\"></marc:controlfield></marc:record>"
216+
+ XML_MARC_COLLECTION_END_TAG;
217+
String actual = resultCollector.toString();
218+
assertEquals(expected, actual);
219+
}
207220
}

metamorph/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@ dependencies {
2424
implementation project(':metafacture-flowcontrol')
2525
implementation project(':metafacture-mangling')
2626
implementation project(':metafacture-javaintegration')
27+
implementation 'org.slf4j:slf4j-api:1.7.21'
2728
testImplementation 'junit:junit:4.12'
2829
testImplementation 'org.mockito:mockito-core:2.5.5'
30+
testRuntimeOnly 'org.slf4j:slf4j-simple:1.7.21'
2931
}
3032

3133
sourceSets {

metamorph/src/main/java/org/metafacture/metamorph/Metamorph.java

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.util.LinkedList;
2929
import java.util.List;
3030
import java.util.Map;
31+
import java.util.regex.Pattern;
3132

3233
import org.metafacture.commons.ResourceUtil;
3334
import org.metafacture.framework.FluxCommand;
@@ -48,6 +49,8 @@
4849
import org.metafacture.metamorph.api.NamedValueReceiver;
4950
import org.metafacture.metamorph.api.NamedValueSource;
5051
import org.metafacture.metamorph.api.SourceLocation;
52+
import org.slf4j.Logger;
53+
import org.slf4j.LoggerFactory;
5154
import org.xml.sax.InputSource;
5255

5356
/**
@@ -64,7 +67,9 @@
6467
@FluxCommand("morph")
6568
public final class Metamorph implements StreamPipe<StreamReceiver>, NamedValuePipe, Maps {
6669

70+
private static final String ELSE_NESTED_KEYWORD = "_elseNested";
6771
public static final String ELSE_KEYWORD = "_else";
72+
public static final String ELSE_FLATTENED_KEYWORD = "_elseFlattened";
6873
public static final char FEEDBACK_CHAR = '@';
6974
public static final char ESCAPE_CHAR = '\\';
7075
public static final String METADATA = "__meta";
@@ -94,6 +99,9 @@ public final class Metamorph implements StreamPipe<StreamReceiver>, NamedValuePi
9499
private MorphErrorHandler errorHandler = new DefaultErrorHandler();
95100
private int recordCount;
96101
private final List<FlushListener> recordEndListener = new ArrayList<>();
102+
private boolean elseNested;
103+
final private Pattern literalPatternOfEntityMarker = Pattern.compile(flattener.getEntityMarker(), Pattern.LITERAL);
104+
private static final Logger LOG = LoggerFactory.getLogger(Metamorph.class);
97105

98106
protected Metamorph() {
99107
// package private
@@ -215,8 +223,15 @@ public void setErrorHandler(final MorphErrorHandler errorHandler) {
215223
}
216224

217225
protected void registerNamedValueReceiver(final String source, final NamedValueReceiver data) {
218-
if (ELSE_KEYWORD.equals(source)) {
219-
elseSources.add(data);
226+
if (ELSE_NESTED_KEYWORD.equals(source)) {
227+
this.elseNested = true;
228+
}
229+
if (ELSE_KEYWORD.equals(source) || ELSE_FLATTENED_KEYWORD.equals(source) || elseNested) {
230+
if (elseSources.isEmpty())
231+
elseSources.add(data);
232+
else
233+
LOG.warn(
234+
"Only one of '_else', '_elseFlattened' and '_elseNested' is allowed. Ignoring the superflous ones.");
220235
} else {
221236
dataRegistry.register(source, data);
222237
}
@@ -268,9 +283,6 @@ public void startEntity(final String name) {
268283
entityCountStack.push(Integer.valueOf(entityCount));
269284

270285
flattener.startEntity(name);
271-
272-
273-
274286
}
275287

276288
@Override
@@ -306,28 +318,38 @@ public void closeStream() {
306318
outputStreamReceiver.closeStream();
307319
}
308320

309-
protected void dispatch(final String path, final String value, final List<NamedValueReceiver> fallback) {
310-
final List<NamedValueReceiver> matchingData = findMatchingData(path, fallback);
311-
if (null != matchingData) {
312-
send(path, value, matchingData);
313-
}
314-
}
315-
316-
private List<NamedValueReceiver> findMatchingData(final String path, final List<NamedValueReceiver> fallback) {
317-
final List<NamedValueReceiver> matchingData = dataRegistry.get(path);
321+
protected void dispatch(final String path, final String value, final List<NamedValueReceiver> fallbackReceiver) {
322+
List<NamedValueReceiver> matchingData = dataRegistry.get(path);
323+
boolean fallback = false;
318324
if (matchingData == null || matchingData.isEmpty()) {
319-
return fallback;
325+
fallback = true;
326+
matchingData = fallbackReceiver;
327+
}
328+
if (null != matchingData) {
329+
send(path, value, matchingData, fallback);
320330
}
321-
return matchingData;
322331
}
323332

324-
private void send(final String key, final String value, final List<NamedValueReceiver> dataList) {
333+
private void send(final String path, final String value, final List<NamedValueReceiver> dataList,
334+
final boolean fallback) {
325335
for (final NamedValueReceiver data : dataList) {
336+
String key = path;
337+
if (fallback && elseNested) {
338+
if (flattener.getCurrentEntityName() != null) {
339+
outputStreamReceiver.startEntity(flattener.getCurrentEntityName());
340+
key = literalPatternOfEntityMarker.split(path)[1];
341+
}
342+
}
326343
try {
327344
data.receive(key, value, null, recordCount, currentEntityCount);
328345
} catch (final RuntimeException e) {
329346
errorHandler.error(e);
330347
}
348+
if (fallback && elseNested) {
349+
if (flattener.getCurrentEntityName() != null) {
350+
outputStreamReceiver.endEntity();
351+
}
352+
}
331353
}
332354
}
333355

metamorph/src/test/java/org/metafacture/metamorph/MetamorphTest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ public final class MetamorphTest {
5252
@Mock
5353
private NamedValueReceiver namedValueReceiver;
5454

55+
@Mock
56+
private DefaultStreamReceiver receiver = new DefaultStreamReceiver();
57+
5558
private Metamorph metamorph;
5659

5760
@Before
@@ -60,6 +63,7 @@ public void createSystemUnderTest() {
6063
metamorph.setReceiver(new DefaultStreamReceiver());
6164
}
6265

66+
6367
@Test
6468
public void shouldMapMatchingPath() {
6569
setupSimpleMappingMorph();

metamorph/src/test/java/org/metafacture/metamorph/TestMetamorphBasics.java

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,78 @@ public void shouldHandleUnmatchedLiteralsInElseSource() {
8686
ordered.verify(receiver).endRecord();
8787
}
8888

89+
@Test
90+
public void shouldHandleUnmatchedLiteralsAndEntitiesInElseSource() {
91+
metamorph = InlineMorph.in(this) //
92+
.with("<rules>") //
93+
.with(" <data source='_else'/>")//
94+
.with("</rules>")//
95+
.createConnectedTo(receiver);
96+
testElseData();
97+
}
98+
99+
@Test
100+
public void shouldHandleUnmatchedLiteralsAndEntitiesInElseFlattenedSource() {
101+
metamorph = InlineMorph.in(this) //
102+
.with("<rules>") //
103+
.with(" <data source='_elseFlattened'/>")//
104+
.with("</rules>")//
105+
.createConnectedTo(receiver);
106+
testElseData();
107+
}
108+
private void testElseData() {
109+
metamorph.startRecord("1");
110+
metamorph.literal("Shikotan", "Aekap");
111+
metamorph.startEntity("Germany");
112+
metamorph.literal("Langeoog", "Moin");
113+
metamorph.endEntity();
114+
metamorph.startEntity("Germany");
115+
metamorph.literal("Baltrum", "Moin Moin");
116+
metamorph.endEntity();
117+
metamorph.endRecord();
118+
119+
final InOrder ordered = inOrder(receiver);
120+
ordered.verify(receiver).startRecord("1");
121+
ordered.verify(receiver).literal("Shikotan", "Aekap");
122+
ordered.verify(receiver).literal("Germany.Langeoog", "Moin");
123+
ordered.verify(receiver).literal("Germany.Baltrum", "Moin Moin");
124+
ordered.verify(receiver).endRecord();
125+
}
126+
127+
@Test
128+
public void shouldHandleUnmatchedLiteralsAndEntitiesInElseNestedSource() {
129+
metamorph = InlineMorph.in(this).with("<rules>")//
130+
.with(" <entity name='USA' >")//
131+
.with(" <data source='USA.Sylt' name='Hawaii' />")
132+
.with(" </entity>")//
133+
.with(" <data source='_elseNested' />")//
134+
.with("</rules>")//
135+
.createConnectedTo(receiver);
136+
137+
metamorph.startRecord("1");
138+
metamorph.literal("Shikotan", "Aekap");
139+
metamorph.startEntity("Germany");
140+
metamorph.literal("Langeoog", "Moin");
141+
metamorph.literal("Baltrum", "Moin Moin");
142+
metamorph.endEntity();
143+
metamorph.startEntity("USA");
144+
metamorph.literal("Sylt", "Aloha");
145+
metamorph.endEntity();
146+
metamorph.endRecord();
147+
148+
final InOrder ordered = inOrder(receiver);
149+
ordered.verify(receiver).startRecord("1");
150+
ordered.verify(receiver).literal("Shikotan", "Aekap");
151+
ordered.verify(receiver).startEntity("Germany");
152+
ordered.verify(receiver).literal("Langeoog", "Moin");
153+
ordered.verify(receiver).literal("Baltrum", "Moin Moin");
154+
ordered.verify(receiver).endEntity();
155+
ordered.verify(receiver).startEntity("USA");
156+
ordered.verify(receiver).literal("Hawaii", "Aloha");
157+
ordered.verify(receiver).endEntity();
158+
ordered.verify(receiver).endRecord();
159+
}
160+
89161
@Test
90162
public void shouldMatchCharacterWithQuestionMarkWildcard() {
91163
metamorph = InlineMorph.in(this)

0 commit comments

Comments
 (0)