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

Convert marked array entity into actual array object. #110

Merged
merged 3 commits into from
Jan 20, 2022
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
36 changes: 23 additions & 13 deletions metafix/src/main/java/org/metafacture/metafix/Metafix.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public class Metafix implements StreamPipe<StreamReceiver>, Maps { // checkstyle
private int entityCount;
private StreamReceiver outputStreamReceiver;
private String recordIdentifier;
private List<Value.Hash> entities = new ArrayList<>();
private List<Value> entities = new ArrayList<>();

public Metafix() {
flattener.setReceiver(new DefaultStreamReceiver() {
Expand Down Expand Up @@ -170,20 +170,33 @@ private void emit(final String field, final Value value) {
});
}

private void addValue(final String name, final Value value) {
final int index = entityCountStack.peek() - 1;
if (index < 0 || entities.size() <= index) {
currentRecord.add(name, value);
}
else {
entities.get(index).matchType()
.ifArray(a -> a.add(value))
.ifHash(h -> h.add(name, value))
.orElseThrow();
}
}

@Override
public void startEntity(final String name) {
if (name == null) {
throw new IllegalArgumentException("Entity name must not be null.");
}
++entityCount;
final Integer currentEntityIndex = entityCountStack.peek() - 1;
final Value.Hash previousEntity = currentEntityIndex < 0 ||
entities.size() <= currentEntityIndex ? null : entities.get(currentEntityIndex);
entityCountStack.push(Integer.valueOf(entityCount));

final Value value = name.endsWith(ARRAY_MARKER) ? Value.newArray() : Value.newHash();
// TODO: Remove array marker? => name.substring(0, name.length() - ARRAY_MARKER.length());

addValue(name, value);
entities.add(value);

entityCountStack.push(Integer.valueOf(++entityCount));
flattener.startEntity(name);
final Value value = Value.newHash();
(previousEntity != null ? previousEntity : currentRecord).add(name, value);
entities.add(value.asHash());
}

@Override
Expand All @@ -195,10 +208,7 @@ public void endEntity() {
@Override
public void literal(final String name, final String value) {
LOG.debug("Putting '{}': '{}'", name, value);
final Integer currentEntityIndex = entityCountStack.peek() - 1;
final Value.Hash currentEntity = currentEntityIndex < 0 ||
entities.size() <= currentEntityIndex ? null : entities.get(currentEntityIndex);
(currentEntity != null ? currentEntity : currentRecord).add(name, new Value(value));
addValue(name, new Value(value));
// TODO: keep flattener as option?
// flattener.literal(name, value);
}
Expand Down
29 changes: 2 additions & 27 deletions metafix/src/main/java/org/metafacture/metafix/Value.java
Original file line number Diff line number Diff line change
Expand Up @@ -305,21 +305,6 @@ void apply(final Hash hash, final String field, final Value value) {
void apply(final Hash hash, final String field, final Value value) {
hash.add(field, value);
}
},
/* For an indexed representation of arrays as hashes with 1, 2, 3 etc. keys.
* i.e. ["a", "b", "c"] as { "1":"a", "2":"b", "3": "c" }
* This is what is produced by JsonDecoder and Metafix itself for arrays.
* TODO? maybe this would be a good general internal representation, resulting
* in every value being either a hash or a string, no more separate array type.*/
INDEXED {
@Override
void apply(final Hash hash, final String field, final Value value) {
hash.add(nextIndex(hash), field.equals(ReservedField.$append.name()) ? value : newHash(h -> h.put(field, value)));
}

private String nextIndex(final Hash hash) {
return "" + (hash.size() + 1) /* TODO? check if keys are actually all ints? */;
}
};

abstract void apply(Hash hash, String field, Value value);
Expand Down Expand Up @@ -697,7 +682,7 @@ private Value insert(final InsertMode mode, final String[] fields, final Value n
// TODO: move impl into enum elements, here call only value.insert
value.matchType()
.ifArray(a -> a.insert(mode, tail, newValue))
.ifHash(h -> h.insert(insertMode(mode, field, tail), tail, newValue))
.ifHash(h -> h.insert(mode, tail, newValue))
.orElseThrow();
}
}
Expand All @@ -708,7 +693,7 @@ private Value insert(final InsertMode mode, final String[] fields, final Value n
private Value processRef(final InsertMode mode, final Value newValue, final String field, final String[] tail) {
final Value referencedValue = getReferencedValue(field);
if (referencedValue != null) {
return referencedValue.asHash().insert(insertMode(mode, field, tail), tail, newValue);
return referencedValue.asHash().insert(mode, tail, newValue);
}
else {
throw new IllegalArgumentException("Using ref, but can't find: " + field + " in: " + this);
Expand Down Expand Up @@ -738,16 +723,6 @@ private Value getReferencedValue(final String field) {
return referencedValue;
}

private InsertMode insertMode(final InsertMode mode, final String field, final String[] tail) {
// if the field is marked as array, this hash should be smth. like { 1=a, 2=b }
final boolean isIndexedArray = field.endsWith(Metafix.ARRAY_MARKER);
final boolean nextIsRef = tail.length > 0 && (
tail[0].startsWith(ReservedField.$first.name()) ||
tail[0].startsWith(ReservedField.$last.name()) ||
isNumber(tail[0]));
return isIndexedArray && !nextIsRef ? InsertMode.INDEXED : mode;
}

/**
* Removes the given field/value pair from this hash.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,7 @@ public void complexAppendWithArrayOfObjects() {
@Test
public void appendWithWildcard() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"set_array('stringimals[]')",
"copy_field('?nimal', 'stringimals[].$append')"
),
i -> {
Expand Down Expand Up @@ -542,6 +543,7 @@ public void simpleCopyWithWildcard() {
@Test
public void appendWithMultipleWildcards() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"set_array('stringimals[]')",
"copy_field('?ni??l', 'stringimals[].$append')"
),
i -> {
Expand Down Expand Up @@ -572,6 +574,7 @@ public void appendWithMultipleWildcards() {
@Test
public void appendWithAsteriksWildcard() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"set_array('stringimals[]')",
"copy_field('*al', 'stringimals[].$append')"
),
i -> {
Expand Down Expand Up @@ -601,6 +604,7 @@ public void appendWithAsteriksWildcard() {
@Test
public void appendWithBracketWildcard() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"set_array('stringimals[]')",
"copy_field('[ac]nimal', 'stringimals[].$append')"
),
i -> {
Expand Down Expand Up @@ -630,6 +634,7 @@ public void appendWithBracketWildcard() {
// See https://github.com/metafacture/metafacture-fix/issues/89
public void appendWithAsteriksWildcardAtTheEnd() {
MetafixTestHelpers.assertFix(streamReceiver, Arrays.asList(
"set_array('stringimals[]')",
"copy_field('ani*', 'stringimals[].$append')"
),
i -> {
Expand Down