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

org.instancio.Instancio Maven / Gradle / Ivy

There is a newer version: 5.0.2
Show newest version
/*
 * Copyright 2022-2023 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.internal.ApiImpl;
import org.instancio.internal.ApiValidator;
import org.instancio.internal.OfClassApiImpl;
import org.instancio.internal.OfCollectionApiImpl;
import org.instancio.internal.OfMapApiImpl;
import org.instancio.settings.Keys;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;

/**
 * Instancio API for creating instances of a class.
 *
 * 

Usage

* *

Create and populate an instance of a class

* Returns an object fully populated with random data with non-null values. * *
{@code
 * Person person = Instancio.create(Person.class);
 * }
* *

Customise object's values

* Returns an object populated with random data and some specified fields' values customised. * *
{@code
 * Person person = Instancio.of(Person.class)
 *     .set(field(Person::getFullName), "Homer Simpson")
 *     .supply(all(LocalDateTime.class), () -> LocalDateTime.now())
 *     .generate(field(Phone::getNumber), gen -> gen.text().pattern("(#d#d#d) #d#d#d-#d#d#d#d"))
 *     .create();
 * }
* *

Allow {@code null} values to be generated

* Default behaviour is to populate every field with a non-null value. * Specifying nullable will randomly generate either {@code null} or non-null value. * *
{@code
 * Person person = Instancio.of(Person.class)
 *     .withNullable(field(Person::getDateOfBirth))
 *     .withNullable(all(Gender.class))
 *     .withNullable(allStrings())
 *     .create();
 * }
* *

Ignore certain fields or classes

* Ignored fields will not be populated. Their values will be {@code null} * (unless they have a default value assigned). * *
{@code
 * Person person = Instancio.of(Person.class)
 *     .ignore(fields().named("id"))  // Person.id, Address.id, etc.
 *     .ignore(all(LocalDateTime.class))
 *     .create();
 * }
* *

Creating instances of a class from a {@code Model}

* Instancio builder API parameters can be saved as a {@link Model} object using * the {@link InstancioApi#toModel()} method. Objects can then be generated based * on the model. Models can be useful: * *
    *
  • as a prototype for creating customised instances of a class * by overriding model parameters
  • *
  • reducing code duplication by re-using the same model in different * parts of the code
  • *
* *
{@code
 * // Create a model
 * Model simpsons = Instancio.of(Person.class)
 *     .supply(all(Address.class), () -> new Address("742 Evergreen Terrace", "Springfield", "US"))
 *     .supply(field(Person::getPets), () -> List.of(
 *                  new Pet(PetType.CAT, "Snowball"),
 *                  new Pet(PetType.DOG, "Santa's Little Helper"))
 *     //... other specs
 *     .toModel();
 *
 * // Use the above model as is
 * Person person = Instancio.create(simpsons);
 *
 * // Use the model but override the name
 * Person homer = Instancio.of(simpsons).set(field(Person::getName), "Homer").create();
 * Person marge = Instancio.of(simpsons).set(field(Person::getName), "Marge").create();
 *
 * // A model can also used to create another model.
 * // This snippet creates a new model from the original model to include a new pet.
 * Model withNewPet = Instancio.of(simpsons)
 *     .supply(field(Person::getPets), () -> List.of(
 *                  new Pet(PetType.PIG, "Plopper"),
 *                  new Pet(PetType.CAT, "Snowball"),
 *                  new Pet(PetType.DOG, "Santa's Little Helper"))
 *     .toModel();
 * }
* *

Creating generic classes

* There are two options for creating instances of a generic type. * *

Option 1: using a {@link TypeToken}

*
{@code
 * Pair pairOfFruits = Instancio.create(new TypeToken>() {}); // note the empty '{}' braces
 * }
* *

Option 2: using {@code withTypeParameters} to specify the type arguments

*
{@code
 * Pair pairOfFruits = Instancio.of(Pair.class)
 *     .withTypeParameters(Apple.class, Banana.class)
 *     .create();
 * }
*

* The second approach allows specifying arbitrary type parameters at runtime, * however using this method will produce an "unchecked assignment" warning. * * @see InstancioApi * @see Select * @since 1.0.1 */ public final class Instancio { private Instancio() { // non-instantiable } /** * Creates an instance of the specified class. * * @param type to create * @param the type of object * @return an object of the specified type * @since 1.0.1 */ public static T create(final Class type) { return of(type).create(); } /** * Creates a {@link List} of random size. * *

Unless configured otherwise, the generated size will be between * {@link Keys#COLLECTION_MIN_SIZE} and {@link Keys#COLLECTION_MAX_SIZE}, * inclusive. * *

To create a list of a specific size, use {@link #ofList(Class)}. * * @param elementType class to generate as list elements * @param element type * @return API builder reference * @since 3.0.1 */ public static List createList(final Class elementType) { return ofList(elementType).create(); } /** * Creates a {@link Set} of random size. * *

Unless configured otherwise, the generated size will be between * {@link Keys#COLLECTION_MIN_SIZE} and {@link Keys#COLLECTION_MAX_SIZE}, * inclusive. * *

To create a {@code Set} of a specific size, use {@link #ofSet(Class)}. * * @param elementType class to generate as set elements * @param element type * @return API builder reference * @since 3.0.1 */ public static Set createSet(final Class elementType) { return ofSet(elementType).create(); } /** * Creates a {@link Map} of random size. * *

Unless configured otherwise, the generated size will be between * {@link Keys#MAP_MIN_SIZE} and {@link Keys#MAP_MAX_SIZE}, inclusive. * *

To create a {@code Map} of a specific size, use {@link #ofMap(Class, Class)}. * * @param keyType class to generate as map keys * @param valueType class to generate as map values * @param key type * @param value type * @return API builder reference * @since 3.0.1 */ public static Map createMap(final Class keyType, final Class valueType) { return ofMap(keyType, valueType).create(); } /** * Creates an infinite stream of instances of the specified class. *

* Example: *

{@code
     * List persons = Instancio.stream(Person.class)
     *     .limit(5)
     *     .collect(Collectors.toList());
     * }
* * @param type to create * @param the type of object * @return an infinite stream of objects of the specified type * @since 1.1.9 */ public static Stream stream(final Class type) { return of(type).stream(); } /** * Creates an object of type specified by the type token. * This method can be used for creating instances of generic types. *

* Example: *

{@code
     * Pair pair = Instancio.create(new TypeToken>(){});
     * }
* * @param typeToken specifying the type to create * @param the type of object * @return an object of the specified type */ public static T create(final TypeTokenSupplier typeToken) { return of(typeToken).create(); } /** * Creates an infinite stream of objects of type specified by the type token. * This method can be used for creating streams of generic types. *

* Example: *

{@code
     * List> pairs = Instancio.stream(new TypeToken>() {})
     *     .limit(5)
     *     .collect(Collectors.toList());
     * }
* * @param typeToken specifying the type to create * @param the type of object * @return an infinite stream of objects of the specified type * @since 1.1.9 */ public static Stream stream(final TypeTokenSupplier typeToken) { return of(typeToken).stream(); } /** * Creates an object populated using the given model. * If the object needs to be customised, use the {@link #of(Model)} method. *

* For an example of how to create a model, see {@link InstancioApi#toModel()}. * * @param model a model that will be used as a template for creating the object * @param the type of object * @return an object created based on the model * @see InstancioApi#toModel() * @see #of(Model) * @see #stream(Model) */ public static T create(final Model model) { return of(model).create(); } /** * Creates an infinite stream of objects populated using the given model. *

* Example: *

{@code
     * Model model = Instancio.of(Person.class)
     *     .ignore(field(Person::getId))
     *     .generate(field(Person::dateOfBirth), gen -> gen.temporal().localDate().past())
     *     .toModel();
     *
     * List persons = Instancio.stream(model)
     *     .limit(5)
     *     .collect(Collectors.toList());
     * }
* * @param model that will be used to generate the objects * @param the type of object * @return an infinite stream of objects created based on the model * @see #create(Model) * @see #of(Model) * @since 2.4.0 */ public static Stream stream(final Model model) { return of(model).stream(); } /** * Builder version of {@link #create(Class)} that allows customisation of generated values. * *
{@code
     * Person person = Instancio.of(Person.class)
     *     .generate(allInts(), gen -> gen.ints().min(1).max(99))
     *     .supply(all(Address.class), () -> new Address("742 Evergreen Terrace", "Springfield", "US"))
     *     .supply(field("pets"), () -> List.of(
     *                         new Pet(PetType.CAT, "Snowball"),
     *                         new Pet(PetType.DOG, "Santa's Little Helper")))
     *     .create();
     * }
* * @param type to create * @param the type of object * @return API builder reference */ public static InstancioOfClassApi of(final Class type) { ApiValidator.validateRootClass(type); return new OfClassApiImpl<>(type); } /** * Builder version of {@link #create(TypeTokenSupplier)} that allows customisation of generated values. * *
{@code
     * List persons = Instancio.of(new TypeToken>(){})
     *     .generate(allInts(), gen -> gen.ints().min(1).max(99))
     *     .supply(all(Address.class), () -> new Address("742 Evergreen Terrace", "Springfield", "US"))
     *     .supply(field("pets"), () -> List.of(
     *                         new Pet(PetType.CAT, "Snowball"),
     *                         new Pet(PetType.DOG, "Santa's Little Helper")))
     *     .create();
     * }
* * @param typeToken specifying the type to create * @param the type of object * @return API builder reference */ public static InstancioApi of(final TypeTokenSupplier typeToken) { return new ApiImpl<>(typeToken); } /** * Builder version of {@link #create(Model)} that allows overriding of generation * parameters of an existing model. * *
{@code
     * Model personModel = Instancio.of(Person.class)
     *     .generate(allInts(), gen -> gen.ints().min(1).max(99))
     *     .supply(all(Address.class), () -> new Address("742 Evergreen Terrace", "Springfield", "US"))
     *     .supply(field("pets"), () -> List.of(
     *                         new Pet(PetType.CAT, "Snowball"),
     *                         new Pet(PetType.DOG, "Santa's Little Helper")))
     *     .toModel();
     *
     * // Use the existing model and add/override generation parameters
     * Person simpsonKid = Instancio.of(personModel)
     *     .generate(field("fullName"), gen -> gen.oneOf("Lisa Simpson", "Bart Simpson"))
     *     .create();
     * }
* * @param model specifying generation parameters of the object to create * @param the type of object * @return API builder reference */ public static InstancioApi of(final Model model) { return new ApiImpl<>(model); } /** * Builder API for generating a {@link List} that allows customising generated values. * * @param elementType class to generate as list elements * @param element type * @return API builder reference * @since 2.0.0 */ @SuppressWarnings("all") public static InstancioOfCollectionApi> ofList(final Class elementType) { return new OfCollectionApiImpl(List.class, ApiValidator.validateOfListElementType(elementType)); } /** * Builder API for generating a {@link List} using a type token. * * @param elementTypeToken specifying the element type * @param element type * @return API builder reference * @since 2.16.0 */ @SuppressWarnings("all") public static InstancioOfCollectionApi> ofList(final TypeTokenSupplier elementTypeToken) { return new OfCollectionApiImpl(List.class, ApiValidator.validateTypeToken(elementTypeToken)); } /** * Builder API for generating a {@link List} using the specified model for list elements. * * @param elementModel a model for creating list elements * @param element type * @return API builder reference * @since 2.5.0 */ public static InstancioOfCollectionApi> ofList(final Model elementModel) { return OfCollectionApiImpl.fromElementModel(cast(List.class), elementModel); } /** * Builder API for generating a {@link Set} that allows customisation of generated values. * * @param elementType class to generate as set elements * @param element type * @return API builder reference * @since 2.0.0 */ @SuppressWarnings("all") public static InstancioOfCollectionApi> ofSet(final Class elementType) { return new OfCollectionApiImpl(Set.class, ApiValidator.validateOfSetElementType(elementType)); } /** * Builder API for generating a {@link Set} using a type token. * * @param elementTypeToken specifying the element type * @param element type * @return API builder reference * @since 2.16.0 */ @SuppressWarnings("all") public static InstancioOfCollectionApi> ofSet(final TypeTokenSupplier elementTypeToken) { return new OfCollectionApiImpl(Set.class, ApiValidator.validateTypeToken(elementTypeToken)); } /** * Builder API for generating a {@link Set} using the specified model for list elements. * * @param elementModel a model for creating set elements * @param element type * @return API builder reference * @since 2.5.0 */ public static InstancioOfCollectionApi> ofSet(final Model elementModel) { return OfCollectionApiImpl.fromElementModel(cast(Set.class), elementModel); } /** * Builder API for generating a {@link Map} that allowss customisation of generated values. * * @param keyType class to generate as map keys * @param valueType class to generate as map values * @param key type * @param value type * @return API builder reference * @since 2.0.0 */ @SuppressWarnings("all") public static InstancioOfCollectionApi> ofMap( final Class keyType, final Class valueType) { return new OfMapApiImpl(Map.class, ApiValidator.validateOfMapKeyOrValueType(keyType), ApiValidator.validateOfMapKeyOrValueType(valueType)); } /** * Builder API for generating a {@link Map} using type tokens. * * @param keyTypeToken specifying the key type * @param valueTypeToken specifying the value type * @param key type * @param value type * @return API builder reference * @since 2.16.0 */ @SuppressWarnings("all") public static InstancioOfCollectionApi> ofMap( final TypeTokenSupplier keyTypeToken, final TypeTokenSupplier valueTypeToken) { return new OfMapApiImpl(Map.class, ApiValidator.validateTypeToken(keyTypeToken), ApiValidator.validateTypeToken(valueTypeToken)); } @SuppressWarnings("unchecked") private static > Class cast(final Class collectionClass) { return (Class) collectionClass; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy