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

import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.List;
import net.ranides.assira.trace.ExceptionUtils;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
@SuppressWarnings("PMD")
public abstract class ForMemberTraits<Q> {
    
    public static final Field PUBLIC        = $field("f_public");
    public static final Field PROTECTED     = $field("f_protected");
    public static final Field PRIVATE       = $field("f_private");
    public static final Field FINAL         = $field("f_final");
    public static final Field STATIC        = $field("f_static");
    public static final Field VOLATILE      = $field("f_volatile");
    public static final Field TRANSIENT     = $field("f_transient");
    public static final Member ABSTRACT     = $method("m_abstract");
    public static final Member METHOD       = $method("m_no_abstract");
    public static final Member SYNCHRONIZED = $method("m_synchronized");
    public static final Member STRICT       = $method("m_strict");
    public static final Member NATIVE       = $method("m_native");
    public static final Field NOTHING       = $field("f_nothing");
    public static final Field LIST1         = $field("f_list1");
    public static final Field LIST2         = $field("f_list2");
    
    public static final Member GETTER      = $field("getLength");
    public static final Member SETTER      = $field("setLength");
  
    public int getLength;
    
    public Void setLength;
    
    public int f_public = 77;
    
    protected int f_protected;
    
    private int f_private = 99;
    
    int f_nothing;
    
    public final int f_final = 0;
    
    static int f_static;
    
    volatile int f_volatile;
    
    transient int f_transient;
    
    List<String> f_list1;
    
    List<Q> f_list2;
    
    public abstract void m_abstract();
    
    public void m_no_abstract() { }
    
    public synchronized void m_synchronized() { }
    
    public strictfp void m_strict() { }
    
    public native void m_native();
    
    public static class Bean {
        
        public void getName1() { }
        
        public Void getName2() { return null; }
        
        public String getName3(int value) { return null; }
        
        public String getName4() { return null; }
        
        public String get() { return null; }
        
        public String name6() { return null; }
        
        public String getname5() { return null; }
        
        public String isVisible1() { return null; }
        
        public boolean isVisible2() { return false; }
        
        public Boolean isVisible3() { return false; }
        
        public boolean isvisible4() { return false; }
        
        public boolean is() { return false; }
        
        public void setName1(int value) { }
        
        public Bean setName2(int value) { return this; }
        
        public Bean setName3(int value) { return this; }
        
        public void name5(int value) { }
        
        public void setName6() { }
        
        public void set(int value) { }
        
        public void setname7(int value) { }
        
        public Void setName8(int value) { return null; }
        
    }
    
    public static class Bean2 extends Bean {
        
        @Override
        public Bean setName2(int value) { return this; }
        
        @Override
        public Bean2 setName3(int value) { return this; }
        
        public Bean2 setName4(int value) { return this; }
        
    }
    
    public static Field $field(String name) {
        try {
            return ForMemberTraits.class.getDeclaredField(name);
        } catch(ReflectiveOperationException cause) {
            throw ExceptionUtils.rethrow(cause);
        }
    }
    
    public static Method $method(String name) {
        return $method(ForMemberTraits.class, name);
    }
    
    public static Method $method(Class<?> clazz, String name) {
        for(Method m : clazz.getDeclaredMethods()) {
            if(name.equals(m.getName())) {
                return m;
            }
        }
        throw new AssertionError("Method not found: " + name + " in class: " + clazz);
    }
    
}
