All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.instancio.Assign Maven / Gradle / Ivy

/*
 * Copyright 2022-2024 the original author or authors.
 *
 * 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
 *
 *      https://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 org.instancio;

import org.instancio.documentation.ExperimentalApi;
import org.instancio.internal.ApiValidator;
import org.instancio.internal.assignment.InternalGivenOrigin;
import org.instancio.internal.assignment.InternalGivenOriginDestinationAction;
import org.instancio.internal.assignment.InternalValueOf;

/**
 * A collection of static factory methods for creating assignments.
 *
 * @see Assignment
 * @see InstancioApi#assign(Assignment...)
 * @since 3.0.0
 */
@ExperimentalApi
public final class Assign {

    /**
     * Creates an assignment builder with a given {@code target} selector.
     * This builder provides two options:
     *
     * 
    *
  1. Assign value directly to the {@code target}
  2. *
  3. Assign value of the {@code target} to another selector
  4. *
* *

1. Assign to {@code target}

* *

The first option is to assign a value directly to the {@code target} * using {@code set()}, {@code supply()}, or {@code generate()} methods. * *

Example: * *

{@code
     * Assignment personName = Assign.valueOf(Person::getName).set("Homer Simpson");
     *
     * Person person = Instancio.of(Person.class)
     *     .assign(personName)
     *     .create();
     * }
* *

This sets the {@code Person.name} field to "Homer Simpson". * The above snippet is equivalent to: * *

{@code
     * Person person = Instancio.of(Person.class)
     *     .set(Select.field(Person::getName), "Homer Simpson")
     *     .create();
     * }
* *

The difference is that {@link InstancioApi#assign(Assignment...)} * allows passing multiple assignments dynamically to the method since * it accepts a vararg. This provides more flexibility when creating * objects in different states. * *

2. Assign {@code target} to another selector

* *

The second variant of the builder allows assigning the value of * the {@code target} to a destination selector: * *

{@code
     * Assign.valueOf(origin).to(destination)
     * }
* *

The value can be assigned as is, or mapped to another value * using the {@code as(Function)} method: * *

Example: *

{@code
     * Assignment assignment = Assign.valueOf(field(Address::getCountryCode))
     *      .to(field(Address::getCountryName))
     *      .as((String countryCode) -> getCountryName(countryCode));
     * }
* * @param target the selector * @return builder for constructing an assignment * @see #valueOf(GetMethodSelector) * @see #valueOf(Class) * @since 3.0.0 */ @ExperimentalApi public static ValueOf valueOf(final TargetSelector target) { return new InternalValueOf(target); } /** * Creates an assignment for a given target {@code type}. * This is a shorthand API of {@link #valueOf(TargetSelector)} allowing: * *
{@code
     * Assign.valueOf(all(Integer.class))
     * }
* *

to be specified as a slightly shorter version: * *

{@code
     * Assign.valueOf(Integer.class)
     * }
* * @param target the type of the target's value * @param the type of value * @return builder for constructing an assignment * @see #valueOf(TargetSelector) * @since 3.0.0 */ @ExperimentalApi public static ValueOf valueOf(final Class target) { return new InternalValueOf(Select.all(target)); } /** * Creates an assignment for a given {@code target} method reference. * This is a shorthand API of {@link #valueOf(TargetSelector)} allowing: * *
{@code
     * Assign.valueOf(field(Pojo::getValue))
     * }
* *

to be specified as a slightly shorter version: * *

{@code
     * Assign.valueOf(Pojo::getValue)
     * }
* * @param target the method reference for the target field * @param type declaring the method * @param return type of the method * @return builder for constructing an assignment * @see #valueOf(TargetSelector) * @since 3.0.0 */ @ExperimentalApi public static ValueOf valueOf(final GetMethodSelector target) { return new InternalValueOf(Select.field(target)); } /** * Creates a conditional assigment for a given pair of {@code origin} and * {@code destination} selectors. This method allows mapping predicates * to destination values, and also supports {@code else} semantics with * the following syntax: * *
{@code
     * Assign.given(origin, destination)
     *     .set(originPredicate1, "value1")
     *     .set(originPredicate2, "value2")
     *     .supply(originPredicate3, () -> getValue3())
     *     .generate(originPredicate4, gen -> gen.oneOf("value4A", "value4B"))
     *     .elseSet("other-value");
     * }
* *

A destination will be set to a given value only if the corresponding * predicate is satisfied. If none of the predicates match, the value from * the {@code else} branch will be set. Note that the {@code else} branch is * optional. If it is not specified, a random value will be generated * when none of the predicates match. * *

Example: *

{@code
     * Assignment phoneCountryCode = Assign.given(field(Address::getCountry), field(Phone::getCountryCode))
     *     .set(When.isIn("Canada", "USA"), "+1")
     *     .set(When.is("Italy"), "+39")
     *     .set(When.is("Poland"), "+48")
     *     .set(When.is("Germany"), "+49")
     *     .elseSupply(() -> Assertions.fail("unexpected country"));
     *
     * Person person = Instancio.of(Person.class)
     *     .generate(field(Address::getCountry), gen -> gen.oneOf("Canada", "Germany", "Italy", "Poland", "USA"))
     *     .assign(phoneCountryCode)
     *     .create();
     * }
* *

In the above example, the generated country names should match one * of the assignment predicates, therefore the assertion failure in * {@code elseSupply()} should not be reachable, and could be omitted. * * @param origin selector whose target the origin predicate * will be evaluated against * @param destination selector whose targets will be set to a * given value if the origin predicate is satisfied * @return builder for constructing a conditional assignment * @see #given(TargetSelector) * @since 3.0.0 */ @ExperimentalApi public static GivenOriginDestination given(final TargetSelector origin, final TargetSelector destination) { ApiValidator.validateAssignmentOrigin(origin); return new InternalGivenOriginDestinationAction(origin, destination); } /** * Creates a conditional for a given {@code origin} and one or more * {@code destination} selectors. This method allows mapping an origin * to different destinations, but unlike * {@link #given(TargetSelector, TargetSelector)} this method does not * support {@code else} semantics: * *

{@code
     * Assign.given(origin)
     *     .is("foo")
     *     .set(destination1, "value1")
     *     .set(destination2, "value2")
     *     .supply(destination3, () -> getValue3())
     *     .generate(destination4, gen -> gen.oneOf("value4A", "value4B"));
     * }
* *

All destinations will be set to the corresponding values if the predicate * is satisfied. * *

Example: *

{@code
     * Assignment orderFields = Assign.given(Order::getStatus)
     *     .is(OrderStatus.CANCELLED)
     *     .set(field(Order::getCancellationReason), "Shipping delays")
     *     .generate(field(Order::getCancellationDate), gen -> gen.temporal().localDate().past());
     *
     * List orders = Instancio.ofList(Order.class)
     *     .size(20)
     *     .assign(orderFields)
     *     .create();
     * }
* *

The above snippet will generate a list of random orders. If an order * with a {@code CANCELLED} status is generated, the order will have * the expected values as specified by the assignment. It is possible * to specify different values for other order statuses. Since the example * above does not specify this, for all other order statuses, random values * will be generated. * * @param origin selector whose target the origin predicate will be evaluated against * @return builder for constructing a conditional assignment * @see #given(TargetSelector, TargetSelector) * @see #given(Class) * @see #given(GetMethodSelector) * @since 3.0.0 */ @ExperimentalApi public static GivenOrigin given(final TargetSelector origin) { ApiValidator.validateAssignmentOrigin(origin); return new InternalGivenOrigin(origin); } /** * Creates a conditional assignment for a given {@code origin} method * reference and one or more {@code destination} selectors. This is * a shorthand API of {@link #given(TargetSelector)} allowing: * *

{@code
     * Assign.given(field(Pojo::getValue))
     * }
* *

to be specified as a slightly shorter version: * *

{@code
     * Assign.given(Pojo::getValue)
     * }
* * @param origin a method reference for the origin value * @param type declaring the method * @param return type of the method * @return builder for constructing a conditional assignment * @see #given(TargetSelector) * @since 3.0.0 */ @ExperimentalApi public static GivenOrigin given(final GetMethodSelector origin) { return new InternalGivenOrigin(Select.field(origin)); } /** * Creates a conditional assignment for a given {@code origin} type. * This is a shorthand API of {@link #given(TargetSelector)} allowing: * *
{@code
     * Assign.given(all(Integer.class))
     * }
*

* to be specified as a slightly shorter version: * *

{@code
     * Assign.given(Integer.class)
     * }
* * @param origin type of the origin value * @param the type of value * @return builder for constructing a conditional assignment * @see #given(TargetSelector) * @since 3.0.0 */ @ExperimentalApi public static GivenOrigin given(final Class origin) { return new InternalGivenOrigin(Select.all(origin)); } private Assign() { // non-instantiable } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy