package nl.jqno.equalsverifier;

/**
 * Enum of warnings that can be suppressed in {@link nl.jqno.equalsverifier.EqualsVerifier}.
 *
 * @see nl.jqno.equalsverifier.api.EqualsVerifierApi#suppress(Warning...)
 */
public enum Warning {
    /**
     * Signals that not all fields are relevant in the {@code equals} contract. {@code
     * EqualsVerifier} will not fail if one or more fields do not affect the outcome of {@code
     * equals}.
     *
     * <p>Only applies to non-transient fields.
     */
    ALL_FIELDS_SHOULD_BE_USED,

    /**
     * Signals that non-final fields are not relevant in the {@code equals} contract. {@code
     * EqualsVerifier} will not fail if one or more non-final fields do not affect the outcome of
     * {@code equals}.
     *
     * <p>Only applies to non-transient fields.
     */
    ALL_NONFINAL_FIELDS_SHOULD_BE_USED,

    /**
     * Disables the check for reference equality on fields.
     *
     * <p>EqualsVerifier will check if the {@code equals} method calls equals on the object fields
     * of the class under test, instead of the {@code ==} operator, since normally this signifies a
     * mistake (e.g. comparing string fields with {@code ==}).
     *
     * <p>However, sometimes {@code ==} is used intentionally, or the field in question doesn't
     * implement {@code equals} itself, so a call to the {@code equals} method of that field is
     * essentially a reference equality check instead of a value equality check. In these cases,
     * this warning can be suppressed.
     */
    REFERENCE_EQUALITY,

    /**
     * Disables the check, when the {@code equals} method is overridden in the class under test,
     * that an instance of this class should be equal to an identical copy of itself.
     *
     * <p>Normally, it is important that an object be equal to an identical copy of itself: after
     * all, this is the point of overriding {@code equals} in the first place.
     *
     * <p>However, when the class is part of a hierarchy, but should be (pseudo-)singleton, it can
     * be useful to suppress this warning. This can happen in certain implementations of the Null
     * Object Pattern, for example.
     *
     * <p>If this warning is suppressed, and it turns out that an instance of the class under test
     * is equal to an identical copy of itself after all, {@link EqualsVerifier} will fail.
     */
    IDENTICAL_COPY,

    /**
     * Disables the check, when the {@code equals} method is overridden in the class under test,
     * that an instance of this class should be equal to an identical copy of itself.
     *
     * <p>Normally, it is important that an object be equal to an identical copy of itself: after
     * all, this is the point of overriding {@code equals} in the first place.
     *
     * <p>However, when the class is a kind of versioned entity and there is an {@code id} field
     * that is zero when the object is new, it is often the case that two new objects are never
     * equal to each other. In these cases, it can be useful to suppress this warning.
     *
     * <p>You cannot use {@link #IDENTICAL_COPY} in these cases, because when the {@code id}s are
     * equal, the objects should be, too, and {@link EqualsVerifier} would fail in this case.
     *
     * <p>If this warning is suppressed, and it turns out that an instance of the class under test
     * is equal to an identical copy of itself after all, {@link EqualsVerifier} will NOT fail.
     */
    IDENTICAL_COPY_FOR_VERSIONED_ENTITY,

    /**
     * Disables the check that verifies {@code equals} is actually overridden.
     *
     * <p>Can be used when a whole package of classes is automatically scanned and presented to
     * EqualsVerifier, and one or more of them don't need to override {@code equals}.
     */
    INHERITED_DIRECTLY_FROM_OBJECT,

    /**
     * Disables the example check for cached {@code hashCode}.
     *
     * <p>The example check verifies that the cached {@code hashCode} is properly initialized. You
     * can use this, if creating an example object is too cumbersome. In this case, null can be
     * passed as an example.
     *
     * <p>Note that suppressing this warning can be dangerous and should only be done in unusual
     * circumstances.
     */
    NO_EXAMPLE_FOR_CACHED_HASHCODE,

    /**
     * Disables checks for non-final fields on which {@code equals} and {@code hashCode} depend.
     *
     * <p>{@link EqualsVerifier}'s standard behaviour is to disallow non-final fields being used in
     * {@code equals} and {@code hashCode} methods, since classes that depend on non-final fields in
     * these methods cannot reliably be used in collections.
     *
     * <p>However, sometimes an external library requires that fields be non-final. An example of
     * this are Java Beans. In such a case, suppress this warning to prevent {@link EqualsVerifier}
     * from checking for non-final fields.
     */
    NONFINAL_FIELDS,

    /**
     * Disables checks for {@link NullPointerException} within {@code equals}, {@code hashCode} and
     * {@code toString} methods.
     *
     * <p>Sometimes the constructor of a class makes sure no field can be null. If this is the case,
     * and if the fields cannot be made null later in the lifecycle of the class by setters or other
     * methods, suppress this warning to disable the check for {@link NullPointerException}.
     */
    NULL_FIELDS,

    /**
     * Disables the check that all fields used in {@code equals} must also be used in {@code
     * hashCode}.
     *
     * <p>This is useful when bringing legacy systems under test, where you don't want to change the
     * existing {@code hashCode} behaviour but you do want to use EqualsVerifier.
     *
     * <p>Note that {@code hashCode}s with higher distributions give better performance when used in
     * collections such as {@link java.util.HashMap}. Therefore, if possible, you should use all
     * fields that are used in {@code equals}, in {@code hashCode} as well.
     */
    STRICT_HASHCODE,

    /**
     * Disables some of the stricter inheritance tests.
     *
     * <p>{@link EqualsVerifier}'s standard behaviour, if T is not final and neither are its {@code
     * equals} and {@code hashCode} methods, is to require a reference to a subclass of T for which
     * no instance can be equal to any instance of T, to make sure that subclasses that can redefine
     * {@code equals} or {@code hashCode} don't break the contract; or it asks to call the {@code
     * usingGetClass} method if T uses {@code getClass()} instead of {@code instanceof} in its
     * {@code equals} method.
     *
     * <p>Some may find that too strict for their liking; suppressing this warning disables that
     * test.
     *
     * @see nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi#withRedefinedSubclass(Class)
     */
    STRICT_INHERITANCE,

    /**
     * Disables the check that fields marked with the @Id or @EmbeddedId annotations in JPA entities
     * may not be used in the {@code equals} contract.
     *
     * <p>When this warning is suppressed, the fields marked with @Id or @EmbeddedId will become the
     * entity's surrogate key. Only these fields can now be part of the {@code equals} contract; all
     * other fields may no longer be used in {@code equals}.
     */
    SURROGATE_KEY,

    /**
     * Disables the check that fields marked with the @Id or @EmbeddedId annotations in JPA entities
     * may not be used in the {@code equals} contract.
     *
     * <p>When this warning is suppressed, all fields will become part of the entity's key, and
     * EqualsVerifier will operate as if the entity were a normal class.
     */
    SURROGATE_OR_BUSINESS_KEY,

    /**
     * Disables the check that collection fields in JPA, or @Basic fields marked with
     * FetchType.LAZY, should be accessed through their getter methods in {@code equals} and
     * {@code hashCode} methods.
     *
     * <p>Normally, it is necessary to go through the getter for these fields, because their
     * content may not be materialized in some instances. Calling the getter will materialize them,
     * but referencing the field directly will not. This can lead to situations where the
     * {@code equals} method of objects that should be equal to each other returns false, because
     * one instance has the content materialized and the other does not.
     */
    JPA_GETTER,

    /**
     * Disables the check that transient fields not be part of the {@code equals} contract.
     *
     * <p>{@link EqualsVerifier}'s standard behaviour is to disallow transient fields being used in
     * {@code equals} and {@code hashCode} methods, since these fields may not be restored to their
     * original state after deserialization, which would break {@code equals}.
     *
     * <p>If measures are taken that this will never happen, this warning can be suppressed to
     * disable {@link EqualsVerifier}'s transience test.
     */
    TRANSIENT_FIELDS,

    /**
     * Disables the check that equality of {@code BigDecimal} fields is implemented using
     * {@code compareTo} rather than {@code equals}.
     *
     * <p>{@code BigDecimal} objects that are equal using {@code compareTo} are not necessarily
     * equal using {@code equals}, for example the values of {@literal 1} and {@literal 1.0}.
     * For variants of the same value to be considered equal, classes with {@code BigDecimal}
     * fields should use {@code compareTo} to check equality of non-null {@code BigDecimal}
     * references and produce the same hashcode for all equal variants.
     *
     * <p>{@code EqualsVerifier} checks for this by default but it can be disabled by suppressing
     * this warning.
     */
    BIGDECIMAL_EQUALITY,

    /**
     * Disables checks with fields with value 0 within {@code equals}, {@code hashCode} and
     * {@code toString} methods.
     *
     * <p>Sometimes the constructor of a class makes sure no field can be 0. If this is the case,
     * and if the fields cannot be made 0 later in the lifecycle of the class by setters or other
     * methods, suppress this warning to disable the checks with fields that have value 0.
     */
    ZERO_FIELDS
}
