How to use maru-dog Beanプロパティデータバインドライブラリ (5)

前回は拡張コンバータについて説明をしました。今回は、第1回の終りのほうで少し触れたフィールド実名によるバインドについて簡単に解説したいと思います。

これまで基本的には@Bound、@Bindアノテーションが付与されたフィールドに対してバインドを行う方法でした。その際に@Bound、@Bindのname項目にバインド時の名前が定義されていればその名前をバインドの名前解決に利用し、定義されていなければフィールド名をバインドの名前解決に利用するという処理が主だったかと思います。

フィールド名による名前解決は各Beanに定義されているフィールドの実名のみを利用してバインドを行います。その際に@Bind、@Boundアノテーションを付与して明示的にバインドのための名前を定義していてもその情報は無視されます。

有効なアノテーションはコンバータアノテーションと@Fromのみです。

それでは以下に簡単な例を示します。第1回で利用した例とほとんど同じです。

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.annotation.From;
import org.maru.dog.converter.Converter;

public class Main {

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

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

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

    }

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

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

    static class UserBean {

        private String userId;

        @Bound(name = "name")
        private String userName;

        private String address;

        private short age;

        private String gender;

        @From(UserMaster.class)
        private String date;

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

    }

    static class UserMaster{
        private String userId;

        private String password;

        private String date;
    }

    static class UserProfile {

        private String userName;

        private String address;

        private short age;

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

        @Bind(name = "name")
        private String nickName;

        private String date;
    }

    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.");
            }
        }
    }
}

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

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

まず、バインド処理を行う際に使うメソッドがこれまでと違ってます。

フィールド名によるバインドを行う際には以下のメソッドを利用します。

Director#bindByFieldName(T target, K... inputs)
Director#getInstanceByFieldNameBind(Class target, K... inputs)
Director#getInstanceByFieldNameBind(T target, K... inputs)

※getInstanceByFieldNameBindはversion-0.6.2以降でのみ利用可能です。

基本的に@Bind、@Boundアノテーションが付与されていないのが見て取れます。フィールド名の一致によるバインドなので、どちらか一方にしかないないフィールドについてはバインド処理は行われません。(上記例ではpasswordフィールド)

また、UserBeanのuserNameフィールドですが@Bound(name = "name")アノテーションが設定されており、通常のバインド処理の場合UserProfileのnickNameの値がバインドされるますが、フィールド名でのバインド処理の場合は、付与されたアノテーション情報を無視して、同名のUserBeanのuserNameがバインドされているのが分かります。

dateについてはUserMaster、UserProfile両方ともに存在します。このような場合はターゲット側で@Fromアノテーションを付与し、どちらのクラスからバインドするかを明示しておく必要があります。もし、明示しなかった場合は重複エラーとなります。上記例ではUserBeanを指定しており、実行結果もUserBeanのdateの値と同じものがバインドされていることが見て取れます。

以上がフィールド名によるバインドの概要になります。

フィールド名による名前解決メソッドもbindByFieldNameはDirector自身を返しgetInstanceByFieldNameBindはターゲットインスタンスを返すため、以下のような記述が可能です。

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

今回は以上になります。

サイトページ:http://maru.sourceforge.jp/
ドキュメントページ:http://maru.sourceforge.jp/document_dog.html