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

Commit

Permalink
Integrate feedback from PR #78 (see #65)
Browse files Browse the repository at this point in the history
Co-authored-by: Jens Wille <[email protected]>
  • Loading branch information
fsteeg and blackwinter committed Nov 30, 2021
1 parent 5fa6e03 commit 77dcd2b
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 68 deletions.
141 changes: 73 additions & 68 deletions metafix/src/main/java/org/metafacture/metafix/Value.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
Expand Down Expand Up @@ -235,7 +234,7 @@ public String toString() {
return result;
}

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

Expand Down Expand Up @@ -302,59 +301,66 @@ public void remove(final int index) {

private void removeNested(final String[] fields) {
if (fields.length >= 1 && fields[0].equals(ASTERISK)) {
for (int i = 0; i < size(); ++i) {
remove(i);
}
list.clear();
}
else if (fields.length >= 1 && isNumber(fields[0])) {
final int index = Integer.parseInt(fields[0]) - 1;
final int index = Integer.parseInt(fields[0]) - 1; // TODO: 0-based Catmandu vs. 1-based Metafacture
if (index >= 0 && index < size()) {
remove(index);
}
}
}

public Value find(final String[] fields) {
Value result = null;
if (fields.length > 0) {
if (fields[0].equals(ASTERISK)) {
result = find(tail(fields));
private Value find(final String[] path) {
final Value result;
if (path.length > 0) {
if (path[0].equals(ASTERISK)) {
result = newArray(a -> forEach(v -> a.add(findInValue(tail(path), v))));
}
else if (isNumber(fields[0])) {
final int index = Integer.parseInt(fields[0]) - 1;
else if (isNumber(path[0])) {
final int index = Integer.parseInt(path[0]) - 1; // TODO: 0-based Catmandu vs. 1-based Metafacture
if (index >= 0 && index < size()) {
final Value value = get(index);
// TODO: move impl into enum elements, here call only value.find
if (value != null) {
switch (value.type) {
case Hash:
result = value.asHash().find(tail(fields));
break;
case Array:
result = find(tail(fields));
break;
case String:
result = value;
break;
default:
break;
}
}
result = findInValue(tail(path), get(index));
}
else {
result = null;
}
}
// TODO: WDCD? copy_field('your.name','author[].name'), where name is an array
else {
final Value newResult = newArray();
forEach(c -> {
newResult.asArray().add(c.asHash().find(fields[0])); /* TODO: non-hash */
});
result = newResult;
result = newArray(a -> forEach(v -> a.add(findInValue(path, v))));
}
}
else {
result = new Value(this);
}
return result;
}

private Value findInValue(final String[] path, final Value value) {
final Value result;
// TODO: move impl into enum elements, here call only value.find
if (value != null) {
switch (value.type) {
case Hash:
result = value.asHash().find(path);
break;
case Array:
result = value.asArray().find(path);
break;
case String:
result = value;
break;
default:
result = null;
break;
}
}
else {
result = null;
}
return result;
}
}

/**
Expand All @@ -367,6 +373,8 @@ 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 Expand Up @@ -452,7 +460,10 @@ public Value find(final String fieldPath) {

private Value find(final String[] fields) {
final String field = fields[0];

if (field.equals(ASTERISK)) {
// TODO: search in all elements of value.asHash()?
return find(tail(fields));
}
return fields.length == 1 || !containsField(field) ? get(field) :
findNested(field, tail(fields));
}
Expand All @@ -463,25 +474,13 @@ private Value findNested(final String field, final String[] remainingFields) {
if (value != null) {
switch (value.type) {
case Array:
if (remainingFields[0].equals(ASTERISK)) {
result = value.asArray().find(tail(remainingFields));
}
else {
result = value.asArray().find(remainingFields);
}
result = value.asArray().find(remainingFields);
break;
case Hash:
if (remainingFields[0].equals(ASTERISK)) {
result = value.asHash().find(tail(remainingFields));
}
else {
result = value.asHash().find(remainingFields);
}
result = value.asHash().find(remainingFields);
break;
case String:
throw new IllegalStateException("expected string, got " + value.type);
default:
throw new IllegalStateException("unexpected, got " + value.type);
throw new IllegalStateException(UNEXPECTED + value.type);
}
}
return result;
Expand Down Expand Up @@ -518,9 +517,17 @@ public Value insert(final InsertMode mode, final String fieldPath, final String

private Value insert(final InsertMode mode, final String[] fields, final String newValue) {
final String field = fields[0];

if (fields.length == 1 && !fields[0].equals(ASTERISK)) {
mode.apply(this, field, newValue);
if (field.equals(APPEND_FIELD) || field.equals(LAST_FIELD)) {
// TODO: WDCD? $last, $append skipped for hashes here:
return insert(mode, tail(fields), newValue);
}
if (fields.length == 1) {
if (fields[0].equals(ASTERISK)) {
//TODO: WDCD? insert into each element?
}
else {
mode.apply(this, field, newValue);
}
}
else {
if (!containsField(field)) {
Expand All @@ -532,17 +539,13 @@ private Value insert(final InsertMode mode, final String[] fields, final String
switch (value.type) {
// TODO: move impl into enum elements, here call only value.insert
case Hash:
final String[] tail = tail(fields);
final String[] rest = tail[0].startsWith("$") ? tail(tail) : tail; // TODO: why?
value.asHash().insert(mode, rest, newValue);
value.asHash().insert(mode, tail(fields), newValue);
break;
case Array:
insertArray(mode, newValue, tail(fields), value.asArray());
break;
case String:
throw new IllegalStateException("expected array or hash, got " + value.type);
default:
throw new IllegalStateException("expected array or hash, got " + value.type);
throw new IllegalStateException(UNEXPECTED + value.type);
}
}
}
Expand All @@ -554,12 +557,13 @@ private void insertArray(final InsertMode mode, final String newValue, final Str
final Array array) {
switch (fields[0]) {
case ASTERISK:
// TODO: WDCD? descend into the array?
break;
case APPEND_FIELD:
array.add(newHash(h -> h.insert(mode, tail(fields), newValue)));
break;
case LAST_FIELD:
if (array.size() > 0) {
if (size() > 0) {
final Value last = array.get(array.size() - 1);
if (last.isHash()) {
last.asHash().insert(mode, tail(fields), newValue);
Expand All @@ -568,18 +572,18 @@ private void insertArray(final InsertMode mode, final String newValue, final Str
break;
default:
if (isNumber(fields[0])) {
// TODO: WDCD? insert at the given index? also descend into the array?
if (fields.length == 1) {
array.add(new Value(newValue));
}
if (fields.length > 1) {
final Value newHash = Value.newHash();
newHash.asHash().put(fields[1], new Value(newValue));
mode.apply(newHash.asHash(), fields[1], newValue);
array.add(newHash);
}
}
else {
final String[] rem = fields;
array.add(newHash(h -> h.insert(mode, rem, newValue)));
array.add(newHash(h -> h.insert(mode, fields, newValue)));
}
break;
}
Expand Down Expand Up @@ -610,7 +614,7 @@ else if (containsField(field)) {
if (value != null) {
switch (value.type) {
case String:
break;
throw new IllegalStateException(UNEXPECTED + value.type);
case Array:
value.asArray().removeNested(tail(fields));
break;
Expand All @@ -635,9 +639,10 @@ private void appendValue(final String[] newName, final Value v) {
if (v != null) {
switch (v.type) {
case String:
append(Arrays.asList(newName).stream().collect(Collectors.joining(".")), v.asString());
append(String.join(".", newName), v.asString());
break;
case Array:
// TODO: do something here?
break;
case Hash:
appendValue(newName, v.asHash().find(tail(newName)));
Expand All @@ -652,9 +657,9 @@ public void transformFields(final List<String> params, final UnaryOperator<Strin
final String field = params.get(0);
final Value value = find(field);
if (value != null) {
removeNested(field.replace(".*", ""));
removeNested(field);
if (operator != null) {
value.asList(a -> a.forEach(v -> append(field.replace(".*", ""), operator.apply(v.toString()))));
value.asList(a -> a.forEach(v -> append(field, operator.apply(v.toString()))));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,38 @@ public void removeEntity() {
});
}

@Test
public void removeArray() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"remove_field('name')"),
i -> {
i.startRecord("1");
i.literal("name", "max");
i.literal("name", "mo");
i.endRecord();
}, o -> {
o.get().startRecord("1");
o.get().endRecord();
});
}

@Test
public void removeArrayElementsByWildcard() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"remove_field('name.*')"),
i -> {
i.startRecord("1");
i.literal("name", "max");
i.literal("name", "mo");
i.endRecord();
}, o -> {
o.get().startRecord("1");
o.get().startEntity("name");
o.get().endEntity();
o.get().endRecord();
});
}

@Test
public void setArray() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
Expand Down Expand Up @@ -730,6 +762,26 @@ public void accessArrayByIndex() {
}

@Test
public void accessArrayImplicit() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"upcase('name')"),
i -> {
i.startRecord("1");
i.literal("name", "max");
i.literal("name", "mo");
i.endRecord();
}, (o, f) -> {
o.get().startRecord("1");
o.get().startEntity("name");
o.get().literal("1", "MAX");
o.get().literal("2", "MO");
o.get().endEntity();
o.get().endRecord();
});
}

@Test
@Disabled("TODO: WDCD? explicit * for array fields?")
public void accessArrayByWildcard() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"upcase('name.*')"),
Expand Down Expand Up @@ -856,4 +908,5 @@ public void accessArrayOfObjectsByDoListBind() {
o.get().endRecord();
});
}

}

0 comments on commit 77dcd2b

Please sign in to comment.