Skip to content

Commit df8395c

Browse files
committed
Pass macro() variables to nested Fix contexts. (#243)
1 parent d39c2c3 commit df8395c

File tree

2 files changed

+88
-28
lines changed

2 files changed

+88
-28
lines changed

metafix/src/main/java/org/metafacture/metafix/RecordTransformer.java

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -63,20 +63,22 @@ public class RecordTransformer { // checkstyle-disable-line ClassFanOutComplexit
6363
private final List<Consumer<Record>> consumers = new LinkedList<>();
6464
private final List<Map<String, String>> vars = new ArrayList<>();
6565
private final Metafix metafix;
66+
private final RecordTransformer parent;
6667

6768
private Supplier<String> currentMessageSupplier;
6869

6970
/*package-private*/ RecordTransformer(final Metafix metafix, final Fix fix) {
70-
this(metafix, fix.getElements());
71+
this(metafix, fix.getElements(), null);
72+
addVars(metafix.getVars());
7173
}
7274

73-
private RecordTransformer(final Metafix metafix, final List<Expression> expressions) {
75+
private RecordTransformer(final Metafix metafix, final List<Expression> expressions, final RecordTransformer parent) {
7476
this.metafix = metafix;
75-
addVars(metafix.getVars());
77+
this.parent = parent;
7678

7779
expressions.forEach(e -> {
78-
final Params params = new Params(e.getParams(), vars);
79-
final Options options = new Options(e.getOptions(), vars);
80+
final Params params = new Params(e.getParams(), this);
81+
final Options options = new Options(e.getOptions(), this);
8082

8183
if (e instanceof Do) {
8284
processDo((Do) e, params, options);
@@ -96,6 +98,10 @@ else if (e instanceof MethodCall) {
9698
});
9799
}
98100

101+
private RecordTransformer childTransformer(final List<Expression> expressions) {
102+
return new RecordTransformer(metafix, expressions, this);
103+
}
104+
99105
public void addVars(final Map<String, String> additionalVars) {
100106
vars.add(additionalVars);
101107
}
@@ -125,7 +131,7 @@ public void transform(final Record record) {
125131
private void processDo(final Do expression, final Params params, final Options options) {
126132
processFix(() -> executionExceptionMessage(expression), () -> {
127133
final FixContext context = getInstance(expression.getName(), FixContext.class, FixBind::valueOf);
128-
final RecordTransformer recordTransformer = new RecordTransformer(metafix, expression.getElements());
134+
final RecordTransformer recordTransformer = childTransformer(expression.getElements());
129135

130136
return record -> context.execute(metafix, record, params.resolve(), options.resolve(), recordTransformer);
131137
});
@@ -140,14 +146,14 @@ private void processIf(final If ifExpression, final Params ifParams, final Optio
140146

141147
processFix(() -> executionExceptionMessage(ifExpression, ifExpression.eResource()), () -> {
142148
final FixPredicate ifPredicate = getInstance(ifExpression.getName(), FixPredicate.class, FixConditional::valueOf);
143-
final RecordTransformer ifTransformer = new RecordTransformer(metafix, ifExpression.getElements());
149+
final RecordTransformer ifTransformer = childTransformer(ifExpression.getElements());
144150

145151
final List<FixPredicate> elseIfPredicates = mapList(elseIfExpressions, e -> getInstance(e.getName(), FixPredicate.class, FixConditional::valueOf));
146-
final List<Params> elseIfParamsList = mapList(elseIfExpressions, e -> new Params(e.getParams(), vars));
147-
final List<Options> elseIfOptionsList = mapList(elseIfExpressions, e -> new Options(e.getOptions(), vars));
148-
final List<RecordTransformer> elseIfTransformers = mapList(elseIfExpressions, e -> new RecordTransformer(metafix, e.getElements()));
152+
final List<Params> elseIfParamsList = mapList(elseIfExpressions, e -> new Params(e.getParams(), this));
153+
final List<Options> elseIfOptionsList = mapList(elseIfExpressions, e -> new Options(e.getOptions(), this));
154+
final List<RecordTransformer> elseIfTransformers = mapList(elseIfExpressions, e -> childTransformer(e.getElements()));
149155

150-
final RecordTransformer elseTransformer = elseExpression != null ? new RecordTransformer(metafix, elseExpression.getElements()) : null;
156+
final RecordTransformer elseTransformer = elseExpression != null ? childTransformer(elseExpression.getElements()) : null;
151157

152158
return record -> {
153159
if (ifPredicate.test(metafix, record, ifParams.resolve(), ifOptions.resolve())) {
@@ -182,7 +188,7 @@ private void processIf(final If ifExpression, final Params ifParams, final Optio
182188
private void processUnless(final Unless expression, final Params params, final Options options) {
183189
processFix(() -> executionExceptionMessage(expression, expression.eResource()), () -> {
184190
final FixPredicate predicate = getInstance(expression.getName(), FixPredicate.class, FixConditional::valueOf);
185-
final RecordTransformer recordTransformer = new RecordTransformer(metafix, expression.getElements());
191+
final RecordTransformer recordTransformer = childTransformer(expression.getElements());
186192

187193
return record -> {
188194
if (!predicate.test(metafix, record, params.resolve(), options.resolve())) {
@@ -255,6 +261,12 @@ private String executionExceptionMessage(final EObject object, final Resource re
255261
resource.getURI(), node.getStartLine(), NodeModelUtils.getTokenText(node));
256262
}
257263

264+
private Map<String, String> getVars() {
265+
final Map<String, String> mergedVars = parent != null ? parent.getVars() : new HashMap<>();
266+
vars.forEach(mergedVars::putAll);
267+
return mergedVars;
268+
}
269+
258270
private abstract static class AbstractResolvable<T> {
259271

260272
protected boolean isResolvable(final String value) {
@@ -265,25 +277,19 @@ protected String resolveVars(final String value, final Map<String, String> vars)
265277
return value == null ? null : StringUtil.format(value, Metafix.VAR_START, Metafix.VAR_END, false, vars);
266278
}
267279

268-
protected Map<String, String> mergeVars(final List<Map<String, String>> vars) {
269-
final Map<String, String> mergedVars = new HashMap<>();
270-
vars.forEach(mergedVars::putAll);
271-
return mergedVars;
272-
}
273-
274280
protected abstract T resolve();
275281

276282
}
277283

278284
private static class Params extends AbstractResolvable<List<String>> {
279285

280286
private final List<String> list;
281-
private final List<Map<String, String>> vars;
287+
private final RecordTransformer recordTransformer;
282288
private final boolean resolve;
283289

284-
private Params(final List<String> list, final List<Map<String, String>> vars) {
290+
private Params(final List<String> list, final RecordTransformer recordTransformer) {
285291
this.list = list;
286-
this.vars = vars;
292+
this.recordTransformer = recordTransformer;
287293

288294
resolve = list.stream().anyMatch(this::isResolvable);
289295
}
@@ -292,10 +298,10 @@ private Params(final List<String> list, final List<Map<String, String>> vars) {
292298
protected List<String> resolve() {
293299
if (resolve) {
294300
final List<String> resolvedList = new ArrayList<>(list.size());
295-
final Map<String, String> mergedVars = mergeVars(vars);
301+
final Map<String, String> vars = recordTransformer.getVars();
296302

297303
for (final String entry : list) {
298-
resolvedList.add(resolveVars(entry, mergedVars));
304+
resolvedList.add(resolveVars(entry, vars));
299305
}
300306

301307
return resolvedList;
@@ -310,11 +316,11 @@ protected List<String> resolve() {
310316
private static class Options extends AbstractResolvable<Map<String, String>> {
311317

312318
private final Map<String, String> map = new LinkedHashMap<>();
313-
private final List<Map<String, String>> vars;
319+
private final RecordTransformer recordTransformer;
314320
private final boolean resolve;
315321

316-
private Options(final org.metafacture.metafix.fix.Options options, final List<Map<String, String>> vars) {
317-
this.vars = vars;
322+
private Options(final org.metafacture.metafix.fix.Options options, final RecordTransformer recordTransformer) {
323+
this.recordTransformer = recordTransformer;
318324

319325
boolean resolveTemp = false;
320326

@@ -341,10 +347,10 @@ private Options(final org.metafacture.metafix.fix.Options options, final List<Ma
341347
protected Map<String, String> resolve() {
342348
if (resolve) {
343349
final Map<String, String> resolvedMap = new LinkedHashMap<>(map.size());
344-
final Map<String, String> mergedVars = mergeVars(vars);
350+
final Map<String, String> vars = recordTransformer.getVars();
345351

346352
for (final Map.Entry<String, String> entry : map.entrySet()) {
347-
resolvedMap.put(resolveVars(entry.getKey(), mergedVars), resolveVars(entry.getValue(), mergedVars));
353+
resolvedMap.put(resolveVars(entry.getKey(), vars), resolveVars(entry.getValue(), vars));
348354
}
349355

350356
return resolvedMap;

metafix/src/test/java/org/metafacture/metafix/MetafixRecordTest.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2052,6 +2052,60 @@ public void shouldCallMacroWithVariables() {
20522052
);
20532053
}
20542054

2055+
@Test
2056+
public void shouldCallMacroWithVariablesPassedToNestedBinds() {
2057+
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
2058+
"put_vars(a: '1', b: '2')", // global variables
2059+
"do macro('test', b: '22', c: '33')", // "static" local variables
2060+
" do once()",
2061+
" add_field('test', '$[a]-$[b]-$[c]-$[d]')",
2062+
" end",
2063+
"end",
2064+
"macro('test', c: '333', d: '444')", // "dynamic" local variables
2065+
"macro('test', b: '555', d: '666')",
2066+
"add_field('vars', '$[a]-$[b]')"
2067+
),
2068+
i -> {
2069+
i.startRecord("1");
2070+
i.endRecord();
2071+
},
2072+
o -> {
2073+
o.get().startRecord("1");
2074+
o.get().literal("test", "1-22-333-444");
2075+
o.get().literal("vars", "1-2");
2076+
o.get().endRecord();
2077+
}
2078+
);
2079+
}
2080+
2081+
@Test
2082+
public void shouldCallMacroWithVariablesPassedToNestedConditionals() {
2083+
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
2084+
"put_vars(a: '1', b: '2')", // global variables
2085+
"do macro('test', b: '22', c: '33')", // "static" local variables
2086+
" if any_equal('cond', '$[d]')",
2087+
" add_field('test', '$[a]-$[b]-$[c]-$[d]')",
2088+
" end",
2089+
"end",
2090+
"macro('test', c: '333', d: '444')", // "dynamic" local variables
2091+
"macro('test', b: '555', d: '666')",
2092+
"add_field('vars', '$[a]-$[b]')"
2093+
),
2094+
i -> {
2095+
i.startRecord("1");
2096+
i.literal("cond", "666");
2097+
i.endRecord();
2098+
},
2099+
o -> {
2100+
o.get().startRecord("1");
2101+
o.get().literal("cond", "666");
2102+
o.get().literal("test", "1-555-33-666");
2103+
o.get().literal("vars", "1-2");
2104+
o.get().endRecord();
2105+
}
2106+
);
2107+
}
2108+
20552109
@Test
20562110
public void shouldNotLeakVariablesFromMacro() {
20572111
MetafixTestHelpers.assertProcessException(IllegalArgumentException.class, "Variable 'c' was not assigned!\nAssigned variables:\n{a=1, b=2}", () ->

0 commit comments

Comments
 (0)