diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/FixtureMonkeyBuilder.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/FixtureMonkeyBuilder.java
index d3fa6b80a..b577677fe 100644
--- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/FixtureMonkeyBuilder.java
+++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/FixtureMonkeyBuilder.java
@@ -58,10 +58,13 @@
import com.navercorp.fixturemonkey.buildergroup.ArbitraryBuilderGroup;
import com.navercorp.fixturemonkey.customizer.MonkeyManipulatorFactory;
import com.navercorp.fixturemonkey.expression.ArbitraryExpressionFactory;
+import com.navercorp.fixturemonkey.expression.MonkeyExpression;
import com.navercorp.fixturemonkey.expression.MonkeyExpressionFactory;
import com.navercorp.fixturemonkey.resolver.ManipulatorOptimizer;
import com.navercorp.fixturemonkey.resolver.NoneManipulatorOptimizer;
import com.navercorp.fixturemonkey.tree.ApplyStrictModeResolver;
+import com.navercorp.fixturemonkey.tree.NextNodePredicate;
+import com.navercorp.fixturemonkey.tree.NodeResolver;
@SuppressWarnings("unused")
@API(since = "0.4.0", status = Status.MAINTAINED)
@@ -443,8 +446,21 @@ public FixtureMonkeyBuilder enableLoggingFail(boolean enableLoggingFail) {
}
public FixtureMonkeyBuilder useExpressionStrictMode() {
- this.monkeyExpressionFactory = expression ->
- () -> new ApplyStrictModeResolver(new ArbitraryExpressionFactory().from(expression).toNodeResolver());
+ this.monkeyExpressionFactory = expression -> {
+ MonkeyExpression monkeyExpression = new ArbitraryExpressionFactory().from(expression);
+
+ return new MonkeyExpression() {
+ @Override
+ public NodeResolver toNodeResolver() {
+ return new ApplyStrictModeResolver(monkeyExpression.toNodeResolver());
+ }
+
+ @Override
+ public List toNextNodePredicate() { // TODO:
+ return monkeyExpression.toNextNodePredicate();
+ }
+ };
+ };
return this;
}
diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/ArbitraryManipulator.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/ArbitraryManipulator.java
index 4beac85f6..6a8c9e15d 100644
--- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/ArbitraryManipulator.java
+++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/ArbitraryManipulator.java
@@ -21,7 +21,6 @@
import org.apiguardian.api.API;
import org.apiguardian.api.API.Status;
-import com.navercorp.fixturemonkey.tree.CompositeNodeResolver;
import com.navercorp.fixturemonkey.tree.NodeResolver;
import com.navercorp.fixturemonkey.tree.ObjectTree;
@@ -35,13 +34,6 @@ public final class ArbitraryManipulator {
this.nodeManipulator = nodeManipulator;
}
- ArbitraryManipulator withPrependNodeResolver(NodeResolver nodeResolver) {
- return new ArbitraryManipulator(
- new CompositeNodeResolver(nodeResolver, this.nodeResolver),
- this.nodeManipulator
- );
- }
-
public NodeResolver getNodeResolver() {
return nodeResolver;
}
diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/InnerSpec.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/InnerSpec.java
index 6f1b3212b..8585d3b76 100644
--- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/InnerSpec.java
+++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/InnerSpec.java
@@ -25,6 +25,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -42,16 +43,14 @@
import com.navercorp.fixturemonkey.customizer.InnerSpecState.FilterHolder;
import com.navercorp.fixturemonkey.customizer.InnerSpecState.ManipulatorHolderSet;
import com.navercorp.fixturemonkey.customizer.InnerSpecState.NodeResolverObjectHolder;
-import com.navercorp.fixturemonkey.tree.CompositeNodeResolver;
import com.navercorp.fixturemonkey.tree.ContainerElementPredicate;
-import com.navercorp.fixturemonkey.tree.DefaultNodeResolver;
-import com.navercorp.fixturemonkey.tree.IdentityNodeResolver;
+import com.navercorp.fixturemonkey.tree.NextNodePredicate;
import com.navercorp.fixturemonkey.tree.NodeAllElementPredicate;
import com.navercorp.fixturemonkey.tree.NodeElementPredicate;
import com.navercorp.fixturemonkey.tree.NodeKeyPredicate;
-import com.navercorp.fixturemonkey.tree.NodeResolver;
import com.navercorp.fixturemonkey.tree.NodeValuePredicate;
import com.navercorp.fixturemonkey.tree.PropertyNameNodePredicate;
+import com.navercorp.fixturemonkey.tree.StartNodePredicate;
/**
* A type-independent specification for configuring nested properties.
@@ -69,7 +68,7 @@ public final class InnerSpec {
private static final int FIRST_MANIPULATOR_SEQUENCE = 0;
private final int sequence;
- private final NodeResolver treePathResolver;
+ private final List nextNodePredicates;
private final InnerSpecState state;
private final List innerSpecs;
@@ -83,12 +82,22 @@ public final class InnerSpec {
*
*/
public InnerSpec() {
- this(FIRST_MANIPULATOR_SEQUENCE, IdentityNodeResolver.INSTANCE, new InnerSpecState(), new ArrayList<>());
+ this(
+ FIRST_MANIPULATOR_SEQUENCE,
+ Collections.singletonList(StartNodePredicate.INSTANCE),
+ new InnerSpecState(),
+ new ArrayList<>()
+ );
}
- private InnerSpec(int sequence, NodeResolver treePathResolver, InnerSpecState state, List innerSpecs) {
+ private InnerSpec(
+ int sequence,
+ List nextNodePredicates,
+ InnerSpecState state,
+ List innerSpecs
+ ) {
this.sequence = sequence;
- this.treePathResolver = treePathResolver;
+ this.nextNodePredicates = new ArrayList<>(nextNodePredicates);
this.state = state;
this.innerSpecs = innerSpecs;
}
@@ -101,7 +110,7 @@ private InnerSpec(int sequence, NodeResolver treePathResolver, InnerSpecState st
* to be applied to the currently referred property.
*/
public InnerSpec inner(InnerSpec innerSpec) {
- InnerSpec appendInnerSpec = newAppendNodeResolver(innerSpec, this.treePathResolver);
+ InnerSpec appendInnerSpec = newAppendNextNodePredicate(innerSpec, this.nextNodePredicates);
this.innerSpecs.add(appendInnerSpec);
return this;
}
@@ -119,7 +128,7 @@ public InnerSpec size(int minSize, int maxSize) {
}
this.state.setContainerInfoHolder(
- new ContainerInfoHolder(this.sequence + manipulateSize, this.treePathResolver, minSize, maxSize)
+ new ContainerInfoHolder(this.sequence + manipulateSize, this.nextNodePredicates, minSize, maxSize)
);
manipulateSize++;
return this;
@@ -342,7 +351,7 @@ public InnerSpec valueLazy(Supplier> supplier) {
* Sets an entry in the currently referred map property with a key and value
* obtained lazily from the given suppliers.
*
- * @param keySupplier a supplier function that provides the value of the map key to set.
+ * @param keySupplier a supplier function that provides the value of the map key to set.
* @param valueSupplier a function that provides the value of the map value to set.
*/
public InnerSpec entryLazy(Supplier> keySupplier, Supplier> valueSupplier) {
@@ -462,7 +471,7 @@ public InnerSpec listElement(int index, Consumer consumer) {
/**
* Sets every element within the currently referred container property.
*
- * @param value value of the elements to set
+ * @param value value of the elements to set
*/
public InnerSpec allListElement(@Nullable Object value) {
return listElement(NO_OR_ALL_INDEX_INTEGER_VALUE, value);
@@ -506,11 +515,11 @@ public InnerSpec property(String propertyName, Consumer consumer) {
/**
* Sets the post-condition for the currently referred property.
*
- * @param type type of the property to set
- * @param filter a predicate function that determines the post-condition of the property
+ * @param type type of the property to set
+ * @param filter a predicate function that determines the post-condition of the property
*/
public InnerSpec postCondition(Class type, Predicate filter) {
- this.state.setFilterHolder(new FilterHolder(manipulateSize++, this.treePathResolver, type, filter));
+ this.state.setFilterHolder(new FilterHolder(manipulateSize++, this.nextNodePredicates, type, filter));
return this;
}
@@ -519,16 +528,16 @@ public ManipulatorSet getManipulatorSet(MonkeyManipulatorFactory monkeyManipulat
return monkeyManipulatorFactory.newManipulatorSet(manipulatorHolderSet);
}
- private InnerSpec newAppendNodeResolver(InnerSpec innerSpec, NodeResolver nodeResolver) {
+ private InnerSpec newAppendNextNodePredicate(InnerSpec innerSpec, List nextNodePredicates) {
InnerSpec newSpec = new InnerSpec(
innerSpec.sequence,
- innerSpec.treePathResolver,
- innerSpec.state.withPrefix(nodeResolver),
+ innerSpec.nextNodePredicates,
+ innerSpec.state.withPrefix(nextNodePredicates),
new ArrayList<>()
);
for (InnerSpec spec : innerSpec.innerSpecs) {
- newSpec.innerSpecs.add(newAppendNodeResolver(spec, nodeResolver));
+ newSpec.innerSpecs.add(newAppendNextNodePredicate(spec, nextNodePredicates));
}
return newSpec;
}
@@ -540,13 +549,11 @@ private void setMapKey(Object mapKey) {
);
}
- NodeResolver nextKeyNodeResolver = new CompositeNodeResolver(
- this.treePathResolver,
- new DefaultNodeResolver(new NodeElementPredicate(entrySize - 1)),
- new DefaultNodeResolver(new NodeKeyPredicate())
- );
+ List nextKeyNodeNodePredicate = new ArrayList<>(this.nextNodePredicates);
+ nextKeyNodeNodePredicate.add(new NodeElementPredicate(entrySize - 1));
+ nextKeyNodeNodePredicate.add(new NodeKeyPredicate());
- setValue(nextKeyNodeResolver, mapKey);
+ setValue(nextKeyNodeNodePredicate, mapKey);
}
private void setMapAllKey(Object mapKey) {
@@ -556,33 +563,25 @@ private void setMapAllKey(Object mapKey) {
);
}
- NodeResolver nextKeyNodeResolver = new CompositeNodeResolver(
- this.treePathResolver,
- new DefaultNodeResolver(new NodeAllElementPredicate()),
- new DefaultNodeResolver(new NodeKeyPredicate())
- );
+ List nextKeyNodePredicate = new ArrayList<>(this.nextNodePredicates);
+ nextKeyNodePredicate.add(new NodeAllElementPredicate());
+ nextKeyNodePredicate.add(new NodeKeyPredicate());
- setValue(nextKeyNodeResolver, mapKey);
+ setValue(nextKeyNodePredicate, mapKey);
}
private void setMapValue(@Nullable Object mapValue) {
- NodeResolver nextValueNodeResolver = new CompositeNodeResolver(
- this.treePathResolver,
- new DefaultNodeResolver(new NodeElementPredicate(entrySize - 1)),
- new DefaultNodeResolver(new NodeValuePredicate())
- );
-
- setValue(nextValueNodeResolver, mapValue);
+ List nextValueNodePredicate = new ArrayList<>(this.nextNodePredicates);
+ nextValueNodePredicate.add(new NodeElementPredicate(entrySize - 1));
+ nextValueNodePredicate.add(new NodeValuePredicate());
+ setValue(nextValueNodePredicate, mapValue);
}
private void setMapAllValue(@Nullable Object mapValue) {
- NodeResolver nextValueNodeResolver = new CompositeNodeResolver(
- this.treePathResolver,
- new DefaultNodeResolver(new NodeAllElementPredicate()),
- new DefaultNodeResolver(new NodeValuePredicate())
- );
-
- setValue(nextValueNodeResolver, mapValue);
+ List nextValueNodePredicate = new ArrayList<>(this.nextNodePredicates);
+ nextValueNodePredicate.add(new NodeAllElementPredicate());
+ nextValueNodePredicate.add(new NodeValuePredicate());
+ setValue(nextValueNodePredicate, mapValue);
}
private void setMapEntry(Object key, @Nullable Object value) {
@@ -591,31 +590,25 @@ private void setMapEntry(Object key, @Nullable Object value) {
}
private void setPropertyValue(String propertyName, @Nullable Object value) {
- CompositeNodeResolver nextNodeResolver = new CompositeNodeResolver(
- this.treePathResolver,
- new DefaultNodeResolver(new PropertyNameNodePredicate(propertyName))
- );
-
- setValue(nextNodeResolver, value);
+ List nextNodePredicates = new ArrayList<>(this.nextNodePredicates);
+ nextNodePredicates.add(new PropertyNameNodePredicate(propertyName));
+ setValue(nextNodePredicates, value);
}
private void setListElement(int index, @Nullable Object value) {
- CompositeNodeResolver nextNodeResolver = new CompositeNodeResolver(
- this.treePathResolver,
- new DefaultNodeResolver(new ContainerElementPredicate(index))
- );
-
- setValue(nextNodeResolver, value);
+ List nextNodePredicates = new ArrayList<>(this.nextNodePredicates);
+ nextNodePredicates.add(new ContainerElementPredicate(index));
+ setValue(nextNodePredicates, value);
}
@SuppressWarnings("unchecked")
- private void setValue(NodeResolver nextNodeResolver, @Nullable Object nextValue) {
+ private void setValue(List nextNodePredicates, @Nullable Object nextValue) {
int nextSequence = this.sequence + manipulateSize;
if (nextValue instanceof InnerSpec) {
InnerSpec prefix = new InnerSpec(
nextSequence,
- nextNodeResolver,
+ nextNodePredicates,
new InnerSpecState(),
new ArrayList<>()
);
@@ -628,7 +621,7 @@ private void setValue(NodeResolver nextNodeResolver, @Nullable Object nextValue)
Consumer consumer = (Consumer)nextValue;
InnerSpec nextInnerSpec = new InnerSpec(
nextSequence,
- nextNodeResolver,
+ nextNodePredicates,
new InnerSpecState(),
new ArrayList<>()
);
@@ -642,14 +635,14 @@ private void setValue(NodeResolver nextNodeResolver, @Nullable Object nextValue)
nextInnerSpecState.setObjectHolder(
new NodeResolverObjectHolder(
nextSequence,
- nextNodeResolver,
+ nextNodePredicates,
nextValue
)
);
InnerSpec nextInnerSpec = new InnerSpec(
nextSequence,
- nextNodeResolver,
+ nextNodePredicates,
nextInnerSpecState,
new ArrayList<>()
);
diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/InnerSpecState.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/InnerSpecState.java
index f1516c71a..786c14932 100644
--- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/InnerSpecState.java
+++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/InnerSpecState.java
@@ -18,6 +18,7 @@
package com.navercorp.fixturemonkey.customizer;
+import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
@@ -26,8 +27,7 @@
import org.apiguardian.api.API;
import org.apiguardian.api.API.Status;
-import com.navercorp.fixturemonkey.tree.CompositeNodeResolver;
-import com.navercorp.fixturemonkey.tree.NodeResolver;
+import com.navercorp.fixturemonkey.tree.NextNodePredicate;
@API(since = "0.5.0", status = Status.MAINTAINED)
final class InnerSpecState {
@@ -65,33 +65,36 @@ FilterHolder getFilterHolder() {
return filterHolder;
}
- InnerSpecState withPrefix(NodeResolver nodeResolver) {
+ InnerSpecState withPrefix(List nextNodePredicates) {
InnerSpecState newState = new InnerSpecState();
if (this.objectHolder != null) {
+ List concat = new ArrayList<>(nextNodePredicates);
+ concat.addAll(this.objectHolder.nextNodePredicates);
newState.objectHolder = new NodeResolverObjectHolder(
this.objectHolder.sequence,
- new CompositeNodeResolver(
- nodeResolver,
- this.objectHolder.nodeResolver
- ),
+ concat,
this.objectHolder.value
);
}
if (this.filterHolder != null) {
+ List concat = new ArrayList<>(nextNodePredicates);
+ concat.addAll(this.filterHolder.nextNodePredicates);
newState.filterHolder = new FilterHolder(
this.filterHolder.sequence,
- new CompositeNodeResolver(nodeResolver, this.filterHolder.nodeResolver),
+ concat,
this.filterHolder.type,
this.filterHolder.predicate
);
}
if (this.containerInfoHolder != null) {
+ List concat = new ArrayList<>(nextNodePredicates);
+ concat.addAll(this.containerInfoHolder.nextNodePredicates);
newState.containerInfoHolder = new ContainerInfoHolder(
this.containerInfoHolder.sequence,
- new CompositeNodeResolver(nodeResolver, this.containerInfoHolder.nodeResolver),
+ concat,
this.containerInfoHolder.elementMinSize,
this.containerInfoHolder.elementMaxSize
);
@@ -102,13 +105,18 @@ InnerSpecState withPrefix(NodeResolver nodeResolver) {
public static class ContainerInfoHolder {
private final int sequence;
- private final NodeResolver nodeResolver;
+ private final List nextNodePredicates;
private final int elementMinSize;
private final int elementMaxSize;
- public ContainerInfoHolder(int sequence, NodeResolver nodeResolver, int elementMinSize, int elementMaxSize) {
+ public ContainerInfoHolder(
+ int sequence,
+ List nextNodePredicates,
+ int elementMinSize,
+ int elementMaxSize
+ ) {
this.sequence = sequence;
- this.nodeResolver = nodeResolver;
+ this.nextNodePredicates = nextNodePredicates;
this.elementMinSize = elementMinSize;
this.elementMaxSize = elementMaxSize;
}
@@ -117,8 +125,8 @@ int getSequence() {
return sequence;
}
- NodeResolver getNodeResolver() {
- return nodeResolver;
+ List getNextNodePredicates() {
+ return this.nextNodePredicates;
}
int getElementMinSize() {
@@ -132,13 +140,18 @@ int getElementMaxSize() {
public static class FilterHolder {
private final int sequence;
- private final NodeResolver nodeResolver;
+ private final List nextNodePredicates;
private final Class> type;
private final Predicate> predicate;
- public FilterHolder(int sequence, NodeResolver nodeResolver, Class> type, Predicate> predicate) {
+ public FilterHolder(
+ int sequence,
+ List nextNodePredicates,
+ Class> type,
+ Predicate> predicate
+ ) {
this.sequence = sequence;
- this.nodeResolver = nodeResolver;
+ this.nextNodePredicates = nextNodePredicates;
this.type = type;
this.predicate = predicate;
}
@@ -147,8 +160,8 @@ public int getSequence() {
return sequence;
}
- NodeResolver getNodeResolver() {
- return nodeResolver;
+ List getNextNodePredicates() {
+ return this.nextNodePredicates;
}
Class> getType() {
@@ -162,17 +175,17 @@ Predicate> getPredicate() {
public static class NodeResolverObjectHolder {
private final int sequence;
- private final NodeResolver nodeResolver;
+ private final List nextNodePredicates;
private final Object value;
- public NodeResolverObjectHolder(int sequence, NodeResolver nodeResolver, Object value) {
+ public NodeResolverObjectHolder(int sequence, List nextNodePredicates, Object value) {
this.sequence = sequence;
- this.nodeResolver = nodeResolver;
+ this.nextNodePredicates = nextNodePredicates;
this.value = value;
}
- NodeResolver getNodeResolver() {
- return nodeResolver;
+ List getNextNodePredicates() {
+ return this.nextNodePredicates;
}
Object getValue() {
diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/MonkeyManipulatorFactory.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/MonkeyManipulatorFactory.java
index f375685ea..dd22932ab 100644
--- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/MonkeyManipulatorFactory.java
+++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/MonkeyManipulatorFactory.java
@@ -19,7 +19,6 @@
package com.navercorp.fixturemonkey.customizer;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -50,10 +49,11 @@
import com.navercorp.fixturemonkey.customizer.Values.Just;
import com.navercorp.fixturemonkey.customizer.Values.Unique;
import com.navercorp.fixturemonkey.expression.MonkeyExpressionFactory;
-import com.navercorp.fixturemonkey.tree.NextNodePredicate;
+import com.navercorp.fixturemonkey.tree.CompositeNodeResolver;
+import com.navercorp.fixturemonkey.tree.NodePredicateResolver;
import com.navercorp.fixturemonkey.tree.NodeResolver;
import com.navercorp.fixturemonkey.tree.ObjectNode;
-import com.navercorp.fixturemonkey.tree.PropertyPredicate;
+import com.navercorp.fixturemonkey.tree.StaticNodeResolver;
@API(since = "0.4.10", status = Status.MAINTAINED)
public final class MonkeyManipulatorFactory {
@@ -129,7 +129,7 @@ public ContainerInfoManipulator newContainerInfoManipulator(
int newSequence = sequence.getAndIncrement();
return new ContainerInfoManipulator(
- monkeyExpressionFactory.from(expression).toNodeResolver().toNextNodePredicate(),
+ monkeyExpressionFactory.from(expression).toNextNodePredicate(),
new ArbitraryContainerInfo(
min,
max
@@ -162,7 +162,12 @@ public List newRegisteredArbitraryManipulators(
ArbitraryBuilderContext context = registeredArbitraryBuilder.getContext();
List arbitraryManipulators = context.getManipulators().stream()
- .map(it -> it.withPrependNodeResolver(prependPropertyNodeResolver(property, objectNodes)))
+ .map(
+ it -> new ArbitraryManipulator(
+ new CompositeNodeResolver(new StaticNodeResolver(objectNodes), it.getNodeResolver()),
+ it.getNodeManipulator()
+ )
+ )
.collect(Collectors.toList());
manipulators.addAll(arbitraryManipulators);
@@ -177,19 +182,36 @@ public ManipulatorSet newManipulatorSet(ManipulatorHolderSet manipulatorHolderSe
List setArbitraryManipulators = manipulatorHolderSet.getNodeResolverObjectHolders()
.stream()
- .map(it -> new ArbitraryManipulator(
- it.getNodeResolver(),
- convertToNodeManipulator(baseSequence + it.getSequence(), it.getValue())
- )
+ .map(
+ it -> {
+ List nextNodeResolvers = it.getNextNodePredicates().stream()
+ .map(NodePredicateResolver::new)
+ .collect(Collectors.toList());
+
+ CompositeNodeResolver compositeNodeResolver = new CompositeNodeResolver(nextNodeResolvers);
+ return new ArbitraryManipulator(
+ compositeNodeResolver,
+ convertToNodeManipulator(baseSequence + it.getSequence(), it.getValue())
+ );
+ }
)
.collect(Collectors.toList());
List filterArbitraryManipulators = manipulatorHolderSet.getPostConditionManipulators()
.stream()
- .map(it -> new ArbitraryManipulator(
- it.getNodeResolver(),
- new NodeFilterManipulator(it.getType(), it.getPredicate())
- ))
+ .map(
+ it -> {
+ List nextNodeResolvers = it.getNextNodePredicates().stream()
+ .map(NodePredicateResolver::new)
+ .collect(Collectors.toList());
+
+ CompositeNodeResolver compositeNodeResolver = new CompositeNodeResolver(nextNodeResolvers);
+ return new ArbitraryManipulator(
+ compositeNodeResolver,
+ new NodeFilterManipulator(it.getType(), it.getPredicate())
+ );
+ }
+ )
.collect(Collectors.toList());
arbitraryManipulators.addAll(setArbitraryManipulators);
arbitraryManipulators.addAll(filterArbitraryManipulators);
@@ -197,7 +219,7 @@ public ManipulatorSet newManipulatorSet(ManipulatorHolderSet manipulatorHolderSe
List containerInfoManipulators = manipulatorHolderSet.getContainerInfoManipulators()
.stream()
.map(it -> new ContainerInfoManipulator(
- it.getNodeResolver().toNextNodePredicate(),
+ it.getNextNodePredicates(),
new ArbitraryContainerInfo(
it.getElementMinSize(),
it.getElementMaxSize()
@@ -269,24 +291,4 @@ private NodeManipulator convertToNodeManipulator(int sequence, @Nullable Object
);
}
}
-
- private NodeResolver prependPropertyNodeResolver(Property property, List objectNodes) {
- return new NodeResolver() {
- @Override
- public List resolve(ObjectNode objectNode) {
- for (ObjectNode node : objectNodes) {
- ObjectNode parent = node.getParent();
- while (parent != null) {
- parent = parent.getParent();
- }
- }
- return objectNodes;
- }
-
- @Override
- public List toNextNodePredicate() {
- return Collections.singletonList(new PropertyPredicate(property));
- }
- };
- }
}
diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeSetDecomposedValueManipulator.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeSetDecomposedValueManipulator.java
index 1991f3928..4758972fb 100644
--- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeSetDecomposedValueManipulator.java
+++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeSetDecomposedValueManipulator.java
@@ -23,6 +23,7 @@
import static com.navercorp.fixturemonkey.api.type.Types.isAssignable;
import static com.navercorp.fixturemonkey.api.type.Types.nullSafe;
+import java.util.Collections;
import java.util.List;
import java.util.function.Function;
@@ -41,8 +42,8 @@
import com.navercorp.fixturemonkey.api.tree.TreeNodeManipulator;
import com.navercorp.fixturemonkey.api.type.Types;
import com.navercorp.fixturemonkey.tree.GenerateFixtureContext;
-import com.navercorp.fixturemonkey.tree.IdentityNodeResolver;
import com.navercorp.fixturemonkey.tree.ObjectNode;
+import com.navercorp.fixturemonkey.tree.StartNodePredicate;
@API(since = "0.4.0", status = Status.MAINTAINED)
public final class NodeSetDecomposedValueManipulator implements NodeManipulator {
@@ -119,7 +120,7 @@ private void setValue(ObjectNode objectNode, @Nullable Object value) {
new ArbitraryContainerInfo(decomposedContainerSize, decomposedContainerSize);
objectNode.addTreeNodeManipulator(
new ContainerInfoManipulator(
- IdentityNodeResolver.INSTANCE.toNextNodePredicate(),
+ Collections.singletonList(StartNodePredicate.INSTANCE),
containerInfo,
sequence
)
diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/ArbitraryExpression.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/ArbitraryExpression.java
index 390413ae0..2445c0e31 100644
--- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/ArbitraryExpression.java
+++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/ArbitraryExpression.java
@@ -34,10 +34,11 @@
import com.navercorp.fixturemonkey.tree.CompositeNodeResolver;
import com.navercorp.fixturemonkey.tree.ContainerElementPredicate;
-import com.navercorp.fixturemonkey.tree.DefaultNodeResolver;
-import com.navercorp.fixturemonkey.tree.IdentityNodeResolver;
+import com.navercorp.fixturemonkey.tree.NextNodePredicate;
+import com.navercorp.fixturemonkey.tree.NodePredicateResolver;
import com.navercorp.fixturemonkey.tree.NodeResolver;
import com.navercorp.fixturemonkey.tree.PropertyNameNodePredicate;
+import com.navercorp.fixturemonkey.tree.StartNodePredicate;
public final class ArbitraryExpression implements MonkeyExpression, Comparable {
private final List expList;
@@ -142,6 +143,16 @@ public NodeResolver toNodeResolver() {
return nodeResolver;
}
+ @Override
+ public List toNextNodePredicate() {
+ List nextNodePredicates = new ArrayList<>();
+ nextNodePredicates.add(StartNodePredicate.INSTANCE);
+ for (Exp exp : expList) {
+ nextNodePredicates.addAll(exp.toNextNodePredicates());
+ }
+ return nextNodePredicates;
+ }
+
private static final class ExpIndex implements Comparable {
public static final ExpIndex ALL_INDEX_EXP_INDEX = new ExpIndex(NO_OR_ALL_INDEX_INTEGER_VALUE);
@@ -225,24 +236,36 @@ public Exp(String expression) {
}
public NodeResolver toNodeResolver() {
- NodeResolver nodeResolver = IdentityNodeResolver.INSTANCE;
+ NodeResolver nodeResolver = new NodePredicateResolver(StartNodePredicate.INSTANCE);
if (!HEAD_NAME.equals(name)) {
nodeResolver = new CompositeNodeResolver(
nodeResolver,
- new DefaultNodeResolver(new PropertyNameNodePredicate(name))
+ new NodePredicateResolver(new PropertyNameNodePredicate(name))
);
}
for (ExpIndex index : indices) {
nodeResolver = new CompositeNodeResolver(
nodeResolver,
- new DefaultNodeResolver(new ContainerElementPredicate(index.getIndex()))
+ new NodePredicateResolver(new ContainerElementPredicate(index.getIndex()))
);
}
return nodeResolver;
}
+ public List toNextNodePredicates() {
+ List nextNodePredicates = new ArrayList<>();
+ if (!HEAD_NAME.equals(name)) {
+ nextNodePredicates.add(new PropertyNameNodePredicate(name));
+ }
+
+ for (ExpIndex index : indices) {
+ nextNodePredicates.add(new ContainerElementPredicate(index.getIndex()));
+ }
+ return nextNodePredicates;
+ }
+
public String getName() {
return name;
}
diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/MonkeyExpression.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/MonkeyExpression.java
index 8d834211e..658c9df08 100644
--- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/MonkeyExpression.java
+++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/expression/MonkeyExpression.java
@@ -18,13 +18,17 @@
package com.navercorp.fixturemonkey.expression;
+import java.util.List;
+
import org.apiguardian.api.API;
import org.apiguardian.api.API.Status;
+import com.navercorp.fixturemonkey.tree.NextNodePredicate;
import com.navercorp.fixturemonkey.tree.NodeResolver;
@API(since = "0.4.0", status = Status.MAINTAINED)
-@FunctionalInterface
public interface MonkeyExpression {
NodeResolver toNodeResolver();
+
+ List toNextNodePredicate();
}
diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/ApplyStrictModeResolver.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/ApplyStrictModeResolver.java
index bdb6381b6..6f5e1ee69 100644
--- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/ApplyStrictModeResolver.java
+++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/ApplyStrictModeResolver.java
@@ -23,6 +23,9 @@
import org.apiguardian.api.API;
import org.apiguardian.api.API.Status;
+/**
+ * A {@link NodeResolver} that applies strict mode.
+ */
@API(since = "0.4.0", status = Status.MAINTAINED)
public final class ApplyStrictModeResolver implements NodeResolver {
private final NodeResolver nodeResolver;
@@ -32,17 +35,12 @@ public ApplyStrictModeResolver(NodeResolver nodeResolver) {
}
@Override
- public List resolve(ObjectNode objectNode) {
- List selectedNodes = nodeResolver.resolve(objectNode);
+ public List resolve(ObjectNode nextNode) {
+ List selectedNodes = nodeResolver.resolve(nextNode);
if (selectedNodes.isEmpty()) {
throw new IllegalArgumentException("No matching results for given NodeResolvers.");
}
return selectedNodes;
}
-
- @Override
- public List toNextNodePredicate() {
- return nodeResolver.toNextNodePredicate();
- }
}
diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/CompositeNodeResolver.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/CompositeNodeResolver.java
index 482397d5d..df7ab63d1 100644
--- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/CompositeNodeResolver.java
+++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/CompositeNodeResolver.java
@@ -24,7 +24,6 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
-import java.util.stream.Collectors;
import org.apiguardian.api.API;
import org.apiguardian.api.API.Status;
@@ -42,9 +41,9 @@ public CompositeNodeResolver(List nodeResolvers) {
}
@Override
- public List resolve(ObjectNode objectNode) {
+ public List resolve(ObjectNode nextNode) {
LinkedList nextNodes = new LinkedList<>();
- nextNodes.add(objectNode);
+ nextNodes.add(nextNode);
for (NodeResolver nodeResolver : nodeResolvers) {
List resolvedNodes = new LinkedList<>();
while (!nextNodes.isEmpty()) {
@@ -83,9 +82,7 @@ private List distinct(List resolvers) {
NodeResolver resolver = resolvers.get(i);
if (resolver instanceof CompositeNodeResolver) {
CompositeNodeResolver compositeNodeResolver = (CompositeNodeResolver)resolver;
- List componentNodeResolvers = compositeNodeResolver.flatten().stream()
- .filter(it -> !(it instanceof IdentityNodeResolver))
- .collect(Collectors.toList());
+ List componentNodeResolvers = compositeNodeResolver.flatten();
result.add(new CompositeNodeResolver(componentNodeResolvers));
} else {
@@ -111,12 +108,4 @@ public boolean equals(Object obj) {
public int hashCode() {
return Objects.hash(nodeResolvers);
}
-
- @Override
- public List toNextNodePredicate() {
- return flatten().stream()
- .flatMap(it -> it.toNextNodePredicate().stream())
- .filter(Objects::nonNull)
- .collect(Collectors.toList());
- }
}
diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/DefaultNodeResolver.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/DefaultNodeResolver.java
deleted file mode 100644
index 56f995619..000000000
--- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/DefaultNodeResolver.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Fixture Monkey
- *
- * Copyright (c) 2021-present NAVER Corp.
- *
- * 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 com.navercorp.fixturemonkey.tree;
-
-import static com.navercorp.fixturemonkey.api.generator.DefaultNullInjectGenerator.NOT_NULL_INJECT;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.stream.Collectors;
-
-import org.apiguardian.api.API;
-import org.apiguardian.api.API.Status;
-
-@API(since = "0.4.0", status = Status.MAINTAINED)
-public final class DefaultNodeResolver implements NodeResolver {
- private final NextNodePredicate nextNodePredicate;
-
- public DefaultNodeResolver(NextNodePredicate nextNodePredicate) {
- this.nextNodePredicate = nextNodePredicate;
- }
-
- @Override
- public List resolve(ObjectNode objectNode) {
- objectNode.expand();
- List resolved = objectNode.getChildren().asList().stream()
- .filter(it -> nextNodePredicate.test(it.getArbitraryProperty().getObjectProperty()))
- .collect(Collectors.toList());
-
- objectNode.setNullInject(NOT_NULL_INJECT);
- for (ObjectNode node : resolved) {
- node.setNullInject(NOT_NULL_INJECT);
- }
-
- return resolved;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null || getClass() != obj.getClass()) {
- return false;
- }
- DefaultNodeResolver that = (DefaultNodeResolver)obj;
- return nextNodePredicate.equals(that.nextNodePredicate);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(nextNodePredicate);
- }
-
- @Override
- public List toNextNodePredicate() {
- return Collections.singletonList(nextNodePredicate);
- }
-}
diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/IdentityNodeResolver.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/IdentityNodeResolver.java
deleted file mode 100644
index 9c23b8b20..000000000
--- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/IdentityNodeResolver.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Fixture Monkey
- *
- * Copyright (c) 2021-present NAVER Corp.
- *
- * 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 com.navercorp.fixturemonkey.tree;
-
-import static com.navercorp.fixturemonkey.api.generator.DefaultNullInjectGenerator.NOT_NULL_INJECT;
-import static com.navercorp.fixturemonkey.api.type.Types.nullSafe;
-
-import java.util.Collections;
-import java.util.List;
-
-import org.apiguardian.api.API;
-import org.apiguardian.api.API.Status;
-
-import com.navercorp.fixturemonkey.api.property.SingleElementProperty;
-
-@API(since = "0.4.0", status = Status.MAINTAINED)
-public final class IdentityNodeResolver implements NodeResolver {
- public static final IdentityNodeResolver INSTANCE = new IdentityNodeResolver();
-
- private IdentityNodeResolver() {
- }
-
- @Override
- public List resolve(ObjectNode objectNode) {
- ObjectNode resultNode = getChildNodeIfWrapped(objectNode);
- resultNode.setNullInject(NOT_NULL_INJECT);
-
- return Collections.singletonList(resultNode);
- }
-
- private ObjectNode getChildNodeIfWrapped(ObjectNode objectNode) {
- ObjectNode searchNode = objectNode;
-
- while (isWrappedNode(searchNode)) {
- searchNode.expand();
- searchNode = nullSafe(searchNode.getChildren()).asList().get(0);
- }
-
- return searchNode;
- }
-
- private boolean isWrappedNode(ObjectNode searchNode) {
- searchNode.expand();
- List children = nullSafe(searchNode.getChildren()).asList();
-
- return children.size() == 1
- && children.get(0).getResolvedProperty() instanceof SingleElementProperty;
- }
-
- @Override
- public List toNextNodePredicate() {
- return Collections.singletonList(StartNodePredicate.INSTANCE);
- }
-}
diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodePredicateResolver.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodePredicateResolver.java
new file mode 100644
index 000000000..3cfe31bbf
--- /dev/null
+++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodePredicateResolver.java
@@ -0,0 +1,111 @@
+/*
+ * Fixture Monkey
+ *
+ * Copyright (c) 2021-present NAVER Corp.
+ *
+ * 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 com.navercorp.fixturemonkey.tree;
+
+import static com.navercorp.fixturemonkey.api.generator.DefaultNullInjectGenerator.NOT_NULL_INJECT;
+import static com.navercorp.fixturemonkey.api.type.Types.nullSafe;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+import org.apiguardian.api.API;
+import org.apiguardian.api.API.Status;
+
+import com.navercorp.fixturemonkey.api.property.SingleElementProperty;
+
+/**
+ * A {@link NodeResolver} that resolves the next nodes by the given {@link NextNodePredicate}.
+ */
+@API(since = "1.1.4", status = Status.EXPERIMENTAL)
+public final class NodePredicateResolver implements NodeResolver {
+ private final NextNodePredicate nextNodePredicate;
+
+ public NodePredicateResolver(NextNodePredicate nextNodePredicate) {
+ this.nextNodePredicate = nextNodePredicate;
+ }
+
+ /**
+ * Resolves the next nodes by the given {@link NextNodePredicate}.
+ * If the {@code nextNodePredicate} is {@link StartNodePredicate}, it resolves the given {@code nextNode}.
+ *
+ * @param nextNode it may be the root node or the parent node resolved by the previous NodeResolver
+ * @return the next nodes that satisfy the given {@link NextNodePredicate},
+ * or an empty list if there are no such nodes. {@link StartNodePredicate} always returns given {@code nextNode}.
+ */
+ @Override
+ public List resolve(ObjectNode nextNode) {
+ if (nextNodePredicate == StartNodePredicate.INSTANCE) {
+ return Collections.singletonList(resolveStartNode(nextNode));
+ }
+
+ nextNode.expand();
+ List resolved = nextNode.getChildren().asList().stream()
+ .filter(it -> nextNodePredicate.test(it.getArbitraryProperty().getObjectProperty()))
+ .collect(Collectors.toList());
+
+ nextNode.setNullInject(NOT_NULL_INJECT);
+ for (ObjectNode node : resolved) {
+ node.setNullInject(NOT_NULL_INJECT);
+ }
+
+ return resolved;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ NodePredicateResolver that = (NodePredicateResolver)obj;
+ return nextNodePredicate.equals(that.nextNodePredicate);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(nextNodePredicate);
+ }
+
+ public ObjectNode resolveStartNode(ObjectNode startNode) {
+ ObjectNode resultNode = getChildNodeIfWrapped(startNode);
+ resultNode.setNullInject(NOT_NULL_INJECT);
+
+ return resultNode;
+ }
+
+ private ObjectNode getChildNodeIfWrapped(ObjectNode objectNode) {
+ ObjectNode searchNode = objectNode;
+
+ searchNode.expand();
+ while (isWrappedNode(searchNode)) {
+ searchNode = nullSafe(searchNode.getChildren()).asList().get(0);
+ }
+
+ return searchNode;
+ }
+
+ private boolean isWrappedNode(ObjectNode searchNode) {
+ List children = nullSafe(searchNode.getChildren()).asList();
+
+ return children.size() == 1 && children.get(0).getResolvedProperty() instanceof SingleElementProperty;
+ }
+}
diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodeResolver.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodeResolver.java
index 3134f6360..e6a96fe85 100644
--- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodeResolver.java
+++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/NodeResolver.java
@@ -25,7 +25,11 @@
@API(since = "0.4.0", status = Status.MAINTAINED)
public interface NodeResolver {
- List resolve(ObjectNode objectNode);
-
- List toNextNodePredicate();
+ /**
+ * Resolves the next nodes. The nextNode can be omitted if it cannot be resolved from traversal.
+ *
+ * @param nextNode it may be the root node or the parent node resolved by the previous {@link NodeResolver}
+ * @return the next nodes
+ */
+ List resolve(ObjectNode nextNode);
}
diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/StaticNodeResolver.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/StaticNodeResolver.java
new file mode 100644
index 000000000..4cad5d99c
--- /dev/null
+++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/tree/StaticNodeResolver.java
@@ -0,0 +1,47 @@
+/*
+ * Fixture Monkey
+ *
+ * Copyright (c) 2021-present NAVER Corp.
+ *
+ * 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 com.navercorp.fixturemonkey.tree;
+
+import java.util.List;
+
+import org.apiguardian.api.API;
+import org.apiguardian.api.API.Status;
+
+/**
+ * A {@link NodeResolver} that resolves the provided nodes statically.
+ */
+@API(since = "1.1.4", status = Status.EXPERIMENTAL)
+public final class StaticNodeResolver implements NodeResolver {
+ private final List nodes;
+
+ public StaticNodeResolver(List nodes) {
+ this.nodes = nodes;
+ }
+
+ /**
+ * Resolves the next nodes statically. It always returns the provided nodes.
+ *
+ * @param nextNode it may be the root node or the parent node resolved by the previous {@link NodeResolver}
+ * @return the provided nodes statically
+ */
+ @Override
+ public List resolve(ObjectNode nextNode) {
+ return nodes;
+ }
+}