How to use maru-dogデータバインドライブラリ (2)

前回は最もシンプルな利用例を紹介しましたが、今回はシンプルコンバータについて前回の例をもとに紹介します。

UserProfileクラスのgenderはbyte型で1が男性(man)、2が女性(woman)を表していますが、バインド先のUserBeanのgenderはString型でman、womanを設定しなければならないような場合にコンバータを利用します。

Marudogでは2種類のコンバータをサポートしているのですが、シンプルコンバータについては基本的に以下の規約を守っていればいいだけです。

  • publicクラスであること
  • デフォルトコンストラクタを持っていること
  • コンバータメソッドのメソッド名がexecuteであり、引数は@Bindが付与されたフィールド(もしくはメソッドの戻り値)と同じ型であり、戻り値は@Boundが付与されたフィールド(もしくはsetterメソッドの引数の型)と同じ型であること
  • 状態を持たないこと

それでは前回のサンプルコードにコンバータを追加した例を示します。

import org.maru.dog.Director;
import org.maru.dog.Marudog;
import org.maru.dog.annotation.Bind;
import org.maru.dog.annotation.Bound;
import org.maru.dog.converter.Converter;

public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Director director = Marudog.getDirector();

        UserMaster master = getUserMaster();
        UserProfile profile = getUserProfile();
        UserBean user = new UserBean();

        director.bind(user, master, profile);
        System.out.println(user);
    }

    private static UserMaster getUserMaster() {
        UserMaster master = new UserMaster();
        master.userId = "ABC123";
        master.password = "PASSWORD";
        return master;
    }

    private static UserProfile getUserProfile() {
        UserProfile profile = new UserProfile();
        profile.address = "Tokyo/Japan";
        profile.age = 25;
        profile.gender = 1;
        profile.userName = "Maru dog";
        return profile;
    }

    static class UserBean {
        @Bound
        private String userId;

        @Bound
        private String userName;

        @Bound
        private String address;

        @Bound
        private short age;

        @Bound
        private String gender;

        @Override
        public String toString() {
            return "UserBean [userId=" + userId + ", userName=" + userName
                    + ", address=" + address + ", age=" + age + ", gender="
                    + gender + "]";
        }

    }

    static class UserMaster{
        @Bind
        private String userId;

        private String password;
    }

    static class UserProfile {
        @Bind
        private String userName;

        @Bind
        private String address;

        @Bind
        private short age;

        // 1:man 2:woman
        @Bind
        @Converter(converterClass = GenderConverter.class)
        private byte gender;
    }

    static public class GenderConverter {
        public GenderConverter(){}

        public String execute(byte gender) {
            if (gender == 1) {
                return "man";
            } else if (gender == 2){
                return "woman";
            } else {
                throw new IllegalArgumentException("Unknown gender.");
            }
        }
    }

}

注目すべき点はUserProfileクラスのgenderフィールドに付与した@Converterアノテーションです。このアノテーションを変換を行いたいデータを持するバインド元のフィールド(もしくはメソッド)に付与し、コンバータクラスを設定するだけです。

コンバータクラスはGenderConverterであり、上記で述べた最低限の規約を守った非常にシンプルなものです。

上記プログラムの実行結果は以下のようになります。

UserBean [userId=ABC123, userName=Maru dog, address=Tokyo/Japan, age=25, gender=man]

UserBeanのgenderに変換後の"man"が設定されていることが分かると思います。

処理概要は、Director内部でコンバータが生成されバインド前にコンバータのexecuteメソッドを呼び出し、データを変換してバインドを行っています。一度利用されたコンバータはDirector内部でキャッシュされます。従ってSingletonなオブジェクトであるといます。

今回はここまでですが、最後にDirectorのbind、bindByFieldNameそれそれのメソッドはDirector自身を返すので以下のような記述が可能です。

Director director = Marudog.getDirector();
ResutBean result = director.bind(userBean, userMaster, userProfile)
                           .bind(orderBean, userOrder, userBean, orderMaster)
                           .bind(productBean, orderedProduct, productMaster)
                           .getInstance(ResultBean.class, userBean, orderedBean, productBean);

プロジェクトサイト:http://maru.sourceforge.jp/index.html
ドキュメント:http://maru.sourceforge.jp/document_dog.html