Home of: [工房 "藤車"] > [SourceForge.net における PageMixer]

フィルタの組み合わせ

本節では、 PageMixer フレームワークにおいて、 複数のフィルタを1つのフィルタとして扱う方法に関して説明します。

概要

クラス図

本節におけるクラス図を以下に示します。

クラス図
クラス図 (クリックで拡大表示)

色づけされているのが本節で定義するクラスで、 それ以外は PageMixer において定義済みです。

オブジェクト図

本節におけるオブジェクト図を以下に示します。

オブジェクト図
オブジェクト図 (クリックで拡大表示)

クラス名

本チュートリアルでは、 クラスは全てクラス名のみで表記されています。 完全な名称は以下の通りです。

PageMixer フレームワークのクラス

表記完全名
ConsumerContext jp.ne.dti.lares.foozy.pagemixer.mixer.ConsumerContext
DataProvider jp.ne.dti.lares.foozy.pagemixer.mixer.DataProvider
Filter jp.ne.dti.lares.foozy.pagemixer.mixer.Filter
FilterPipeline jp.ne.dti.lares.foozy.pagemixer.mixer.FilterPipeline
Renderer jp.ne.dti.lares.foozy.pagemixer.mixer.Renderer

チュートリアルの固有クラス

表記完全名
BasketFilter pagemixer.filter.BasketFilter
BasketEntryIterationFilter pagemixer.filter.BasketEntryIterationFilter
BasketTotalTextInsetFilter pagemixer.filter.BasketTotalTextInsetFilter
Bootstrap pagemixer.filter.Bootstrap

動機

例えば、 HTML ページの "買い物篭" 機能のために、 いくつかのフィルタクラスがあるとします。

これらのフィルタを別々に取り扱う場合、 これらの生成を1つづつ行わなければなりません。

お互いに接続済みの一連のフィルタを返すユーティリティメソッドを定義する、 というのは一見良いアイディアに見えますが、 そのメソッドが "最初のフィルタ" オブジェクトを返すとすると、 Renderer に "最後のフィルタ" を繋ぐことが出来ません。

フィルタを "木目細かく" 保つことは、 機能実現に多くのフィルタが必要になることを意味します。 そのため、フィルタ集合の取り扱いが容易でなければなりません。

FilterPipeline からの派生

1つのフィルタとして扱うためのフィルタ群の組み合わせのために、 PageMixer フレームワークは、 "FilterPipeline" クラスを提供しています。

このクラスは、 push されたフィルタを内部的に接続し、 自分に供給された Token シーケンスをそれらのフィルタに供給します。 それ自身が Filter クラスの派生クラスですので、 push されたフィルタ群が処理し終えた Token シーケンスを、 それが接続されたフィルタへと供給します。 このため、 FilterPipeline を1つの Filter として扱うことが出来ます。

HTML ページの "買い物篭" 機能のためのフィルタを組み合わせるフィルタは、 以下のように定義されます。


public class BasketFilter
    extends FilterPipeline
{
    public BasketFilter(Object providerKey,
                        Object dataKey)
    {
        super();

        push(new BasketEntryIterationFilter(providerKey,
                                            dataKey));
        push(new BasketTotalTextInsetFilter(providerKey));
    }
}

FilterPipeline からの派生

BasketEntryIterationFilter は、 "部分シーケンスの繰り返し" 節において説明しました。

"BasketTotalTextInsetFilter" は、 DataProvider から供給される全商品の、 合計金額をはめ込むフィルタです。 それぞれのフィルタは、 これまでの節での知識で十分理解できる程度の、 非常に単純で簡単なものですので、 本節ではこれらの説明を省略します。 詳細は、ソースファイルを直接参照してください。

繋いで混ぜる

以上で必要なものが全て揃いました。 実行コードは以下のようになります (詳細は BasketFilter を参照してください)。

try{
    // DataProvider の設定/取得用のキー
    final Object providerkey =
    "Shop.Basket.BasketEntryProvider";

    // 反復ごとのデータ設定/取得用のキー
    final Object dataKey =
    "Shop.Basket.BasketEntry";

    Bootstrap bootstrap =
    new Bootstrap.Default(filename)
    {
        protected void prepare(ConsumerContext context)
        {
            List entryList = BasketEntry.getEntryList();

            ListDataProvider provider =
            new ListDataProvider(entryList);

            // DataProvider をコンテキストに設定
            context.setValue(providerKey, provider);
        }
    };

    BasketFilter filter =
    new BasketFilter(providerKey, dataKey);

    // フィルタの適用
    bootstrap.execute(filter);
}
catch(Exception e){
    e.printStackTrace(System.err);
}
繋いで混ぜる

入力用のサンプル HTML ファイルは、 配布物中の "src/demo/servlet/war/WEB-INF/page/demosite" 配下にある "basket.ja.html" です。


次節「効率的な組み合わせ」へ