Skip to content

Commit

Permalink
Merge pull request #329 from metafacture/145-retainNested
Browse files Browse the repository at this point in the history
Add support for nested paths in `retain()` Fix function.
  • Loading branch information
blackwinter authored Nov 20, 2023
2 parents c7ce860 + 5cc686d commit 49e3fb1
Show file tree
Hide file tree
Showing 7 changed files with 707 additions and 4 deletions.
84 changes: 81 additions & 3 deletions metafix/src/main/java/org/metafacture/metafix/Value.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,12 @@
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
Expand Down Expand Up @@ -303,6 +305,13 @@ private Value withPathAppend(final String field) {
.orElseThrow());
}

private void retainFields(final Collection<String> fields) {
matchType()
.ifArray(a -> a.retainFields(fields))
.ifHash(h -> h.retainFields(fields))
.orElseThrow();
}

enum Type {
Array,
Hash,
Expand Down Expand Up @@ -387,6 +396,23 @@ private abstract static class AbstractValueType implements JsonValue {
@Override
public abstract void toJson(JsonGenerator jsonGenerator);

protected <T> Map<T, Collection<String>> retainFields(final Collection<String> fields, final Function<String, Set<T>> function) {
final Map<T, Collection<String>> retainFields = new HashMap<>();

fields.forEach(p -> {
final String[] parts = p.split(FIELD_PATH_SEPARATOR, 2);

function.apply(parts[0]).forEach(f -> {
final Collection<String> retainNested = retainFields.computeIfAbsent(f, k -> new HashSet<>());
if (parts.length > 1) {
retainNested.add(parts[1]);
}
});
});

return retainFields;
}

}

/**
Expand Down Expand Up @@ -428,10 +454,57 @@ public Stream<Value> stream() {
return list.stream();
}

private IntStream indexes() {
return IntStream.range(0, size());
}

private void removeEmptyValues() {
list.removeIf(REMOVE_EMPTY_VALUES);
}

private void retainFields(final Collection<String> fields) {
final Map<Integer, Collection<String>> retainFields = retainFields(fields, this::findFields);

final int max = size() - 1;
indexes().map(i -> max - i).forEach(i -> {
final Collection<String> retainNested = retainFields.get(i);
if (retainNested == null) {
remove(i);
}
else if (!retainNested.isEmpty()) {
get(i).retainFields(retainNested);
}
});
}

private Set<Integer> findFields(final String pattern) {
final Set<Integer> fieldSet = new LinkedHashSet<>();

if ("*".equals(pattern)) {
indexes().forEach(fieldSet::add);
}
else {
final int index;

switch (pattern) {
case "$first":
index = 0;
break;
case "$last":
index = size() - 1;
break;
default:
index = Integer.parseInt(pattern) - 1; // TODO: 0-based Catmandu vs. 1-based Metafacture
}

if (index >= 0 && index < size()) {
fieldSet.add(index);
}
}

return fieldSet;
}

public void forEach(final Consumer<Value> consumer) {
list.forEach(consumer);
}
Expand Down Expand Up @@ -696,10 +769,15 @@ public void removeField(final String field) {
* @param fields the field names
*/
public void retainFields(final Collection<String> fields) {
final Set<String> retainFields = new HashSet<>();
fields.forEach(f -> retainFields.addAll(findFields(f)));
final Map<String, Collection<String>> retainFields = retainFields(fields, this::findFields);

map.keySet().retainAll(retainFields.keySet());

map.keySet().retainAll(retainFields);
retainFields.forEach((k, v) -> {
if (!v.isEmpty()) {
getField(k).retainFields(v);
}
});
}

/**
Expand Down
135 changes: 135 additions & 0 deletions metafix/src/test/java/org/metafacture/metafix/MetafixRecordTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2335,6 +2335,141 @@ public void retain() {
});
}

@Test // checkstyle-disable-line JavaNCSS
public void retainNested() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"retain('a.b.c','a.[cd].b','b[].2.c','c[].*.a','c[].2.b')"
),
i -> {
i.startRecord("1");
i.startEntity("a");
i.startEntity("a");
i.literal("b", "1");
i.literal("c", "2");
i.endEntity();
i.startEntity("b");
i.literal("c", "1");
i.literal("d", "2");
i.endEntity();
i.startEntity("c");
i.literal("b", "1");
i.literal("c", "2");
i.endEntity();
i.endEntity();
i.startEntity("b[]");
i.startEntity("1");
i.literal("a", "1");
i.literal("b", "2");
i.endEntity();
i.startEntity("2");
i.literal("a", "1");
i.literal("b", "2");
i.literal("c", "3");
i.endEntity();
i.startEntity("3");
i.literal("c", "4");
i.endEntity();
i.endEntity();
i.startEntity("c[]");
i.startEntity("1");
i.literal("a", "1");
i.literal("b", "2");
i.endEntity();
i.startEntity("2");
i.literal("a", "1");
i.literal("b", "2");
i.literal("c", "3");
i.endEntity();
i.startEntity("3");
i.literal("c", "4");
i.endEntity();
i.endEntity();
i.startEntity("d");
i.literal("e", "5");
i.endEntity();
i.literal("e", "6");
i.endRecord();
},
(o, f) -> {
o.get().startRecord("1");
o.get().startEntity("a");
o.get().startEntity("b");
o.get().literal("c", "1");
o.get().endEntity();
o.get().startEntity("c");
o.get().literal("b", "1");
f.apply(2).endEntity();
o.get().startEntity("b[]");
o.get().startEntity("1");
o.get().literal("c", "3");
f.apply(2).endEntity();
o.get().startEntity("c[]");
o.get().startEntity("1");
o.get().literal("a", "1");
o.get().endEntity();
o.get().startEntity("2");
o.get().literal("a", "1");
o.get().literal("b", "2");
o.get().endEntity();
o.get().startEntity("3");
f.apply(2).endEntity();
o.get().endRecord();
}
);
}

@Test
public void retainNestedReservedFields() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"retain('b[].$first.b','c[].$last')"
),
i -> {
i.startRecord("1");
i.startEntity("b[]");
i.startEntity("1");
i.literal("a", "1");
i.literal("b", "2");
i.endEntity();
i.startEntity("2");
i.literal("a", "1");
i.literal("b", "2");
i.literal("c", "3");
i.endEntity();
i.startEntity("3");
i.literal("c", "4");
i.endEntity();
i.endEntity();
i.startEntity("c[]");
i.startEntity("1");
i.literal("a", "1");
i.literal("b", "2");
i.endEntity();
i.startEntity("2");
i.literal("a", "1");
i.literal("b", "2");
i.literal("c", "3");
i.endEntity();
i.startEntity("3");
i.literal("c", "4");
i.endEntity();
i.endEntity();
i.endRecord();
},
(o, f) -> {
o.get().startRecord("1");
o.get().startEntity("b[]");
o.get().startEntity("1");
o.get().literal("b", "2");
f.apply(2).endEntity();
o.get().startEntity("c[]");
o.get().startEntity("1");
o.get().literal("c", "4");
f.apply(2).endEntity();
o.get().endRecord();
}
);
}

@Test
public void shouldDeleteEmptyArrays() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"node" : {
"properties" : {
"ccm:educationallearningresourcetype" : [ "https://w3id.org/kim/hcrt/image" ]
}
},
"lrt" : [ "https://w3id.org/kim/hcrt/image" ]
}
Loading

0 comments on commit 49e3fb1

Please sign in to comment.