読者です 読者をやめる 読者になる 読者になる
無料で使えるシステムトレードフレームワーク「Jiji」 をリリースしました!

・OANDA Trade APIを利用した、オープンソースのシステムトレードフレームワークです。
・自分だけの取引アルゴリズムで、誰でも、いますぐ、かんたんに、自動取引を開始できます。

データ更新を行うユーティリティ

検索条件作成ユーティリティ向けに定義したプロパティを再利用して、データの更新を行うユーティリティも作ってみました。専用のユーティリティとペアで使うことで、
↓のような感じで指定したモデルの属性を更新(以下の例では、年齢を"2"に更新)できるようにするものです。

// 更新対象のモデル
Kitten mii = null; // 略
//mii の age プロパティを2に更新 
set( KittenProperties.AGE, 2 ).update( mii );

Google App Engineでは、取り出したモデルの属性を再設定すれば、データストアで記録された値も更新されるので、

public void update(Class<X> clazz,  Key key, Values<? super  X> values) 
throws UpdateFailedException {
    X object = (X) Tx.getPersistenceManager().getObjectById(clazz, key);
    values.update(object);
}

のような感じでデータ更新APIが作れます。

登場人物

  • Values
  • ValuesImpl
    • Valuesの実装。↑の「set(...)」で作成されるオブジェクトになります。
    • 更新する属性をMapで保持し、「java.beans.PropertyDescriptor」を使用して指定されたモデルの属性を更新します。
  • setメソッド
    • 更新対象プロパティと新しい値を受け取って、更新データを生成するユーティリティメソッドです。
    • staticインポートしての利用を想定。

実装

Values
/**
 * 更新データ
 * 
 * @param <X> モデルの型
 */
public interface Values<X> {
    
    /**
     * モデルのデータを更新する
     * @param item モデル
     * @return 更新後のモデル
     * @throws UpdateFailedException 更新時に何らかのエラーが発生した場合
     */
    X update( X item ) throws UpdateFailedException;
    
    /**
     * 更新データを追加する。
     * @param <V> 値の型
     * @param property プロパティ
     * @param value 更新後の値
     * @return 自身
     */
    <V> Values<X> set( Property<X,V> property, V value );
}
ValuesImpl
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

/**
 * {@link Values}の実装。
 * 
 * @param <X> モデルの型
 */
public class ValuesImpl<X> implements Values<X> {
    
    /**
     * 更新データセット
     */
    Map<Property<X, ?>, Object> values = 
        new HashMap<Property<X, ?>, Object>();
    
    @Override public <V> Values<X> set(Property<X, V> property, V value) {
        values.put(property, value);
        return this;
    }

    @Override public X update(X item) throws UpdateFailedException {
        for ( Map.Entry<Property<X, ?>, Object> e : values.entrySet() ) {
            try {
                PropertyDescriptor pd = new PropertyDescriptor( 
                        e.getKey().getName(), item.getClass() );
                pd.getWriteMethod().invoke(item, e.getValue());
            } catch (SecurityException ex) {
                throw new UpdateFailedException(ex);
            } catch (IllegalArgumentException ex) {
                throw new UpdateFailedException(ex);
            } catch (IllegalAccessException ex) {
                throw new UpdateFailedException(ex);
            } catch (InvocationTargetException ex) {
                throw new UpdateFailedException(ex);
            } catch (IntrospectionException ex) {
                throw new UpdateFailedException(ex);
            }
        }
        return item;
    }
}
setメソッド
/**
 * 更新データを作成する。
 * @param <X> モデルの型
 * @param <V> 値の型
 * @param property 更新するプロパティ
 * @param value 更新後の値
 * @return 更新データ
 */
public static <X, V> Values<X> set( Property<X, V> property, V value ) {
    return new ValuesImpl<X>().set(property, value);
}