Skip to content

Commit

Permalink
Allow to pass data through metamorph
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
dr0i committed Oct 9, 2020
1 parent ad48cd4 commit f009e28
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 16 deletions.
41 changes: 25 additions & 16 deletions metamorph/src/main/java/org/metafacture/metamorph/Metamorph.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.metafacture.commons.ResourceUtil;
import org.metafacture.framework.FluxCommand;
Expand Down Expand Up @@ -64,6 +65,7 @@
@FluxCommand("morph")
public final class Metamorph implements StreamPipe<StreamReceiver>, NamedValuePipe, Maps {

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

protected Metamorph() {
// package private
Expand Down Expand Up @@ -215,7 +219,10 @@ public void setErrorHandler(final MorphErrorHandler errorHandler) {
}

protected void registerNamedValueReceiver(final String source, final NamedValueReceiver data) {
if (ELSE_KEYWORD.equals(source)) {
if (ELSE_AND_PASS_ENTITY_EVENTS_KEYWORD.equals(source)) {
this.passEntityEvents = true;
}
if (ELSE_KEYWORD.equals(source) || this.passEntityEvents) {
elseSources.add(data);
} else {
dataRegistry.register(source, data);
Expand Down Expand Up @@ -268,9 +275,6 @@ public void startEntity(final String name) {
entityCountStack.push(Integer.valueOf(entityCount));

flattener.startEntity(name);



}

@Override
Expand Down Expand Up @@ -306,28 +310,33 @@ public void closeStream() {
outputStreamReceiver.closeStream();
}

protected void dispatch(final String path, final String value, final List<NamedValueReceiver> fallback) {
final List<NamedValueReceiver> matchingData = findMatchingData(path, fallback);
if (null != matchingData) {
send(path, value, matchingData);
}
}

private List<NamedValueReceiver> findMatchingData(final String path, final List<NamedValueReceiver> fallback) {
final List<NamedValueReceiver> matchingData = dataRegistry.get(path);
protected void dispatch(final String path, final String value, final List<NamedValueReceiver> fallbackReceiver) {
List<NamedValueReceiver> matchingData = dataRegistry.get(path);
boolean fallback = false;
if (matchingData == null || matchingData.isEmpty()) {
return fallback;
fallback = true;
matchingData = fallbackReceiver;
}
if (null != matchingData) {
send(path, value, matchingData, fallback);
}
return matchingData;
}

private void send(final String key, final String value, final List<NamedValueReceiver> dataList) {
private void send(final String path, final String value, final List<NamedValueReceiver> dataList, final boolean fallback) {
for (final NamedValueReceiver data : dataList) {
String key=path;
if (fallback && value != null && passEntityEvents) {
outputStreamReceiver.startEntity(flattener.getCurrentEntityName());
key=literalPatternOfEntityMarker.split(path)[1];
}
try {
data.receive(key, value, null, recordCount, currentEntityCount);
} catch (final RuntimeException e) {
errorHandler.error(e);
}
if (fallback && value!=null && passEntityEvents) {
outputStreamReceiver.endEntity();
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;

Expand All @@ -33,6 +34,7 @@
import org.metafacture.framework.helpers.DefaultStreamReceiver;
import org.metafacture.metamorph.api.Maps;
import org.metafacture.metamorph.api.NamedValueReceiver;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
Expand All @@ -52,6 +54,9 @@ public final class MetamorphTest {
@Mock
private NamedValueReceiver namedValueReceiver;

@Mock
private DefaultStreamReceiver receiver = new DefaultStreamReceiver();

private Metamorph metamorph;

@Before
Expand All @@ -60,6 +65,7 @@ public void createSystemUnderTest() {
metamorph.setReceiver(new DefaultStreamReceiver());
}


@Test
public void shouldMapMatchingPath() {
setupSimpleMappingMorph();
Expand Down Expand Up @@ -189,4 +195,56 @@ public void shouldThrowIllegalStateExceptionIfEntityIsNotClosed() {
metamorph.endRecord(); // Exception expected
}

@Test
public void metamorph1() {
metamorph = InlineMorph.in(this) //
.with("<rules>") //
.with(" <data source='_else'/>")//
.with("</rules>")//
.createConnectedTo(receiver);

metamorph.startRecord("1");
metamorph.startEntity("clone");
metamorph.literal("id", "0");
metamorph.endEntity();
metamorph.startEntity("clone");
metamorph.literal("id", "1");
metamorph.endEntity();
metamorph.endRecord();

final InOrder ordered = inOrder(receiver);
ordered.verify(receiver).startRecord("1");
ordered.verify(receiver).literal("clone.id", "0");
ordered.verify(receiver).literal("clone.id", "1");
ordered.verify(receiver).endRecord();
}

@Test
public void metamorph1_1() {
metamorph = InlineMorph.in(this).with("<meta>") //
.with("</meta>")//
.with("<rules>")//
.with(" <data source='_elseAndPassEntityEvents' />")//
.with("</rules>")//
.createConnectedTo(receiver);

metamorph.startRecord("1");
metamorph.startEntity("clone");
metamorph.literal("id", "0");
metamorph.endEntity();
metamorph.startEntity("clone");
metamorph.literal("id", "1");
metamorph.endEntity();
metamorph.endRecord();

final InOrder ordered = inOrder(receiver);
ordered.verify(receiver).startRecord("1");
ordered.verify(receiver).startEntity("clone");
ordered.verify(receiver).literal("id", "0");
ordered.verify(receiver).endEntity();
ordered.verify(receiver).startEntity("clone");
ordered.verify(receiver).literal("id", "1");
ordered.verify(receiver).endEntity();
ordered.verify(receiver).endRecord();
}
}

0 comments on commit f009e28

Please sign in to comment.