Skip to content

Commit

Permalink
Support _elseNested pass-through in Metafix
Browse files Browse the repository at this point in the history
  • Loading branch information
fsteeg committed Dec 1, 2020
1 parent 9b36c3b commit 16e5a81
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ public class Metafix implements StreamPipe<StreamReceiver>, NamedValuePipe, Maps
public static final String VAR_END = "]";

private static final String ENTITIES_NOT_BALANCED = "Entity starts and ends are not balanced";
private static final Object ELSE_NESTED_KEYWORD = "_elseNested";
private static final Object ELSE_FLATTENED_KEYWORD = "_elseFlattened";

private static final InterceptorFactory NULL_INTERCEPTOR_FACTORY = new NullInterceptorFactory();
private static final Map<String, String> NO_VARS = Collections.emptyMap();
Expand Down Expand Up @@ -128,6 +130,10 @@ public List<NamedValueReceiver> get(final String path) {
private final List<Expression> expressions = new ArrayList<>();
private Map<String, String> vars = NO_VARS;

private boolean elseNested;
private boolean elseNestedEntityStarted;
private String currentLiteralName;

public Metafix() {
init();
}
Expand Down Expand Up @@ -189,7 +195,7 @@ private void init() {
flattener.setReceiver(new DefaultStreamReceiver() {
@Override
public void literal(final String name, final String value) {
dispatch(name, value, getElseSources());
dispatch(name, value, getElseSources(), false);
}
});
}
Expand Down Expand Up @@ -249,8 +255,16 @@ protected void setErrorHandler(final MorphErrorHandler errorHandler) {
}

protected void registerNamedValueReceiver(final String source, final NamedValueReceiver data) {
if (ELSE_KEYWORD.equals(source)) {
elseSources.add(data);
if (ELSE_NESTED_KEYWORD.equals(source)) {
elseNested = true;
}
if (ELSE_KEYWORD.equals(source) || ELSE_FLATTENED_KEYWORD.equals(source) || elseNested) {
if (elseSources.isEmpty()) {
elseSources.add(data);
}
else {
System.out.println("Only one of '_else', '_elseFlattened' and '_elseNested' is allowed. Ignoring the superflous ones.");
}
}
else {
dataRegistry.register(source, data);
Expand All @@ -270,7 +284,7 @@ public void startRecord(final String identifier) {
recordCount %= Integer.MAX_VALUE;

outputStreamReceiver.startRecord(identifier);
dispatch(StandardEventNames.ID, identifier, null);
dispatch(StandardEventNames.ID, identifier, null, false);
}

@Override
Expand Down Expand Up @@ -304,13 +318,14 @@ public void startEntity(final String name) {

@Override
public void endEntity() {
dispatch(flattener.getCurrentPath(), "", null);
dispatch(flattener.getCurrentPath(), "", getElseSources(), true);
currentEntityCount = entityCountStack.pop().intValue();
flattener.endEntity();
}

@Override
public void literal(final String name, final String value) {
currentLiteralName = name;
flattener.literal(name, value);
}

Expand All @@ -334,17 +349,42 @@ public void closeStream() {
outputStreamReceiver.closeStream();
}

private void dispatch(final String path, final String value, final List<NamedValueReceiver> fallback) {
private void dispatch(final String path, final String value, final List<NamedValueReceiver> fallback, final boolean endEntity) {
final List<NamedValueReceiver> matchingData = findMatchingData(path, fallback);

if (matchingData != null) {
send(path, value, matchingData);
}
else if (fallback != null) {
if (endEntity) {
if (elseNestedEntityStarted) {
outputStreamReceiver.endEntity();
elseNestedEntityStarted = false;
}
}
else {
final String entityName = elseNested ? flattener.getCurrentEntityName() : null;

if (entityName != null) {
if (findMatchingData(entityName, fallback) == null) {
if (!elseNestedEntityStarted) {
outputStreamReceiver.startEntity(entityName);
elseNestedEntityStarted = true;
}

send(currentLiteralName, value, fallback);
}
}
else {
send(path, value, fallback);
}
}
}
}

private List<NamedValueReceiver> findMatchingData(final String path, final List<NamedValueReceiver> fallback) {
final List<NamedValueReceiver> matchingData = dataRegistry.get(path);
return matchingData == null || matchingData.isEmpty() ? fallback : matchingData;
return matchingData != null && !matchingData.isEmpty() ? matchingData : null;
}

private void send(final String key, final String value, final List<NamedValueReceiver> dataList) {
Expand Down Expand Up @@ -380,7 +420,7 @@ public void receive(final String name, final String value, final NamedValueSourc
final int end = Math.min(name.indexOf(flattener.getEntityMarker()), name.indexOf(FixBuilder.ARRAY_MARKER));
final String firstNameSegment = end == -1 ? name : name.substring(0, end);
if (name.length() != 0 && name.charAt(0) == FEEDBACK_CHAR && !JSONLD_KEYWORDS.contains(firstNameSegment)) {
dispatch(name, value, null);
dispatch(name, value, null, false);
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ public class MetafixDslTest {
private static final String LITERAL_B = "lit-B";
private static final String LITERAL_HAWAII = "Hawaii";
private static final String LITERAL_MOIN = "Moin";
private static final String LITERAL_MOIN_MOIN = "Moin Moin";
private static final String LITERAL_LANGEOOG = "Langeoog";
private static final String LITERAL_BALTRUM = "Baltrum";

@RegisterExtension
private MockitoRule mockitoRule = MockitoJUnit.rule();
Expand Down Expand Up @@ -419,16 +422,16 @@ public void shouldHandleUnmatchedLiteralsInElseSource() {
);

metafix.startRecord("1");
metafix.literal("Langeoog", LITERAL_MOIN);
metafix.literal(LITERAL_LANGEOOG, LITERAL_MOIN);
metafix.literal("Sylt", LITERAL_ALOHA);
metafix.literal("Baltrum", "Moin Moin");
metafix.literal(LITERAL_BALTRUM, LITERAL_MOIN_MOIN);
metafix.endRecord();

final InOrder ordered = Mockito.inOrder(streamReceiver);
ordered.verify(streamReceiver).startRecord("1");
ordered.verify(streamReceiver).literal("Langeoog", LITERAL_MOIN);
ordered.verify(streamReceiver).literal(LITERAL_LANGEOOG, LITERAL_MOIN);
ordered.verify(streamReceiver).literal(LITERAL_HAWAII, LITERAL_ALOHA);
ordered.verify(streamReceiver).literal("Baltrum", "Moin Moin");
ordered.verify(streamReceiver).literal(LITERAL_BALTRUM, LITERAL_MOIN_MOIN);
ordered.verify(streamReceiver).endRecord();
ordered.verifyNoMoreInteractions();
}
Expand Down Expand Up @@ -882,6 +885,39 @@ public void shouldNotFeedbackJsonLdKeywords() {
Mockito.verify(streamReceiver).literal("@id", LITERAL_HAWAII);
}

@Test
public void shouldNotFeedbackJsonLdKeywordsNested() {
final Metafix metafix = fix(
"do entity('USA')",
" map('USA.Sylt', 'Hawaii')",
"end",
"map(_elseNested)"
);

metafix.startRecord("1");
metafix.literal("Shikotan", "Aekap");
metafix.startEntity("Germany");
metafix.literal(LITERAL_LANGEOOG, LITERAL_MOIN);
metafix.literal(LITERAL_BALTRUM, LITERAL_MOIN_MOIN);
metafix.endEntity();
metafix.startEntity("USA");
metafix.literal("Sylt", LITERAL_ALOHA);
metafix.endEntity();
metafix.endRecord();

final InOrder ordered = Mockito.inOrder(streamReceiver);
ordered.verify(streamReceiver).startRecord("1");
ordered.verify(streamReceiver).literal("Shikotan", "Aekap");
ordered.verify(streamReceiver).startEntity("Germany");
ordered.verify(streamReceiver).literal(LITERAL_LANGEOOG, "Moin");
ordered.verify(streamReceiver).literal(LITERAL_BALTRUM, LITERAL_MOIN_MOIN);
ordered.verify(streamReceiver).endEntity();
ordered.verify(streamReceiver).startEntity("USA");
ordered.verify(streamReceiver).literal("Hawaii", "Aloha");
ordered.verify(streamReceiver).endEntity();
ordered.verify(streamReceiver).endRecord();
}

@Test
@Disabled("Fix syntax")
public void shouldReplaceVariables() {
Expand Down

0 comments on commit 16e5a81

Please sign in to comment.