SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

developerWorks Liaison(AD)

企業システムでも使われるウィジェット技術
第1回 「IBM共通のウィジェット技術iWidget」

  • X ポスト
  • このエントリーをはてなブックマークに追加

 ウィジェット/ガジェット/ミニアプリ/ブログパーツ、こんな言葉を目にすることはないでしょうか? 明確な定義はありませんが、これらは小さな画面を持つ軽量なアプリケーションの総称として使われます。本連載では、ウィジェット関連の技術動向についてご紹介していきます。第1回となる本稿ではユーザー・インターフェースにおいてウィジェットの果たす役割と価値を整理した上で、コードを交えてIBMが取り組むiWidget仕様に基づいたアプリケーションの仕組みを解説します。

  • X ポスト
  • このエントリーをはてなブックマークに追加

はじめに

 ウィジェット/ガジェット/ミニアプリ/ブログパーツ、こんな言葉を目にすることはないでしょうか? 明確な定義はありませんが、これらは小さな画面を持つ(あるいは非常に限られた面積の画面しか持てないといった方が正確かもしれません)軽量なアプリケーションの総称として使われます。ウェブサイトであれ、パソコンのデスクトップであれ、あるいはモバイルデバイス上であれ、こうしたアプリケーションの数は増加の一途をたどっており、日常的に利用するちょっとした機能をこれらによって満たしている方も多いことと思います。

 本連載では、ウィジェット関連の技術動向についてご紹介していきます。第1回となる本稿ではユーザー・インターフェースにおいてウィジェットの果たす役割と価値を整理した上で、コードを交えてIBMが取り組むiWidget仕様に基づいたアプリケーションの仕組みを解説します。

 なお、一般にアプリケーション開発の世界では、こうした単体である程度の機能を提供するミニアプリという意味だけではなく、GUI(グラフィカルユーザー・インターフェース)を構成するボタンや入力フィールドといった粒度の小さな部品という意味でも"ウィジェット"という言葉が使われます。本稿ではことわりがない限り、"ウィジェット"といえば前者を総称する言葉として使うこととします。

ウィジェット技術浸透の背景

 そもそも、なぜウィジェットというものが必要なのでしょうか? あるいはなぜこれだけの広がりを見せるまでに至ったのでしょうか? 少し考えてみたいと思います。

ユーザー・インターフェースのコンポーネント化

 インターネット上のウェブサイトであっても、イントラネット内であっても、ユーザーがその時々に利用する画面、つまりユーザー・インターフェースは複雑になってきています。これは一時点に閲覧したい情報、あるいは使い分けなければならない画面が多岐にわたってきていることに起因します。SOAやWeb2.0といった流れによってこの傾向はますます強くなっており、今後も加速されると予想されます。SOA/Web2.0時代のユーザー・インターフェースに求められているのは、必要なバックエンドサービスを適切にまとめて操作できる使いやすい画面といえるでしょう。多数のサービスを境目なく1つの全画面アプリケーションで美しく表現することも考えられます。しかし、それよりは個別あるいは限られた数のサービスに対応した"コンポーネント化された"小さな画面部品を並べた方がいろいろな意味で現実的かもしれません。

図1:部品を組み立てる vs 1画面に紡ぎあげる
図1:部品を組み立てる vs 1画面に紡ぎあげる
  • 再利用性:言うまでもなく、同じ部品を様々なシーンで活用できることは多重開発を防ぐことになります。
  • 図2:画面部品の再利用
    図2:画面部品の再利用

     

  • 細かいカスタムニーズへの対応:1つの画面が複数の部品から成り立つということは、場面や権限、業務といった様々な切り口で柔軟にその組み替えることで最適化できることを意味します。
  • 変更に強い:たとえ呼び込みたいサービスの1つに仕様変更があったとしても、その影響を受けるコンポーネントさえ対応すれば済みます。コードの変更が最小限に抑えられることは、スピードや品質など様々な点で有利です。
  • 図3:部品交換による変更への対応
    図3:部品交換による変更への対応

 上記に挙げた点だけでも、ウィジェットがもたらすユーザー・インターフェースのコンポーネント化(部品化)のメリットが大きいことはご理解いただけたのではないでしょうか。

最大公約数的な技術が主要スキル

 従来から様々なアプリケーションのコンポーネント化技術・仕様は存在しています。しかしながら、多くの場合、それらはサーバー側のアプリケーション実行環境やフレームワーク、プログラミング言語、開発ツールとセットになっています。Java EEや.NETがその代表例です。一方、Webブラウザに出すとなると、ユーザー・インターフェース層のために生成される最終的なコードは決まってHTML/XML/JavaScript/CSSといったものです。これまでの開発とは、サーバー環境とWebブラウザ側の両方のスキルを身につけてはじめて開発することが可能であったわけです。これは言い換えると、HTML/XML/JavaScript/CSSは誰もが知っている最大公約数的なスキルセットということになります。Web技術の進化と浸透に伴い、Webブラウザ以外でもそれを再利用したくなるのが自然な流れといえるでしょう。最近はクラサバ・アプリケーションにおいても一部はWebブラウザ部品を使って実現されることが多くなりました。

 少し長くなりましたが、ウィジェットで利用される技術について、現在大きなトレンドとして次のことがあげられます。

  • "最大公約数的"スキルさえあれば開発可能。
  • 仕様で定めるのは、生成されるブラウザ内で動作するコードに対する決めごとが主であり、それを作り出すアプリケーションを動かすサーバー側プラットフォームは問わない。それを支えるものとして、プログラミング言語やプラットフォームに依存しないXMLやJSONといったデータ型、バックエンドにHTTPで簡単にアクセスできるREST APIの活用促進。
  • クライアントアプリケーション型(非Webブラウザ)であっても、Webブラウザ部品を内包してWeb技術を最大限活用する傾向。
図4:ウィジェット開発に求められる主要スキル
図4:ウィジェット開発に求められる主要スキル

 誰もが知っているスキルをベースとすることによって、ウィジェット開発の敷居は飛躍的に下がります。特定プラットフォームに特化した知識がなくても始められますし、得意なプラットフォーム、得意な開発ツール、既存の資産に合わせた実装方式を選択することにより、より高度なアプリケーションへと発展させることも容易です。数多くの開発者が参入し、世の中に何十万と言う数のウィジェットの存在が"最大公約数的スキル"に主軸を置くことの効果を示していると思いませんか?

混沌とするウィジェット仕様

 ウィジェットの仕様がいくつも存在するといっても、実際どのようなものがあるのか、代表的なものをご紹介しておきます。

表1 代表的ウィジェット仕様
仕様名 中心企業/団体 タイプ 備考
Googleガジェット Google ブラウザ/
デスクトップ
圧倒数のウィジェットがGoogleガジェットサイトのディレクトリに登録されている。利用場所はWebブラウザだけではなく、デスクトップでも利用されている。これに対応したWebサイトのフレームワークが多いほか、ブログパーツとしても簡単に配置できる。新旧2種類のAPIがある。
OpenSocial OpenSocial.org ブラウザ ウィジェットだけの仕様ではない。特にウィジェットまわりはGoogleガジェットの新APIを利用している。対応しているソーシャルネットワークサービスのサイトが多い。
Googleデスクトップガジェット Google デスクトップ Googleデスクトップで動作するウィジェット。
Windows Vistaサイドバーガジェット Microsoft デスクトップ Windows Vistaが提供する標準機能。
Dashboardウィジェット Apple デスクトップ MAC OS Xが提供する標準機能。
Yahoo!ウィジェット Yahoo! デスクトップ
W3Cウィジェット W3C デスクトップ/
モバイル
標準化中のウィジェット仕様。ウェブ標準化団体のW3Cが取り組んでいることで注目を浴びています。少なくとも現在はデスクトップやモバイルが主フォーカスとなっているようです。
ブログパーツ なし ブラウザ 数行のHTMLコードをコピーペーストするだけでコンテンツをWebページに埋め込むことができるものの総称。
OpenAjax Metadata OpenAjax Alliance ブラウザ/
デスクトップ
Ajax系技術の標準化を行っている団体で策定中の標準仕様。IBMが考案したiWidget仕様がベース。

 いかがでしょうか? 類似した目的をもっているにも関わらず、仕様は整理されているどころか、多種多様で混沌としていることがご理解いただけたのではないでしょうか。

IBMが取り組むウィジェット関連技術

 さて、ここからはIBMで取り組んでいるウィジェット技術についてご紹介します。

iWidget仕様

 前述の通り、ウィジェットの標準仕様の策定は様々な形ですすんでいるものの、まだまだ足並みが揃うというには遠い状況です。一方、多種多様なソフトウェアにおいて何らかのユーザー・インターフェースを提供するのが当たり前になってきています。ソフトウェアベンダーでもあるIBMも例外ではなく、いち早く製品間で共通のコンポーネント化仕様に統一することによって、多くの相乗効果を望むことができます。この共通仕様はユーザー・インターフェースを提供するあらゆる製品で利用できることが望ましいです。そこに求められるのは軽量であること、そしてプラットフォームを選ばないことです。こうしてソフトウェア、ハードウェアを問わず、組織横断的に様々な視点からの要求を集約して作り上げたIBMのコンポーネント仕様がiWidget仕様です。iWidgetによってもたらされる効果は前述のウィジェットとしての一般的な効果に加えて下記があげられます。

  • 複数製品間での部品の共有や相互乗り入れの容易性:企業システム、コンシューマー向けサービスを問わず、つなぎこみたい機能は多岐にわたることが想定されます。iWidgetという共通軸をもつことで、相互にフロント機能を統合・連携することが可能なだけでなく、同じスキルで複数の製品を拡張することもできます。
  • これまで企業向けシステムで培ったウィジェット間連携のノウハウの踏襲:画面を構成するウィジェット間が連携することによってより生産性の高いユーザー・インターフェースを実現できることは、IBMがこれまでにブラウザベース、クライアントアプリケーション型のいずれでも実証してきたことです。こうしたアプリケーションを総称してコンポジット・アプリケーションとも呼んでいます。詳しくは こちら「生産性を向上させるコンポジット・アプリケーション」も参照ください。
  • 図5 コンポジット・アプリケーション
    図5 コンポジット・アプリケーション
  • 他仕様への対応の容易性:ウィジェット仕様間のアダプタ(ラッパー)を開発しさえすれば、異なる仕様に基づいた資産も再利用しやすくなります。現在の混沌とした状況の中からまた新しい仕様が生まれる可能性もあります。その時でも柔軟に対応ができるわけです。実際、IBMでは、iWidgetをポートレット(JSR168/JSR286)として配置するアダプタや、GoogleガジェットをiWidgetとして配置するアダプタを提供することで、既存の投資を守り、かつ外部のコンテンツも取り込める仕組みを提供しています。
  • 図6 仕様間の相互乗り入れ
    図6 仕様間の相互乗り入れ

 iWidget仕様は現時点ではまだIBMが自社標準として策定したものにすぎません。しかし、より多くの方に利用いただきやすくなるよう、OpenAjax Allianceという標準化団体にこのiWidget仕様を業界標準仕様のベースとして提案し、現在OpenAjax Metadataとして標準化活動が進行中です。詳細や標準化の最新の状況については下記サイトにてご覧いただけます。

Dojo Toolkit

 見栄えもよく操作性も高いWebユーザー・インターフェースをより簡単に作るために利用できるオープンソースのJavaScriptライブラリの1つです。Webブラウザ間の非互換を抽象化するだけでなく、使いやすいGUI部品や国際化など、企業アプリケーションでの利用に耐える十分な機能を備えているものです。IBMはではこのプロジェクトに積極的に投資・参加するだけでなく、標準Webフレームワークの1つとして多くの製品で採用しています。以降、解説するiWidgetフレームワークでもDojo Toolkitを活用しています。

セキュア・マッシュアップ

 IBMではウィジェット仕様だけでなく、ウィジェットにおけるセキュリティについても力を入れて取り組んでおります。こちらについて、本連載の第2回で取り上げる予定です。

iWidget仕様

 それでは、iWidgetとはどのような仕様なのか、基本的なコードをご覧いただきながらアプリケーション開発を解説することとします。なお、iWidgetを理解するためには、HTML/JavaScriptの基礎知識は必須です。加えて、iWidgetフレームワークの実装にも使われているDojo ToolkitというJavaScriptライブラリに関する知識があると、より理解しやすいです。必要に応じて関連サイトを参照しながらお読みください。

HelloWorld

 まずはプログラミングでおなじみのHelloWorldのiWidget版です。このシンプルなiWidgetを作成するのに必要なファイルはiWidgetの定義ファイル1つだけです。ウィジェット定義は以下のようなXMLとなります。

サンプル1:HelloWorldWidget.xml
<?xml version="1.0" encoding="UTF-8"?>
<iw:iwidget name="HelloWorldWidget"
 xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget"
 supportedModes="view" mode="view">
    <!-- VIEWモードのコンテンツ  -->
    <iw:content mode="view">
        <![CDATA[ <b>Hello World!</b> ]]>
    </iw:content>
</iw:iwidget>

 このiWidgetを表示させた例が下記になります。コンテンツ周囲の見栄えは埋め込むページのスタイルやテーマによって変わりますが、この詳細については本稿では割愛します。

図7 HelloWorldWidget実行結果
図7 HelloWorldWidget実行結果

 このウィジェットのポイントは以下の通りです。

  • "iw:":で始まる名前空間のついたタグはiWidget仕様で定義されたものです。
  • コンテンツ:<iw:content>要素の中に書かれています。この中はHTMLをエスケープすることなく記述できるよう、CDATAとして記述しています。
  • モード:<iw:content>要素にはmode属性として"view"が指定されています。ウィジェットには通常表示されるコンテンツの他、設定画面やヘルプ画面など、複数のモードとそれに応じたコンテンツを表示することができます。"view"と指定することによって、ここに指定されたコードがVIEW(通常)モードのコンテンツであることを示しています。
  • 図8:iWidgetのモード
    図8:iWidgetのモード
    • 対応モード:<iw:iwidget>要素のsupportedModes属性ではこのウィジェットが対応しているモードを列挙します。この例ではVIEWモードのみに対応します。
    • デフォルトモード:<iw:iwidget>要素のmode属性ではデフォルトモードを指定します。

 ウィジェットの定義ファイルが出来上がったら、これをhttp(s)でアクセスできる任意のWebサーバーに配置します。そしてウィジェットを埋め込みたいページには下記のようなHTMLコードを記述します。

サンプル2:Widgetをページに挿入するためのコード
<span id="helloworld" class="mm_iWidget">
<a href="http://[hostfqdn]:[port]/path/to/HelloWorldWidget.xml" class="mm_Definition"></a>
</span>

 実際にこのようなHTMLを記述することは少ないです。それはiWidgetをドラッグ&ドロップでページに配置できる環境においては、こうしたコードの挿入はメニュー操作の結果として自動的に行われていたり、ポータルサイトのような仕組みで生成されたりするからです。ただし、裏でこのような動作をしていることだけは覚えておくと処理の流れを理解しやすいでしょう。

 これだけの記述でウィジェットが表示される仕掛けは次のようになります。

  • ウィジェットを表示できるページには、<head>要素内で、あらかじめウィジェットを表示するためのJavaScriptフレームワークが読み込まれています。このフレームワークのURLは環境(製品)によってまちまちですのでここでは扱いません。このフレームワークがいわばWebブラウザ内で動作するiWidgetを表示するためのミドルウェア、iWidgetコンテナといえるものです。
  • このフレームワークはマイクロフォーマット式に事前定義されたclass属性を手掛かりにHTMLページ内を動的に書き換える仕組みを備えています。一般的にclass属性は適用するCSS指定するために利用しますが、マイクロフォーマットでは、HTMLのマークアップに意味を持たせるためにこのclass属性を転用します。
  • 上記の例ではclass属性"mm_iWidget"がつく<span>タグを見つけたフレームワークはclass属性 "mm_Definition"が指定された子要素<a>のhref属性から、ここに表示したいウィジェットの定義ファイルのありかを知ります。
  • ウィジェット定義ファイルが動的に読み込まれ、<iw:content>で指定されたコンテンツが挿入されます。

 以上が基本的な流れとなります。

RSSリーダー

 さて、前述のHelloWorldのようにウィジェット定義ファイルにコンテンツを直接記述したのでは、静的なアプリケーションしか書けません。動的にバックエンドから取得したデータを表示するようなアプリケーションはどのように書けばよいのでしょうか? 外部リソースとしてRSSフィードを読み込んで表示するもう少し高度な例を使って解説したいと思います。

図9 ウィジェット動作例
図9 ウィジェット動作例

 今回用意するファイルは2つ、ウィジェット定義ファイルと、アプリケーションロジックを記述したJavaScriptファイルです。

サンプル3:FeedReaderWidget.xml
<?xml version="1.0" encoding="UTF-8"?>
<iw:iwidget
 name="HellodWWidget"
 xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget"
 iScope="com.ibm.jp.naoyam.samples.widgets.HellodWWidget"
 supportedModes="view" mode="view">
    
    <!-- このウィジェットの動作に必要なライブラリを記述
    ここで読み込むライブラリのいずれかで、上記iScopeで指定するクラスを提供する-->
    <iw:resource uri="widget.js"/>
    
    <iw:content mode="view">
        <![CDATA[<div id="_IWID_VIEWROOT"></div>]]>
    </iw:content>
</iw:iwidget>

 先ほどの例に以下の要素が加わっています。

  • <iw:iwidget>要素では、iScope属性が設定されています。iWidgetでは、ウィジェットのアプリケーションロジックをつかさどるのはJavaScriptのオブジェクトです。このiScopeで指定されたJavaScriptのクラスのインスタンスがこのウィジェットに割り当てられます
  • <iw:resource>要素によって、外部のJavaScriptファイルを明記しています。この中では、先ほどiScopeで指定されていたJavaScriptのクラスを提供する.jsファイルのURLを指定します。
  • <iw:content>要素の中、今回は目印となるタグを除けば具体的コンテンツは空のままです。アプリケーションロジックでコンテンツを外から書き換えることにします。id属性を割り当てることで書き換える箇所を特定しやすくしています。

 続いて、アプリケーションロジックのJavaScriptファイルがこちらです。

サンプル4:widget.js(アプリケーションロジック)
// クラス宣言
dojo.declare("com.ibm.jp.naoyam.samples.widgets.HellodWWidget", null, {
    domID: null,
    /**
     * LifeCycle イベント。ウィジェットがロードされたときに呼ばれる
     */
    onLoad: function(){
        // このように記述することで、Firebugなどのコンソールにメッセージ出力
        console.log("HellodWWidget#onLoad");
        /**
         * 1つのページに同じウィジェットを2つ以上配置しても識別できるよう、
         * フレームワークは各ウィジェットにユニークなIDを割り当てる。
         * このIDはウィジェット内のタグのプレフィックスとしても使われ、ページ内の
         * 特定の要素にアクセスしたいときに多用するためメンバー変数に格納
         */
        this.domID = "_" + this.iContext.widgetId + "_";
        console.log(this.domID);
    },
    /**
     * LifeCycle イベント。VIEWモードになったときに呼ばれる
     */
    onview: function(){
        console.log("HellodWWidget#onview");
        //コンテンツの取得・描画を行うfunctionを対象RSSフィードを指定してコール
        this.renderfeed("http://www.ibm.com/developerworks/jp/rss/dw_dwjp.xml");
    },
    renderfeed: function(url){
        console.log("HellodWWidget#renderfeed");
        // ここではDojoが提供するAPIを仕様してAjaxコールを発行します
        dojo.xhrGet({
            /**
             * iWidgetフレームワークが提供するプロキシーコンポーネントを介してリモートリソースを取得。
             * iContext.io.rewriteURIでリモートリソースのURLがプロキシー経由のURLに変換。
             * オリジナル: http://www.ibm.com/developerworks/jp/rss/dw_dwjp.xml
             * 変換後: /mum/proxy/http/www.ibm.com/developerworks/jp/rss/dw_dwjp.xml
             */
            url: this.iContext.io.rewriteURI(url),
            mywidget: this,
            handleAs: 'xml',
            load: function(response){
                var title = dojo.query("title", response)[0].textContent;
                var items = dojo.query("item", response);
                // 取得したフィードからHTML組み立てています
                var buff = "<div><b>" + title + "</b></div>";
                dojo.forEach(items, function(item){
                    var title = dojo.query("link", item)[0].textContent;
                    var link = dojo.query("link", item)@[0].textContent;
                    buff += "<div><a";
                    buff += " href='" + link + "'";
                    buff += " target='_blank'";
                    buff += ">";
                    buff += title;
                    buff += "</a></div>";
                })
                // dojo.byIdでIDが一意にわかる任意の要素を簡単に取得
                dojo.byId(this.mywidget.domID + "VIEWROOT").innerHTML = buff;
            }
        })
    }
});

 いかがでしょうか? 2つのサンプルを交えて、iWidgetの動作の仕組みを追うとともに、基本的なアプリケーションの記述方法をご紹介しました。

図10:iWidget動作の流れ
図10:iWidget動作の流れ

 今回の例では利用していませんが、アプリケーションとして実現したい様々な機能を実装しやすいよう、フレームワークにはサーバーサイドのコードを使うことなくJavaScriptだけで利用できる下記をはじめとする機能も提供されています。

  • 設定情報の永続化
  • 1ページに同じウィジェットを複数配置しても識別できるユニークなIDの自動割り当て
  • ユーザー情報の取得
  • ウィジェットのメタ情報の取得

 本解説からは割愛しますが、是非iWidget仕様を参考にお試しください。

IBM製品での採用状況

 最後に、IBMのソフトウェア製品やテクノロジーでiWidget対応をしているものは次々に出てきています。ここではその一部を名称だけですがご紹介します。

iWidgetを自由に組み合わせて表示できる製品

 iWidgetをユーザー・インターフェースの中に配置することができる製品群です。

  • IBM Mashup Center / IBM Lotus Mashups
  • IBM Lotus Connections
  • IBM WebSphere Portal
  • WebSphere Business Space

iWidgetを提供する、あるいは対応するiWidgetが提供されている製品

 汎用的なiWidgetを提供する製品、あるいは提供されたiWidget経由でアクセスすることができる製品の一部です。

  • IBM Mashup Center / IBM Lotus Mashups
  • IBM Lotus Forms / IBM Lotus Forms Turbo
  • IBM Lotus Quickr
  • IBM Lotus Sametime
  • IBM FileNet P8

iWidgetを開発できるツール

 iWidgetはテキストエディターだけで開発することも可能です、しかしながら、より生産性高く対象プラットフォームやスキルに応じたアプリケーション開発ができる下記ツールも提供されています。

  • IBM Lotus Widget Factory
  • IBM WebSphere Portlet Factory
  • IBM WebSphere Dashboard Framework
  • IBM WebSphere sMash
  • IBM Rational Application Developer
  • IBM Lotus Domino Designer

まとめ

 連載第1回となりました今回は、世の中のウィジェット技術について、その有用性を示すとともに、標準化が進みきらずに混沌している状況であることをご説明しました。また、その状況下でIBMが力を入れて適用範囲を広げているiWidget仕様について、サンプルコードを交えて解説し、iWidget対応の製品についても一覧ではありますが、ご紹介しました。特定のプラットフォームや開発ツールに依存することなく、今お持ちのスキルの延長で使っていただける仕様となっていますので是非お試しください。

 なお、今回ご紹介のコードはIBM Mashup Centerで稼働確認をしております。このIBM Mashup Centerは60日間無償トライアル版の他、インターネット上の無料でお試しいただける公開サイトLotus Greenhouseでも提供しておりますので、併せてご利用ください。詳しくはIBM Mashup Centerの技術情報のサイトをご覧ください。

参考資料

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加

【AD】本記事の内容は記事掲載開始時点のものです 企画・制作 株式会社翔泳社

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/4542 2009/11/02 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング