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

Commit

Permalink
Extract find* and transform* methods from Value.Array (#102)
Browse files Browse the repository at this point in the history
To a `Path` class that in the end should become something like
https://metacpan.org/pod/Catmandu::Path::simple
  • Loading branch information
fsteeg committed Feb 1, 2022
1 parent 2225a80 commit 2a14c70
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 105 deletions.
20 changes: 10 additions & 10 deletions metafix/src/main/java/org/metafacture/metafix/FixMethod.java
Original file line number Diff line number Diff line change
Expand Up @@ -293,13 +293,13 @@ public void apply(final Metafix metafix, final Record record, final List<String>
@Override
public void apply(final Metafix metafix, final Record record, final List<String> params, final Map<String, String> options) {
final String value = params.get(1);
record.transformFields(params, s -> s + value);
record.transformField(params.get(0), s -> s + value);
}
},
capitalize {
@Override
public void apply(final Metafix metafix, final Record record, final List<String> params, final Map<String, String> options) {
record.transformFields(params, s -> s.substring(0, 1).toUpperCase() + s.substring(1));
record.transformField(params.get(0), s -> s.substring(0, 1).toUpperCase() + s.substring(1));
}
},
count {
Expand All @@ -314,7 +314,7 @@ public void apply(final Metafix metafix, final Record record, final List<String>
downcase {
@Override
public void apply(final Metafix metafix, final Record record, final List<String> params, final Map<String, String> options) {
record.transformFields(params, String::toLowerCase);
record.transformField(params.get(0), s -> s.toLowerCase());
}
},
filter {
Expand All @@ -334,7 +334,7 @@ public void apply(final Metafix metafix, final Record record, final List<String>
@Override
public void apply(final Metafix metafix, final Record record, final List<String> params, final Map<String, String> options) {
final String search = params.get(1);
record.transformFields(params, s -> String.valueOf(s.indexOf(search))); // TODO: multiple
record.transformField(params.get(0), s -> String.valueOf(s.indexOf(search))); // TODO: multiple
}
},
join_field {
Expand Down Expand Up @@ -365,14 +365,14 @@ public void apply(final Metafix metafix, final Record record, final List<String>
}

final String defaultValue = map.get(Maps.DEFAULT_MAP_KEY); // TODO: Catmandu uses 'default'
record.transformFields(params, k -> map.getOrDefault(k, defaultValue));
record.transformField(params.get(0), k -> map.getOrDefault(k, defaultValue));
}
},
prepend {
@Override
public void apply(final Metafix metafix, final Record record, final List<String> params, final Map<String, String> options) {
final String value = params.get(1);
record.transformFields(params, s -> value + s);
record.transformField(params.get(0), s -> value + s);
}
},
replace_all {
Expand All @@ -381,7 +381,7 @@ public void apply(final Metafix metafix, final Record record, final List<String>
final String search = params.get(1);
final String replace = params.get(2);

record.transformFields(params, s -> s.replaceAll(search, replace));
record.transformField(params.get(0), s -> s.replaceAll(search, replace));
}
},
reverse {
Expand Down Expand Up @@ -433,7 +433,7 @@ public void apply(final Metafix metafix, final Record record, final List<String>
substring {
@Override
public void apply(final Metafix metafix, final Record record, final List<String> params, final Map<String, String> options) {
record.transformFields(params, s -> s.substring(getInteger(params, 1), getInteger(params, 2) - 1));
record.transformField(params.get(0), s -> s.substring(getInteger(params, 1), getInteger(params, 2) - 1));
}
},
sum {
Expand All @@ -447,7 +447,7 @@ public void apply(final Metafix metafix, final Record record, final List<String>
trim {
@Override
public void apply(final Metafix metafix, final Record record, final List<String> params, final Map<String, String> options) {
record.transformFields(params, String::trim);
record.transformField(params.get(0), String::trim);
}
},
uniq {
Expand All @@ -461,7 +461,7 @@ public void apply(final Metafix metafix, final Record record, final List<String>
upcase {
@Override
public void apply(final Metafix metafix, final Record record, final List<String> params, final Map<String, String> options) {
record.transformFields(params, String::toUpperCase);
record.transformField(params.get(0), s -> s.toUpperCase());
}
};

Expand Down
114 changes: 114 additions & 0 deletions metafix/src/main/java/org/metafacture/metafix/Path.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* Copyright 2022 Fabian Steeg, hbz NRW
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.metafacture.metafix;

import org.metafacture.metafix.Value.Array;

import java.util.Arrays;
import java.util.function.UnaryOperator;

/**
* Our goal here is something like https://metacpan.org/pod/Catmandu::Path::simple
*
* @author Fabian Steeg (fsteeg)
*
*/
public class Path {
private static final String ASTERISK = "*";
private String[] path;

public Path(final String[] path) {
this.path = path;
}

public Value findInArray(final Value.Array array) {
final Value result;
if (path.length > 0) {
final String currentSegment = path[0];
if (currentSegment.equals(ASTERISK)) {
result = Value.newArray(a -> array.forEach(v -> a.add(findInValue(v, tail(path)))));
}
else if (Value.isNumber(currentSegment)) {
final int index = Integer.parseInt(currentSegment) - 1; // TODO: 0-based Catmandu vs. 1-based Metafacture
if (index >= 0 && index < array.size()) {
result = findInValue(array.get(index), tail(path));
}
else {
result = null;
}
}
// TODO: WDCD? copy_field('your.name','author[].name'), where name is an array
else {
result = Value.newArray(a -> array.forEach(v -> a.add(findInValue(v, path))));
}
}
else {
result = new Value(array);
}
return result;
}

private Value findInValue(final Value value, final String[] p) {
// TODO: move impl into enum elements, here call only value.find
return value == null ? null : value.extractType((m, c) -> m
.ifArray(a -> c.accept(new Path(p).findInArray(a)))
.ifHash(h -> c.accept(h.find(p)))
.orElse(c)
);
}

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

public void transformInArray(final Array array, final UnaryOperator<String> operator) {
final String currentSegment = path[0];
final int size = array.size();

if (path.length == 0 || currentSegment.equals(ASTERISK)) {
for (int i = 0; i < size; ++i) {
transformValueAt(array, i, tail(path), operator);
}
}
else if (Value.isNumber(currentSegment)) {
final int index = Integer.parseInt(currentSegment) - 1; // TODO: 0-based Catmandu vs. 1-based Metafacture
if (index >= 0 && index < size) {
transformValueAt(array, index, tail(path), operator);
}
}
// TODO: WDCD? copy_field('your.name','author[].name'), where name is an array
else {
for (int i = 0; i < size; ++i) {
transformValueAt(array, i, tail(path), operator);
}
}

array.getList().removeIf(v -> Value.isNull(v));
}

private void transformValueAt(final Array array, final int index, final String[] p, final UnaryOperator<String> operator) {
final Value value = array.get(index);
if (value != null) {
value.matchType()
.ifString(s -> array.set(index, operator != null ? new Value(operator.apply(s)) : null))
.orElse(v -> new Value.TypeMatcher(v)
.ifArray(a -> new Path(p).transformInArray(a, operator))
.ifHash(h -> h.transformPath(p, operator))
.orElseThrow());
}
}
}
Loading

3 comments on commit 2a14c70

@blackwinter
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would maybe FixPath be better? (Avoiding name clash with java.nio.file.Path.)

@blackwinter
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if you're at that point yet, but would it also make sense to adopt Catmandu's terminology? (FixPath.get()/.set()/.update()/etc.)

@fsteeg
Copy link
Member Author

@fsteeg fsteeg commented on 2a14c70 Feb 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if you're at that point yet, but would it also make sense to adopt Catmandu's terminology? (FixPath.get()/.set()/.update()/etc.)

Yes, my plan was to move over all methods that can/will be implemented by get/set/update/create/delete and then start restructuring and renaming them with that goal.

Please sign in to comment.