Checks.java

package io.github.jonloucks.contracts.api;

/**
 * Checks used internally and supported for external use.
 */
public final class Checks {
    
    /**
     * Utility class instantiation protection
     */
    private Checks() {
        // conflicting standards.  100% code coverage vs throwing exception on instantiation of utility class.
        // Java modules protects agents invoking private methods.
        // There are unit tests that will fail if this constructor is not private
    }
    
    /**
     * Check if given Contract is not null or invalid
     *
     * @param contract the Contract to check
     * @param <T>      the deliverable type
     * @return a valid contract
     * @throws IllegalArgumentException when invalid
     */
    public static <T> Contract<T> contractCheck(Contract<T> contract) {
        return nullCheck(contract, "Contract must be present.");
    }
    
    /**
     * Check if given Contracts is not null or invalid
     * @param contracts the Contracts to check
     * @return a valid Contracts
     */
    public static Contracts contractsCheck(Contracts contracts) {
        return nullCheck(contracts, "Contracts must be present.");
    }
    
    /**
     * Check if given Promisor is not null or invalid
     *
     * @param promisor the Promisor to check
     * @param <T>      the deliverable type
     * @return a valid promisor
     * @throws IllegalArgumentException when invalid
     */
    public static <T> Promisor<T> promisorCheck(Promisor<T> promisor) {
        return nullCheck(promisor, "Promisor must be present.");
    }
    
    /**
     * Check if given config is not null or invalid
     *
     * @param config the config to check
     * @param <T>      the type of config
     * @return a valid config
     * @throws IllegalArgumentException when invalid
     */
    public static <T> T configCheck(T config) {
        return nullCheck(config, "Config must be present.");
    }
    
    /**
     * Check if given builder is not null or invalid
     *
     * @param builder the builder to check
     * @param <T>      the type of builder
     * @return a valid builder
     * @throws IllegalArgumentException when invalid
     */
    public static <T> T builderCheck(T builder) {
        return nullCheck(builder, "Builder must be present.");
    }
    
    /**
     * Check if given builder consumer is not null or invalid
     *
     * @param builderConsumer the builder consumer to check
     * @param <T>      the type of builder consumer
     * @return a valid builder consumer
     * @throws IllegalArgumentException when invalid
     */
    public static <T> T builderConsumerCheck(T builderConsumer) {
        return nullCheck(builderConsumer, "Builder consumer must be present.");
    }
    
    /**
     * Check if given type is not null or invalid
     *
     * @param type the type to check
     * @param <T>      the type of type
     * @return a valid type
     * @throws IllegalArgumentException when invalid
     */
    public static <T> T typeCheck(T type) {
        return nullCheck(type, "Type was must be present.");
    }
    
    /**
     * Check if given name is not null or invalid
     *
     * @param name the name to check
     * @param <T>      the type of name
     * @return a valid name
     * @throws IllegalArgumentException when invalid
     */
    public static <T> T nameCheck(T name) {
        return nullCheck(name, "Name was must be present.");
    }
    
    /**
     * Check if given message is not null or invalid
     *
     * @param t   the message to check
     * @param <T> the type of message (normally a String)
     * @return a valid message
     * @throws IllegalArgumentException when invalid
     */
    public static <T> T messageCheck(T t) {
        return nullCheck(t, "Message must be present.");
    }
    
    /**
     * Check if given instance is not null
     *
     * @param t       the instance to check
     * @param message the message used if an exception is thrown
     * @param <T>     the type of instance
     * @return the value passed
     * @throws IllegalArgumentException when invalid
     */
    public static <T> T nullCheck(T t, String message) {
        return illegalCheck(t, null == t, message);
    }
    
    /**
     * Check if given instance is not null
     *
     * @param t       the instance to check
     * @param failed  if true an IllegalArgumentException is thrown
     * @param message the message used if an exception is thrown
     * @param <T>     the type of instance
     * @return the value passed
     * @throws IllegalArgumentException when invalid
     */
    public static <T> T illegalCheck(T t, boolean failed, String message) {
        if (null == message) {
            throw new IllegalArgumentException("Message for illegal check must be present.");
        }
        if (failed) {
            throw new IllegalArgumentException(message);
        }
        return t;
    }
    
    /**
     * A simple runtime validation of deployed implementation
     *
     * @param contracts the contracts to check
     */
    public static void validateContracts(Contracts contracts) {
        final Contracts validContracts = contractsCheck(contracts);
        try {
            final Contract<String> contract = Contract.create("validation contract");
            final String deliverableValue = "validate value";
            
            if (validContracts.isBound(contract)) {
                throw new ContractException("Contract should not be bound.");
            }
            final AutoClose bindReturn = validContracts.bind(contract, () -> deliverableValue);
            if (null == bindReturn) {
                throw new ContractException("Contract bind returned null.");
            }
            try (AutoClose closeBinding = bindReturn) {
                final AutoClose ignoredWarning = closeBinding;
                if (!validContracts.isBound(contract)) {
                    throw new ContractException("Contract should have been bound.");
                }
                if (!deliverableValue.equals(validContracts.claim(contract))) {
                    throw new ContractException("Contract claiming not working.");
                }
            }
            if (validContracts.isBound(contract)) {
                throw new ContractException("Contract unbinding not working.");
            }
        } catch (ContractException thrown) {
            throw thrown;
        } catch (RuntimeException thrown) {
            throw new ContractException("Contracts unexpected validation error.", thrown);
        }
    }
}