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

Commit

Permalink
Fix path wildcards in combination with arrays of hashes. (45d0182)
Browse files Browse the repository at this point in the history
Previously, when a wildcard matched multiple fields of which at least one was an array of hashes, `FixPath.findIn()` returned a nested array (e.g., `[[{value=>Mary}, {value=>University}], {value=>Max}]`).

Now, matched arrays are flattened (i.e., `[{value=>Mary}, {value=>University}, {value=>Max}]`).

See also #142.
  • Loading branch information
blackwinter committed Feb 16, 2022
1 parent 45d0182 commit 98fa41e
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 22 deletions.
45 changes: 27 additions & 18 deletions metafix/src/main/java/org/metafacture/metafix/FixPath.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,29 +54,38 @@ public Value findIn(final Hash hash) {
final String currentSegment = path[0];
final String[] remainingPath = tail(path);

final Value result;

if (currentSegment.equals(ASTERISK)) {
// TODO: search in all elements of value.asHash()?
return new FixPath(remainingPath).findIn(hash);
result = new FixPath(remainingPath).findIn(hash);
}
final List<Value> result = new ArrayList<Value>();
hash.findFields(currentSegment).collect(Collectors.toSet()).forEach(f -> {
final Value value = hash.getField(f);
else if (remainingPath.length == 0) {
result = hash.get(currentSegment);
}
else {
final List<Value> list = new ArrayList<>();

if (value != null) {
if (remainingPath.length == 0) {
result.add(value);
}
else {
value.matchType()
.ifArray(a -> result.add(new FixPath(remainingPath).findIn(a)))
.ifHash(h -> result.add(new FixPath(remainingPath).findIn(h)))
.orElseThrow();
hash.findFields(currentSegment).forEach(f -> {
final Value value = hash.getField(f);

if (value != null) {
if (remainingPath.length == 0) {
list.add(value);
}
else {
value.matchType()
.ifArray(a -> list.add(new FixPath(remainingPath).findIn(a)))
.ifHash(h -> list.add(new FixPath(remainingPath).findIn(h)))
.orElseThrow();
}
}
}
});
return path.length == 1 ? hash.get(currentSegment) :
result.size() == 1 ? result.get(0) :
result.size() == 0 ? null : new Value(result);
});

result = Value.fromList(list);
}

return result;
}

/*package-private*/ Value findIn(final Array array) {
Expand Down
13 changes: 9 additions & 4 deletions metafix/src/main/java/org/metafacture/metafix/Value.java
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,14 @@ public Value asList(final Consumer<Array> consumer) {
}
}

/*package-private*/ static Value fromList(final List<Value> list) {
list.removeIf(Objects::isNull);

return list.isEmpty() ? null : list.size() == 1 ? list.get(0) : newArray(a -> list.forEach(v -> v.matchType()
.ifArray(b -> b.forEach(a::add))
.orElse(a::add)));
}

public TypeMatcher matchType() {
return new TypeMatcher(this);
}
Expand Down Expand Up @@ -522,10 +530,7 @@ public void replace(final String field, final Value value) {
*/
public Value get(final String field) {
// TODO: special treatment (only) for exact matches?
final List<Value> list = findFields(field).map(this::getField).collect(Collectors.toList());
return list.isEmpty() ? null : list.size() == 1 ? list.get(0) : newArray(a -> list.forEach(v -> v.matchType()
.ifArray(b -> b.forEach(a::add))
.orElse(a::add)));
return fromList(findFields(field).map(this::getField).collect(Collectors.toList()));
}

public Value getField(final String field) {
Expand Down
52 changes: 52 additions & 0 deletions metafix/src/test/java/org/metafacture/metafix/MetafixBindTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,58 @@ public void shouldIterateOverListWithWildcard() {
shouldIterateOverList("n?me", 3);
}

private void shouldIterateOverListOfHashes(final String path, final int expectedCount) {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"do list(path: '" + path + "', 'var': '$i')",
" add_field('trace', 'true')",
"end",
"retain('trace')"
),
i -> {
i.startRecord("1");
i.startEntity("name");
i.literal("value", "Mary");
i.endEntity();
i.startEntity("name");
i.literal("value", "University");
i.endEntity();
i.startEntity("nome");
i.literal("value", "Max");
i.endEntity();
i.endRecord();
},
(o, f) -> {
o.get().startRecord("1");
f.apply(expectedCount).literal("trace", "true");
o.get().endRecord();
}
);
}

@Test
public void shouldIterateOverListOfHashes() {
shouldIterateOverListOfHashes("name.value", 2);
}

@Test
// See https://github.com/metafacture/metafacture-fix/issues/119
public void shouldIterateOverListOfHashesWithCharacterClass() {
shouldIterateOverListOfHashes("n[ao]me.value", 3);
}

@Test
// See https://github.com/metafacture/metafacture-fix/issues/119
@Disabled("See https://github.com/metafacture/metafacture-fix/issues/143")
public void shouldIterateOverListOfHashesWithAlternation() {
shouldIterateOverListOfHashes("name.value|nome.value", 3);
}

@Test
// See https://github.com/metafacture/metafacture-fix/issues/119
public void shouldIterateOverListOfHashesWithWildcard() {
shouldIterateOverListOfHashes("n?me.value", 3);
}

@Test // checkstyle-disable-line JavaNCSS
// See https://github.com/metafacture/metafacture-fix/issues/119
public void shouldPerformComplexOperationWithPathWildcard() {
Expand Down

0 comments on commit 98fa41e

Please sign in to comment.