blob: 146062cecca9fe52041455b390511a435c8e8225 [file] [log] [blame]
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
= NetBeans プラットフォームフィードリーダーのチュートリアル
:jbake-type: platform_tutorial
:jbake-tags: tutorials
:jbake-status: published
:syntax: true
:source-highlighter: pygments
:toc: left
:toc-title:
:icons: font
:experimental:
:description: NetBeans プラットフォームフィードリーダーのチュートリアル - Apache NetBeans
:keywords: Apache NetBeans Platform, Platform Tutorials, NetBeans プラットフォームフィードリーダーのチュートリアル
NetBeans プラットフォームフィードリーダーのチュートリアルへようこそ。このチュートリアルで構築するフィードリーダーは、Mozilla Firefox Sage プラグインをモデルにした、簡単な RSS/Atom フィードブラウザです。ブラウザで開くことができる個別のフィードエントリを表すサブノードを持つ、フィードのツリーを提示します。
最終結果を説明するために、このチュートリアルで構築するフィードリーダーを次に示します。 link:https://netbeans.org/rss-091.xml[NetBeans Highlights フィード]からのフィードエントリが表示されています。
image::images/feedreader_60-result.png[]
== 事前に必要な知識
このチュートリアルの操作では、NetBeans プラットフォーム開発に関する知識は必要ありません。Java プログラミングの経験があれば役立ちますが、必須ではありません。ただし、このチュートリアルを開始する前に次のドキュメントを読んでおくと、有用な予備知識が得られ、役に立つでしょう。
* link:https://netbeans.apache.org/tutorials/60/nbm-feedreader_background.html[FeedReader アプリケーションを作成するための準備]。このドキュメントには、このチュートリアルの背景が説明されています。このチュートリアルで行うすべてのことが、概念的に説明されています。このチュートリアルで構築するサンプルのソースコードがある場所も示されています。
* link:../61/nbm-htmleditor_ja.html[NetBeans プラットフォームクイックスタート]。この短いチュートリアルには、NetBeans プラットフォーム上にリッチクライアントアプリケーションを構築する詳細なプロセスが説明されています。主な開発段階とツールがカバーされています。また、このチュートリアルの結果として HTML エディタが作成されます。
== アプリケーションの設定
NetBeans IDE では、NetBeans 上のアプリケーション構築は、アプリケーションの基盤として使用する多くのファイルを生成することから始まります。たとえば、IDE には、NetBeans プラットフォーム上に構築されるモジュールおよびアプリケーションで必要なすべての基本ファイルを設定する、「モジュールプロジェクト」ウィザード、「モジュールスイートプロジェクト」ウィザード、および「ライブラリラッパーモジュールプロジェクト」ウィザードがあります。
* *モジュールスイートプロジェクト。*互いに依存関係を持つ一連のモジュールプロジェクトおよびライブラリラッパーモジュールプロジェクトをグループ化するプロジェクト。グループ単位でまとめて配備を行うことができます。
* *ライブラリラッパーモジュールプロジェクト。*ライブラリ JAR ファイルを自らのクラスパス上に置き、モジュールから JAR ファイルのパッケージの一部またはすべてを公開パッケージとしてエクスポートするプロジェクト。
* *モジュールプロジェクト。*NetBeans プラットフォーム上に構築されたモジュールまたはアプリケーションの機能、ビジネスロジック、およびユーザーインタフェースを実装するためのプロジェクト。
=== モジュールスイートプロジェクトの作成
[start=1]
1. 「ファイル」>「新規プロジェクト」(Ctrl-Shift-N) を選択します。「カテゴリ」で「NetBeans モジュール」を選択します。「プロジェクト」で「モジュールスイートプロジェクト」を選択します。画面は次のようになります。
image::images/feedreader_60-suite-wiz.png[]
「次へ」をクリックします。
[start=2]
1. 「名前と場所」パネルの「プロジェクト名」に「 ``feedreader-suite`` 」と入力します。「プロジェクトの場所」を使用コンピュータ上の任意のフォルダに変更します。画面は次のようになります。
image::images/feedreader_60-suite-wiz2.png[]
「完了」をクリックします。
IDE によって ``feedreader-suite`` プロジェクトが作成され、「プロジェクト」ウィンドウで次のように表示されます。
image::images/feedreader_60-suite.png[]
プロジェクトには、次のサブセクションで作成するモジュールプロジェクトおよびライブラリラッパーモジュールプロジェクトが含まれます。
=== ライブラリのラップ
1 つのモジュールにフィードリーダーアプリケーション全体をバンドルできました。ただし、このアプリケーションは RomeRome Fetcher、および JDom ライブラリを必要とします。
* *Rome。*非常に簡単な API を使用して、RSS および Atom フィードを読み取ります。
* *Rome Fetcher。*HTTP 経由でフィードを検索できます。
* *JDom。*XML 構文解析 API です。これは、Rome ライブラリで使用するためだけに、フィードリーダーに必要なものです。
あとで、これらのライブラリで使用する可能性のあるより多くのモジュールを持つフィードリーダーアプリケーションを拡張する場合、フィードリーダー全体にではなくライブラリモジュールのみに依存させることをお勧めします。また、ライブラリモジュールは「自動読み込み」が可能です。これは、NetBeans が必要なときだけライブラリモジュールを読み込むことを意味します。それまでは、実行時にメモリーが占有されることはありません。
[start=1]
1. 次に示すように、「プロジェクト」ウィンドウで、モジュールスイートプロジェクトの「モジュール」ノードを右クリックし、「新規ライブラリを追加」をクリックします。
image::images/feedreader_60-add-lib0.png[]
これを行うと、次のようになります。
image::images/feedreader_60-lib-wiz.png[]
[start=2]
1. 前に示す「ライブラリを選択」パネルで、JDom をダウンロードした場所のフォルダを参照して ``jdom.jar`` および ``LICENSE.txt`` を選択し、「次へ」をクリックします。
[start=3]
1. 「名前と場所」パネルで、デフォルトをすべて受け入れます。画面は次のようになります。
image::images/feedreader_60-lib-wiz3.png[]
NOTE: ライブラリラッパーモジュールプロジェクトは、モジュールスイートプロジェクト内に保存されます。別の場所に保存することもできますが、バージョン管理上の目的により、モジュールスイートプロジェクト内に配置することをお勧めします。そのため、 ``feedreader-suite`` モジュールスイートプロジェクトは「モジュールスイートに追加」ドロップダウンで選択されています。
「次へ」をクリックします。
[start=4]
1. 「基本モジュール構成」パネルで、デフォルトをすべて受け入れます。画面は次のようになります。
image::images/feedreader_60-lib-wiz2.png[]
「完了」をクリックします。
新規ライブラリラッパーモジュールプロジェクトが IDE で開き、「プロジェクト」ウィンドウに表示されます。「プロジェクト」ウィンドウには次のものが表示されます。
image::images/feedreader_60-lib-wiz4.png[]
[start=5]
1. この節の手順 1 に戻り、Rome 用のライブラリラッパーモジュールプロジェクトを作成します。すべてのデフォルトを受け入れます。
[start=6]
1. この節の手順 1 に戻り、Rome Fetcher 用のライブラリラッパーモジュールプロジェクトを作成します。すべてのデフォルトを受け入れます。
これで、3 つのライブラリラッパーモジュールプロジェクトを持つモジュールスイートプロジェクトができました。これは、このチュートリアルで利用できる、多くの有用な Java クラスを提供します。
=== モジュールプロジェクトの作成
この節では、アプリケーションが提供する機能性に関するプロジェクトを作成します。このプロジェクトは、前の節で作成したライブラリラッパーモジュールによって利用可能になったクラスを使用します。
[start=1]
1. 次に示すように、「プロジェクト」ウィンドウで、モジュールスイートプロジェクトの「モジュール」ノードを右クリックし、「新規を追加」をクリックします。
image::images/feedreader_60-module-project.png[]
これを行うと、次のようになります。
image::images/feedreader_60-module-wiz.png[]
[start=2]
1. 「名前と場所」パネルで、「プロジェクト名」に「 ``FeedReader`` 」と入力します。すべてのデフォルトを受け入れます。「次へ」をクリックします。
[start=3]
1. 「基本モジュール構成」パネルで、「コード名ベース」の ``yourorghere`` ``myorg`` に置き換え、コード名ベース全体を ``org.myorg.feedreader`` にします。「モジュール表示名」に「 ``FeedReader`` 」と入力します。「ローカライズ版バンドル」と「XML レイヤー」の場所はそのままにしておきます。これらは ``org/myorg/feedreader`` という名前のパッケージに格納されます。画面は次のようになります。
image::images/feedreader_60-module-wiz2.png[]
「完了」をクリックします。
IDE によって FeedReader プロジェクトが作成されます。このプロジェクトには、モジュールのソースと、プロジェクトの Ant 構築スクリプトなどのプロジェクトメタデータがすべて含まれます。IDE でプロジェクトが開きます。「プロジェクト」ウィンドウ (Ctrl-1) で、プロジェクトの論理構造を表示できます。また、「ファイル」ウィンドウ (Ctrl-2) で、プロジェクトのファイル構造を表示できます。「プロジェクト」ウィンドウは次のように表示されます。
image::images/feedreader_60-module.png[]
これで、新しいアプリケーションのソースの構造が作成されました。次の節では、いくつかのコードの追加を開始します。
== フィードリーダーウィンドウの作成
この節では、「ウィンドウコンポーネント」ウィザードを使用して、カスタムウィンドウコンポーネントを作成するファイルと、このコンポーネントを呼び出すアクションを作成するファイルを生成します。また、このウィザードは、アクションをメニュー項目として ``layer.xml`` に登録し、ウィンドウコンポーネントをシリアライズするためのエントリを追加します。この節のすぐあとで、「ウィンドウコンポーネント」ウィザードが生成するファイルを試す方法を説明します。
[start=1]
1. ``FeedReader`` プロジェクトノードを右クリックし、「新規」>「その他」を選択します。「カテゴリ」で「モジュールの開発」を選択します。次に示すように、「ファイルの種類」で「ウィンドウコンポーネント」を選択します。
image::images/feedreader_60-windowcomp-wiz.png[]
「次へ」をクリックします。
[start=2]
1. 「基本設定」パネルで、ドロップダウンリストから ``explorer`` を選択し、次に示すように「アプリケーションの起動時に開く」をクリックします。
image::images/feedreader_60-windowcomp-wiz2.png[]
「次へ」をクリックします。
[start=3]
1. 「名前と場所」パネルで、「クラス名の接頭辞」として「Feed」を入力し、 ``rss16.gif (
image::images/feedreader_rss16.gif[])`` を保存した場所を参照します。この GIF ファイルが、アクションを呼び出すメニュー項目に表示されます。画面は次のようになります。
image::images/feedreader_60-windowcomp-wiz3.png[]
「完了」をクリックします。
「プロジェクト」ウィンドウに次が表示されます。
image::images/feedreader_60-windowcomp.png[]
IDE によって、次の新しいファイルが作成されます。
* ``FeedAction.java`` Open Feed Window」というラベルと ``rss16.gif`` 画像 (
image::images/feedreader_rss16.gif[]) を使用して、「ウィンドウ」メニューに表示するアクションを定義します。Feed ウィンドウを開きます。
* ``FeedTopComponent.java`` Feed ウィンドウを定義します。
* ``FeedTopComponentSettings.xml`` ``org.myorg.feedreader`` リッチクライアントアプリケーションのすべてのインタフェースを指定します。それぞれインスタンス化することなく、インスタンスの簡単な検索を可能にします。クラスの読み込みやオブジェクトの作成の必要をなくし、パフォーマンスを向上させます。 ``layer.xml`` ファイルの ``Windows2/Components`` フォルダに登録されます。
* ``FeedTopComponentWstcref.xml`` コンポーネントへの参照を指定します。コンポーネントが複数のモードに属することができるようにします。 ``layer.xml`` ファイルの ``Windows2/Modes`` フォルダに登録されます。
IDE によって次の既存のファイルが変更されます。
* * *
``project.xml`` 2 つのモジュール、 ``ユーティリティー API `` (Javadoc を参照するには link:http://bits.netbeans.org/dev/javadoc/org-openide-util/overview-summary.html[ここ]をクリック) および ``ウィンドウシステム`` (Javadoc を参照するには link:http://bits.netbeans.org/dev/javadoc/org-openide-windows/overview-summary.html[ここ]をクリック) の依存関係が追加されています。
* ``Bundle.properties``
次の 3 つのキーと値のペアが追加されています。
* ``CTL_FeedAction`` ``FeedAction.java`` に定義されたメニュー項目のラベルをローカライズします。
* ``CTL_FeedTopComponent`` ``FeedTopComponent.java`` のラベルをローカライズします。
* ``HINT_FeedTopComponent`` ``FeedTopComponent.java`` のツールチップをローカライズします。
最後に、3 つの登録エントリが ``layer.xml`` ファイルに追加されています。
``layer.xml`` ファイル内のエントリは次を行います。
* ``<Actions>``
アクションを「ウィンドウ」フォルダのアクションとして登録します。
* ``<Menu>``
アクションを「ウィンドウ」メニューのメニュー項目として登録します。
* ``<Windows2> `` ウィンドウコンポーネントの検索に使用される、 ``FeedTopComponentSettings.xml`` を登録します。コンポーネント参照ファイル ``FeedTopComponentWstcref.xml`` を「explorer」領域に登録します。
== アプリケーションの実行
コードを 1 行も入力せずに、アプリケーションを試してみることができます。これを試すということは、モジュールを NetBeans プラットフォームに配備して、空の Feed ウィンドウが正しく表示されるかどうかを確認するということです。
[start=1]
1. 最初に、NetBeans IDE を定義するが、フィードリーダーアプリケーションで必要としないモジュールをすべて削除します。 ``feedreader-suite`` プロジェクトを右クリックして「プロパティー」を選択し、「プロジェクトプロパティー」ダイアログで「ライブラリ」をクリックします。
「クラスタ」の一覧が表示されます。クラスタはそれぞれ、関連するモジュールの集合です。必要なクラスタはプラットフォームクラスタのみなので、その他のクラスタをすべて選択解除し、プラットフォームクラスタだけが選択されている状態にします。
image::images/feedreader_60-runapp4.png[]
プラットフォームクラスタを展開し、提供されているモジュールを参照します。
image::images/feedreader_60-runapp5.png[]
プラットフォームモジュールは、Swing アプリケーションの共通インフラストラクチャーを提供します。つまり、プラットフォームクラスタが含まれているので、メニューバー、ウィンドウシステム、およびブートストラップ機能などの、アプリケーションのインフラストラクチャーに plumb コードを生成する必要はありません。
「閉じる」をクリックします。
[start=2]
1. 「プロジェクト」ウィンドウで、 ``feedreader-suite`` プロジェクトを右クリックし、「生成物を削除してすべてを構築」を選択します。
[start=3]
1. 次に示すように、「プロジェクト」ウィンドウで ``feedreader-suite`` プロジェクトを右クリックし、「実行」を選択します。
image::images/feedreader_60-runapp.png[]
アプリケーションが起動します。スプラッシュ画面が表示されます。次にアプリケーションが開き、次に示すようにエクスプローラウィンドウとして新しい Feed ウィンドウが表示されます。
image::images/feedreader_60-runapp2.png[]
NOTE: これで、次のモジュールからなるアプリケーションが作成されました。
* アプリケーションのブートストラップ、ライフサイクル管理、その他のインフラストラクチャー関連の用途のために、NetBeans が提供するモジュール。
* このチュートリアルで作成した、3 つのライブラリラッパーモジュール。
* Feed ウィンドウを提供するために、このチュートリアルで作成した FeedReader 機能性モジュール。
アプリケーションの「ウィンドウ」メニューに、新しいメニュー項目が表示されているはずです。Feed ウィンドウが閉じている場合は、次の図に示すように、そのメニュー項目を使用して開くことができます。
image::images/feedreader_60-runapp3.png[]
これでわかるように、コーディングを行わずに、アプリケーションが完成しました。まだ十分ではありませんが、インフラストラクチャー全体が存在し、期待どおりに動作します。次に、NeBeans API の一部を使用して、アプリケーションにコードを追加します。
== アプリケーションへのコードの追加
アプリケーションの基礎ができたので、次に、独自のコードを追加してみましょう。実行する前に、アプリケーションの依存関係を指定する必要があります。依存関係は、拡張または実装する NetBeans API を提供するモジュールです。次に、「新規ファイル」ウィザードとソースエディタを使用して、フィードリーダーアプリケーションを構成するクラスを作成してコーディングします。
=== アプリケーションの依存関係の指定
NetBeans API に属するいくつかのクラスをサブクラス化する必要があります。クラスは、フィードリーダーアプリケーションの依存関係として宣言する必要があるモジュールに属します。次の手順で説明するとおり、「プロジェクトプロパティー」ダイアログを使用して、これを実行します。
[start=1]
1. 「プロジェクト」ウィンドウで、 ``FeedReader`` プロジェクトを右クリックし、「プロパティー」を選択します。「プロジェクトプロパティー」ダイアログで「ライブラリ」をクリックします。次に示すように、一部の API は、すでにモジュールの依存関係として宣言されています。
image::images/feedreader_60-add-lib1.png[]
このライブラリ登録は、このチュートリアルの前の節で「ウィンドウコンポーネント」ウィザードによって行われました。
[start=2]
1. 「依存関係を追加」をクリックします。
[start=3]
1. 次の API を追加します。
[source,java]
----
アクション API
データシステム API
ダイアログ API
エクスプローラおよびプロパティーシート API
ファイルシステム API
ノード API
Rome
Rome-Fetcher
----
画面は次のようになります。
image::images/feedreader_60-add-lib2.png[]
「了解」をクリックして、「プロジェクトプロパティー」ダイアログを終了します。
[start=4]
1. ``FeedReader`` プロジェクトの「ライブラリ」ノードを展開し、現在このプロジェクトで利用可能なモジュールの一覧を確認します。
image::images/feedreader_60-add-lib5.png[]
=== ライブラリラッパーモジュール間の依存関係の設定
これで、使用する NetBeans API モジュールに依存関係を設定できたので、ライブラリラッパーモジュール間にも依存関係を設定してみます。たとえば、Rome JAR JDom JAR からクラスを利用します。これらは現在、個別のライブラリラッパーモジュールにラップされているため、ライブラリラッパーモジュールの「プロジェクトプロパティー」ダイアログを使用して、JAR 間に関係を指定する必要があります。
[start=1]
1. 最初に、Rome JDom に依存させます。「プロジェクト」ウィンドウで、Rome ライブラリラッパーモジュールプロジェクトを右クリックし、「プロパティー」を選択します。「プロジェクトプロパティー」ダイアログで、「ライブラリ」をクリックして「依存関係を追加」をクリックします。 ``jdom`` を追加します。画面は次のようになります。
image::images/feedreader_60-add-lib3.png[]
「了解」をクリックして、「プロジェクトプロパティー」ダイアログを終了します。
[start=2]
1. 最後に、Rome Fetcher Rome JDom の両方に依存するので、次に示すように Rome Fetcher Rome に依存させる必要があります。
image::images/feedreader_60-add-lib4.png[]
Rome はすでに JDom に依存しているため、Rome Fetcher JDom に依存させる必要はありません。
=== RssFeeds フォルダの作成
IDE のユーザーインタフェースを使用して、フォルダを ``layer.xml`` ファイルに追加します。フォルダには、RSS フィードオブジェクトが含まれます。あとで、コードを ``FeedTopComponent.java`` に追加します。これは、このフォルダの内容を表示するために、「ウィンドウコンポーネント」ウィザードによって作成されたものです。
[start=1]
1. 「プロジェクト」ウィンドウで、 ``FeedReader`` プロジェクトノード、「重要なファイル」ノード、「XML レイヤー」ノードを順に展開します。次のノードが表示されます。
* ``<このレイヤー>。`` 現在のモジュールによって提供されたフォルダを公開します。たとえば、このチュートリアルの前の節で説明したように、次に示すような、「Action」、「Menu」、および「Windows2」という名前のフォルダが FeedReader モジュールによって提供されます。
image::images/feedreader_60-feedfolder-1.png[]
* ``<コンテキスト内のこのレイヤー>。`` アプリケーション全体で利用可能なフォルダをすべて公開します。このノードについては、このチュートリアルのあとの節で見ていきます。
[start=2]
1. 次に示すように、「 ``<このレイヤー>`` 」ノードを右クリックし、「新規」>「フォルダ」を選択します。
image::images/feedreader_60-feedfolder-2.png[]
[start=3]
1. 「新規フォルダ」ダイアログに「 ``RssFeeds`` 」と入力します。「了解」をクリックします。これで、次に示すように、新しいフォルダができました。
image::images/feedreader_60-feedfolder-3.png[]
[start=4]
1. ``layer.xml`` ファイルのノードをダブルクリックして、ソースエディタで開きます。次のエントリが追加されています。 `` <folder name="RssFeeds"/>``
=== フィードオブジェクトの作成
次に、URL とそれに関連付けられた Rome フィードをカプセル化する、簡単な POJO を作成します。
[start=1]
1. ``FeedReader`` プロジェクトノードを右クリックし、「新規」>「Java クラス」を選択します。「次へ」をクリックします。
[start=2]
1. クラスの名前を ``Feed`` にして、「パッケージ」ドロップダウンで ``org.myorg.feedreader`` を選択します。「完了」をクリックします。
[start=3]
1. 「ソース」エディタで、デフォルトの ``Feed`` クラスを次に置き換えます。
[source,java]
----
public class Feed implements Serializable {
private static FeedFetcher s_feedFetcher
= new HttpURLFeedFetcher(HashMapFeedInfoCache.getInstance());
private transient SyndFeed m_syndFeed;
private URL m_url;
private String m_name;
protected Feed() {
}
public Feed(String str) throws MalformedURLException {
m_url = new URL(str);
m_name = str;
}
public URL getURL() {
return m_url;
}
public SyndFeed getSyndFeed() throws IOException {
if (m_syndFeed == null) {
try {
m_syndFeed = s_feedFetcher.retrieveFeed(m_url);
if (m_syndFeed.getTitle() != null) {
m_name = m_syndFeed.getTitle();
}
} catch (Exception ex) {
throw new IOException(ex.getMessage());
}
}
return m_syndFeed;
}
@Override
public String toString() {
return m_name;
}
}
----
多くのコードに下線が付いています。これは、それらのパッケージが宣言されていないためです。次の手順で、これを行います。
次の手順に従ってファイルを再整形し、それらの依存関係を宣言します。
[start=1]
1. Alt-Shift-F キーを押し、コードを整形します。
[start=2]
1. Ctrl-Shift-I キーを押し、次のインポート文が選択されていることを確認します。
image::images/feedreader_60-imports.png[]
「了解」をクリックすると、IDE によって次のインポート文がクラスに追加されます。
[source,java]
----
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.fetcher.FeedFetcher;
import com.sun.syndication.fetcher.impl.HashMapFeedInfoCache;
import com.sun.syndication.fetcher.impl.HttpURLFeedFetcher;
import java.io.IOException;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
----
これで、赤い下線はすべてなくなったはずです。そうならない場合、問題が解決するまでチュートリアルを進めないでください。
=== Feed ウィンドウの拡張
[start=1]
1. ``FeedTopComponent.java`` をダブルクリックして、ソースエディタで開きます。
[start=2]
1. クラス宣言の最後に「 ``implements ExplorerManager.Provider`` 」と入力します。
[start=3]
1. その行で Alt-Enter キーを押し、提案の上をクリックします。IDE によって、必須パッケージ ``org.openide.explorer.ExplorerManager`` のインポート文が追加されます。
[start=4]
1. もう一度 Alt-Enter キーを押し、提案の上をクリックします。IDE によって、抽象メソッド ``getExplorerManager()`` が実装されます。
[start=5]
1. 新しい ``getExplorerManager()`` メソッドの本体に「 ``return manager;`` 」と入力します。その行で Alt-Enter キーを押すと、IDE によって ``manager`` というフィールドが作成されます。デフォルトの定義を次に置き換えます。
[source,java]
----
private final ExplorerManager manager = new ExplorerManager();
----
[start=6]
1. 前の手順のフィールド宣言のすぐ下に、次を宣言します。
[source,java]
----
private final BeanTreeView view = new BeanTreeView();
----
[start=7]
1. 最後に、次のコードをコンストラクタの最後に追加します。
[source,java]
----
setLayout(new BorderLayout());
add(view, BorderLayout.CENTER);
view.setRootVisible(true);
try {
manager.setRootContext(new RssNode.RootRssNode());
} catch (DataObjectNotFoundException ex) {
ErrorManager.getDefault().notify(ex);
}
ActionMap map = getActionMap();
map.put("delete", ExplorerUtils.actionDelete(manager, true));
associateLookup(ExplorerUtils.createLookup(manager, map));
----
多くのコードに下線が付いています。これは、関連付けられているパッケージが宣言されていないためです。次の手順で、これを行います。
次の手順に従ってファイルを再整形し、それらの依存関係を宣言します。
[start=1]
1. Alt-Shift-F キーを押し、コードを整形します。
[start=2]
1. Ctrl-Shift-I キーを押し、 ``org.openide.ErrorManager`` を選択して「了解」をクリックします。IDE によって、パッケージ文の下にいくつかのインポート文が追加されます。インポート文のすべてのリストは、次のようになっているはずです。
[source,java]
----
import java.awt.BorderLayout;
import java.io.Serializable;
import javax.swing.ActionMap;
import org.openide.ErrorManager;
import org.openide.explorer.ExplorerManager;
import org.openide.explorer.ExplorerUtils;
import org.openide.explorer.view.BeanTreeView;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;
import org.openide.util.Utilities;
import org.openide.windows.TopComponent;
----
[start=3]
1. ``manager.setRootContext(new RssNode.RootRssNode());`` 行には、まだ赤い下線が付いています。これは、まだ ``RssNode.java`` が作成されていないためです。次のサブセクションでこれを実行します。これで、その他の赤い下線はなくなったはずです。そうならない場合、問題が解決するまでチュートリアルを進めないでください。
=== RssNode クラスの作成
フィードリーダーの最上位ノードは、RssNode クラスによって提供されます。このクラスは、「RssFeeds」ノードをプロキシする `` link:http://bits.netbeans.org/dev/javadoc/org-openide-nodes/org/openide/nodes/FilterNode.html[FilterNode]`` を拡張します。ここで、表示名を定義し、次に示すとおり、2 つのメニュー項目「Add」および「Add Folder」を宣言します。
image::images/feedreader_60-actions.png[]
このクラスを作成するには、次の手順に従います。
[start=1]
1. ``org.myorg.feedreader`` パッケージに ``RssNode.java`` を作成します。
[start=2]
1. デフォルトのクラスを次に置き換えます。
[source,java]
----
public class RssNode extends FilterNode {
public RssNode(Node folderNode) throws DataObjectNotFoundException {
super(folderNode, new RssFolderChildren(folderNode));
}
@Override
public Action[] getActions(boolean popup) {
*//ノードのデータフォルダの
//アクションとパスを宣言:*
DataFolder df = getLookup().lookup(DataFolder.class);
return new Action[]{
new AddRssAction(df),
new AddFolderAction(df)
};
}
public static class RootRssNode extends RssNode {
*//「RssFeeds」ノードのプロキシとして
//フィルタノードが提供されます
//ここでは NetBeans ユーザーディレクトリから取得されます:*
public RootRssNode() throws DataObjectNotFoundException {
super(DataObject.find(Repository.getDefault().getDefaultFileSystem().
getRoot().getFileObject("RssFeeds")).getNodeDelegate());
}
*//バンドルファイルとキーを参照して
//ノードの表示名を設定します
//これらはあとで定義します:*
@Override
public String getDisplayName() {
return NbBundle.getMessage(RssNode.class, "FN_title");
}
}
}
----
クラスの一部に、赤い下線が残ります。これは、まだアクションを作成しておらず、またノードの子を定義するクラスもまだ作成されていないためです。
=== RssFolderChildren クラスの作成
次に、「RSS/Atom Feeds」ノードの子に取り組みます。子は、フォルダかフィードのいずれかです。これらはすべて、次のコードで発生します。
このクラスを作成するには、次の手順に従います。
[start=1]
1. ``org.myorg.feedreader`` パッケージに ``RssFolderChildren.java`` を作成します。
[start=2]
1. デフォルトのクラスを次に置き換えます。
[source,java]
----
public class RssFolderChildren extends FilterNode.Children {
RssFolderChildren(Node rssFolderNode) {
super(rssFolderNode);
}
@Override
protected Node[] createNodes(Node key) {
Node n = key;
*//データフォルダが見つかった場合は RssNode を作成します
//見つからなかった場合、フィードを検索して OneFeedNode を作成します:*
try {
if (n.getLookup().lookup(DataFolder.class) != null) {
return new Node[]{new RssNode(n)};
} else {
Feed feed = getFeed(n);
if (feed != null) {
return new Node[]{
new OneFeedNode(n, feed.getSyndFeed())
};
} else {
// best effort
return new Node[]{new FilterNode(n)};
}
}
} catch (IOException ioe) {
Exceptions.printStackTrace(ioe);
} catch (IntrospectionException exc) {
Exceptions.printStackTrace(exc);
}
// その他のノードの種類 (何かを実行)
return new Node[]{new FilterNode(n)};
}
/** フィードの検索 */
private static Feed getFeed(Node node) {
InstanceCookie ck = node.getCookie(InstanceCookie.class);
if (ck == null) {
throw new IllegalStateException("Bogus file in feeds folder: " + node.getLookup().lookup(FileObject.class));
}
try {
return (Feed) ck.instanceCreate();
} catch (ClassNotFoundException ex) {
Exceptions.printStackTrace(ex);
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
return null;
}
}
----
クラスには赤い下線がいくつか残ります。これは、 ``OneFeedNode`` クラスがまだ作成されていないためです。
=== OneFeedNode クラスの作成
ここでは、次のように、「NetBeans Highlights」ノード下に表示されるような、記事ノードのコンテナに取り組みます。
image::images/feedreader_60-actions2.png[]
見てわかるように、これらのノードにはそれぞれ、フィードから取得した表示名、アイコン、および「Delete」メニュー項目があります。
このクラスを作成するには、次の手順に従います。
[start=1]
1. ``org.myorg.feedreader`` パッケージに ``OneFeedNode.java`` を作成します。
[start=2]
1. デフォルトのクラスを次に置き換えます。
[source,java]
----
public class OneFeedNode extends FilterNode {
OneFeedNode(Node feedFileNode, SyndFeed feed) throws IOException, IntrospectionException {
super(feedFileNode,
new FeedChildren(feed),
new ProxyLookup(
new Lookup[]{Lookups.fixed(
new Object[]{feed}),
feedFileNode.getLookup()
}));
}
@Override
public String getDisplayName() {
SyndFeed feed = getLookup().lookup(SyndFeed.class);
return feed.getTitle();
}
@Override
public Image getIcon(int type) {
return Utilities.loadImage("org/myorg/feedreader/rss16.gif");
}
@Override
public Image getOpenedIcon(int type) {
return getIcon(0);
}
@Override
public Action[] getActions(boolean context) {
return new Action[]{SystemAction.get(DeleteAction.class)};
}
}
----
クラスには赤い下線がいくつか残ります。これは、 ``FeedChildren`` クラスがまだ作成されていないためです。
=== FeedChildren クラスの作成
この節では、フィードによって提供された各記事にノードを提供するコードを追加します。
このクラスを作成するには、次の手順に従います。
[start=1]
1. ``org.myorg.feedreader`` パッケージに ``FeedChildren`` を作成します。
[start=2]
1. デフォルトのクラスを次に置き換えます。
[source,java]
----
public class FeedChildren extends Children.Keys {
private final SyndFeed feed;
public FeedChildren(SyndFeed feed) {
this.feed = feed;
}
@SuppressWarnings(value = "unchecked")
@Override
protected void addNotify() {
setKeys(feed.getEntries());
}
public Node[] createNodes(Object key) {
*//新しい article-level ノードを返します:*
try {
return new Node[]{
new EntryBeanNode((SyndEntry) key)
};
} catch (final IntrospectionException ex) {
Exceptions.printStackTrace(ex);
*//決して発生しません。失敗する理由がありません:*
return new Node[]{new AbstractNode(Children.LEAF) {
@Override
public String getHtmlDisplayName() {
return "" + ex.getMessage() + "";
}
}};
}
}
}
----
クラスには赤い下線がいくつか残ります。これは、 ``EntryBeanNode`` クラスがまだ作成されていないためです。
=== EntryBeanNode クラスの作成
最後に、最下位レベルのノードを扱います。これらは、フィードによって提供される記事を表します。
このクラスを作成するには、次の手順に従います。
[start=1]
1. ``org.myorg.feedreader`` パッケージに ``EntryBeanNode.java`` を作成します。
[start=2]
1. デフォルトのクラスを次に置き換えます。
[source,java]
----
public class EntryBeanNode extends FilterNode {
private SyndEntry entry;
@SuppressWarnings(value = "unchecked")
public EntryBeanNode(SyndEntry entry) throws IntrospectionException {
super(new BeanNode(entry), Children.LEAF,
Lookups.fixed(new Object[]{
entry,
new EntryOpenCookie(entry)
}));
this.entry = entry;
}
*/** HtmlDisplayName の使用により、RSS エントリタイトル内の HTML の
* /**正しい処理およびエスケープ、エンティティーの解決、およびその他が可能になります */*
@Override
public String getHtmlDisplayName() {
return entry.getTitle();
}
*/** エントリの説明からツールチップを作成します */*
@Override
public String getShortDescription() {
return entry.getDescription().getValue();
}
*/** フィードエントリでの開くアクションを提供します */*
@Override
public Action[] getActions(boolean popup) {
return new Action[]{SystemAction.get(OpenAction.class)};
}
@Override
public Action getPreferredAction() {
return (SystemAction) getActions(false) [0];
}
*/** ユーザーが開くアクションを呼び出すときに発生することを指定します */*
private static class EntryOpenCookie implements OpenCookie {
private final SyndEntry entry;
EntryOpenCookie(SyndEntry entry) {
this.entry = entry;
}
public void open() {
try {
URLDisplayer.getDefault().showURL(new URL(entry.getUri()));
} catch (MalformedURLException mue) {
Exceptions.printStackTrace(mue);
}
}
}
}
----
=== Add Folder」メニュー項目の作成
ここで、前に宣言した、フォルダを作成するためのメニュー項目を作成します。
このクラスを作成するには、次の手順に従います。
[start=1]
1. ``org.myorg.feedreader`` パッケージに ``AddFolderAction.java`` を作成します。
[start=2]
1. デフォルトのクラスを次に置き換えます。
[source,java]
----
public class AddFolderAction extends AbstractAction {
private DataFolder folder;
public AddFolderAction(DataFolder df) {
folder = df;
putValue(Action.NAME, NbBundle.getMessage(RssNode.class, "FN_addfolderbutton"));
}
public void actionPerformed(ActionEvent ae) {
NotifyDescriptor.InputLine nd =
new NotifyDescriptor.InputLine(
NbBundle.getMessage(RssNode.class, "FN_askfolder_msg"),
NbBundle.getMessage(RssNode.class, "FN_askfolder_title"),
NotifyDescriptor.OK_CANCEL_OPTION, NotifyDescriptor.PLAIN_MESSAGE);
Object result = DialogDisplayer.getDefault().notify(nd);
if (result.equals(NotifyDescriptor.OK_OPTION)) {
final String folderString = nd.getInputText();
try {
DataFolder.create(folder, folderString);
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
}
}
}
----
=== Add RSS」メニュー項目の作成
この節では、新しいフィードを追加するメニュー項目を作成します。
このクラスを作成するには、次の手順に従います。
[start=1]
1. ``org.myorg.feedreader`` パッケージに ``AddRssAction.java`` を作成します。
[start=2]
1. デフォルトのクラスを次に置き換えます。
[source,java]
----
public class AddRssAction extends AbstractAction {
private DataFolder folder;
public AddRssAction(DataFolder df) {
folder = df;
putValue(Action.NAME, NbBundle.getMessage(RssNode.class, "FN_addbutton"));
}
public void actionPerformed(ActionEvent ae) {
NotifyDescriptor.InputLine nd = new NotifyDescriptor.InputLine(
NbBundle.getMessage(RssNode.class, "FN_askurl_msg"),
NbBundle.getMessage(RssNode.class, "FN_askurl_title"),
NotifyDescriptor.OK_CANCEL_OPTION,
NotifyDescriptor.PLAIN_MESSAGE);
Object result = DialogDisplayer.getDefault().notify(nd);
if (result.equals(NotifyDescriptor.OK_OPTION)) {
String urlString = nd.getInputText();
URL url;
try {
url = new URL(urlString);
} catch (MalformedURLException e) {
String message = NbBundle.getMessage(RssNode.class, "FN_askurl_err", urlString);
Exceptions.attachLocalizedMessage(e, message);
Exceptions.printStackTrace(e);
return;
}
try {
checkConnection(url);
} catch (IOException e) {
String message = NbBundle.getMessage(RssNode.class, "FN_cannotConnect_err", urlString);
Exceptions.attachLocalizedMessage(e, message);
Exceptions.printStackTrace(e);
return;
}
Feed f = new Feed(url);
FileObject fld = folder.getPrimaryFile();
String baseName = "RssFeed";
int ix = 1;
while (fld.getFileObject(baseName + ix, "ser") != null) {
ix++;
}
try {
FileObject writeTo = fld.createData(baseName + ix, "ser");
FileLock lock = writeTo.lock();
try {
ObjectOutputStream str = new ObjectOutputStream(writeTo.getOutputStream(lock));
try {
str.writeObject(f);
} finally {
str.close();
}
} finally {
lock.releaseLock();
}
} catch (IOException ioe) {
Exceptions.printStackTrace(ioe);
}
}
private static void checkConnection(final URL url) throws IOException {
InputStream is = url.openStream();
is.close();
}
}
----
=== RssNode クラスのローカライズ
[start=1]
1. ``FeedReader`` モジュールの ``Bundle.properties`` ファイルを開きます。
[start=2]
1. 次のキーと値のペアを追加します。
[source,java]
----
FN_title=RSS/Atom フィード
FN_addbutton=追加
FN_askurl_title=新規フィード
FN_askurl_msg=RSS/Atom フィードの URL を入力してください
FN_askurl_err=無効な URL: {0}|
FN_addfolderbutton=フォルダを追加
FN_askfolder_msg=フォルダ名を追加
FN_askfolder_title=新規フォルダ
----
``RssNode.java`` で定義された文字列をローカライズする、新しいキーと値のペアについての説明を次に示します。
* *FN_title。*Feed ウィンドウ内で最上位にあるノードのラベルをローカライズします。
次に、フィードを追加するためのユーザーインタフェースのローカライズについて示します。
* *FN_addbutton。*最上位のノードのポップアップに表示される「Add」メニュー項目のラベルをローカライズします。
* *FN_askurl_title。*「New Feed」ダイアログのタイトルをローカライズします。
* *FN_askurl_msg。*「New Feed」ダイアログに表示されるメッセージをローカライズします。
* *FN_askurl_err。*URL が無効な場合に表示されるエラー文字列をローカライズします。
次に、フォルダを追加するためのユーザーインタフェースのローカライズについて示します。
* *FN_addfolderbutton。*最上位のノードのポップアップに表示される「Add Folder」メニュー項目のラベルをローカライズします。
* *FN_askfolder_msg。*「Add Folder」ダイアログに表示されるメッセージをローカライズします。
* *FN_askfolder_title。*「Add Folder」ダイアログのタイトルをローカライズします。
== アプリケーションのブランディング
開発サイクルの最終段階で、アプリケーションを仕上げる間に、次のような疑問が生じます。
* アプリケーションの実行可能ファイルの名前はどうすべきか。
* アプリケーションの起動時、何を表示すべきか。進捗バーか、スプラッシュ画面か、またはその両方か。
* アプリケーションの起動時、タイトルバーに何を表示すべきか。
* NetBeans プラットフォームがデフォルトで提供するメニューおよびツールバーボタンがすべて必要か。
これら疑問はブランディングに関係するもので、NetBeans プラットフォーム上に構築されたアプリケーションを独自のものにするアクティビティーです。IDE には、モジュールスイートプロジェクトの「プロジェクトプロパティー」ダイアログに、ブランディングに役立つパネルが用意されています。
[start=1]
1. ``feedreader-suite`` プロジェクトノード ( ``FeedReader`` プロジェクトノードではない) を右クリックし、「プロパティー」を選択します。「プロジェクトプロパティー」ダイアログで「構築」をクリックします。
[start=2]
1. 「構築」パネルで、「ブランド名」に「 ``feedreader`` 」と入力します。「アプリケーションタイトル」に「 ``Feed Reader Application`` 」と入力します。ブランド名の値によって実行可能ファイルの名前が設定され、アプリケーションタイトルの値によってアプリケーションのタイトルバーが設定されます。
[start=3]
1. 「参照」をクリックし、 ``rss16.gif`` (
image::images/feedreader_rss16.gif[]) アイコンを参照します 。アイコンは、「ヘルプ」>「製品について」ダイアログに表示されます。
画面は次のようになります。
image::images/feedreader_60-brand1.png[]
[start=4]
1. スプラッシュ画面パネルで「参照」をクリックし、 ``splash.gif`` を参照します。必要に応じて、進捗バーの色とテキストサイズを変更します。また、進捗バーが不要な場合は、「有効」を選択解除します。
画面は次のようになります。
image::images/feedreader_60-brand2.png[]
[start=5]
1. 「閉じる」をクリックします。 ``FeedReader Application`` プロジェクトに ``branding`` フォルダが作成されます。これは、「ファイル」ウィンドウ (Ctrl-2) に表示されます。
[start=6]
1. 「ファイル」ウィンドウで、 ``FeedReader Application`` プロジェクトノードを展開します。次が見つかるまでノードを展開します。 ``branding/modules/org-netbeans-core-window.jar/org/netbeans/core/windows``
[start=7]
1. このノードを右クリックして「新規」>「その他」を選択し、「その他」カテゴリで「フォルダ」を選択します。「次へ」をクリックし、フォルダに ``resources`` という名前を付けます。「完了」をクリックします。
[start=8]
1. 新しい ``resources`` ノードを右クリックし、「新規」>「その他」を選択して、「XML」カテゴリから「XML ドキュメント」を選択します。「次へ」をクリックします。ファイルに ``layer`` という名前を付けます。「次へ」をクリックし、「完了」をクリックします。新しい ``layer.xml`` ファイルの内容を次に置き換えます。
[source,xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "https://netbeans.org/dtds/filesystem-1_1.dtd">
<!--
これは「ブランディング」レイヤーです。ブランディング対象のレイヤーファイルとマージされます。この場合、不要なメニュー項目およびツールバーは非表示になります。-->
<filesystem>
<!-- 未使用のツールバーを非表示にする -->
<folder name="Toolbars">
<folder name="File_hidden"/>
<folder name="Edit_hidden"/>
</folder>
<folder name="Menu">
<folder name="File">
<file name="org-openide-actions-SaveAction.instance_hidden"/>
<file name="org-openide-actions-SaveAllAction.instance_hidden"/>
<file name="org-netbeans-core-actions-RefreshAllFilesystemsAction.instance_hidden"/>
<file name="org-openide-actions-PageSetupAction.instance_hidden"/>
<file name="org-openide-actions-PrintAction.instance_hidden"/>
</folder>
<folder name="Edit_hidden"/>
<folder name="Tools_hidden"/>
</folder>
</filesystem>
----
== アプリケーションの配布
IDE では、Ant 構築スクリプトを使用して、アプリケーションの配布版を作成します。構築スクリプトは、プロジェクトを作成するときに作成されます。
[start=1]
1. 「プロジェクト」ウィンドウで、 ``FeedReader Application`` プロジェクトノードを右クリックし、「配布用 ZIP を構築」を選択します。「出力」ウィンドウに、配布用 ZIP が作成される場所が表示されます。
[start=2]
1. ファイルシステムのプロジェクトディレクトリの ``dist`` フォルダ内にある、配布用の ``feedreader.zip`` を検索します。そのファイルを解凍します。 ``bin`` フォルダにあるアプリケーションを起動します。起動中、スプラッシュ画面が表示されます。アプリケーションが起動したら、「ヘルプ」>「製品について」ダイアログに移動し、「<<branding,アプリケーションのブランディング>>」節で指定したアイコンとスプラッシュ画面があることを確認します。
この FeedReader Application が起動して実行中になると、「RSS/Atom フィード」というノードを含む「RSS/Atom フィード」ウィンドウが表示されます。
お疲れさまでした。これで FeedReader のチュートリアルは終了です。
link:http://netbeans.apache.org/community/mailing-lists.html[ご意見をお寄せください]