Skip to content

Commit f009e28

Browse files
committed
Allow to pass data through metamorph
With the new keyword "_elseAndPassEntityEvents" (set with <data source="_elseAndPassEntityEvents" /> ) the known "_else" is triggered AND entity events for these "_else" sources are fired. With this, data can be passed through metamorph. All "_else" data are handled in receivers like all the other data handled by morph rules. Data which is handled by metamorph rules will NOT be passed through (hence the aptly named "_else"). If you want to use data in the morph AND pass it through, you have to add an explicit rule for this, as usual. See #107.
1 parent ad48cd4 commit f009e28

File tree

2 files changed

+83
-16
lines changed

2 files changed

+83
-16
lines changed

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

Lines changed: 25 additions & 16 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;
@@ -64,6 +65,7 @@
6465
@FluxCommand("morph")
6566
public final class Metamorph implements StreamPipe<StreamReceiver>, NamedValuePipe, Maps {
6667

68+
private static final String ELSE_AND_PASS_ENTITY_EVENTS_KEYWORD = "_elseAndPassEntityEvents";
6769
public static final String ELSE_KEYWORD = "_else";
6870
public static final char FEEDBACK_CHAR = '@';
6971
public static final char ESCAPE_CHAR = '\\';
@@ -94,6 +96,8 @@ public final class Metamorph implements StreamPipe<StreamReceiver>, NamedValuePi
9496
private MorphErrorHandler errorHandler = new DefaultErrorHandler();
9597
private int recordCount;
9698
private final List<FlushListener> recordEndListener = new ArrayList<>();
99+
private boolean passEntityEvents;
100+
final private Pattern literalPatternOfEntityMarker = Pattern.compile(flattener.getEntityMarker(), Pattern.LITERAL);
97101

98102
protected Metamorph() {
99103
// package private
@@ -215,7 +219,10 @@ public void setErrorHandler(final MorphErrorHandler errorHandler) {
215219
}
216220

217221
protected void registerNamedValueReceiver(final String source, final NamedValueReceiver data) {
218-
if (ELSE_KEYWORD.equals(source)) {
222+
if (ELSE_AND_PASS_ENTITY_EVENTS_KEYWORD.equals(source)) {
223+
this.passEntityEvents = true;
224+
}
225+
if (ELSE_KEYWORD.equals(source) || this.passEntityEvents) {
219226
elseSources.add(data);
220227
} else {
221228
dataRegistry.register(source, data);
@@ -268,9 +275,6 @@ public void startEntity(final String name) {
268275
entityCountStack.push(Integer.valueOf(entityCount));
269276

270277
flattener.startEntity(name);
271-
272-
273-
274278
}
275279

276280
@Override
@@ -306,28 +310,33 @@ public void closeStream() {
306310
outputStreamReceiver.closeStream();
307311
}
308312

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);
313+
protected void dispatch(final String path, final String value, final List<NamedValueReceiver> fallbackReceiver) {
314+
List<NamedValueReceiver> matchingData = dataRegistry.get(path);
315+
boolean fallback = false;
318316
if (matchingData == null || matchingData.isEmpty()) {
319-
return fallback;
317+
fallback = true;
318+
matchingData = fallbackReceiver;
319+
}
320+
if (null != matchingData) {
321+
send(path, value, matchingData, fallback);
320322
}
321-
return matchingData;
322323
}
323324

324-
private void send(final String key, final String value, final List<NamedValueReceiver> dataList) {
325+
private void send(final String path, final String value, final List<NamedValueReceiver> dataList, final boolean fallback) {
325326
for (final NamedValueReceiver data : dataList) {
327+
String key=path;
328+
if (fallback && value != null && passEntityEvents) {
329+
outputStreamReceiver.startEntity(flattener.getCurrentEntityName());
330+
key=literalPatternOfEntityMarker.split(path)[1];
331+
}
326332
try {
327333
data.receive(key, value, null, recordCount, currentEntityCount);
328334
} catch (final RuntimeException e) {
329335
errorHandler.error(e);
330336
}
337+
if (fallback && value!=null && passEntityEvents) {
338+
outputStreamReceiver.endEntity();
339+
}
331340
}
332341
}
333342

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

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import static org.mockito.ArgumentMatchers.any;
2222
import static org.mockito.ArgumentMatchers.anyInt;
2323
import static org.mockito.ArgumentMatchers.eq;
24+
import static org.mockito.Mockito.inOrder;
2425
import static org.mockito.Mockito.never;
2526
import static org.mockito.Mockito.verify;
2627

@@ -33,6 +34,7 @@
3334
import org.metafacture.framework.helpers.DefaultStreamReceiver;
3435
import org.metafacture.metamorph.api.Maps;
3536
import org.metafacture.metamorph.api.NamedValueReceiver;
37+
import org.mockito.InOrder;
3638
import org.mockito.Mock;
3739
import org.mockito.junit.MockitoJUnit;
3840
import org.mockito.junit.MockitoRule;
@@ -52,6 +54,9 @@ public final class MetamorphTest {
5254
@Mock
5355
private NamedValueReceiver namedValueReceiver;
5456

57+
@Mock
58+
private DefaultStreamReceiver receiver = new DefaultStreamReceiver();
59+
5560
private Metamorph metamorph;
5661

5762
@Before
@@ -60,6 +65,7 @@ public void createSystemUnderTest() {
6065
metamorph.setReceiver(new DefaultStreamReceiver());
6166
}
6267

68+
6369
@Test
6470
public void shouldMapMatchingPath() {
6571
setupSimpleMappingMorph();
@@ -189,4 +195,56 @@ public void shouldThrowIllegalStateExceptionIfEntityIsNotClosed() {
189195
metamorph.endRecord(); // Exception expected
190196
}
191197

198+
@Test
199+
public void metamorph1() {
200+
metamorph = InlineMorph.in(this) //
201+
.with("<rules>") //
202+
.with(" <data source='_else'/>")//
203+
.with("</rules>")//
204+
.createConnectedTo(receiver);
205+
206+
metamorph.startRecord("1");
207+
metamorph.startEntity("clone");
208+
metamorph.literal("id", "0");
209+
metamorph.endEntity();
210+
metamorph.startEntity("clone");
211+
metamorph.literal("id", "1");
212+
metamorph.endEntity();
213+
metamorph.endRecord();
214+
215+
final InOrder ordered = inOrder(receiver);
216+
ordered.verify(receiver).startRecord("1");
217+
ordered.verify(receiver).literal("clone.id", "0");
218+
ordered.verify(receiver).literal("clone.id", "1");
219+
ordered.verify(receiver).endRecord();
220+
}
221+
222+
@Test
223+
public void metamorph1_1() {
224+
metamorph = InlineMorph.in(this).with("<meta>") //
225+
.with("</meta>")//
226+
.with("<rules>")//
227+
.with(" <data source='_elseAndPassEntityEvents' />")//
228+
.with("</rules>")//
229+
.createConnectedTo(receiver);
230+
231+
metamorph.startRecord("1");
232+
metamorph.startEntity("clone");
233+
metamorph.literal("id", "0");
234+
metamorph.endEntity();
235+
metamorph.startEntity("clone");
236+
metamorph.literal("id", "1");
237+
metamorph.endEntity();
238+
metamorph.endRecord();
239+
240+
final InOrder ordered = inOrder(receiver);
241+
ordered.verify(receiver).startRecord("1");
242+
ordered.verify(receiver).startEntity("clone");
243+
ordered.verify(receiver).literal("id", "0");
244+
ordered.verify(receiver).endEntity();
245+
ordered.verify(receiver).startEntity("clone");
246+
ordered.verify(receiver).literal("id", "1");
247+
ordered.verify(receiver).endEntity();
248+
ordered.verify(receiver).endRecord();
249+
}
192250
}

0 commit comments

Comments
 (0)