/*
 *  @author Ranides Atterwim <ranides@gmail.com>
 *  @copyright Ranides Atterwim
 *  @license WTFPL
 *  @url http://ranides.net/projects/assira
 */

package net.ranides.assira.reflection.util;

import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 *
 * @author ranides
 */
public final class MemberUtils {
    
    
    private MemberUtils() { /* utility class */ }
    
    public static boolean isVolatile(Member member) {
        return Modifier.isVolatile(member.getModifiers());
    }

    public static boolean isTransient(Member member) {
        return Modifier.isTransient(member.getModifiers());
    }

    public static boolean isSynchronized(Member member) {
        return Modifier.isSynchronized(member.getModifiers());
    }

    public static boolean isStrict(Member member) {
        return Modifier.isStrict(member.getModifiers());
    }

    public static boolean isStatic(Member member) {
        return Modifier.isStatic(member.getModifiers());
    }

    public static boolean isPublic(Member member) {
        return Modifier.isPublic(member.getModifiers());
    }

    public static boolean isProtected(Member member) {
        return Modifier.isProtected(member.getModifiers());
    }

    public static boolean isPrivate(Member member) {
        return Modifier.isPrivate(member.getModifiers());
    }

    public static boolean isNative(Member member) {
        return Modifier.isNative(member.getModifiers());
    }

    public static boolean isInterface(Member member) {
        return Modifier.isInterface(member.getModifiers());
    }

    public static boolean isFinal(Member member) {
        return Modifier.isFinal(member.getModifiers());
    }

    public static boolean isAbstract(Member member) {
        return Modifier.isAbstract(member.getModifiers());
    }
    
    /**
     * Sprawdza czy podana metoda może być traktowana jako getter 
     * (np {@code getValue}). Akceptuje gettery o nazwie w formie {@code isEnabled}, 
     * o ile zwracają typ {@code bool} .
     * @param text
     * @return
     */
    @SuppressWarnings("PMD")
    public static boolean isGetter(Method method) {
        final Class<?> ctype = method.getDeclaringClass();
        final Class<?> rtype = method.getReturnType();
        
        // eliminacja na podstawie deklaracji
        if(Object.class.equals(ctype)) {
            return false;
        }
        if(method.getParameterTypes().length != 0) {
            return false;
        }
        if(Void.class.equals(rtype) || void.class.equals(rtype)) {
            return false;
        }
        String name = method.getName();
        // akceptacja klasycznego gettera
        if(name.startsWith("get") && name.length()>3 && Character.isUpperCase(name.charAt(3)) ) {
            return true;
        }
        // akceptacja gettera logicznego "isValue"
        if(name.startsWith("is") && name.length()>2 && Character.isUpperCase(name.charAt(2)) && ClassTraits.isBool(rtype) ) {
            return true;
        }
        return false;
    }
    
    /**
     * Sprawdza czy podana metoda może być traktowana jako setter.
     * @param text
     * @return
     */
    public static boolean isSetter(Method method) {
        final Class<?> ctype = method.getDeclaringClass();
        final Class<?> rtype = method.getReturnType();
        
        // eliminacja na podstawie deklaracji
        if(Object.class.equals(ctype)) {
            return false;
        }
        if(method.getParameterTypes().length != 1) {
            return false;
        }
        if(!Void.class.equals(rtype) && !void.class.equals(rtype) && !ctype.equals(rtype)) {
            return false;
        }
        String name = method.getName();
        // akceptacja klasycznego settera
        if(name.startsWith("set") && name.length()>3 && Character.isUpperCase(name.charAt(3)) ) {
            return true;
        }
        return false;
    }
    
}
