com.navercorp.fixturemonkey.ArbitraryBuilder Maven / Gradle / Ivy
/*
* 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;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import org.apiguardian.api.API;
import org.apiguardian.api.API.Status;
import net.jqwik.api.Arbitrary;
import net.jqwik.api.Combinators.F3;
import net.jqwik.api.Combinators.F4;
import com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitrary;
import com.navercorp.fixturemonkey.api.experimental.TypedPropertySelector;
import com.navercorp.fixturemonkey.api.instantiator.Instantiator;
import com.navercorp.fixturemonkey.api.property.PropertySelector;
import com.navercorp.fixturemonkey.api.type.TypeReference;
import com.navercorp.fixturemonkey.api.validator.ArbitraryValidator;
import com.navercorp.fixturemonkey.customizer.InnerSpec;
/**
* A builder instance for generating an instance of given type.
* A complex class could be built by given methods.
*
* @param type to generate
*/
@API(since = "0.4.0", status = Status.MAINTAINED)
public interface ArbitraryBuilder {
/**
* Set one or more properties referenced by expression to {@code value}.
*
* @param expression expression similar to Java syntax, including {@code .}, {@code []}
* common expression including {@code *} referencing properties.
* @param value various type of value including {@link Supplier}, {@link Arbitrary},
* {@link ArbitraryBuilder}, {@code NOT_NULL}, {@code null}.
* @return an {@link ArbitraryBuilder} whose properties referenced by an {@code expression} are set as
* {@code value}.
*/
ArbitraryBuilder set(String expression, @Nullable Object value);
/**
* Set the number of {@code limit} properties referenced by expression to {@code value}.
*
* @param expression expression similar to Java syntax, including {@code .}, {@code []}
* common expression including {@code *} referencing properties.
* @param value various type of value including {@link Supplier}, {@link Arbitrary},
* {@link ArbitraryBuilder}, {@code NOT_NULL}, {@code null}.
* @param limit the count of affected properties referenced by {@code expression}
* @return an {@link ArbitraryBuilder} whose properties referenced by an {@code expression} are
* set as {@code value}.
* @see ArbitraryBuilder#set(String, Object)
*/
ArbitraryBuilder set(String expression, @Nullable Object value, int limit);
/**
* Set one or more properties referenced by expression to {@code value}.
*
* @param propertySelector it selects one or more properties.
* @param value various type of value including {@link Supplier}, {@link Arbitrary},
* {@link ArbitraryBuilder}, {@code NOT_NULL}, {@code null}.
* @return an {@link ArbitraryBuilder} whose properties referenced by an {@code propertySelector}
* are set as {@code value}.
* @see ArbitraryBuilder#set(String, Object)
*/
ArbitraryBuilder set(PropertySelector propertySelector, @Nullable Object value);
/**
* Set one or more properties referenced by expression to {@code value}.
*
* @param propertySelector it selects one or more properties.
* @param value various type of value including {@link Supplier}, {@link Arbitrary},
* {@link ArbitraryBuilder}, {@code NOT_NULL}, {@code null}.
* @param limit the count of affected properties referenced by {@code expression}
* @return an {@link ArbitraryBuilder} whose properties referenced by an {@code propertySelector} are set as
* {@code value}.
* @see ArbitraryBuilder#set(String, Object, int)
*/
ArbitraryBuilder set(PropertySelector propertySelector, @Nullable Object value, int limit);
/**
* Set the {@link ArbitraryBuilder} sampling given {@code value}.
* It is same as {@code set("$", value)}
*
* @param value various type of value including {@link Supplier}, {@link Arbitrary},
* {@link ArbitraryBuilder}, {@code NOT_NULL}, {@code null}.
* @return ArbitraryBuilder is set as {@code value}.
* @see ArbitraryBuilder#set(String, Object)
*/
ArbitraryBuilder set(@Nullable Object value);
/**
* Apply one or more manipulations defined in {@link InnerSpec}.
*
* @param innerSpec a type-independent specification of manipulators
* @return an {@link ArbitraryBuilder} applied the manipulators in {@link InnerSpec}
*/
ArbitraryBuilder setInner(InnerSpec innerSpec);
/**
* Set one or more properties referenced by expression to a result of {@link Supplier}.
* The {@link Supplier} gets the result when manipulation is executed.
* It might be used when to set the latest value or set unique id generated sequentially.
*
* @param expression expression similar to Java syntax, including {@code .}, {@code []}
* common expression including {@code *} referencing properties.
* @param supplier a supplier of result. It might be a value or method.
* @return an {@link ArbitraryBuilder} whose properties referenced by an {@code propertySelector} are set as
* {@code value}.
* @see ArbitraryBuilder#set(String, Object, int)
*/
ArbitraryBuilder setLazy(String expression, Supplier> supplier);
/**
* Set the number of {@code limit} properties referenced by expression to a result of {@link Supplier}.
* The {@link Supplier} gets the result when manipulation is executed.
* It might be used when to set the latest value or set unique id generated sequentially.
*
* @param expression expression similar to Java syntax, including {@code .}, {@code []}
* common expression including {@code *} referencing properties.
* @param supplier a supplier of result. It might be a value or method.
* @param limit the count of affected properties referenced by {@code expression}
* @return an {@link ArbitraryBuilder} whose properties referenced by an {@code expression} are set as
* {@code value}.
* @see ArbitraryBuilder#set(String, Object, int)
*/
ArbitraryBuilder setLazy(String expression, Supplier> supplier, int limit);
/**
* Set one or more properties referenced by expression to a result of {@link Supplier}.
* The {@link Supplier} gets the result when manipulation is executed.
* It might be used when to set the latest value or set unique id generated sequentially.
*
* @param propertySelector it selects one or more properties.
* @param supplier a supplier of result. It might be a value or method.
* @return an {@link ArbitraryBuilder} whose properties referenced by an {@code propertySelector} are set as
* {@code value}.
* @see ArbitraryBuilder#set(String, Object)
*/
ArbitraryBuilder setLazy(PropertySelector propertySelector, Supplier> supplier);
/**
* Set the number of {@code limit} properties referenced by expression to a result of {@link Supplier}.
* The {@link Supplier} gets the result when manipulation is executed.
* It might be used when to set the latest value or set unique id generated sequentially.
*
* @param propertySelector it selects one or more properties.
* @param supplier a supplier of result. It might be a value or method.
* @param limit the count of affected properties referenced by {@code expression}
* @return an {@link ArbitraryBuilder} whose properties referenced by an {@code propertySelector} are set as
* {@code value}.
* @see ArbitraryBuilder#set(String, Object, int)
*/
ArbitraryBuilder setLazy(PropertySelector propertySelector, Supplier> supplier, int limit);
/**
* Set one or more properties referenced by expression to null.
* If a manipulation you've already declared contains an {@code expression}, this manipulation would be omitted.
* It is same as {@code set(expression, null)}.
*
* @param expression expression similar to Java syntax, including {@code .}, {@code []}
* common expression including {@code *} referencing properties.
* @return an {@link ArbitraryBuilder} whose properties referenced by an {@code expression} are set as null.
*/
ArbitraryBuilder setNull(String expression);
/**
* Set one or more properties referenced by expression to null.
* If a manipulation you've already declared contains an {@code expression}, this manipulation would be omitted.
* It is same as {@code set(expression, null)}.
*
* @param propertySelector it selects one or more properties.
* @return an {@link ArbitraryBuilder} whose properties referenced by an {@code propertySelector}
* are set as null.
*/
ArbitraryBuilder setNull(PropertySelector propertySelector);
/**
* Set one or more properties referenced by expression to not null.
* If the properties are null, they are generated randomly for their type.
* It is same as {@code set(expression, NOT_NULL)}.
*
* @param expression expression similar to Java syntax, including {@code .}, {@code []}
* common expression including {@code *} referencing properties.
* @return an {@link ArbitraryBuilder} whose properties referenced by an {@code expression} are set as not null.
*/
ArbitraryBuilder setNotNull(String expression);
/**
* Set one or more properties referenced by expression to not null.
* If the properties are null, they are generated randomly for their type.
* It is same as {@code set(expression, NOT_NULL)}.
*
* @param propertySelector it selects one or more properties.
* @return an {@link ArbitraryBuilder} whose properties referenced by an {@code propertySelector} are set as
* not null.
*/
ArbitraryBuilder setNotNull(PropertySelector propertySelector);
/**
* Set one or more properties referenced by expression post-condition.
*
* @param the type of property.
* @param expression expression similar to Java syntax, including {@code .}, {@code []}
* common expression including {@code *} referencing properties.
* @param type the type of property.
* @param predicate determines the post-condition of properties.
* @return an {@link ArbitraryBuilder} whose properties referenced by an {@code expression}
* satisfy the post-condition.
*/
ArbitraryBuilder setPostCondition(String expression, Class type, Predicate predicate);
/**
* Set one or more properties referenced by expression post-condition.
*
* @param the type of property.
* @param propertySelector it selects one or more properties.
* @param type the type of property.
* @param predicate determines the post-condition of properties.
* @return an {@link ArbitraryBuilder} whose properties referenced by an {@code propertySelector}
* satisfy the post-condition.
*/
ArbitraryBuilder setPostCondition(
PropertySelector propertySelector,
Class type,
Predicate predicate
);
/**
* Set the number of {@code limit} properties referenced by expression post-condition.
*
* @param the type of property.
* @param expression expression similar to Java syntax, including {@code .}, {@code []}
* common expression including {@code *} referencing properties.
* @param type the type of property.
* @param predicate determines the post-condition of properties.
* @param limit the count of affected properties referenced by {@code expression}
* @return an {@link ArbitraryBuilder} whose properties referenced by an {@code expression} satisfy
* the post-condition.
*/
ArbitraryBuilder setPostCondition(
String expression,
Class type,
Predicate predicate,
int limit
);
/**
* Set the number of {@code limit} properties referenced by expression post-condition.
*
* @param the type of property.
* @param propertySelector it selects one or more properties.
* @param type the type of property.
* @param predicate determines the post-condition of properties.
* @param limit the count of affected properties referenced by {@code propertySelector}
* @return an {@link ArbitraryBuilder} whose properties referenced by an {@code propertySelector}
* satisfy the post-condition.
*/
ArbitraryBuilder setPostCondition(
PropertySelector propertySelector,
Class type,
Predicate predicate,
int limit
);
/**
* Set the {@link ArbitraryBuilder} post-condition.
* It is same as {@code setPostCondition("$", Class, Predicate)}
*
* @param predicate determines the post-condition of the {@link ArbitraryBuilder}.
* @return an {@link ArbitraryBuilder} whose properties referenced by an {@code propertySelector}
* satisfy the post-condition.
* @see ArbitraryBuilder#setPostCondition(String, Class, Predicate)
*/
ArbitraryBuilder setPostCondition(Predicate predicate);
/**
* Set the {@code size} of one or more container properties referenced by expression.
*
* @param expression expression similar to Java syntax, including {@code .}, {@code []}
* common expression including {@code *} referencing properties.
* @param size of the container to generate
* @return {@link ArbitraryBuilder} whose size of container properties referenced by an {@code expression} is
* {@code size}
*/
ArbitraryBuilder size(String expression, int size);
/**
* Set the {@code size} of one or more container properties referenced by expression.
*
* @param propertySelector it selects one or more properties.
* @param size of the container to generate
* @return {@link ArbitraryBuilder} whose size of container properties referenced by an {@code expression} is
* {@code size}
*/
ArbitraryBuilder size(PropertySelector propertySelector, int size);
/**
* Set the size of one or more container properties referenced by expression.
* {@code minSize} should be less than or equal to {@code maxSize}.
*
* @param expression expression similar to Java syntax, including {@code .}, {@code []}
* common expression including {@code *} referencing properties.
* @param minSize of the container to generate
* @param maxSize of the container to generate
* @return an {@link ArbitraryBuilder} whose size of container properties referenced by an {@code expression} is
* between {@code minSize} and {@code maxSize}.
*/
ArbitraryBuilder size(String expression, int minSize, int maxSize);
/**
* Set the size of one or more container properties referenced by expression.
* {@code minSize} should be less than or equal to {@code maxSize}.
*
* @param propertySelector it selects one or more properties.
* @param minSize of the container to generate
* @param maxSize of the container to generate
* @return an {@link ArbitraryBuilder} whose size of container properties referenced by an {@code expression} is
* between {@code minSize} and {@code maxSize}.
*/
ArbitraryBuilder size(PropertySelector propertySelector, int minSize, int maxSize);
/**
* Set the size of one or more container properties referenced by expression.
* The size of container properties would be between {@code minSize} and
* {@code minSize} + {@link Constants#DEFAULT_ELEMENT_MAX_SIZE}
*
* It would conflict with {@link ArbitraryBuilder#maxSize(String, int)}.
* The last executed manipulation would set the size of properties.
*
* It is same as {@code size(minSize, minSize + DEFAULT_ELEMENT_MAX_SIZE)}.
*
* @param expression expression similar to Java syntax, including {@code .}, {@code []}
* common expression including {@code *} referencing properties.
* @param minSize of the container to generate
* @return an {@link ArbitraryBuilder} whose size of container properties referenced by an {@code expression}
* is between {@code minSize} and {@code minSize} + {@link Constants#DEFAULT_ELEMENT_MAX_SIZE}.
*/
ArbitraryBuilder minSize(String expression, int minSize);
/**
* Set the size of one or more container properties referenced by expression.
* The size of container properties would be between {@code minSize} and
* {@code minSize} + {@link Constants#DEFAULT_ELEMENT_MAX_SIZE}
*
* It would conflict with {@link ArbitraryBuilder#maxSize(String, int)}.
* The last executed manipulation would set the size of properties.
*
* It is same as {@code size(minSize, minSize + DEFAULT_ELEMENT_MAX_SIZE)}.
*
* @param propertySelector it selects one or more properties.
* @param minSize of the container to generate
* @return an {@link ArbitraryBuilder} whose size of container properties referenced by
* an {@code propertySelector} is between {@code minSize}
* and {@code minSize} + {@link Constants#DEFAULT_ELEMENT_MAX_SIZE}.
*/
ArbitraryBuilder minSize(PropertySelector propertySelector, int minSize);
/**
* Set the size of one or more container properties referenced by expression.
* The size of container properties would be between
* max(0, {@code maxSize} - {@link Constants#DEFAULT_ELEMENT_MAX_SIZE})
* and {@code maxSize}
*
* It would conflict with {@link ArbitraryBuilder#minSize(String, int)}.
* The last executed manipulation would set the size of properties.
*
* It is same as {@code size(expression, Math.max(0, maxSize - DEFAULT_ELEMENT_MAX_SIZE), maxSize)}.
*
* @param expression expression similar to Java syntax, including {@code .}, {@code []}
* common expression including {@code *} referencing properties.
* @param maxSize of the container to generate
* @return an {@link ArbitraryBuilder} whose size of container properties referenced by an {@code expression} is
* max(0, {@code maxSize} - {@link Constants#DEFAULT_ELEMENT_MAX_SIZE})
* and {@code maxSize}
*/
ArbitraryBuilder maxSize(String expression, int maxSize);
/**
* Set the size of one or more container properties referenced by expression.
* The size of container properties would be between
* max(0, {@code maxSize} - {@link Constants#DEFAULT_ELEMENT_MAX_SIZE}) and {@code maxSize}
*
* It would conflict with {@link ArbitraryBuilder#minSize(String, int)}.
* The last executed manipulation would set the size of properties.
*
* It is same as {@code size(expression, Math.max(0, maxSize - DEFAULT_ELEMENT_MAX_SIZE), maxSize)}
*
* @param propertySelector it selects one or more properties.
* @param maxSize of the container to generate
* @return {@link ArbitraryBuilder} whose size of container properties referenced by
* an {@code propertySelector} is max(0, {@code maxSize} - {@link Constants#DEFAULT_ELEMENT_MAX_SIZE})
* and {@code maxSize}
*/
ArbitraryBuilder maxSize(PropertySelector propertySelector, int maxSize);
ArbitraryBuilder thenApply(BiConsumer> biConsumer);
ArbitraryBuilder acceptIf(Predicate predicate, Consumer> consumer);
/**
* Makes {@link ArbitraryBuilder} always sample an equivalent instance.
* All manipulations after {@link #fixed()} would work.
*
* @return a new {@link ArbitraryBuilder} always samples an equivalent instance
*/
ArbitraryBuilder fixed();
/**
* Transforms an instance by applying function to it.
*
* @param mapper the transforming {@link Function}
* @param type to transform
* @return a new {@link ArbitraryBuilder}
*/
ArbitraryBuilder map(Function mapper);
/**
* Combine the result from this {@link ArbitraryBuilder} and another into a new {@link ArbitraryBuilder}
*
* @param other the {@link ArbitraryBuilder} to combine with
* @param combinator a {@link BiFunction} combinator function
* @param the element type of other {@link ArbitraryBuilder}
* @param the element type of the combination
* @return a new combined {@link ArbitraryBuilder}
*/
ArbitraryBuilder zipWith(ArbitraryBuilder other, BiFunction combinator);
/**
* Combine the result from this {@link ArbitraryBuilder} and other and another into a new {@link ArbitraryBuilder}
*
* @param other the {@link ArbitraryBuilder} to combine with
* @param combinator a {@link BiFunction} combinator function
* @param the element type of other {@link ArbitraryBuilder}
* @param the element type of another {@link ArbitraryBuilder}
* @param the element type of the combination
* @return a new combined {@link ArbitraryBuilder}
*/
ArbitraryBuilder zipWith(
ArbitraryBuilder other,
ArbitraryBuilder another,
F3 combinator
);
/**
* Combine the result from this {@link ArbitraryBuilder} and other and another and the other into
* a new {@link ArbitraryBuilder}
*
* @param other the {@link ArbitraryBuilder} to combine with
* @param combinator a {@link BiFunction} combinator function
* @param the element type of other {@link ArbitraryBuilder}
* @param the element type of another {@link ArbitraryBuilder}
* @param the element type of the other {@link ArbitraryBuilder}
* @param the element type of the combination
* @return a new combined {@link ArbitraryBuilder}
*/
ArbitraryBuilder zipWith(
ArbitraryBuilder other,
ArbitraryBuilder another,
ArbitraryBuilder theOther,
F4 combinator
);
/**
* Combine the result from this {@link ArbitraryBuilder} and others into
* a new {@link ArbitraryBuilder}
*
* @param others the list of {@link ArbitraryBuilder} to combine with
* @param combinator a {@link BiFunction} combinator function
* @param the element type of the combination
* @return a new combined {@link ArbitraryBuilder}
*/
ArbitraryBuilder zipWith(
List> others,
Function, R> combinator
);
/**
* Build {@link ArbitraryBuilder} into {@link Arbitrary} for using various support methods
* provided in {@link Arbitrary}
*
* @return an {@link Arbitrary} built by {@link ArbitraryBuilder}
*/
Arbitrary build();
/**
* Generate a single sample value using this {@link ArbitraryBuilder}.
* It might generate differently per sample unless executing {@link #fixed()}.
*
* @return a generated instance
*/
T sample();
/**
* Generate sample value list using this {@link ArbitraryBuilder}.
* All elements might generate differently per sample unless executing {@link #fixed()}.
*
* @return a list of generated instances
*/
List sampleList(int size);
/**
* Generate sample value stream using this {@link ArbitraryBuilder}.
* All elements might generate differently per sample unless executing {@link #fixed()}.
*
* @return a stream of generated instances
*/
Stream sampleStream();
/**
* Copy an {@link ArbitraryBuilder} instance. All manipulations would be copied.
*
* @return a copied {@link ArbitraryBuilder}
*/
ArbitraryBuilder copy();
/**
* Determine if only samples a valid instance or not.
* Default {@code validOnly} is true.
*
* @param validOnly determines generating only valid instance
* @return If true, returned {@link ArbitraryBuilder} would sample a valid instance validated by
* the {@link ArbitraryValidator}.
* If false, returned {@link ArbitraryBuilder} would sample an instance regardless of
* the {@link ArbitraryValidator}.
*/
ArbitraryBuilder validOnly(boolean validOnly);
ArbitraryBuilder instantiate(Instantiator instantiator);
ArbitraryBuilder instantiate(Class> type, Instantiator instantiator);
ArbitraryBuilder instantiate(TypeReference> type, Instantiator instantiator);
/**
* Customizes the arbitrary value generated from selected properties.
* It can be called several times and nested. It has an order dependency.
*
* Without any set APIs, it customizes the arbitrary value.
* With set APIs, it customizes the last value in set APIs.
*
* @param propertySelector the property selector with type
* @param combinableArbitraryCustomizer
* @param the type of the properties selected by {@code propertySelector}.
* @return a customized {@link ArbitraryBuilder}
*/
@API(since = "1.0.9", status = Status.MAINTAINED)
ArbitraryBuilder customizeProperty(
TypedPropertySelector propertySelector,
Function, CombinableArbitrary extends U>> combinableArbitraryCustomizer
);
}