Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 26 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -642,21 +642,41 @@ retain("<sourceField_1>"[, ...])

##### `set_array`

_Currently alias for [`add_array`](#add_array)._
Creates a new array (with optional values), provided that the intermediate structures (i.e. parent fields) exist. To create any missing intermediate structures, use [`add_array`](#add_array) instead.

We advise you to use [`add_array`](#add_array) instead of `set_array` due to changing behaviour in an upcoming release. For more information see: [#309](https://github.com/metafacture/metafacture-fix/issues/309)
```perl
set_array("<targetFieldName>")
set_array("<targetFieldName>", "<value_1>"[, ...])
```

[Example in Playground](https://metafacture.org/playground/?example=set_array)

[Java Code](https://github.com/search?type=code&q=repo:metafacture/metafacture-core+path:FixMethod.java+"+set_array+{")

##### `set_field`

_Currently alias for [`add_field`](#add_field)._
Creates a field with a defined value, provided that the intermediate structures (i.e. parent fields) exist. To create any missing intermediate structures, use [`add_field`](#add_field) instead.

```perl
set_field("<targetFieldName>", "<fieldValue>")
```

[Example in Playground](https://metafacture.org/playground/?example=set_field)

We advise you to use [`add_field`](#add_field) instead of `set_field` due to changing behaviour in an upcoming release. For more information see: [#309](https://github.com/metafacture/metafacture-fix/issues/309)
[Java Code](https://github.com/search?type=code&q=repo:metafacture/metafacture-core+path:FixMethod.java+"+set_field+{")

##### `set_hash`

_Currently alias for [`add_hash`](#add_hash)._
Creates a new hash (with optional values), provided that the intermediate structures (i.e. parent fields) exist. To create any missing intermediate structures, use [`add_hash`](#add_hash) instead.

```perl
set_hash("<targetFieldName>")
set_hash("<targetFieldName>", "subfieldName": "<subfieldValue>"[, ...])
```

[Example in Playground](https://metafacture.org/playground/?example=set_hash)

We advise you to use [`add_hash`](#add_hash) instead of `set_hash` due to changing behaviour in an upcoming release. For more information see: [#309](https://github.com/metafacture/metafacture-fix/issues/309)
[Java Code](https://github.com/search?type=code&q=repo:metafacture/metafacture-core+path:FixMethod.java+"+set_hash+{")

##### `timestamp`

Expand Down
14 changes: 10 additions & 4 deletions metafix/src/main/java/org/metafacture/metafix/FixMethod.java
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ public void apply(final Metafix metafix, final Record record, final List<String>
final String field = params.get(0);
final Value newValue = newArray(params.subList(1, params.size()).stream().map(Value::new));
record.set(field, newValue);
newValue.asArray().forEach(value -> value.withPathSet(newValue.getPath() + "." + value.getPath()));
newValue.asArray().forEach(value -> value.withPathSet(newValue.getPath() + Value.FIELD_PATH_SEPARATOR + value.getPath()));
}
},
add_field {
Expand Down Expand Up @@ -408,19 +408,25 @@ public void apply(final Metafix metafix, final Record record, final List<String>
set_array {
@Override
public void apply(final Metafix metafix, final Record record, final List<String> params, final Map<String, String> options) {
add_array.apply(metafix, record, params, options);
if (parentFieldExists(record, params.get(0))) {
add_array.apply(metafix, record, params, options);
}
}
},
set_field {
@Override
public void apply(final Metafix metafix, final Record record, final List<String> params, final Map<String, String> options) {
add_field.apply(metafix, record, params, options);
if (parentFieldExists(record, params.get(0))) {
add_field.apply(metafix, record, params, options);
}
}
},
set_hash {
@Override
public void apply(final Metafix metafix, final Record record, final List<String> params, final Map<String, String> options) {
add_hash.apply(metafix, record, params, options);
if (parentFieldExists(record, params.get(0))) {
add_hash.apply(metafix, record, params, options);
}
}
},
timestamp {
Expand Down
51 changes: 45 additions & 6 deletions metafix/src/main/java/org/metafacture/metafix/FixPath.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,22 @@
* With all get/set/update/create/delete logic collected here.
*
* @author Fabian Steeg (fsteeg)
*
*/
/*package-private*/ class FixPath {
public class FixPath {

private static final String ASTERISK = "*";

private static final String INDEX_SUBPATH_PATTERN = Value.FIELD_PATH_SEPARATOR_PATTERN + "\\d" + Value.FIELD_PATH_SEPARATOR_PATTERN;
private static final String ASTERISK_SUBPATH = Value.FIELD_PATH_SEPARATOR + ASTERISK + Value.FIELD_PATH_SEPARATOR;

private String[] path;

/*package-private*/ FixPath(final String path) {
/**
* Creates an instance of {@link FixPath} based on the given path string.
*
* @param path the path string
*/
public FixPath(final String path) {
this(Value.split(path));
}

Expand Down Expand Up @@ -111,7 +119,7 @@ private Value findInValue(final Value value, final String[] p) {

@Override
public String toString() {
return String.join(".", path);
return String.join(Value.FIELD_PATH_SEPARATOR, path);
}

/*package-private*/ int size() {
Expand Down Expand Up @@ -141,7 +149,9 @@ else if (value.getPath() != null && hasWildcard()) {
}

private boolean matches(final String thatPath) {
return thatPath != null && thatPath.replaceAll("\\.\\d+\\.", ".*.").equals(String.join(".", this.path));
return thatPath != null && thatPath
.replaceAll(INDEX_SUBPATH_PATTERN, ASTERISK_SUBPATH)
.equals(String.join(Value.FIELD_PATH_SEPARATOR, this.path));
}

private String[] replaceInPath(final String find, final int i) {
Expand Down Expand Up @@ -299,9 +309,29 @@ private Value insertInto(final Value value, final InsertMode mode, final Value n
}
}

/**
* Checks whether the given field is adding to an array.
*
* @param field the field
*
* @return true if the given field is adding to an array
*/
public static boolean isAddingToArray(final String field) {
return field.equals(ReservedField.$prepend.name()) || field.equals(ReservedField.$append.name());
}

/**
* Checks whether any of the path segments are adding to an array.
*
* @return true if any of the path segments are adding to an array
*/
public boolean isAddingToArray() {
return Arrays.stream(path).anyMatch(FixPath::isAddingToArray);
}

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());
final boolean isAddingToArray = isAddingToArray(nextField);
if (result == null) {
result = (isAddingToArray ? Value.newArray() : Value.newHash()).withPathSet(newPath);
hash.put(field, result);
Expand All @@ -320,6 +350,15 @@ private String[] tail(final String[] fields) {
return Arrays.copyOfRange(fields, 1, fields.length);
}

/**
* Creates an instance of {@link FixPath} based on the parent path.
*
* @return an instance of {@link FixPath}, or {@code null} if already at the top level
*/
public FixPath getParentPath() {
return path.length > 1 ? new FixPath(Arrays.copyOfRange(path, 0, path.length - 1)) : null;
}

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

Expand Down
9 changes: 5 additions & 4 deletions metafix/src/main/java/org/metafacture/metafix/Value.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@
*/
public class Value implements JsonValue { // checkstyle-disable-line ClassDataAbstractionCoupling

private static final String FIELD_PATH_SEPARATOR = "\\.";
public static final String FIELD_PATH_SEPARATOR = ".";
/*package-private*/ static final String FIELD_PATH_SEPARATOR_PATTERN = Pattern.quote(FIELD_PATH_SEPARATOR);

private final Array array;
private final Hash hash;
Expand Down Expand Up @@ -409,7 +410,7 @@ public void toJson(final JsonGenerator jsonGenerator) {
}

/*package-private*/ static String[] split(final String fieldPath) {
return fieldPath.split(FIELD_PATH_SEPARATOR);
return fieldPath.split(FIELD_PATH_SEPARATOR_PATTERN);
}

/**
Expand All @@ -431,7 +432,7 @@ private Value withPathAppend(final int i) {
}

private Value withPathAppend(final String field) {
return withPathSet(path == null || path.isEmpty() ? field : path + "." + field);
return withPathSet(path == null || path.isEmpty() ? field : path + FIELD_PATH_SEPARATOR + field);
}

/*package-private*/ Value copy() {
Expand Down Expand Up @@ -574,7 +575,7 @@ protected <T> Map<T, Collection<String>> retainFields(final Collection<String> f
final Map<T, Collection<String>> retainFields = new HashMap<>();

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

function.apply(parts[0]).forEach(f -> {
final Collection<String> retainNested = retainFields.computeIfAbsent(f, k -> new HashSet<>());
Expand Down
14 changes: 14 additions & 0 deletions metafix/src/main/java/org/metafacture/metafix/api/FixFunction.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import org.metafacture.framework.StandardEventNames;
import org.metafacture.io.ObjectWriter;
import org.metafacture.metafix.FixPath;
import org.metafacture.metafix.Metafix;
import org.metafacture.metafix.Record;
import org.metafacture.metafix.Value;
Expand Down Expand Up @@ -194,4 +195,17 @@ default Stream<Value> flatten(final Stream<Value> stream) {
));
}

/**
* Checks whether the given field's parent field exists in the record.
*
* @param record the record
* @param field the field
*
* @return true if the given field's parent field exists in the record
*/
default boolean parentFieldExists(final Record record, final String field) {
final FixPath parentPath = new FixPath(field).getParentPath();
return parentPath == null || !parentPath.isAddingToArray() && record.containsPath(parentPath.toString());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,7 @@ public void shouldDoListAsWithMultipleListsOfDifferentSizes() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"set_array('sourceOrga[]')",
"do list_as(orgId: 'ccm:university[]', orgName: 'ccm:university_DISPLAYNAME[]', orgLoc: 'ccm:university_LOCATION[]')",
" set_hash('sourceOrga[].$append')",
" add_hash('sourceOrga[].$append')",
" copy_field(orgId, 'sourceOrga[].$last.id')",
" copy_field(orgName, 'sourceOrga[].$last.name')",
" copy_field(orgLoc, 'sourceOrga[].$last.location')",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -994,9 +994,9 @@ public void shouldLookupInCopiedNestedArraysCreatedWithPrepend() {
private void shouldLookupInCopiedNestedArraysCreatedWith(final String reservedField) {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"put_map('rswk-indicator', s: 'SubjectHeading')",
"set_array('subject[]')",
"set_array('subject[]." + reservedField + ".componentList[]')",
"set_array('subject[].$last.componentList[]." + reservedField + ".type[]')",
"add_array('subject[]')",
"add_array('subject[]." + reservedField + ".componentList[]')",
"add_array('subject[].$last.componentList[]." + reservedField + ".type[]')",
"do list(path: 'D', 'var': '$i')",
" copy_field('$i', 'subject[].$last.componentList[].$last.type[]." + reservedField + "')",
"end",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2818,11 +2818,9 @@ public void addFieldWithReplaceAllArray() {
private void addFieldWithReplaceAllArray(final boolean replaceAll) {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"do list(path: 'contribution[]', 'var': '$i')",
" set_array('$i.agent.altLabel[]')",
" add_field('$i.agent.altLabel[].$append', 'contribution')",
"end",
"do list(path: 'subject[]', 'var': '$i')",
" set_array('$i.altLabel[]')",
" add_field('$i.altLabel[].$append', 'subject')",
"end",
replaceAll ? "replace_all('contribution[].*.agent.altLabel[].*', 't', '')" : "",
Expand Down Expand Up @@ -2875,10 +2873,10 @@ public void setArrayWithReplaceAll() {
private void setArrayWithReplaceAll(final boolean replaceAll) {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"do list(path: 'contribution[]', 'var': '$i')",
" set_array('$i.agent.altLabel[]', 'contribution')",
" add_array('$i.agent.altLabel[]', 'contribution')",
"end",
"do list(path: 'subject[]', 'var': '$i')",
" set_array('$i.altLabel[]', 'subject')",
" add_array('$i.altLabel[]', 'subject')",
"end",
replaceAll ? "replace_all('contribution[].*.agent.altLabel[].*', 't', '')" : "",
replaceAll ? "replace_all('subject[].*.altLabel[].*', 't', '')" : ""
Expand Down Expand Up @@ -2930,11 +2928,9 @@ public void copyFieldWithReplaceAllArray() {
private void copyFieldWithReplaceAllArray(final boolean replaceAll) {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"do list(path: 'contribution[]', 'var': '$i')",
" set_array('$i.agent.altLabel[]')",
" copy_field('$i.label', '$i.agent.altLabel[].$append')",
"end",
"do list(path: 'subject[]', 'var': '$i')",
" set_array('$i.altLabel[]')",
" copy_field('$i.label', '$i.altLabel[].$append')",
"end",
replaceAll ? "replace_all('contribution[].*.agent.altLabel[].*', 't', '')" : "",
Expand Down Expand Up @@ -2987,11 +2983,9 @@ public void pasteWithReplaceAll() {
private void pasteWithReplaceAll(final boolean replaceAll) {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"do list(path: 'contribution[]', 'var': '$i')",
" set_array('$i.agent.altLabel[]')",
" paste('$i.agent.altLabel[].$append', '$i.label', '~!')",
"end",
"do list(path: 'subject[]', 'var': '$i')",
" set_array('$i.altLabel[]')",
" paste('$i.altLabel[].$append', '$i.label', '~!')",
"end",
replaceAll ? "replace_all('contribution[].*.agent.altLabel[].*', ' !', '')" : "",
Expand Down
Loading