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

org.jeasy.random.EasyRandomParameters Maven / Gradle / Ivy

The newest version!

    /*
     * The MIT License
     *
     *   Copyright (c) 2020, Mahmoud Ben Hassine ([email protected])
     *
     *   Permission is hereby granted, free of charge, to any person obtaining a copy
     *   of this software and associated documentation files (the "Software"), to deal
     *   in the Software without restriction, including without limitation the rights
     *   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     *   copies of the Software, and to permit persons to whom the Software is
     *   furnished to do so, subject to the following conditions:
     *
     *   The above copyright notice and this permission notice shall be included in
     *   all copies or substantial portions of the Software.
     *
     *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     *   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     *   THE SOFTWARE.
     */
    package org.jeasy.random;

    import org.jeasy.random.api.*;
    import org.jeasy.random.randomizers.registry.CustomRandomizerRegistry;
    import org.jeasy.random.randomizers.registry.ExclusionRandomizerRegistry;

    import java.lang.reflect.Field;
    import java.nio.charset.Charset;
    import java.nio.charset.StandardCharsets;
    import java.time.*;
    import java.util.*;
    import java.util.function.Predicate;

    import static java.lang.String.format;
    import static java.time.ZonedDateTime.of;

    /**
     * Parameters of an {@link EasyRandom} instance.
     *
     * @author Mahmoud Ben Hassine ([email protected])
     */
    public class EasyRandomParameters {

        /**
         * Default seed.
         */
        public static final long DEFAULT_SEED = 123L;

        /**
         * Default charset for Strings.
         */
        public static final Charset DEFAULT_CHARSET = StandardCharsets.US_ASCII;

        /**
         * Default collection size range.
         */
        public static final Range DEFAULT_COLLECTION_SIZE_RANGE = new Range<>(1, 100);

        /**
         * Number of different objects to generate for a type.
         */
        public static final int DEFAULT_OBJECT_POOL_SIZE = 10;

        /**
         * Default value for randomization depth, which mean, that randomization depth is unlimited
         */
        public static final int DEFAULT_RANDOMIZATION_DEPTH = Integer.MAX_VALUE;

        /**
         * Default string length size.
         */
        public static final Range DEFAULT_STRING_LENGTH_RANGE = new Range<>(1, 32);

        /**
         * Default date range in which dates will be generated: [now - 10 years, now + 10 years].
         */
        public static final int DEFAULT_DATE_RANGE = 10;

        /**
         * Reference date around which random dates will be generated.
         */
        private static final ZonedDateTime REFERENCE_DATE = of(2020, 1, 1, 0, 0, 0, 0, ZoneId.of("UTC"));

        /**
         * Default dates range.
         */
        public static final Range DEFAULT_DATES_RANGE =
                new Range<>(REFERENCE_DATE.minusYears(DEFAULT_DATE_RANGE), REFERENCE_DATE.plusYears(DEFAULT_DATE_RANGE));

        private long seed;
        private int objectPoolSize;
        private int randomizationDepth;
        private Charset charset;
        private boolean scanClasspathForConcreteTypes;
        private boolean overrideDefaultInitialization;
        private boolean ignoreRandomizationErrors;
        /**
         * 如果其中有一个字段发生异常,是否忽略掉,若忽略掉,则该字段将不处理,其他字段不影响,不忽略,则一旦有字段出错就抛出异常
         */
        private boolean ignoreRandomizationFieldErrors;
        private boolean bypassSetters;
        private Range collectionSizeRange;
        private Range stringLengthRange;
        private Range dateRange;
        private Range timeRange;
        private ExclusionPolicy exclusionPolicy;
        private ObjectFactory objectFactory;
        private RandomizerProvider randomizerProvider;

        // internal params
        private CustomRandomizerRegistry customRandomizerRegistry;
        private ExclusionRandomizerRegistry exclusionRandomizerRegistry;
        private Set userRegistries;
        private Set> fieldExclusionPredicates;
        private Set>> typeExclusionPredicates;

        /**
         * Create a new {@link EasyRandomParameters} with default values.
         */
        public EasyRandomParameters() {
            seed = DEFAULT_SEED;
            charset = DEFAULT_CHARSET;
            scanClasspathForConcreteTypes = false;
            overrideDefaultInitialization = false;
            ignoreRandomizationErrors = false;
            ignoreRandomizationFieldErrors = false;
            bypassSetters = false;
            objectPoolSize = DEFAULT_OBJECT_POOL_SIZE;
            randomizationDepth = DEFAULT_RANDOMIZATION_DEPTH;
            dateRange = new Range<>(DEFAULT_DATES_RANGE.getMin().toLocalDate(), DEFAULT_DATES_RANGE.getMax().toLocalDate());
            timeRange = new Range<>(LocalTime.MIN, LocalTime.MAX);
            collectionSizeRange = DEFAULT_COLLECTION_SIZE_RANGE;
            stringLengthRange = DEFAULT_STRING_LENGTH_RANGE;
            customRandomizerRegistry = new CustomRandomizerRegistry();
            exclusionRandomizerRegistry = new ExclusionRandomizerRegistry();
            userRegistries = new LinkedHashSet<>();
            fieldExclusionPredicates = new HashSet<>();
            typeExclusionPredicates = new HashSet<>();
            exclusionPolicy = new DefaultExclusionPolicy();
            objectFactory = new ObjenesisObjectFactory();
        }

        public Range getCollectionSizeRange() {
            return collectionSizeRange;
        }

        public void setCollectionSizeRange(final Range collectionSizeRange) {
            this.collectionSizeRange = collectionSizeRange;
        }

        public Range getDateRange() {
            return dateRange;
        }

        public void setDateRange(final Range dateRange) {
            this.dateRange = dateRange;
        }

        public Range getTimeRange() {
            return timeRange;
        }

        public void setTimeRange(final Range timeRange) {
            this.timeRange = timeRange;
        }

        public Range getStringLengthRange() {
            return stringLengthRange;
        }

        public void setStringLengthRange(final Range stringLengthRange) {
            this.stringLengthRange = stringLengthRange;
        }

        public long getSeed() {
            return seed;
        }

        public void setSeed(long seed) {
            this.seed = seed;
        }

        public int getObjectPoolSize() {
            return objectPoolSize;
        }

        public void setObjectPoolSize(int objectPoolSize) {
            if (objectPoolSize < 1) {
                throw new IllegalArgumentException("objectPoolSize must be >= 1");
            }
            this.objectPoolSize = objectPoolSize;
        }

        public int getRandomizationDepth() {
            return randomizationDepth;
        }

        public void setRandomizationDepth(int randomizationDepth) {
            if (randomizationDepth < 1) {
                throw new IllegalArgumentException("randomizationDepth must be >= 1");
            }
            this.randomizationDepth = randomizationDepth;
        }

        public Charset getCharset() {
            return charset;
        }

        public void setCharset(Charset charset) {
            Objects.requireNonNull(charset, "Charset must not be null");
            this.charset = charset;
        }

        public boolean isScanClasspathForConcreteTypes() {
            return scanClasspathForConcreteTypes;
        }

        public void setScanClasspathForConcreteTypes(boolean scanClasspathForConcreteTypes) {
            this.scanClasspathForConcreteTypes = scanClasspathForConcreteTypes;
        }

        public boolean isOverrideDefaultInitialization() {
            return overrideDefaultInitialization;
        }

        public void setOverrideDefaultInitialization(boolean overrideDefaultInitialization) {
            this.overrideDefaultInitialization = overrideDefaultInitialization;
        }

        public boolean isIgnoreRandomizationErrors() {
            return ignoreRandomizationErrors;
        }

        public void setIgnoreRandomizationErrors(boolean ignoreRandomizationErrors) {
            this.ignoreRandomizationErrors = ignoreRandomizationErrors;
        }

        public boolean isIgnoreRandomizationFieldErrors() {
            return ignoreRandomizationFieldErrors;
        }

        public void setIgnoreRandomizationFieldErrors(boolean ignoreRandomizationFieldErrors) {
            this.ignoreRandomizationFieldErrors = ignoreRandomizationFieldErrors;
        }

        public boolean isBypassSetters() {
            return bypassSetters;
        }

        public void setBypassSetters(boolean bypassSetters) {
            this.bypassSetters = bypassSetters;
        }

        public ExclusionPolicy getExclusionPolicy() {
            return exclusionPolicy;
        }

        public void setExclusionPolicy(ExclusionPolicy exclusionPolicy) {
            Objects.requireNonNull(exclusionPolicy, "Exclusion policy must not be null");
            this.exclusionPolicy = exclusionPolicy;
        }

        public ObjectFactory getObjectFactory() {
            return objectFactory;
        }

        public void setObjectFactory(ObjectFactory objectFactory) {
            Objects.requireNonNull(objectFactory, "Object factory must not be null");
            this.objectFactory = objectFactory;
        }

        public RandomizerProvider getRandomizerProvider() {
            return randomizerProvider;
        }

        public void setRandomizerProvider(RandomizerProvider randomizerProvider) {
            Objects.requireNonNull(objectFactory, "Randomizer provider must not be null");
            this.randomizerProvider = randomizerProvider;
        }

        public Set> getFieldExclusionPredicates() {
            return fieldExclusionPredicates;
        }

        public Set>> getTypeExclusionPredicates() {
            return typeExclusionPredicates;
        }

        CustomRandomizerRegistry getCustomRandomizerRegistry() {
            return customRandomizerRegistry;
        }

        ExclusionRandomizerRegistry getExclusionRandomizerRegistry() {
            return exclusionRandomizerRegistry;
        }

        Set getUserRegistries() {
            return userRegistries;
        }

        /**
         * Register a custom randomizer for the given field predicate.
         * The predicate must at least specify the field type
         *
         * @param predicate  to identify the field
         * @param randomizer to register
         * @param         The field type
         * @return the current {@link EasyRandomParameters} instance for method chaining
         * @see FieldPredicates
         */
        public  EasyRandomParameters randomize(Predicate predicate, Randomizer randomizer) {
            Objects.requireNonNull(predicate, "Predicate must not be null");
            Objects.requireNonNull(randomizer, "Randomizer must not be null");
            customRandomizerRegistry.registerRandomizer(predicate, randomizer);
            return this;
        }

        /**
         * Register a custom randomizer for a given type.
         *
         * @param type       class of the type to randomize
         * @param randomizer the custom {@link Randomizer} to use
         * @param         The field type
         * @return the current {@link EasyRandomParameters} instance for method chaining
         */
        public  EasyRandomParameters randomize(Class type, Randomizer randomizer) {
            Objects.requireNonNull(type, "Type must not be null");
            Objects.requireNonNull(randomizer, "Randomizer must not be null");
            customRandomizerRegistry.registerRandomizer(type, randomizer);
            return this;
        }

        /**
         * Exclude a field from being randomized.
         *
         * @param predicate to identify the field to exclude
         * @return the current {@link EasyRandomParameters} instance for method chaining
         * @see FieldPredicates
         */
        public EasyRandomParameters excludeField(Predicate predicate) {
            Objects.requireNonNull(predicate, "Predicate must not be null");
            fieldExclusionPredicates.add(predicate);
            exclusionRandomizerRegistry.addFieldPredicate(predicate);
            return this;
        }

        /**
         * Exclude a type from being randomized.
         *
         * @param predicate to identify the type to exclude
         * @return the current {@link EasyRandomParameters} instance for method chaining
         * @see FieldPredicates
         */
        public EasyRandomParameters excludeType(Predicate> predicate) {
            Objects.requireNonNull(predicate, "Predicate must not be null");
            typeExclusionPredicates.add(predicate);
            exclusionRandomizerRegistry.addTypePredicate(predicate);
            return this;
        }

        /**
         * Provide a custom exclusion policy.
         *
         * @param exclusionPolicy to use
         * @return the current {@link EasyRandomParameters} instance for method chaining
         */
        public EasyRandomParameters exclusionPolicy(ExclusionPolicy exclusionPolicy) {
            setExclusionPolicy(exclusionPolicy);
            return this;
        }

        /**
         * Provide a custom object factory.
         *
         * @param objectFactory to use
         * @return the current {@link EasyRandomParameters} instance for method chaining
         */
        public EasyRandomParameters objectFactory(ObjectFactory objectFactory) {
            setObjectFactory(objectFactory);
            return this;
        }

        /**
         * Provide a custom randomizer provider.
         *
         * @param randomizerProvider to use
         * @return the current {@link EasyRandomParameters} instance for method chaining
         */
        public EasyRandomParameters randomizerProvider(RandomizerProvider randomizerProvider) {
            setRandomizerProvider(randomizerProvider);
            return this;
        }

        /**
         * Set the initial random seed.
         *
         * @param seed the initial seed
         * @return the current {@link EasyRandomParameters} instance for method chaining
         */
        public EasyRandomParameters seed(final long seed) {
            setSeed(seed);
            return this;
        }

        /**
         * Set the collection size range.
         *
         * @param minCollectionSize the minimum collection size
         * @param maxCollectionSize the maximum collection size
         * @return the current {@link EasyRandomParameters} instance for method chaining
         */
        public EasyRandomParameters collectionSizeRange(final int minCollectionSize, final int maxCollectionSize) {
            if (minCollectionSize < 0) {
                throw new IllegalArgumentException("minCollectionSize must be >= 0");
            }
            if (minCollectionSize > maxCollectionSize) {
                throw new IllegalArgumentException(format("minCollectionSize (%s) must be <= than maxCollectionSize (%s)",
                        minCollectionSize, maxCollectionSize));
            }
            setCollectionSizeRange(new Range<>(minCollectionSize, maxCollectionSize));
            return this;
        }

        /**
         * Set the string length range.
         *
         * @param minStringLength the minimum string length
         * @param maxStringLength the maximum string length
         * @return the current {@link EasyRandomParameters} instance for method chaining
         */
        public EasyRandomParameters stringLengthRange(final int minStringLength, final int maxStringLength) {
            if (minStringLength < 0) {
                throw new IllegalArgumentException("minStringLength must be >= 0");
            }
            if (minStringLength > maxStringLength) {
                throw new IllegalArgumentException(format("minStringLength (%s) must be <= than maxStringLength (%s)",
                        minStringLength, maxStringLength));
            }
            setStringLengthRange(new Range<>(minStringLength, maxStringLength));
            return this;
        }


        /**
         * Set the number of different objects to generate for a type.
         *
         * @param objectPoolSize the number of objects to generate in the pool
         * @return the current {@link EasyRandomParameters} instance for method chaining
         */
        public EasyRandomParameters objectPoolSize(final int objectPoolSize) {
            setObjectPoolSize(objectPoolSize);
            return this;
        }

        /**
         * Set the randomization depth for objects graph.
         *
         * @param randomizationDepth the maximum randomization depth
         * @return the current {@link EasyRandomParameters} instance for method chaining
         */
        public EasyRandomParameters randomizationDepth(final int randomizationDepth) {
            setRandomizationDepth(randomizationDepth);
            return this;
        }

        /**
         * Set the charset to use for character based fields.
         *
         * @param charset the charset to use
         * @return the current {@link EasyRandomParameters} instance for method chaining
         */
        public EasyRandomParameters charset(final Charset charset) {
            setCharset(charset);
            return this;
        }

        /**
         * Set the date range.
         *
         * @param min date
         * @param max date
         * @return the current {@link EasyRandomParameters} instance for method chaining
         */
        public EasyRandomParameters dateRange(final LocalDate min, final LocalDate max) {
            if (min.isAfter(max)) {
                throw new IllegalArgumentException("Min date should be before max date");
            }
            setDateRange(new Range<>(min, max));
            return this;
        }

        /**
         * Set the time range.
         *
         * @param min time
         * @param max time
         * @return the current {@link EasyRandomParameters} instance for method chaining
         */
        public EasyRandomParameters timeRange(final LocalTime min, final LocalTime max) {
            if (min.isAfter(max)) {
                throw new IllegalArgumentException("Min time should be before max time");
            }
            setTimeRange(new Range<>(min, max));
            return this;
        }

        /**
         * Register a {@link RandomizerRegistry}.
         *
         * @param registry the {@link RandomizerRegistry} to register
         * @return the current {@link EasyRandomParameters} instance for method chaining
         */
        public EasyRandomParameters randomizerRegistry(final RandomizerRegistry registry) {
            Objects.requireNonNull(registry, "Registry must not be null");
            userRegistries.add(registry);
            return this;
        }

        /**
         * Should the classpath be scanned for concrete types when a field with an interface or abstract
         * class type is encountered?
         * 

* Deactivated by default. * * @param scanClasspathForConcreteTypes whether to scan the classpath or not * @return the current {@link EasyRandomParameters} instance for method chaining */ public EasyRandomParameters scanClasspathForConcreteTypes(boolean scanClasspathForConcreteTypes) { setScanClasspathForConcreteTypes(scanClasspathForConcreteTypes); return this; } /** * With this parameter, any randomization error will be silently ignored and the corresponding field will be set to null. *

* Deactivated by default. * * @param ignoreRandomizationErrors whether to silently ignore randomization errors or not * @return the current {@link EasyRandomParameters} instance for method chaining */ public EasyRandomParameters ignoreRandomizationErrors(boolean ignoreRandomizationErrors) { setIgnoreRandomizationErrors(ignoreRandomizationErrors); return this; } /** * Should default initialization of field values be overridden? * E.g. should the values of the {@code strings} and {@code integers} fields below be kept untouched * or should they be randomized. * *

         * {@code
         * public class Bean {
         *     Set strings = new HashSet<>();
         *     List integers;
         *
         *     public Bean() {
         *         integers = Arrays.asList(1, 2, 3);
         *     }
         * }}
         * 
*

* Deactivated by default. * * @param overrideDefaultInitialization whether to override default initialization of field values or not * @return the current {@link EasyRandomParameters} instance for method chaining */ public EasyRandomParameters overrideDefaultInitialization(boolean overrideDefaultInitialization) { setOverrideDefaultInitialization(overrideDefaultInitialization); return this; } /** * Flag to bypass setters if any and use reflection directly instead. False by default. * * @param bypassSetters true if setters should be ignored * @return the current {@link EasyRandomParameters} instance for method chaining */ public EasyRandomParameters bypassSetters(boolean bypassSetters) { setBypassSetters(bypassSetters); return this; } /** * Utility class to hold a range of values. * * @param type of values */ public static class Range { private T min; private T max; public Range(T min, T max) { this.min = min; this.max = max; } public T getMin() { return min; } public void setMin(T min) { this.min = min; } public T getMax() { return max; } public void setMax(T max) { this.max = max; } } /** * Return a shallow copy of randomization parameters. * * @return a shallow copy of randomization parameters. */ public EasyRandomParameters copy() { EasyRandomParameters copy = new EasyRandomParameters(); copy.setSeed(this.getSeed()); copy.setObjectPoolSize(this.getObjectPoolSize()); copy.setRandomizationDepth(this.getRandomizationDepth()); copy.setCharset(this.getCharset()); copy.setScanClasspathForConcreteTypes(this.isScanClasspathForConcreteTypes()); copy.setOverrideDefaultInitialization(this.isOverrideDefaultInitialization()); copy.setIgnoreRandomizationErrors(this.isIgnoreRandomizationErrors()); copy.setBypassSetters(this.isBypassSetters()); copy.setCollectionSizeRange(this.getCollectionSizeRange()); copy.setStringLengthRange(this.getStringLengthRange()); copy.setDateRange(this.getDateRange()); copy.setTimeRange(this.getTimeRange()); copy.setExclusionPolicy(this.getExclusionPolicy()); copy.setObjectFactory(this.getObjectFactory()); copy.setRandomizerProvider(this.getRandomizerProvider()); copy.customRandomizerRegistry = this.getCustomRandomizerRegistry(); copy.exclusionRandomizerRegistry = this.getExclusionRandomizerRegistry(); copy.userRegistries = this.getUserRegistries(); copy.fieldExclusionPredicates = this.getFieldExclusionPredicates(); copy.typeExclusionPredicates = this.getTypeExclusionPredicates(); return copy; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy