Skip to content

Commit

Permalink
Merge pull request #368 from metafacture/127-arrays
Browse files Browse the repository at this point in the history
Implicit array creation with `$append`, general `$prepend` support
  • Loading branch information
fsteeg authored Oct 2, 2024
2 parents 6496352 + fe84442 commit 019ad48
Show file tree
Hide file tree
Showing 36 changed files with 232 additions and 70 deletions.
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

0 comments on commit 019ad48

Please sign in to comment.