Skip to content

Commit 49d88da

Browse files
authored
Merge pull request #241 from metafacture/path-set-append
Remove path replacement workarounds, only set and append paths
2 parents 13b880f + cb7317a commit 49d88da

File tree

11 files changed

+94
-131
lines changed

11 files changed

+94
-131
lines changed

metafix/src/main/java/org/metafacture/metafix/FixMethod.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,8 @@ public void apply(final Metafix metafix, final Record record, final List<String>
120120
public void apply(final Metafix metafix, final Record record, final List<String> params, final Map<String, String> options) {
121121
final String oldName = params.get(0);
122122
final String newName = params.get(1);
123-
Value.asList(record.get(oldName), a -> a.forEach(newValue -> {
124-
record.addNested(newName, newValue);
125-
newValue.updatePathRename(newName);
123+
Value.asList(record.get(oldName), a -> a.forEach(oldValue -> {
124+
record.addNested(newName, oldValue); // we're actually aliasing
126125
}));
127126
}
128127
},

metafix/src/main/java/org/metafacture/metafix/FixPath.java

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@
2222
import java.util.Arrays;
2323
import java.util.HashMap;
2424
import java.util.Map;
25-
import java.util.regex.Pattern;
26-
import java.util.stream.Collectors;
2725

2826
/**
2927
* Our goal here is something like https://metacpan.org/pod/Catmandu::Path::simple
@@ -35,8 +33,6 @@
3533
*/
3634
/*package-private*/ class FixPath {
3735

38-
/*package-private*/ static final Pattern RESERVED_FIELD_PATTERN = Pattern.compile(String.format("(?:%s)",
39-
Arrays.stream(ReservedField.values()).map(f -> Pattern.quote(f.name())).collect(Collectors.joining("|"))));
4036
private static final String ASTERISK = "*";
4137
private String[] path;
4238

@@ -68,8 +64,8 @@ private FixPath(final String[] path) {
6864
}
6965

7066
/*package-private*/ Value findIn(final Array array) {
71-
7267
final Value result;
68+
7369
if (path.length == 0) {
7470
result = new Value(array);
7571
}
@@ -81,13 +77,13 @@ private FixPath(final String[] path) {
8177
if (findInValue != null) {
8278
findInValue.matchType()
8379
// flatten result arrays (use Value#path for structure)
84-
.ifArray(a -> a.forEach(resultArray::add))
85-
.orElse(c -> resultArray.add(findInValue));
80+
.ifArray(a -> a.forEach(t -> resultArray.add(t, false)))
81+
.orElse(c -> resultArray.add(findInValue, false));
8682
}
8783
}));
8884
}
8985
else if (isReference(currentSegment)) {
90-
final Value referencedValue = getReferencedValue(array, currentSegment);
86+
final Value referencedValue = getReferencedValue(array, currentSegment, null);
9187
if (referencedValue != null) {
9288
result = findInValue(referencedValue, tail(path));
9389
}
@@ -100,8 +96,8 @@ else if (isReference(currentSegment)) {
10096
result = Value.newArray(a -> array.forEach(v -> a.add(findInValue(v, path))));
10197
}
10298
}
103-
return result;
10499

100+
return result;
105101
}
106102

107103
private Value findInValue(final Value value, final String[] p) {
@@ -128,6 +124,7 @@ public String toString() {
128124

129125
/*package-private*/ FixPath to(final Value value, final int i) {
130126
final FixPath result;
127+
131128
// One *, no matching path: replace with index of current result
132129
if (countAsterisks() == 1 && !matches(value.getPath())) {
133130
result = new FixPath(replaceInPath(ASTERISK, i));
@@ -139,6 +136,7 @@ else if (value.getPath() != null && hasWildcard()) {
139136
else {
140137
result = this;
141138
}
139+
142140
return result;
143141
}
144142

@@ -158,7 +156,7 @@ private long countAsterisks() {
158156
return Arrays.asList(path).stream().filter(s -> s.equals(ASTERISK)).count();
159157
}
160158

161-
/* package-private */ enum InsertMode {
159+
/*package-private*/ enum InsertMode {
162160

163161
REPLACE {
164162
@Override
@@ -250,10 +248,10 @@ private void removeNestedFrom(final Value value) {
250248
}
251249
}
252250

253-
/*package-private*/ private Value insertInto(final Array array, final InsertMode mode, final Value newValue) {
251+
private Value insertInto(final Array array, final InsertMode mode, final Value newValue) {
254252
// basic idea: reuse findIn logic here? setIn(findIn(array), newValue)
255-
256253
final String field = path[0];
254+
257255
if (path.length == 1) {
258256
mode.apply(array, field, newValue);
259257
}
@@ -262,15 +260,17 @@ private void removeNestedFrom(final Value value) {
262260
array.forEach(value -> insertInto(value, mode, newValue.copy(), field, tail(path)));
263261
}
264262
else if (isReference(field)) {
265-
insertInto(getReferencedValue(array, field), mode, newValue, field, tail(path));
263+
insertInto(getReferencedValue(array, field, newValue.getPath()), mode, newValue, field, tail(path));
266264
}
267265
}
266+
268267
return new Value(array);
269268
}
270269

271270
/*package-private*/ Value insertInto(final Hash hash, final InsertMode mode, final Value newValue) {
272271
// basic idea: reuse findIn logic here? setIn(findIn(hash), newValue)
273272
final String field = path[0];
273+
274274
if (path.length == 1) {
275275
mode.apply(hash, field, newValue);
276276
}
@@ -284,18 +284,17 @@ else if (isReference(field)) {
284284
return new Value(hash);
285285
}
286286

287-
private Value insertInto(final Value value, final InsertMode mode, final Value newValue, final String field,
288-
final String[] tail) {
287+
private Value insertInto(final Value value, final InsertMode mode, final Value newValue, final String field, final String[] tail) {
289288
if (value != null) {
290289
final FixPath fixPath = new FixPath(tail);
291-
newValue.updatePathAddBase(value, field);
290+
newValue.withPathSet(value.getPath());
292291
return value.extractType((m, c) -> m
293292
.ifArray(a -> c.accept(fixPath.insertInto(a, mode, newValue)))
294293
.ifHash(h -> c.accept(fixPath.insertInto(h, mode, newValue)))
295294
.orElseThrow());
296295
}
297296
else {
298-
throw new IllegalArgumentException("Using ref, but can't find: " + field + " in: " + value);
297+
throw new IllegalArgumentException("Can't find: " + field + " in: " + value);
299298
}
300299
}
301300

@@ -323,30 +322,32 @@ private boolean isReference(final String field) {
323322
}
324323

325324
// TODO replace switch, extract to method on array?
326-
private Value getReferencedValue(final Array array, final String field) {
325+
private Value getReferencedValue(final Array array, final String field, final String p) {
327326
Value referencedValue = null;
327+
328328
if (Value.isNumber(field)) {
329329
final int index = Integer.valueOf(field) - 1;
330330
return 0 <= index && index < array.size() ? array.get(index) : null;
331331
}
332+
332333
final ReservedField reservedField = ReservedField.fromString(field);
333334
if (reservedField != null) {
334335
switch (reservedField) {
335336
case $first:
336-
referencedValue = getReferencedValue(array, "1");
337+
referencedValue = getReferencedValue(array, "1", p);
337338
break;
338339
case $last:
339-
referencedValue = getReferencedValue(array, String.valueOf(array.size()));
340+
referencedValue = getReferencedValue(array, String.valueOf(array.size()), p);
340341
break;
341342
case $append:
342-
referencedValue = Value.newHash(); // TODO: append non-hash?
343+
referencedValue = Value.newHash().withPathSet(p); // TODO: append non-hash?
343344
array.add(referencedValue);
344-
referencedValue.updatePathAppend(String.valueOf(array.size()), "");
345345
break;
346346
default:
347347
break;
348348
}
349349
}
350+
350351
return referencedValue;
351352
}
352353

metafix/src/main/java/org/metafacture/metafix/Metafix.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,7 @@ private void init(final Map<String, String> newVars) {
127127
@Override
128128
public void literal(final String name, final String value) {
129129
final String[] split = Value.split(name);
130-
addValue(split[split.length - 1], new Value(value, name));
131-
// TODO could this help with https://github.com/metafacture/metafacture-fix/issues/147?
130+
addValue(split[split.length - 1], new Value(value));
132131
// TODO use full path here to insert only once?
133132
// new FixPath(name).insertInto(currentRecord, InsertMode.APPEND, new Value(value));
134133
}
@@ -236,9 +235,10 @@ private void addValue(final String name, final Value value) {
236235
}
237236
else {
238237
final Value entity = entities.get(index);
238+
value.withPathSet(entity.getPath());
239239
entity.matchType()
240-
.ifArray(a -> a.add(value.updatePathAddBase(entity, name)))
241-
.ifHash(h -> h.add(name, value.updatePathAddBase(entity, name)))
240+
.ifArray(a -> a.add(value))
241+
.ifHash(h -> h.add(name, value))
242242
.orElseThrow();
243243
}
244244
}

metafix/src/main/java/org/metafacture/metafix/Record.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,9 +209,7 @@ public void transform(final String field, final UnaryOperator<String> operator)
209209
toDelete.addFirst(insertPath);
210210
}
211211
else {
212-
final Value newValue = new Value(newString);
213-
insertPath.insertInto(this, InsertMode.REPLACE, newValue);
214-
newValue.setPath(insertPath.toString());
212+
insertPath.insertInto(this, InsertMode.REPLACE, new Value(newString));
215213
}
216214
}
217215
toDelete.forEach(path -> path.removeNestedFrom(this));

metafix/src/main/java/org/metafacture/metafix/Value.java

Lines changed: 29 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -101,18 +101,13 @@ public Value(final Map<String, Value> hash) {
101101
}
102102

103103
public Value(final String string) {
104-
this(string, null);
104+
this(string != null ? Type.String : null, null, null, string);
105105
}
106106

107107
public Value(final int integer) {
108108
this(String.valueOf(integer));
109109
}
110110

111-
public Value(final String string, final String path) {
112-
this(string != null ? Type.String : null, null, null, string);
113-
this.path = path;
114-
}
115-
116111
public static Value newArray() {
117112
return newArray(null);
118113
}
@@ -204,35 +199,6 @@ public Value asList(final Consumer<Array> consumer) {
204199
}
205200
}
206201

207-
/*package-private*/ Value updatePathRename(final String newName) {
208-
if (path != null) {
209-
path = FixPath.RESERVED_FIELD_PATTERN.matcher(newName).replaceAll(Matcher.quoteReplacement(split(path)[0]));
210-
}
211-
212-
return this;
213-
}
214-
215-
/*package-private*/ Value updatePathAddBase(final Value container, final String fallback) {
216-
if (container.path != null) {
217-
final String[] pathSegments = split(path != null ? path : fallback);
218-
final String lastSegment = pathSegments[pathSegments.length - 1];
219-
this.path = container.path + "." + lastSegment;
220-
}
221-
222-
return this;
223-
}
224-
225-
/*package-private*/ Value updatePathAppend(final String suffix, final String fallback) {
226-
if (path != null) {
227-
path = path + suffix;
228-
}
229-
else {
230-
path = fallback + suffix;
231-
}
232-
233-
return this;
234-
}
235-
236202
public TypeMatcher matchType() {
237203
return new TypeMatcher(this);
238204
}
@@ -286,8 +252,17 @@ public String getPath() {
286252
return path;
287253
}
288254

289-
/*package-private*/ void setPath(final String path) {
290-
this.path = path;
255+
/*package-private*/ Value withPathSet(final String p) {
256+
this.path = p;
257+
return this;
258+
}
259+
260+
private Value withPathAppend(final int i) {
261+
return withPathAppend(String.valueOf(i));
262+
}
263+
264+
private Value withPathAppend(final String field) {
265+
return withPathSet(path == null || path.isEmpty() ? field : path + "." + field);
291266
}
292267

293268
/*package-private*/ Value copy() {
@@ -395,8 +370,12 @@ private Array() {
395370
}
396371

397372
public void add(final Value value) {
373+
add(value, true);
374+
}
375+
376+
/* package-private */ void add(final Value value, final boolean appendToPath) {
398377
if (!isNull(value)) {
399-
list.add(value);
378+
list.add(appendToPath ? value.withPathAppend(list.size() + 1) : value);
400379
}
401380
}
402381

@@ -453,7 +432,7 @@ public void remove(final int index) {
453432
}
454433

455434
/*package-private*/ void set(final int index, final Value value) {
456-
list.set(index, value);
435+
list.set(index, value.withPathAppend(index + 1));
457436
}
458437

459438
/*package-private*/ void removeIf(final Predicate<Value> predicate) {
@@ -549,8 +528,12 @@ public int size() {
549528
* @param value the metadata value
550529
*/
551530
public void put(final String field, final Value value) {
531+
put(field, value, true);
532+
}
533+
534+
/*package-private*/ void put(final String field, final Value value, final boolean appendToPath) {
552535
if (!isNull(value)) {
553-
map.put(field, value);
536+
map.put(field, appendToPath ? value.withPathAppend(field) : value);
554537
}
555538
}
556539

@@ -583,8 +566,8 @@ public Value get(final String field) {
583566

584567
return set.isEmpty() ? null : set.size() == 1 ? getField(set.iterator().next(), enforceStringValue) :
585568
newArray(a -> set.forEach(f -> getField(f, enforceStringValue).matchType()
586-
.ifArray(b -> b.forEach(a::add))
587-
.orElse(a::add)
569+
.ifArray(b -> b.forEach(t -> a.add(t, false)))
570+
.orElse(t -> a.add(t, false))
588571
));
589572
}
590573

@@ -628,15 +611,13 @@ public void add(final String field, final Value newValue) {
628611
put(field, newValue);
629612
}
630613
else {
614+
final String basePath = oldValue.getPath();
631615
if (!oldValue.isArray()) { // repeated field: convert single val to first in array
632-
oldValue.updatePathAppend(".1", field);
616+
oldValue.withPathAppend(1);
633617
}
634618

635-
put(field, oldValue.asList(oldVals -> newValue.asList(newVals -> {
636-
for (int i = 0; i < newVals.size(); ++i) {
637-
oldVals.add(newVals.get(i).updatePathAppend("." + (i + 1 + oldVals.size()), field));
638-
}
639-
})));
619+
put(field, oldValue.asList(oldVals -> newValue.asList(newVals ->
620+
newVals.forEach(newVal -> oldVals.add(newVal.withPathSet(basePath))))));
640621
}
641622
}
642623

0 commit comments

Comments
 (0)