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

com.codebox.bean.ValueBuilder Maven / Gradle / Ivy

Go to download

Javabean Tester Simplifies POJO Testing and greatly simplifies Lombok Bean Testing!

The newest version!
/*
 * JavaBean Tester (https://github.com/hazendaz/javabean-tester)
 *
 * Copyright 2012-2024 Hazendaz.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of The Apache Software License,
 * Version 2.0 which accompanies this distribution, and is available at
 * http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 * Contributors:
 *     CodeBox (Rob Dawson).
 *     Hazendaz (Jeremy Landis).
 */
package com.codebox.bean;

import com.codebox.enums.LoadData;
import com.codebox.enums.LoadType;
import com.codebox.instance.ClassInstance;
import com.codebox.instance.ConstructorInstance;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import lombok.Data;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Value Builder Builds values from given type.
 */
@Data
public class ValueBuilder {

    /** The Constant Logger. */
    private static final Logger logger = LoggerFactory.getLogger(ValueBuilder.class);

    /** The load data. */
    private LoadData loadData;

    /**
     * Builds the value.
     *
     * @param 
     *            the generic type
     * @param clazz
     *            the clazz
     * @param loadType
     *            the load type
     *
     * @return the object
     */
    public  Object buildValue(final Class clazz, final LoadType loadType) {
        // Next check for a no-arg constructor
        final Constructor[] ctrs = clazz.getConstructors();
        for (final Constructor ctr : ctrs) {
            if (ctr.getParameterTypes().length == 0 && clazz != String.class) {
                if (this.loadData == LoadData.ON && !containsSelf(clazz)) {
                    // Load Underlying Data to deeply test when it doesn't contain self
                    final JavaBeanTesterWorker beanTesterWorker = new JavaBeanTesterWorker<>(clazz);
                    beanTesterWorker.setLoadData(this.loadData);
                    beanTesterWorker.getterSetterTests(new ClassInstance().newInstance(clazz));
                    return null;
                }
                // The class has a no-arg constructor, so just call it
                return ConstructorInstance.newInstance(ctr);
            }
        }

        // Specific rules for common classes
        Object returnObject = null;
        switch (loadType) {
            case ALTERNATE_DATA:
                returnObject = ValueBuilder.setAlternateValues(clazz);
                break;
            case NULL_DATA:
                returnObject = ValueBuilder.setNullValues(clazz);
                break;
            case STANDARD_DATA:
            default:
                returnObject = ValueBuilder.setStandardValues(clazz);
                break;
        }

        if (returnObject != null || loadType == LoadType.NULL_DATA) {
            return returnObject;
        }

        if (clazz.isAssignableFrom(BigDecimal.class)) {
            return BigDecimal.ONE;
        }

        if (clazz.isAssignableFrom(UUID.class)) {
            return UUID.fromString("00000000-0000-0000-0000-000123456789");
        }

        if (clazz.isAssignableFrom(Instant.class)) {
            return Instant.ofEpochSecond(1L);
        }

        if (clazz.isAssignableFrom(List.class)) {
            return new ArrayList<>();
        }

        if (clazz.isAssignableFrom(Map.class)) {
            return new HashMap<>();
        }

        if (clazz.isAssignableFrom(ConcurrentMap.class)) {
            return new ConcurrentHashMap<>();
        }

        if (clazz.isAssignableFrom(Set.class)) {
            return new TreeSet<>();
        }

        if (clazz.isAssignableFrom(Date.class)) {
            return new Date();
        }

        if (clazz.isAssignableFrom(LocalDate.class)) {
            return LocalDate.now();
        }

        if (clazz.isAssignableFrom(LocalDateTime.class)) {
            return LocalDateTime.of(2000, 10, 1, 0, 0);
        }

        if (clazz.isAssignableFrom(LocalTime.class)) {
            return LocalTime.of(0, 0);
        }

        if (clazz.isAssignableFrom(OffsetDateTime.class)) {
            return OffsetDateTime.of(2000, 10, 1, 0, 0, 0, 0, ZoneOffset.MIN);
        }

        if (clazz.isAssignableFrom(ZonedDateTime.class)) {
            return ZonedDateTime.of(LocalDateTime.of(2020, 11, 16, 10, 26, 00, 01), ZoneId.of("UTC"));
        }

        if (clazz == Logger.class) {
            return LoggerFactory.getLogger(clazz);
        }

        if (clazz.isEnum()) {
            return clazz.getEnumConstants()[0];
        }

        // XXX Add additional rules here

        // XXX Don't fail this...until alternative solution is determined
        ValueBuilder.logger.warn(
                "Unable to build value for class '{}', please raise ticket with JavaBeanTester for desired support.",
                clazz.getName());
        return null;
    }

    /**
     * Set using alternate test values.
     *
     * @param 
     *            the type parameter associated with the class under test.
     * @param clazz
     *            the class under test.
     *
     * @return Object the Object to use for test.
     */
    private static  Object setAlternateValues(final Class clazz) {
        return ValueBuilder.setValues(clazz, "ALT_VALUE", 1, Boolean.FALSE, Integer.valueOf(2), Long.valueOf(2),
                Double.valueOf(2.0), Float.valueOf(2.0F), Character.valueOf('N'), Byte.valueOf((byte) 2));
    }

    /**
     * Set using null test values.
     *
     * @param 
     *            the type parameter associated with the class under test.
     * @param clazz
     *            the class under test.
     *
     * @return Object the Object to use for test.
     */
    private static  Object setNullValues(final Class clazz) {
        return ValueBuilder.setValues(clazz, null, 0, null, null, null, null, null, null, null);
    }

    /**
     * Set using standard test values.
     *
     * @param 
     *            the type parameter associated with the class under test.
     * @param clazz
     *            the class under test.
     *
     * @return Object the Object to use for test.
     */
    private static  Object setStandardValues(final Class clazz) {
        return ValueBuilder.setValues(clazz, "TEST_VALUE", 1, Boolean.TRUE, Integer.valueOf(1), Long.valueOf(1),
                Double.valueOf(1.0), Float.valueOf(1.0F), Character.valueOf('Y'), Byte.valueOf((byte) 1));
    }

    /**
     * Set Values for object.
     *
     * @param 
     *            the type parameter associated with the class under test.
     * @param clazz
     *            the class instance under test.
     * @param string
     *            value of string object.
     * @param arrayLength
     *            amount of array objects to create.
     * @param booleanValue
     *            value of boolean object.
     * @param integerValue
     *            value of integer object.
     * @param longValue
     *            value of long object.
     * @param doubleValue
     *            value of double object.
     * @param floatValue
     *            value of float object.
     * @param characterValue
     *            value of character object.
     * @param byteValue
     *            value of character object.
     *
     * @return Object value determined by input class. If not found, returns null.
     */
    private static  Object setValues(final Class clazz, final String string, final int arrayLength,
            final Boolean booleanValue, final Integer integerValue, final Long longValue, final Double doubleValue,
            final Float floatValue, final Character characterValue, final Byte byteValue) {
        if (clazz == String.class) {
            return string;
        }
        if (clazz.isArray()) {
            return Array.newInstance(clazz.getComponentType(), arrayLength);
        }
        if (clazz == boolean.class || clazz == Boolean.class) {
            return ValueBuilder.initializeBoolean(clazz, booleanValue);
        }
        if (clazz == int.class || clazz == Integer.class) {
            return ValueBuilder.initializeInteger(clazz, integerValue);
        }
        if (clazz == long.class || clazz == Long.class) {
            return ValueBuilder.initializeLong(clazz, longValue);
        }
        if (clazz == double.class || clazz == Double.class) {
            return ValueBuilder.initializeDouble(clazz, doubleValue);
        }
        if (clazz == float.class || clazz == Float.class) {
            return ValueBuilder.initializeFloat(clazz, floatValue);
        }
        if (clazz == char.class || clazz == Character.class) {
            return ValueBuilder.initializeCharacter(clazz, characterValue);
        }
        if (clazz == byte.class || clazz == Byte.class) {
            return ValueBuilder.initializeByte(clazz, byteValue);
        }
        return null;
    }

    /**
     * Initialize boolean.
     *
     * @param 
     *            the generic type
     * @param clazz
     *            the clazz
     * @param booleanValue
     *            the boolean value
     *
     * @return the object
     */
    private static  Object initializeBoolean(final Class clazz, final Boolean booleanValue) {
        if (clazz == boolean.class && booleanValue == null) {
            return Boolean.FALSE;
        }
        return booleanValue;
    }

    /**
     * Initialize integer.
     *
     * @param 
     *            the generic type
     * @param clazz
     *            the clazz
     * @param integerValue
     *            the integer value
     *
     * @return the object
     */
    private static  Object initializeInteger(final Class clazz, final Integer integerValue) {
        if (clazz == int.class && integerValue == null) {
            return Integer.valueOf(-1);
        }
        return integerValue;
    }

    /**
     * Initialize long.
     *
     * @param 
     *            the generic type
     * @param clazz
     *            the clazz
     * @param longValue
     *            the long value
     *
     * @return the object
     */
    private static  Object initializeLong(final Class clazz, final Long longValue) {
        if (clazz == long.class && longValue == null) {
            return Long.valueOf(-1);
        }
        return longValue;
    }

    /**
     * Initialize double.
     *
     * @param 
     *            the generic type
     * @param clazz
     *            the clazz
     * @param doubleValue
     *            the double value
     *
     * @return the object
     */
    private static  Object initializeDouble(final Class clazz, final Double doubleValue) {
        if (clazz == double.class && doubleValue == null) {
            return Double.valueOf(-1.0);
        }
        return doubleValue;
    }

    /**
     * Initialize float.
     *
     * @param 
     *            the generic type
     * @param clazz
     *            the clazz
     * @param floatValue
     *            the float value
     *
     * @return the object
     */
    private static  Object initializeFloat(final Class clazz, final Float floatValue) {
        if (clazz == float.class && floatValue == null) {
            return Float.valueOf(-1.0F);
        }
        return floatValue;
    }

    /**
     * Initialize character.
     *
     * @param 
     *            the generic type
     * @param clazz
     *            the clazz
     * @param characterValue
     *            the character value
     *
     * @return the object
     */
    private static  Object initializeCharacter(final Class clazz, final Character characterValue) {
        if (clazz == char.class && characterValue == null) {
            return Character.valueOf('\u0000');
        }
        return characterValue;
    }

    /**
     * Initialize byte.
     *
     * @param 
     *            the generic type
     * @param clazz
     *            the clazz
     * @param byteValue
     *            the byte value
     *
     * @return the object
     */
    private static  Object initializeByte(final Class clazz, final Byte byteValue) {
        if (clazz == byte.class && byteValue == null) {
            return Byte.valueOf((byte) -1);
        }
        return byteValue;
    }

    /**
     * Contains self.
     *
     * @param 
     *            the generic type
     * @param clazz
     *            the clazz
     * @return true, if successful
     */
    private  boolean containsSelf(final Class clazz) {
        final List fields = Arrays.asList(clazz.getDeclaredFields());
        for (Field field : fields) {
            if (field.getType().equals(clazz)) {
                return true;
            }
        }
        return false;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy