/*
 * Operation.java
 * 
 * Author: http://www.hrtdotnet.jp/
 * 
 */
package jp.hrtdotnet.java.util;

import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

/**
 * クラスやオブジェクトの操作をします。
 * 
 * @version 2.0
 * @author hrtdotnet.jp
 * <br>http://www.hrtdotnet.jp/
 * @since 2.0
 */
public class Operation {

    /** 修飾子に使われない値です。 */
    public static final int UNDEFINED         = 0x00000000;
    /** public 修飾子を表す int 値です。 */
    public static final int PUBLIC           = 0x00000001;
    /** private 修飾子を表す int 値です。 */
    public static final int PRIVATE          = 0x00000002;
    /** protected 修飾子を表す int 値です。 */
    public static final int PROTECTED        = 0x00000004;
    /** static 修飾子を表す int 値です。 */
    public static final int STATIC           = 0x00000008;
    /** final 修飾子を表す int 値です。 */
    public static final int FINAL            = 0x00000010;
    /** synchronized 修飾子を表す int 値です。 */
    public static final int SYNCHRONIZED     = 0x00000020;
    /** volatile 修飾子を表す int 値です。 */
    public static final int VOLATILE         = 0x00000040;
    /** transient 修飾子を表す int 値です。 */
    public static final int TRANSIENT        = 0x0000008;
    /** native 修飾子を表す int 値です。 */
    public static final int NATIVE           = 0x00000100;
    /** interface 修飾子を表す int 値です。 */
    public static final int INTERFACE        = 0x00000200;
    /** abstract 修飾子を表す int 値です。 */
    public static final int ABSTRACT         = 0x00000400;
    /** strictfp 修飾子を表す int 値です。 */
    public static final int STRICT           = 0x00000800;

    
    
    /**
     * 指定したクラスのオブジェクトを生成します。
     * 
     * @param classPath クラスパス
     * @param parameterTypes コンストラクタ引数の型のクラス配列
     * @param initargs コンストラクタ引数のオブジェクト配列
     * @return 生成したオブジェクト
     * @throws IllegalArgumentException
     *          コンストラクタに与えるオブジェクトの引数が不正な場合
     * @throws InstantiationException
     *          コンストラクタがabstractであった場合
     * @throws IllegalAccessException
     *          修飾子などの指定でアクセス制御のためコンストラクタにアクセスできなかった場合
     * @throws InvocationTargetException
     *          コンストラクタが例外をスローした場合
     * @throws SecurityException
     *          情報へのアクセスが拒否あれた場合
     * @throws NoSuchMethodException
     *          一致するコンストラクタが無い場合
     * @throws ClassNotFoundException
     *          クラスが存在しなかった場合
     * @since 2.0
     */
    public static Object newInstance(String classPath, Class[] parameterTypes, Object[] initargs)
        throws IllegalArgumentException, InstantiationException, IllegalAccessException,
                InvocationTargetException, SecurityException, NoSuchMethodException,
                ClassNotFoundException {
        Class c = Class.forName(classPath);
        Constructor constructor = c.getConstructor(parameterTypes);
        return constructor.newInstance(initargs);
    }

    /**
     * 指定したクラスのオブジェクトを生成します。
     * このメソッドでオブジェクトを作成する場合は例外がスローされません。
     * 
     * @param classPath クラスパス
     * @param parameterTypes コンストラクタ引数の型のクラス配列
     * @param initargs コンストラクタの引数に与えるオブジェクト配列
     * @return 生成したオブジェクト
     * @since 2.0
     */
    public static Object newInstanceIgnoreError(String classPath, Class[] parameterTypes, Object[] initargs) {        
        Object o = null;
        try {
            o = newInstance(classPath, parameterTypes, initargs);
        } catch (Throwable e) {
        }
        return o;
    }

    /**
     * 指定したメソッドを実行します。
     * 
     * @param methodName メソッドの名前
     * @param argTypes メソッドの引数の型のクラス配列
     * @param obj メソッドを実行するオブジェクト
     * @param args メソッドの引数に与えるオブジェクト配列
     * @return 実行したメソッドの戻り値
     * @throws SecurityException
     *          情報へのアクセスが拒否あれた場合
     * @throws NoSuchMethodException
     *          メソッドが見つからない場合
     * @throws IllegalArgumentException
     *          メソッドの引数として不正な場合
     * @throws IllegalAccessException
     *          修飾子などでメソッドにアクセスできなかった場合
     * @throws InvocationTargetException
     *          メソッドが例外をスローした場合
     * @since 2.0
     */
    public static Object invokeMethod (String methodName, Class[] argTypes, Object obj, Object[] args)
        throws SecurityException, NoSuchMethodException, IllegalArgumentException,
            IllegalAccessException, InvocationTargetException {
        return invoke(obj.getClass(), methodName, argTypes, obj, args);
    }

    /**
     * staticメソッドを実行します。
     * 
     * @param classPath クラスパス
     * @param methodName メソッドの名前
     * @param argTypes メソッドの引数の型のクラス配列
     * @param args メソッドの引数に与えるオブジェクト配列
     * @return 実行したメソッドの戻り値
     * @throws SecurityException
     *          情報へのアクセスが拒否あれた場合
     * @throws NoSuchMethodException
     *          メソッドが見つからない場合
     * @throws IllegalArgumentException
     *          メソッドの引数として不正な場合
     * @throws IllegalAccessException
     *          修飾子などでメソッドにアクセスできなかった場合
     * @throws InvocationTargetException
     *          メソッドが例外をスローした場合
     * @throws ClassNotFoundException
     *          クラスが存在しなかった場合
     *          
     * @since 2.0
     */
    public static Object invokeStaticMethod(String classPath, String methodName, Class[] argTypes, Object[] args)
        throws SecurityException, NoSuchMethodException, IllegalArgumentException,
            IllegalAccessException, InvocationTargetException, ClassNotFoundException {
        Class c = Class.forName(classPath);
        return invoke(c, methodName, argTypes, null, args);
    }
    
    /**
     * staticメソッドを実行します。
     * 
     * @param c クラス
     * @param methodName メソッドの名前
     * @param argTypes メソッドの引数の型のクラス配列
     * @param args メソッドの引数に与えるオブジェクト配列
     * @return 実行したメソッドの戻り値
     * @throws SecurityException
     *          情報へのアクセスが拒否あれた場合
     * @throws NoSuchMethodException
     *          メソッドが見つからない場合
     * @throws IllegalArgumentException
     *          メソッドの引数として不正な場合
     * @throws IllegalAccessException
     *          修飾子などでメソッドにアクセスできなかった場合
     * @throws InvocationTargetException
     *          メソッドが例外をスローした場合
     * @since 2.0
     */
    public static Object invokeStaticMethod(Class c, String methodName, Class[] argTypes, Object[] args)
        throws SecurityException, NoSuchMethodException, IllegalArgumentException,
            IllegalAccessException, InvocationTargetException {
        return invoke(c, methodName, argTypes, null, args);
    }
    
    
    
    /**
     * 指定した文字列から始まる引数無しの public メソッドを連続して実行します。
     * static, インスタンスメソッドともに実行されます。
     * 対象メソッド実行中に発生した例外は無視され次のメソッドの実行に移ります。
     * <br>
     * なお実行されるメソッドのオブジェクトは引数無しコンストラクタから生成された
     * オブジェクトに限ります。
     * 
     * @param cls 実行するメソッドのクラス
     *         指定されたクラスの引数なしコンストラクタのオブジェクトが生成される。
     * @param startStr 実行するメソッド名の前文字列
     * 
     * @throws NoSuchMethodException nullコンストラクタが存在しない場合
     * @throws SecurityException セキュリティマネージャが有効となっておりインスタンスの生成や実行メソッドの取得を拒否された場合
     * @throws InvocationTargetException 実行したメソッドが例外をスローした場合
     * @throws IllegalAccessException clsに指定したクラス、またはそのnullコンストラクタにアクセスできない、
     *                                  また何かしらの理由で実行メソッドにアクセスできなかった場合
     * @throws InstantiationException インスタンスの生成に失敗した場合
     * @throws IllegalArgumentException startStrが空文字など不正な場合
     * @throws NullPointerException cls、もしくはstartStrがnullの場合
     * 
     * @since 2.0
     */
    public static void invokeMethodRun(Class cls, String startStr)
        throws SecurityException, IllegalArgumentException, NoSuchMethodException,
            InstantiationException, IllegalAccessException, InvocationTargetException, NullPointerException {
        invokeMethodRun(cls, startStr, null, null, UNDEFINED);
    }

    /**
     * 指定した文字列から始まる引数無しのpublicメソッドを連続して実行します。
     * static,インスタンスメソッドともに実行されます。
     * 対象メソッド実行中に発生した例外は無視され次のメソッドの実行に移ります。
     * <br>
     * 実行されるメソッドのオブジェクトは引数無しコンストラクタから生成されたオブジェクトに限ります。
     * <br><br>
     * メソッドを実行する前後に実行するメソッドを指定できます。
     * 前後のメソッドは実行メソッドがstaticであればstaticのメソッド、
     * インスタンスであればインスタンスのメソッドが実行されます。
     * <br>
     * なお前後に実行するメソッドは引数無しのメソッドに限ります。
     * 
     * @param cls 実行するメソッドのクラス
     * @param startStr 実行するメソッド名の前文字列
     * @param setUpStr メソッド実行前に実行する引数無しメソッドの名前
     * @param tearDownStr メソッド実行後に実行するメソッドの名前
     * 
     * @throws NoSuchMethodException nullコンストラクタが存在しない場合
     * @throws SecurityException セキュリティマネージャが有効となっておりインスタンスの生成や実行メソッドの取得を拒否された場合
     * @throws InvocationTargetException 実行したメソッドが例外をスローした場合
     * @throws IllegalAccessException clsに指定したクラス、またはそのnullコンストラクタにアクセスできない、
     *                                  また何かしらの理由で実行メソッドにアクセスできなかった場合
     * @throws InstantiationException インスタンスの生成に失敗した場合
     * @throws IllegalArgumentException startStrが空文字など不正な場合
     * @throws NullPointerException cls、もしくはstartStrがnullの場合
     * 
     * @since 2.0
     */

    public static void invokeMethodRun(Class cls, String startStr, String setUpStr, String tearDownStr)
        throws SecurityException, IllegalArgumentException, NoSuchMethodException,
                InstantiationException, IllegalAccessException, InvocationTargetException, NullPointerException {
        invokeMethodRun(cls, startStr, setUpStr, tearDownStr, UNDEFINED);
    }
    

    /**
     * 指定した文字列から始まる引数無しのpublicメソッドを連続して実行します。
     * static,インスタンスメソッドともに実行されます。
     * 対象メソッド実行中に発生した例外は無視され次のメソッドの実行に移ります。
     * <br>
     * 実行されるメソッドのオブジェクトは引数無しコンストラクタから生成されたオブジェクトに限ります。
     * <br><br>
     * メソッドを実行する前後に実行するメソッドや実行するメソッドの修飾子を指定できます。
     * 前後のメソッドは実行メソッドがstaticであればstaticのメソッド、
     * インスタンスであればインスタンスのメソッドが実行されます。
     * <br>
     * なお前後に実行するメソッドは引数無しのメソッドに限ります。
     * 修飾子を指定した場合、指定された修飾子を含むメソッドのみを実行されます。
     * 修飾子を表す定数は当クラスに用意されており以下の通りです。
     * <ul>
     * <li>UNDEFINED : 修飾子を指定しません。</li>
     * <li>PUBLIC : public 修飾子を表します。</li>
     * <li>PRIVATE : private修飾子を表します。</li>
     * <li>PROTECTED : protected 修飾子を表します。</li>
     * <li>STATIC : static 修飾子を表します。</li>
     * <li>FINAL : final 修飾子を表します。</li>
     * <li>SYNCHRONIZED : synchronized 修飾子を表します。</li>
     * <li>VOLATILE : volatile 修飾子を表します。</li>
     * <li>TRANSIENT : transient 修飾子を表します。</li>
     * <li>NATIVE : native 修飾子を表します。</li>
     * <li>INTERFACE : interface 修飾子を表します。</li>
     * <li>ABSTRACT : abstract 修飾子を表します。</li>
     * <li>STRICT : strictfp 修飾子を表します。</li>
     * </ul>
     * 
     * @param cls 実行するメソッドのクラス
     * @param startStr 実行するメソッド名の前文字列。
     * @param setUpStr メソッド実行前に実行する引数無しメソッドの名前
     * @param tearDownStr メソッド実行後に実行するメソッドの名前
     * @param isMod 実行するメソッドの修飾子
     * 
     * @throws NoSuchMethodException nullコンストラクタが存在しない場合
     * @throws SecurityException セキュリティマネージャが有効となっておりインスタンスの生成や実行メソッドの取得を拒否された場合
     * @throws InvocationTargetException 実行したメソッドが例外をスローした場合
     * @throws IllegalAccessException clsに指定したクラス、またはそのnullコンストラクタにアクセスできない、
     *                                  また何かしらの理由で実行メソッドにアクセスできなかった場合
     * @throws InstantiationException インスタンスの生成に失敗した場合
     * @throws IllegalArgumentException startStrが空文字など不正な場合
     * @throws NullPointerException cls、もしくはstartStrがnullの場合
     * 
     * @since 2.0
     */
    public static void invokeMethodRun(Class cls, String startStr, String setUpStr, String tearDownStr, int isMod)
        throws SecurityException, NoSuchMethodException, IllegalArgumentException,
                InstantiationException, IllegalAccessException, InvocationTargetException, NullPointerException {

        if (cls == null) {
            throw new NullPointerException("Class-object is null.");
        }
        
        // Object 生成
        Constructor constructor = cls.getConstructor(new Class[] {});
        Object obj = constructor.newInstance(new Object[] {});

        invokeAllPublicMethodRun(cls, obj, startStr, setUpStr, tearDownStr, isMod, UNDEFINED);
    }


    /**
     * 指定した文字列から始まる引数無しのpublicインスタンスメソッドを連続して実行します。
     * staticメソッドは実行されません。
     * 対象メソッド実行中に発生した例外は無視され次のメソッドの実行に移ります。
     * 
     * @param obj 実行するメソッドのオブジェクト
     * @param startStr 実行するメソッド名の前文字列
     * 
     * @throws InvocationTargetException 実行したメソッドが例外をスローした場合
     * @throws IllegalAccessException 何かしらの理由で実行メソッドにアクセスできなかった場合
     * @throws IllegalArgumentException startStrが空文字など不正な場合
     * @throws NullPointerException obj、もしくはstartStrがnullであった場合
     * 
     * @since 2.0
     */
    public static void invokeMethodRun(Object obj, String startStr)
        throws IllegalArgumentException, NullPointerException, IllegalAccessException,
                InvocationTargetException {
        invokeMethodRun(obj, startStr, null, null, UNDEFINED);
    }
    
    
    /**
     * 指定した文字列から始まる引数無しのpublicインスタンスメソッドを連続して実行します。
     * staticメソッドは実行されません。
     * 対象メソッド実行中に発生した例外は無視され次のメソッドの実行に移ります。
     * <br><br>
     * メソッドを実行する前後に実行するメソッドを指定できます。
     * 前後のメソッドがstaticメソッドの場合は実行されません。
     * <br>
     * なお前後に実行するメソッドは引数無しのメソッドに限ります。
     * 
     * @param obj 実行するメソッドのオブジェクト
     * @param startStr 実行するメソッド名の前文字列
     * @param setUpStr メソッド実行前に実行する引数無しメソッドの名前
     * @param tearDownStr メソッド実行後に実行するメソッドの名前
     * 
     * @throws InvocationTargetException 実行したメソッドが例外をスローした場合
     * @throws IllegalAccessException 何かしらの理由で実行メソッドにアクセスできなかった場合
     * @throws IllegalArgumentException startStrが空文字など不正な場合
     * @throws NullPointerException obj、もしくはstartStrがnullであった場合
     * 
     * @since 2.0
     */
    public static void invokeMethodRun(Object obj, String startStr, String setUpStr, String tearDownStr)
        throws IllegalArgumentException, NullPointerException, IllegalAccessException, InvocationTargetException
    {
        invokeMethodRun(obj, startStr, setUpStr, tearDownStr, UNDEFINED);
    }    

    /**
     * 指定した文字列から始まる引数無しのpublicインスタンスメソッドを連続して実行します。
     * staticメソッドは実行されません。
     * 対象メソッド実行中に発生した例外は無視され次のメソッドの実行に移ります。
     * <br><br>
     * メソッドを実行する前後に実行するメソッドや実行するメソッドの修飾子を指定できます。
     * 前後のメソッドがstaticメソッドの場合は実行されません。
     * <br>
     * なお前後に実行するメソッドは引数無しのメソッドに限ります。
     * <br><br>
     * 修飾子を指定した場合、指定された修飾子を含むメソッドのみを実行されます。
     * 修飾子を表す定数は当クラスに用意されており以下の通りです。
     * <ul>
     * <li>UNDEFINED : 修飾子を指定しません。</li>
     * <li>PUBLIC : public 修飾子を表します。</li>
     * <li>PRIVATE : private修飾子を表します。</li>
     * <li>PROTECTED : protected 修飾子を表します。</li>
     * <li>STATIC : static 修飾子を表します。</li>
     * <li>FINAL : final 修飾子を表します。</li>
     * <li>SYNCHRONIZED : synchronized 修飾子を表します。</li>
     * <li>VOLATILE : volatile 修飾子を表します。</li>
     * <li>TRANSIENT : transient 修飾子を表します。</li>
     * <li>NATIVE : native 修飾子を表します。</li>
     * <li>INTERFACE : interface 修飾子を表します。</li>
     * <li>ABSTRACT : abstract 修飾子を表します。</li>
     * <li>STRICT : strictfp 修飾子を表します。</li>
     * </ul>
     * 
     * @param obj 実行するメソッドのオブジェクト
     * @param startStr 実行するメソッド名の前文字列
     * @param setUpStr メソッド実行前に実行する引数無しメソッドの名前
     * @param tearDownStr メソッド実行後に実行するメソッドの名前
     * @param isMod 実行するメソッドの修飾子
     * 
     * @throws InvocationTargetException 実行したメソッドが例外をスローした場合
     * @throws IllegalAccessException 何かしらの理由で実行メソッドにアクセスできなかった場合
     * @throws IllegalArgumentException startStrが空文字など不正な場合
     * @throws NullPointerException obj、もしくはstartStrがnullであった場合
     * 
     * @since 2.0
     */
    public static void invokeMethodRun(Object obj, String startStr, String setUpStr, String tearDownStr, int isMod) throws IllegalArgumentException, NullPointerException, IllegalAccessException, InvocationTargetException
    {
        if (obj == null) {
            throw new NullPointerException("Object-object is null.");
        }

        Class cls = obj.getClass();
        invokeAllPublicMethodRun(cls, obj, startStr, setUpStr, tearDownStr, isMod, STATIC);

    }
    
    
    /**
     * 指定した文字列から始まる引数無しのpublic staticメソッドを連続して実行します。
     * インスタンスメソッドは実行されません。
     * 対象メソッド実行中に発生した例外は無視され次のメソッドの実行に移ります。
     * 
     * @param cls 実行するメソッドのクラス
     * @param startStr 実行するメソッド名の前文字列
     * 
     * @throws InvocationTargetException 実行したメソッドが例外をスローした場合
     * @throws IllegalAccessException 何かしらの理由で実行メソッドにアクセスできなかった場合
     * @throws IllegalArgumentException startStrが空文字など不正な場合
     * @throws NullPointerException cls、もしくはstartStrがnullであった場合
     * 
     * @since 2.0
     */
    public static void invokeStaticMethodRun(Class cls, String startStr)
        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, NullPointerException {
        invokeStaticMethodRun(cls, startStr, null, null, 0);
    }

    
    /**
     * 指定した文字列から始まる引数無しの public static メソッドを連続して実行します。
     * インスタンスメソッドは実行されません。
     * 対象メソッド実行中に発生した例外は無視され次のメソッドの実行に移ります。
     * <br><br>
     * メソッドを実行する前後に実行するメソッドを指定できます。
     * 前後のメソッドがインスタンスメソッドの場合は実行されません。
     * <br>
     * なお前後に実行するメソッドは引数無しのメソッドに限ります。
     * 
     * @param cls 実行するメソッドのクラス
     * @param startStr 実行するメソッド名の前文字列
     * @param setUpStr メソッド実行前に実行する引数無しメソッドの名前
     * @param tearDownStr メソッド実行後に実行するメソッドの名前
     * 
     * @throws InvocationTargetException 実行したメソッドが例外をスローした場合
     * @throws IllegalAccessException 何かしらの理由で実行メソッドにアクセスできなかった場合
     * @throws IllegalArgumentException startStrが空文字など不正な場合
     * @throws NullPointerException cls、もしくはstartStrがnullであった場合
     * 
     * @since 2.0
     */
    public static void invokeStaticMethodRun(Class cls, String startStr, String setUpStr, String tearDownStr) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
    {
        invokeStaticMethodRun(cls, startStr, null, null, 0);
    }

    
    /**
     * 指定した文字列から始まる引数無しのpublic staticメソッドを連続して実行します。
     * インスタンスメソッドは実行されません。
     * 対象メソッド実行中に発生した例外は無視され次のメソッドの実行に移ります。
     * <br><br>
     * メソッドを実行する前後に実行するメソッドや実行するメソッドの修飾子を指定できます。
     * 前後のメソッドがインスタンスメソッドの場合は実行されません。
     * <br><br>
     * 修飾子を指定した場合、指定された修飾子を含むメソッドのみを実行されます。
     * 修飾子を表す定数は当クラスに用意されており以下の通りです。
     * <ul>
     * <li>UNDEFINED : 修飾子を指定しません。</li>
     * <li>PUBLIC : public 修飾子を表します。</li>
     * <li>PRIVATE : private修飾子を表します。</li>
     * <li>PROTECTED : protected 修飾子を表します。</li>
     * <li>STATIC : static 修飾子を表します。</li>
     * <li>FINAL : final 修飾子を表します。</li>
     * <li>SYNCHRONIZED : synchronized 修飾子を表します。</li>
     * <li>VOLATILE : volatile 修飾子を表します。</li>
     * <li>TRANSIENT : transient 修飾子を表します。</li>
     * <li>NATIVE : native 修飾子を表します。</li>
     * <li>INTERFACE : interface 修飾子を表します。</li>
     * <li>ABSTRACT : abstract 修飾子を表します。</li>
     * <li>STRICT : strictfp 修飾子を表します。</li>
     * </ul>
     * 
     * @param cls 実行するメソッドのクラス
     * @param startStr 実行するメソッド名の前文字列
     * @param setUpStr メソッド実行前に実行する引数無しメソッドの名前
     * @param tearDownStr メソッド実行後に実行するメソッドの名前
     * @param isMod 実行するメソッドの修飾子
     * 
     * @throws InvocationTargetException 実行したメソッドが例外をスローした場合
     * @throws IllegalAccessException 何かしらの理由で実行メソッドにアクセスできなかった場合
     * @throws IllegalArgumentException startStrが空文字など不正な場合
     * @throws NullPointerException cls、もしくはstartStrがnullであった場合
     * @since 2.0
     */
    public static void invokeStaticMethodRun(Class cls, String startStr, String setUpStr, String tearDownStr, int isMod) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        if (cls == null) {
            throw new NullPointerException("Class-object is null.");
        }
        invokeAllPublicMethodRun(cls, null, startStr, setUpStr, tearDownStr, STATIC, UNDEFINED);
    }

    
    /**
     * 指定したオブジェクトのトレースをします。
     * 
     * @param out 出力先
     * @param o トレースするオブジェクト
     * @since 1.0
     */
    public static void variableTrace(PrintStream out, Object o) {
        if (out == null) {
            throw new NullPointerException("PrintStream is null.");
        }
        
        if (o == null) {
            out.println("object is null.");
        }
        String[] array = getVariables(o);
        
        if (array.length == 0) {
            out.println(o.getClass().getName() + " have not a variable.");
        }
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < array.length; i++) {
            sb.append(array[i] + ", ");
        }
        out.println(sb.toString());
        out.flush();
    }

    /**
     * 指定したオブジェクトのトレースをします。
     * 
     * @param out 出力先
     * @param o トレースするオブジェクト
     * @since 1.0
     */
    public static void variableTrace(PrintWriter out, Object o) {        
        if (out == null) {
            throw new NullPointerException("PrintWriter is null.");
        }
        
        if (o == null) {
            out.println("object is null.");
        }
        String[] array = getVariables(o);
        
        if (array.length == 0) {
            out.println(o.getClass().getName() + " have not a variable.");
        }
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < array.length; i++) {
            sb.append(array[i] + ", ");
        }
        out.println(sb.toString());
        out.flush();
    }

    /**
     * 指定した修飾子を含まれているかを判定します。
     * 識別値はJava 1.4.2_11でのMethodクラスで定義されているものと同値ですが、当クラスでも定義されています。
     * 
     * @param mod 対象のクラスやメンバ（変数・メソッド）の修飾子
     * @param isMod 含まれるか判定する修飾子の識別値
     * @return 修飾子が含まれている場合はtrue、含まれていない場合はfalse
     * @since 2.0
     */
    public static boolean isModifier(int mod, int isMod) {
        
        if ((isMod & PUBLIC) != 0) {
            if (!Modifier.isPublic(mod)) {
                return false;
            }
        }

        if ((isMod & PROTECTED) != 0) {
            if (!Modifier.isProtected(mod)) {
                return false;
            }
        }

        if ((isMod & PRIVATE) != 0) {
            if (!Modifier.isPrivate(mod)) {
                return false;
            }
        }

        if ((isMod & ABSTRACT) != 0) {
            if (!Modifier.isAbstract(mod)) {
                return false;
            }
        }

        if ((isMod & STATIC) != 0) {
            if (!Modifier.isStatic(mod)) {
                return false;
            }
        }

        if ((isMod & FINAL) != 0) {
            if (!Modifier.isFinal(mod)) {
                return false;
            }
        }

        if ((isMod & TRANSIENT) != 0) {
            if (!Modifier.isTransient(mod)) {
                return false;
            }
        }

        if ((isMod & VOLATILE) != 0) {
            if (!Modifier.isVolatile(mod)) {
                return false;
            }
        }

        if ((isMod & SYNCHRONIZED) != 0) {
            if (!Modifier.isSynchronized(mod)) {
                return false;
            }
        }

        if ((isMod & NATIVE) != 0) {
            if (!Modifier.isNative(mod)) {
                return false;
            }
        }

        if ((isMod & STRICT) != 0) {
            if (!Modifier.isStrict(mod)) {
                return false;
            }
        }

        if ((isMod & INTERFACE) != 0) {
            if (!Modifier.isInterface(mod)) {
                return false;
            }
        }
        
        return true;
    }


    /**
     * 指定したメソッドを実行します。
     * @param c
     * @param methodName
     * @param argTypes
     * @param obj
     * @param args
     * @return
     * @throws SecurityException
     * @throws NoSuchMethodException
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    private static Object invoke(Class c, String methodName, Class[] argTypes, Object obj, Object[] args)
            throws SecurityException, NoSuchMethodException, IllegalArgumentException,
            IllegalAccessException, InvocationTargetException
    {
        Method m = c.getMethod(methodName, argTypes);
        return m.invoke(obj, args);
    }


    /**
     * 指定したクラスの全てのpublicメソッドを実行します。
     * @param cls
     * @param obj
     * @param startStr
     * @param setUpStr
     * @param tearDownStr
     * @param isMod
     * @param unMod
     * @throws InvocationTargetException 
     * @throws IllegalAccessException 
     * @throws IllegalArgumentException 
     * @throws NullPointerException
     */
    private static void invokeAllPublicMethodRun(Class cls, Object obj, String startStr,
            String setUpStr, String tearDownStr, int isMod, int unMod)
        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException,
                NullPointerException {

        if (startStr == null) {
            throw new NullPointerException("Start-string is null.");
        } else if (startStr.length() == 0) {            
            throw new IllegalArgumentException("Start-string is empty.");
        }

        Method setUp = null;
        if (setUpStr != null && setUpStr.length() != 0) {
            try {
                setUp = cls.getMethod(setUpStr, null);
            } catch (Exception e) {
                setUp = null;
            }
        }

        Method tearDown = null;
        if (tearDownStr != null && tearDownStr.length() != 0) {
            try {
                tearDown = cls.getMethod(tearDownStr, null);
            } catch (Exception e) {
                tearDown = null;
            }
        }

        // Method 実行
        Method[] m = cls.getMethods();
        for (int i = 0; i < m.length; i++) {
            if (m[i].getName().startsWith(startStr)) {
                int mod = m[i].getModifiers();
                if (isMod != UNDEFINED) {
                    if (!isModifier(mod, isMod)) {
                        continue;
                    }
                }
                
                if (unMod != UNDEFINED) {
                    if (isModifier(mod, unMod)) {
                        continue;
                    }
                }
                
                if (m[i].getParameterTypes().length == 0) {
                    if (setUp != null) {
                        if (eqaulsModifier(mod, setUp.getModifiers())) {
                            setUp.invoke(obj, null);
                        }
                    }

                    try {
                        m[i].invoke(obj, null);
                    } catch (Exception e) {
                        // メソッド実行失敗は無視
                    }

                    if (tearDown != null) {
                        if (eqaulsModifier(mod, tearDown.getModifiers())) {
                            tearDown.invoke(obj, null);
                        }
                    }
                }
            }
        }
    }
    
    private static String[] getVariables(Object obj) {
        Class cls = obj.getClass();
        Field[] fields = cls.getFields();
        List l = new ArrayList();
        for (int i = 0; i < fields.length; i++) {
            try {
                l.add(fields[i].getName() + "=" + fields[i].get(obj));
            } catch (IllegalArgumentException e) {
                // トレース用なので無視
            } catch (IllegalAccessException e) {
                // トレース用なので無視
            }
        }
        return (String[])l.toArray(new String[0]);
    }

    private static boolean eqaulsModifier(int mod, int mod2) {
        if (Modifier.isStatic(mod)) {
            if (Modifier.isStatic(mod)) {
                return true;
            }
        } else {
            if (!Modifier.isStatic(mod)) {
                return true;
            }            
        }
        return false;
    }

}
