Skip to content
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
97 changes: 61 additions & 36 deletions src/main/java/ru/objectsfill/core/RandomValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,22 @@
import static ru.objectsfill.utils.FieldUtils.getObjectUnaryOperator;

/**
The RandomValue class is designed to populate POJO classes with random data.
* Main entry point for populating POJO classes with random data.
* Provides static methods for filling single objects, collections, arrays, and streams.
*
* <p>Basic usage:
* <pre>{@code
* MyClass obj = RandomValue.fill(MyClass.class);
* }</pre>
*
* <p>Advanced usage with {@link Fill} builder:
* <pre>{@code
* MyClass obj = RandomValue.fill(
* Fill.object(MyClass.class)
* .collectionSize(10)
* .valueLength(15)
* .gen());
* }</pre>
*/
public final class RandomValue {

Expand All @@ -23,11 +38,11 @@ private RandomValue() {
}

/**

Fills the given object with random values.
@param fill The object containing all the information about the target object.
@param <T> The type of the target object.
@return The filled object.
* Fills the given object with random values using the provided configuration.
*
* @param fill the configuration object describing the target object and generation parameters
* @param <T> the type of the target object
* @return the filled object
*/
@SuppressWarnings("unchecked")
public static <T> T fill(Fill fill) {
Expand All @@ -36,34 +51,39 @@ public static <T> T fill(Fill fill) {
}

/**
Fills the given object with random values shorter.
@param object The object to create fill.
@param <T> The type of the target object.
@return The filled object.
* Fills the given object instance with random values using default parameters.
*
* @param object the object instance to fill
* @param <T> the type of the target object
* @return the filled object
*/
public static <T> T fill(Object object) {
Fill gen = Fill.object(object).gen();
return fill(gen);
}

/**
Fills the given object with random values shorter.
@param clazz The class to create fill.
@param <T> The type of the target object.
@return The filled object.
* Creates a new instance of the given class and fills it with random values using default parameters.
*
* @param clazz the class to instantiate and fill
* @param <T> the type of the target object
* @return the filled object
*/
public static <T> T fill(Class<?> clazz) {
Fill gen = Fill.object(clazz).gen();
return fill(gen);
}

/**

Fills the given collection with random values.
@param collection The collection type for populating.
@param fill The object containing all the information about the target collection.
@param <T> The type of the collection.
@param <K> The type of the elements in the collection.
* Populates the given collection with randomly generated elements.
* The number of elements is determined by {@link Fill#getCollectionSize()}.
* If a mutation function is configured via {@link ru.objectsfill.object_param.Extend#wrapByFunction},
* each generated element is transformed through it before being added.
*
* @param collection the collection to populate
* @param fill the configuration describing the element type and generation parameters
* @param <T> the collection type
* @param <K> the type of elements in the collection
*/
@SuppressWarnings({"unchecked", "unused"})
public static <T extends Collection<K>, K> void fillCollection(T collection, Fill fill) {
Expand All @@ -73,18 +93,20 @@ public static <T extends Collection<K>, K> void fillCollection(T collection, Fil
for (int i = 0; i < fill.getCollectionSize(); i++) {
Object o = mutationFunction.apply(new ElementCreationService().generateSingleValue(fill.getClazz(), fill));

if (o.getClass().isAssignableFrom(fill.getClazz())) {
if (fill.getClazz().isAssignableFrom(o.getClass())) {
collection.add((K) o);
}
}
}

/**

Fills the given collection with random values.
@param fill The object containing all the information about the target collection.
@param <K> The type of stream
@return not closed stream
* Creates a stream of randomly generated elements.
* The stream size is determined by {@link Fill#getCollectionSize()}.
* If a mutation function is configured, each element is transformed through it.
*
* @param fill the configuration describing the element type and generation parameters
* @param <K> the type of stream elements
* @return a finite stream of randomly generated elements
*/
@SuppressWarnings({"unchecked", "unused"})
public static <K> Stream<K> fillStream(Fill fill) {
Expand All @@ -95,30 +117,33 @@ public static <K> Stream<K> fillStream(Fill fill) {
for (int i = 0; i < fill.getCollectionSize(); i++) {
Object o = mutationFunction.apply(new ElementCreationService().generateSingleValue(fill.getClazz(), fill));

if (o.getClass().isAssignableFrom(fill.getClazz())) {
if (fill.getClazz().isAssignableFrom(o.getClass())) {
listForStream.add((K) o);
}
}
return listForStream.stream();
}

/**
Creates and fills an array with random values.
@param fill The object containing all the information about the target array.
@param <T> The type of the elements in the array.
@return The filled array.
* Creates and fills an array with randomly generated elements.
* The array size is determined by {@link Fill#getCollectionSize()}.
*
* @param fill the configuration describing the element type and generation parameters
* @param <T> the component type of the array
* @return the filled array
*/
@SuppressWarnings({"unchecked", "unused"})
public static <T> T[] fillArray(Fill fill) {
return (T[]) new FillArray().createArray(fill.getClazz(), fill);
}

/**

Generates a single random value.
@param fill The object containing all the information about the target value.
@param <K> The type of the value.
@return The generated value.
* Generates a single random value of the type specified in the {@link Fill} configuration.
* If a mutation function is configured, the generated value is transformed through it.
*
* @param fill the configuration describing the value type and generation parameters
* @param <K> the type of the generated value
* @return the generated value
*/
@SuppressWarnings({"unchecked", "unused"})
public static <K> K fillSingleVal(Fill fill) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,25 @@
import static ru.objectsfill.types.primitive_type.PrimitiveTypeName.*;

/**
* A necessary class for reflection to traverse fields.
* Callback that populates each field of an object with a randomly generated value during reflection traversal.
* Handles field exclusion, extended per-field parameters, and primitive array special-casing.
*/
public record RandomValueFieldSetterCallback(Fill fill) implements FieldCallback {

/**
* Function to check excluded fields.
* Curried function that checks whether a field is not in the excluded field list.
*/
private static final Function<Field, Function<Fill, Boolean>> checkExcludedName =
checkField ->
fillObjectParam ->
!fillObjectParam.getExcludedField().contains(checkField.getName());

/**
* Overrides the method for field traversal.
* Processes a single field: skips final and excluded fields, applies extended parameters if present,
* and delegates to the appropriate generation method.
*
* @param field The field to process.
* @throws IllegalAccessException If the field is inaccessible.
* @param field the field to populate
* @throws IllegalAccessException if the field cannot be accessed via reflection
*/
@Override
public void doWith(Field field) throws IllegalAccessException {
Expand All @@ -54,10 +56,11 @@ public void doWith(Field field) throws IllegalAccessException {


/**
* split field fill
* Generates a value for the field using the default (unmodified) {@link Fill} parameters.
* If the field is a primitive array, delegates to {@link PrimitiveTypeName} for specialized handling.
*
* @param field The field to process.
* @throws IllegalAccessException If the field is inaccessible.
* @param field the field to populate
* @throws IllegalAccessException if the field cannot be accessed via reflection
*/
private void generateWithNoFillChange(Field field) throws IllegalAccessException {
Class<?> type = getTypeClass(field, fill);
Expand All @@ -77,10 +80,12 @@ private void generateWithNoFillChange(Field field) throws IllegalAccessException
}

/**
* split field fill
* Generates a value for the field using the given {@link Fill} configuration
* and sets it on the target object via reflection.
*
* @param field The field to process.
* @throws IllegalAccessException If the field is inaccessible.
* @param field the field to populate
* @param extendedParameterForField the {@link Fill} configuration (possibly with per-field overrides)
* @throws IllegalAccessException if the field cannot be accessed via reflection
*/
private void generateExtendedValue(Field field, Fill extendedParameterForField) throws IllegalAccessException {

Expand All @@ -93,9 +98,11 @@ private void generateExtendedValue(Field field, Fill extendedParameterForField)
}

/**
* split field fill
* Builds a new {@link Fill} with per-field overrides (collection size, value length)
* from the matching {@link Extend} parameter, if one exists for the given field.
*
* @param field The field to process.
* @param field the field to look up in the extended parameters list
* @return an {@link Optional} containing the customized {@link Fill}, or empty if no match
*/
private Optional<Fill> getExtendedParameterForField(Field field) {

Expand All @@ -106,7 +113,7 @@ private Optional<Fill> getExtendedParameterForField(Field field) {
.excludeField(fill.getExcludedField())
.fieldParams(fill.getExtendedFieldParams())
.collectionSize(Optional.ofNullable(extendedFieldParameter.getCollectionSize()).orElse(fill.getCollectionSize()))
.valueLength(Optional.ofNullable(extendedFieldParameter.getValueLength()).orElse(fill.getCollectionSize()))
.valueLength(Optional.ofNullable(extendedFieldParameter.getValueLength()).orElse(fill.getValueLength()))
.setDeep(fill.getDeep())
.withGeneric(fill.getGenericType())
.gen()
Expand All @@ -115,10 +122,11 @@ private Optional<Fill> getExtendedParameterForField(Field field) {
}

/**
* get fields by class or name
* Returns a predicate that matches an {@link Extend} parameter to a field
* either by field name or by assignable class type.
*
* @param field The field to process.
* @return get fields by class or name
* @param field the field to match against
* @return a predicate for filtering {@link Extend} parameters
*/
public static Predicate<Extend> getExtendPredicate(Field field) {
return fillFieldParameter -> {
Expand Down
15 changes: 10 additions & 5 deletions src/main/java/ru/objectsfill/functions/BinaryFunction.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
package ru.objectsfill.functions;

/**
* binary operator function
* A two-argument functional interface that performs an operation and returns no result.
* Used for field-level operations that may require reflective access.
*
* @param <T> the type of the first argument
* @param <R> the type of the second argument
*/
@FunctionalInterface
public interface BinaryFunction<T, R> {

/**
* binary operator function
* @param t first argument
* @param r second argument
* @throws IllegalAccessException add ex for function
* Applies this function to the given arguments.
*
* @param t the first argument
* @param r the second argument
* @throws IllegalAccessException if reflective field access is denied
*/
void apply(T t, R r) throws IllegalAccessException;
}
Loading
Loading