Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implicit array creation with $append, general $prepend support #368

Merged
merged 10 commits into from
Oct 2, 2024
Merged
32 changes: 27 additions & 5 deletions metafix/src/main/java/org/metafacture/metafix/FixPath.java
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,9 @@ void apply(final Array array, final String field, final Value value) {
final ReservedField reservedField = ReservedField.fromString(field);
if (reservedField != null) {
switch (reservedField) {
case $prepend:
array.add(0, value);
break;
case $append:
array.add(value);
break;
Expand Down Expand Up @@ -275,10 +278,8 @@ else if (isReference(field)) {
mode.apply(hash, field, newValue);
}
else {
if (!hash.containsField(field)) {
hash.put(field, Value.newHash().withPathSet(newValue.getPath()));
}
insertInto(hash.get(field), mode, newValue, field, tail(path));
final String[] tail = tail(path);
insertInto(getContainerValue(hash, field, newValue.getPath(), tail[0]), mode, newValue, field, tail);
}

return new Value(hash);
Expand All @@ -298,12 +299,29 @@ private Value insertInto(final Value value, final InsertMode mode, final Value n
}
}

private Value getContainerValue(final Hash hash, final String field, final String newPath, final String nextField) {
Value result = hash.get(field);
final boolean isAddingToArray = nextField.equals(ReservedField.$prepend.name()) || nextField.equals(ReservedField.$append.name());
if (result == null) {
result = (isAddingToArray ? Value.newArray() : Value.newHash()).withPathSet(newPath);
hash.put(field, result);
}
else {
if (isAddingToArray && result.isString()) {
final Value value = result;
result = Value.newArray(a -> a.add(value));
hash.put(field, result);
}
}
return result;
}

private String[] tail(final String[] fields) {
return Arrays.copyOfRange(fields, 1, fields.length);
}

private enum ReservedField {
$append, $first, $last;
$prepend, $append, $first, $last;

private static final Map<String, ReservedField> STRING_TO_ENUM = new HashMap<>();
static {
Expand Down Expand Up @@ -343,6 +361,10 @@ private Value getReferencedValue(final Array array, final String field, final St
referencedValue = Value.newHash().withPathSet(p); // TODO: append non-hash?
array.add(referencedValue);
break;
case $prepend:
referencedValue = Value.newHash().withPathSet(p);
array.add(0, referencedValue);
break;
default:
break;
}
Expand Down
18 changes: 17 additions & 1 deletion metafix/src/main/java/org/metafacture/metafix/Value.java
Original file line number Diff line number Diff line change
Expand Up @@ -433,8 +433,24 @@ public void add(final Value value) {
}

/* package-private */ void add(final Value value, final boolean appendToPath) {
add(list.size(), value, appendToPath);
}

/* package-private */ void add(final int index, final Value value) {
add(index, value, true);
}

/* package-private */ void add(final int index, final Value value, final boolean appendToPath) {
if (!isNull(value)) {
list.add(appendToPath ? value.withPathAppend(list.size() + 1) : value);
list.add(index, appendToPath ? value.withPathAppend(index + 1) : value);
updateIndexesInPathsAfter(index);
}
}

private void updateIndexesInPathsAfter(final int start) {
for (int index = start + 1; index < list.size(); index = index + 1) {
final Value value = list.get(index);
value.withPathSet(value.getPath().replaceAll("\\d+$", String.valueOf(index + 1)));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -928,14 +928,23 @@ public void shouldLookupInNestedArrays() {
}

@Test
public void shouldLookupInCopiedNestedArrays() {
public void shouldLookupInCopiedNestedArraysCreatedWithAppend() {
shouldLookupInCopiedNestedArraysCreatedWith("$append");
}

@Test
public void shouldLookupInCopiedNestedArraysCreatedWithPrepend() {
shouldLookupInCopiedNestedArraysCreatedWith("$prepend");
}

private void shouldLookupInCopiedNestedArraysCreatedWith(final String reservedField) {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"put_map('rswk-indicator', s: 'SubjectHeading')",
"set_array('subject[]')",
"set_array('subject[].$append.componentList[]')",
"set_array('subject[].$last.componentList[].$append.type[]')",
"set_array('subject[]." + reservedField + ".componentList[]')",
"set_array('subject[].$last.componentList[]." + reservedField + ".type[]')",
"do list(path: 'D', 'var': '$i')",
" copy_field('$i', 'subject[].$last.componentList[].$last.type[].$append')",
" copy_field('$i', 'subject[].$last.componentList[].$last.type[]." + reservedField + "')",
"end",
"lookup('subject[].*.componentList[].*.type[].*', 'rswk-indicator')",
"retain('subject[]')"
Expand Down
144 changes: 139 additions & 5 deletions metafix/src/test/java/org/metafacture/metafix/MetafixRecordTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,115 @@ public void addWithAppendInNewArray() {
);
}

@Test
public void addWithAppendInImplicitArray() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"add_field('my.name.$append','patrick')",
"add_field('my.name.$append','nicolas')"
),
i -> {
i.startRecord("1");
i.endRecord();

i.startRecord("2");
i.startEntity("my");
i.literal("name", "max");
i.endEntity();
i.endRecord();

i.startRecord("3");
i.endRecord();
},
o -> {
o.get().startRecord("1");
o.get().startEntity("my");
o.get().literal("name", "patrick");
o.get().literal("name", "nicolas");
o.get().endEntity();
o.get().endRecord();

o.get().startRecord("2");
o.get().startEntity("my");
o.get().literal("name", "max");
o.get().literal("name", "patrick");
o.get().literal("name", "nicolas");
o.get().endEntity();
o.get().endRecord();

o.get().startRecord("3");
o.get().startEntity("my");
o.get().literal("name", "patrick");
o.get().literal("name", "nicolas");
o.get().endEntity();
o.get().endRecord();
}
);
}

@Test
public void addWithPrependInImplicitArray() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"add_field('my.name.$prepend','patrick')",
"add_field('my.name.$prepend','nicolas')"
),
i -> {
i.startRecord("1");
i.endRecord();

i.startRecord("2");
i.startEntity("my");
i.literal("name", "max");
i.endEntity();
i.endRecord();

i.startRecord("3");
i.endRecord();
},
o -> {
o.get().startRecord("1");
o.get().startEntity("my");
o.get().literal("name", "nicolas");
o.get().literal("name", "patrick");
o.get().endEntity();
o.get().endRecord();

o.get().startRecord("2");
o.get().startEntity("my");
o.get().literal("name", "nicolas");
o.get().literal("name", "patrick");
o.get().literal("name", "max");
o.get().endEntity();
o.get().endRecord();

o.get().startRecord("3");
o.get().startEntity("my");
o.get().literal("name", "nicolas");
o.get().literal("name", "patrick");
o.get().endEntity();
o.get().endRecord();
}
);
}

@Test
public void addWithLastInNonArray() {
MetafixTestHelpers.assertExecutionException(IllegalStateException.class, "Expected Array or Hash, got String", () ->
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"add_field('my.name.$last','patrick')"
),
i -> {
i.startRecord("1");
i.startEntity("my");
i.literal("name", "max");
i.endEntity();
i.endRecord();
},
o -> {
}
)
);
}

@Test
public void addWithAppendInArray() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
Expand Down Expand Up @@ -1417,11 +1526,9 @@ public void renameArrayOfHashes() {
}

@Test
@MetafixToDo("Do we actually need/want implicit $append? WDCD?")
public void copyIntoArrayOfHashesImplicitAppend() {
public void copyIntoImplicitArrayAppend() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"set_array('author[]')",
"copy_field('your.name','author[].name')",
"copy_field('your.name','author[].$append.name')",
"remove_field('your')"),
i -> {
i.startRecord("1");
Expand All @@ -1446,7 +1553,34 @@ public void copyIntoArrayOfHashesImplicitAppend() {
}

@Test
public void copyIntoArrayOfHashesExplicitAppend() {
public void copyIntoImplicitArrayPrepend() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"copy_field('your.name','author[].$prepend.name')",
"remove_field('your')"),
i -> {
i.startRecord("1");
i.startEntity("your");
i.literal("name", "max");
i.endEntity();
i.startEntity("your");
i.literal("name", "mo");
i.endEntity();
i.endRecord();
}, (o, f) -> {
o.get().startRecord("1");
o.get().startEntity("author[]");
o.get().startEntity("1");
o.get().literal("name", "mo");
o.get().endEntity();
o.get().startEntity("2");
o.get().literal("name", "max");
f.apply(2).endEntity();
o.get().endRecord();
});
}

@Test
public void copyIntoExplicitArrayAppend() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"set_array('author[]')",
"copy_field('your.name','author[].$append.name')",
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"test" : "test",
"object" : {
"arrayOfObjects" : [ {
"arrayOfObject" : [ {
"key" : "value"
}, {
"key" : "more_value"
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"arrayOfObjects" : [ {
"key" : "value",
"key_2" : "more_value",
"arrayOfObject" : [ {
"key" : "value"
}, {
"key" : "more_value"
} ],
"key" : "value",
"key_2" : "more_value"
} ]
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
{
"arrayOfObjects_1" : [ {
"arrayOfObjects_2" : [ {
"key" : "value",
"key_2" : "more_value",
"key_3" : "even_more_value",
"key_4" : "so_much_value",
"arrayOfObject_1" : [ {
"arrayOfObject_2" : [ {
"key" : "value"
}, {
"key" : "more_value"
} ]
}, {
"arrayOfObjects_3" : [ {
"arrayOfObject_3" : [ {
"key" : "even_more_value"
}, {
"key" : "so_much_value"
} ]
} ],
"key" : "value",
"key_2" : "more_value",
"key_3" : "even_more_value",
"key_4" : "so_much_value"
} ]
}

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
{
"arrayOfObjects" : [ {
"key" : "value"
}, {
"key" : "more_value"
} ],
"key" : "value",
"key_2" : "more_value"
"key_2" : "more_value",
"object" : {
"arrayOfObject" : [ {
"key" : "value"
}, {
"key" : "more_value"
} ]
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"key" : "value",
"key_2" : "more_value",
"object" : {
"test" : [ "value", "more_value" ]
},
"key" : "value",
"key_2" : "more_value"
}
}

This file was deleted.

This file was deleted.

This file was deleted.

Loading
Loading