Skip to content
This repository has been archived by the owner on Jan 27, 2025. It is now read-only.

Don't restrict bind scope to the bound var #83

Merged
merged 4 commits into from
Dec 3, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -92,21 +92,33 @@ else if (sub instanceof Unless) {
private void processBind(final Do theDo, final EList<String> params) {
if (theDo.getName().equals("list")) { // TODO impl multiple binds via FixBind enum
final Map<String, String> options = options(theDo.getOptions());
final Record fullRecord = record.shallowClone();

record.findList(options.get("path"), a -> a.forEach(value -> {
// for each value, bind the current record/scope/context to the given var name:
record = new Record();
record.put(options.get("var"), value);

processSubexpressions(theDo.getElements());
record.remove(options.get("var"));

// and remember the things we added while bound (this probably needs some tweaking):
fullRecord.addAll(record);
}));

record = fullRecord;
record.findList(options.get("path"), a -> {
for (int i = 0; i < a.size(); ++i) {
final Value value = a.get(i);
final String var = options.get("var");
// with var -> keep full record in scope, add the var:
if (var != null) {
record.put(var, value);
processSubexpressions(theDo.getElements());
record.remove(var);
}
// w/o var -> use the currently bound value as the record:
else {
if (value.isHash()) {
final Record fullRecord = record.shallowClone();
blackwinter marked this conversation as resolved.
Show resolved Hide resolved
record = new Record();
record.addAll(value.asHash());
processSubexpressions(theDo.getElements());
a.set(i, new Value(record));
record = fullRecord;
}
else {
// TODO: bind to arrays (if that makes sense) and strings (access with '.')
throw new IllegalStateException(Value.UNEXPECTED + value);
blackwinter marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
});
}
else {
LOG.warn("Unprocessed bind: {}", theDo);
Expand Down
9 changes: 6 additions & 3 deletions metafix/src/main/java/org/metafacture/metafix/Value.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
* or a {@link java.lang.String String}.
*/
public class Value {

/*package-private*/ static final String UNEXPECTED = "expected array or hash, got ";
blackwinter marked this conversation as resolved.
Show resolved Hide resolved
/*package-private*/ static final String APPEND_FIELD = "$append";
private static final String LAST_FIELD = "$last";
private static final String ASTERISK = "*";
Expand Down Expand Up @@ -419,6 +419,11 @@ private void insert(final InsertMode mode, final String[] fields, final String n
break;
}
}

/*package-private*/ void set(final int i, final Value value) {
list.set(i, value);
blackwinter marked this conversation as resolved.
Show resolved Hide resolved
}

}

/**
Expand All @@ -428,8 +433,6 @@ public static class Hash extends AbstractValueType {

private static final String FIELD_PATH_SEPARATOR = "\\.";

private static final String UNEXPECTED = "expected array or hash, got ";

private final Map<String, Value> map = new LinkedHashMap<>();

/**
Expand Down
100 changes: 99 additions & 1 deletion metafix/src/test/java/org/metafacture/metafix/MetafixBindTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,104 @@ public void doList() {
});
}

@Test
public void doListFullRecordInScope() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"do list('path': 'name', 'var': 'n')",
" if any_equal('type','book')",
" paste('title','~Book:','n')",
" else",
" paste('title','~Journal:','n')",
" end",
"end",
"retain('title')"),
i -> {
i.startRecord("1");
i.literal("type", "book");
i.literal("name", "A book");
i.endRecord();
i.startRecord("2");
i.literal("type", "journal");
i.literal("name", "A journal");
i.endRecord();
}, o -> {
o.get().startRecord("1");
o.get().literal("title", "Book: A book");
o.get().endRecord();
o.get().startRecord("2");
o.get().literal("title", "Journal: A journal");
o.get().endRecord();
});
}

@Test
public void bindingScopeWithVar() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"do list('path':'foo','var':'loop')",
" copy_field('test','loop.baz')",
" copy_field('loop.bar','loop.qux')",
"end"),
i -> {
i.startRecord("1");
i.startEntity("foo");
i.literal("bar", "1");
i.endEntity();
i.startEntity("foo");
i.literal("bar", "2");
i.endEntity();
i.literal("test", "42");
i.endRecord();
}, (o, f) -> {
o.get().startRecord("1");
o.get().startEntity("foo");
o.get().startEntity("1");
o.get().literal("bar", "1");
o.get().literal("baz", "42");
o.get().literal("qux", "1");
f.apply(1).endEntity();
o.get().startEntity("2");
o.get().literal("bar", "2");
o.get().literal("baz", "42");
o.get().literal("qux", "2");
f.apply(2).endEntity();
o.get().literal("test", "42");
o.get().endRecord();
});
}

@Test
public void bindingScopeWithoutVar() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"do list('path':'foo')",
" copy_field('test','baz')",
" copy_field('bar','qux')",
"end"),
i -> {
i.startRecord("1");
i.startEntity("foo");
i.literal("bar", "1");
i.endEntity();
i.startEntity("foo");
i.literal("bar", "2");
i.endEntity();
i.literal("test", "42");
i.endRecord();
}, (o, f) -> {
o.get().startRecord("1");
o.get().startEntity("foo");
o.get().startEntity("1");
o.get().literal("bar", "1");
o.get().literal("qux", "1");
f.apply(1).endEntity();
o.get().startEntity("2");
o.get().literal("bar", "2");
o.get().literal("qux", "2");
f.apply(2).endEntity();
o.get().literal("test", "42");
o.get().endRecord();
});
}

@Test
public void doListPathWithDots() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
Expand Down Expand Up @@ -99,8 +197,8 @@ public void doListPathWithDots() {
@Test
public void doListWithAppendAndLast() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"set_array('author[]')",
"do list('path': 'creator', 'var': 'c')",
" set_array('author[]')",
" copy_field('c.name', 'author[].$append.name')",
" add_field('author[].$last.type', 'Default')",
"end",
Expand Down