Skip to content

Commit

Permalink
Merge positive and negative index property
Browse files Browse the repository at this point in the history
  • Loading branch information
leeonky committed Oct 15, 2023
1 parent 66ce56b commit 4f6235c
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 19 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ dependencies {
testAnnotationProcessor 'org.projectlombok:lombok:1.18.12'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.6.3'

testImplementation dep(':DAL-java', '0.3.22')
testImplementation dep(':DAL-java', '0.4.2')
testImplementation dep(':java-compiler-util', '0.0.3')
testImplementation "io.cucumber:cucumber-java:6.10.4"
testImplementation group: 'org.mockito', name: 'mockito-inline', version: '4.0.0'
Expand Down
41 changes: 30 additions & 11 deletions src/main/java/com/github/leeonky/jfactory/CollectionExpression.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.github.leeonky.util.CollectionHelper;
import com.github.leeonky.util.Property;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -34,11 +35,32 @@ private boolean isMatch(Expression<E> expression, Object value) {
@Override
@SuppressWarnings("unchecked")
public Producer<?> buildProducer(JFactory jFactory, Producer<P> parent) {
CollectionProducer<?, E> collectionProducer = cast(parent.childOrDefault(property.getName()),
CollectionProducer<?, E> producer = cast(parent.childOrDefault(property.getName()),
CollectionProducer.class).orElseThrow(IllegalArgumentException::new);
children.forEach((k, v) ->
collectionProducer.setChild(k.toString(), v.buildProducer(jFactory, collectionProducer)));
return collectionProducer;
groupByAdjustedPositiveAndNegativeIndexExpression(producer).forEach((index, expressions) ->
producer.setChild(index.toString(), merge(expressions).buildProducer(jFactory, producer)));
return producer;
}

private Map<Integer, List<Expression<E>>> groupByAdjustedPositiveAndNegativeIndexExpression(
CollectionProducer<?, E> collectionProducer) {
Map<Integer, List<Expression<E>>> result = new LinkedHashMap<>();
for (Map.Entry<Integer, Expression<E>> entry : children.entrySet()) {
int index = entry.getKey();
int addedProducerCount = collectionProducer.fillCollectionWithDefaultValue(index);
if (index < 0) {
index = collectionProducer.childrenCount() + index;
result = adjustIndexByInserted(result, addedProducerCount);
}
result.computeIfAbsent(index, k -> new ArrayList<>()).add(entry.getValue());
}
return result;
}

private LinkedHashMap<Integer, List<Expression<E>>> adjustIndexByInserted(
Map<Integer, List<Expression<E>>> result, int addedProducerCount) {
return result.entrySet().stream().collect(LinkedHashMap::new,
(m, e) -> m.put(e.getKey() + addedProducerCount, e.getValue()), LinkedHashMap::putAll);
}

@Override
Expand All @@ -49,13 +71,10 @@ public Expression<P> mergeTo(Expression<P> newExpression) {
@Override
@SuppressWarnings("unchecked")
protected Expression<P> mergeFrom(CollectionExpression<P, ?> origin) {
origin.children.forEach((index, expression) ->
children.put(index, mergeFromOrAssign(index, (Expression<E>) expression)));
return this;
}

private Expression<E> mergeFromOrAssign(Integer index, Expression<E> expression) {
return children.containsKey(index) ? expression.mergeTo(children.get(index)) : expression;
children.forEach((index, expression) ->
origin.children.put(index, origin.children.containsKey(index) ?
origin.children.get(index).mergeTo((Expression) expression) : (Expression) expression));
return origin;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,17 @@ public void setChild(String property, Producer<?> producer) {
children.set(intIndex, producer);
}

private void fillCollectionWithDefaultValue(int index) {
public int fillCollectionWithDefaultValue(int index) {
int changed = 0;
if (index >= 0) {
for (int i = children.size(); i <= index; i++)
for (int i = children.size(); i <= index; i++, changed++)
children.add(placeholderFactory.apply(i));
} else {
int count = max(children.size(), -index) - children.size();
for (int i = 0; i < count; i++)
for (int i = 0; i < count; i++, changed++)
children.add(i, placeholderFactory.apply(i));
}
return changed;
}

@Override
Expand Down Expand Up @@ -90,4 +92,8 @@ protected <T> void setupAssociation(String association, RootInstance<T> instance
objectProducer.setupAssociation(association, instance, cachedChildren));

}

public int childrenCount() {
return children.size();
}
}
6 changes: 6 additions & 0 deletions src/main/java/com/github/leeonky/jfactory/Expression.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.github.leeonky.util.Property;

import java.util.List;

abstract class Expression<P> {
protected final Property<P> property;
protected boolean intently = false;
Expand All @@ -22,6 +24,10 @@ public boolean isMatch(P object) {

public abstract Producer<?> buildProducer(JFactory jFactory, Producer<P> parent);

static <T> Expression<T> merge(List<Expression<T>> expressions) {
return expressions.stream().reduce(Expression::mergeTo).get();
}

protected Expression<P> mergeTo(Expression<P> newExpression) {
return newExpression;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Builder<?> apply(Builder<?> builder) {
<T> Collection<Expression<T>> expressions(BeanClass<T> type, ObjectFactory<T> objectFactory) {
return keyValues.values().stream().map(keyValue -> keyValue.createExpression(type, objectFactory))
.collect(Collectors.groupingBy(Expression::getProperty)).values().stream()
.map(expressions -> expressions.stream().reduce(Expression::mergeTo).get())
.map(Expression::merge)
.collect(Collectors.toList());
}

Expand Down
70 changes: 67 additions & 3 deletions src/test/resources/features/3-input-property.feature
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,7 @@ Feature: input property
"""
public class Bean {
public String value;
public String value2;
}
"""
And the following bean class:
Expand Down Expand Up @@ -515,9 +516,72 @@ Feature: input property
beans.value[]: [hello world]
"""

# TODO -1 -2 increase by insert from left
# TODO mix [0] [-2]
# TODO merge [0] [-1]
Scenario: collection override when use both positive and negative index
When build:
"""
jFactory.type(Beans.class)
.property("beans[0].value", "world")
.property("beans[-2].value", "hello")
.create();
"""
Then the result should:
"""
beans.value[]: [hello world]
"""
When build:
"""
jFactory.type(Beans.class)
.property("beans[-2].value", "hello")
.property("beans[0].value", "world")
.create();
"""
Then the result should:
"""
beans: [{
value= world
}, null]
"""

Scenario: mixed using positive and negative index
When build:
"""
jFactory.type(Beans.class)
.property("beans[2].value", "world")
.property("beans[-2].value", "hello")
.create();
"""
Then the result should:
"""
beans: [null {value= hello} {value= world}]
"""

Scenario: merge same sub object when mixed using positive and negative index
Given the following bean class:
"""
public class BeanRef {
public Bean bean;
}
"""
Given the following bean class:
"""
public class BeanRefs {
public BeanRef[] beanRefs;
}
"""
When build:
"""
jFactory.type(BeanRefs.class)
.property("beanRefs[-1].bean.value", "hello")
.property("beanRefs[0].bean.value2", "world")
.create();
"""
Then the result should:
"""
beanRefs.bean[]= [{
value= hello
value2= world
}]
"""

Rule: intently create

Expand Down

0 comments on commit 4f6235c

Please sign in to comment.