001package io.cui.tools.property;
002
003import java.io.Serializable;
004import java.lang.reflect.Field;
005import java.lang.reflect.Modifier;
006import java.util.Optional;
007
008import io.cui.tools.reflect.MoreReflection;
009
010/**
011 * Members of this enum define the way the corresponding property is subject to the contracts
012 * regarding the canonical {@link Object} methods like {@link Object#equals(Object)},
013 * {@link Object#hashCode()} and {@link Object#toString()} and the {@link Serializable} contract
014 *
015 * @author Oliver Wolff
016 */
017public enum PropertyMemberInfo {
018
019    /**
020     * Defines a default property contract, saying it is not transient and defines the
021     * Object-identity, {@link Object#equals(Object)},
022     * {@link Object#hashCode()} and {@link Object#toString()}
023     */
024    DEFAULT,
025
026    /**
027     * Defines a property that is not transient, and is not part of the object-identity and should
028     * therefore be ignored in the methods {@link Object#equals(Object)},
029     * {@link Object#hashCode()}
030     */
031    NO_IDENTITY,
032
033    /**
034     * Defines a transient property that is not part of the object-identity and should
035     * therefore be ignored in the methods {@link Object#equals(Object)} and the serialization.
036     */
037    TRANSIENT,
038
039    /** The actual state can not be defined. */
040    UNDEFINED;
041
042    /**
043     * Resolves {@link PropertyMemberInfo} for a given property with {@link MoreReflection}. This
044     * method can solely distinguish between the states {@link #UNDEFINED}, {@link #DEFAULT} and
045     * {@link #TRANSIENT}. {@link #NO_IDENTITY} must be defined from the caller if necessary;
046     *
047     * @param beanType to be checked, must not be null
048     * @param propertyName to be checked, must not be null
049     * @return the corresponding {@link PropertyReadWrite} for a given property
050     */
051    public static PropertyMemberInfo resolveForBean(final Class<?> beanType, final String propertyName) {
052        Optional<Field> fieldOption = MoreReflection.accessField(beanType, propertyName);
053        if (!fieldOption.isPresent()) {
054            return UNDEFINED;
055        }
056        if (Modifier.isTransient(fieldOption.get().getModifiers())) {
057            return PropertyMemberInfo.TRANSIENT;
058        }
059        return PropertyMemberInfo.DEFAULT;
060    }
061}