ImplementConnectionWizard
データベースエクスプローラの接続情報を利用する(続)
データベース接続選択処理の実装(続)
ImplementConnectionPanelでGUI側の実装をしましたが、この状態ではまだウィザードの機能としては不十分です。
- DatabaseConnectionを選択しなくてもNextをクリックできてしまう
- 選択したDatabaseConnectionを保持することができない
パネルの移動の可否判定や、GUIでの選択をコンテキスト(WizardDescriptor)へ保持するのはVisualクラスに対応するWizardクラスの役割です。
次のステップとしてWizardクラスに上記の処理を実装しましょう。
Wizardとのインターフェイスの実装
その前にEntityVisualPanel1を修正して以下の機能を実装します。
- Wizardが選択したDatabaseConnectionを取得可能とする
- Wizardに対してリストからDatabaseConnectionが選択されたことを通知可能にする
選択したDatabaseConnectionを参照できるように次のメソッドをEntityVisualPanel1に実装しましょう。
DatabaseConnection selectedConnection() { DatabaseConnection[] dc = ConnectionManager.getDefault().getConnections(); for (int i = 0; i < dc.length; i++) { if (dc[i].getName().equals(connectionList.getSelectedValue())) { return dc[i]; } } return null; }
JList(connectionListフィールド)にはDatabaseConnectionのnameプロパティを与えているので、selectedConnectionメソッドではnameプロパティが一致するDatabaseConnectionのインスタンスを返します。
次に、connectionListのvalueChangedイベントハンドラを実装します。
その前に、EntityWizardPanel1に対してイベントを通知できるようにEntityVisualPanel1にEntityWizardPanel1の参照を与えられるようにフィールドの追加とコンストラクタの修正を行います。
EntityWizardPanel1 wizard;
/** Creates new form EntityVisualPanel1 */ public EntityVisualPanel1(EntityWizardPanel1 initWizard) { wizard = initWizard; ConnectionManager.getDefault().addConnectionListener(this); initComponents(); setupList(); }
EntityVisualPanel1を生成するのはEntityWizardPanel1なのでコンストラクタ呼び出しにthisを与えれば済むのでこの方法が良いと思います。
次に、connectionListのEventsタブでvalueChangedイベントハンドラを割り当てて、そこから今追加したEntityWizardPanel1の呼び出しを実装します。
private void connectionListValueChanged(javax.swing.event.ListSelectionEvent evt) { wizard.fireChangeEvent(); }
これで、DatabaseConnectionが選択される都度、EntityWizardPanel1へイベントが通知されるようになります。
Wizardの実装
importの追加
import java.util.HashSet; import java.util.Iterator; import java.util.Set; // ここより上を追加 import java.awt.Component; import javax.swing.event.ChangeListener; // ここより下を追加 import javax.swing.event.ChangeEvent; // 下は既存 import org.openide.WizardDescriptor; import org.openide.util.HelpCtx;
WizardがNetBeansにイベントを通知するためのコードはあらかじめコメントとして生成されるソースに含まれています。このコードを有効にするために、java.util.HashSetなどをimportしましょう。
Componentの型を特化する
EntityWizardPanel1からEntityVisualPanel1のメソッド(上記selectedConnectionメソッド)を呼び出すので、単なるCompoenetクラスとなっているフィールドをEntityVisualPanel1に修正して利用時のキャストを不要にします。
private EntityVisualPanel1 component;
同様に、EntityVisualPanel1のコンストラクタの修正に対応させます。
public Component getComponent() { if (component == null) { component = new EntityVisualPanel1(this); } return component; }
NetBeansへ状態を通知可能にする。
最初に単にtrueを返すように実装しているisValidメソッドを修正して、DatabaseConnectionが設定されている場合にのみtrueを返すようにしましょう。この修正を行うと、connectionListが未選択だとNextボタンが無効化されるようになります。
public boolean isValid() { return component.selectedConnection() != null; }
次に、有効状態の変更を通知できるように、addChangeListener、removeChangeListener、fireChangeEventの3つのメソッドのコメントアウトを外します。逆に最初に生成されたソースのaddChangeListener、removeChangeListenerメソッドの実装を削除します。
なお、EntityVisualPanel1のconnectionListValueChangedメソッドで直截fireChangeEventを呼び出すように実装しているため、ここについての修正は以上で完了です。
選択されたDatabaseConnectionを保持する
最後に選択されたDatabaseConnectionを保持して後続のパネルから利用可能にします。
このためには、コンテキスト(WizardDescriptor)を利用します。Wizardクラスがコンテキストを利用するためのインターフェイスとして読み込みのためのreadSettings、保存のためのstoreSetteingsの2つのメソッドがあらかじめ用意されています。
ここでは保存のためなのでstoreSettingsメソッドを修正することになります。
public void storeSettings(Object settings) { ((WizardDescriptor)settings).putProperty("connection", component.selectedConnection()); }
これによって、後続の処理はreadSettingsメソッドの呼び出しで与えられたsettingsオブジェクトに対して、((WizardDescriptor?)settings).getProperty("connection")を呼び出すことで、このパネルで選択されたDatabaseConnectionを利用することが可能となります。
コネクションの後始末を実装しておく
なお、後続のパネルでウィザードをキャンセルした場合に、もしDatabaseConnectionが接続状態だと余分なリソースの利用となるので望ましくないかも知れません(もっとも、データベースエクスプローラを利用すればユーザーはコネクションを切断できます)。
DatabaseConnectionのようなオブジェクトをWizardDescriptorに保持した場合は、Iteratorクラスのクリーンアップ処理に廃棄処理を実装することができます。そのタイミングで切断処理を実装しましょう。
EntityWizardIterator.javaを開いて、最初にimport宣言を追加します。
import org.netbeans.api.db.explorer.ConnectionManager; import org.netbeans.api.db.explorer.DatabaseConnection;
次にuninitializeメソッドを探してください。NetBeansは最後にuninitializeメソッドを呼び出すので、このメソッドに切断処理を実装します。
public void uninitialize(WizardDescriptor wizard) { DatabaseConnection dc = (DatabaseConnection)wizard.getProperty("connection"); if (dc != null) { ConnectionManager.getDefault().disconnect(dc); } panels = null; }
なおウィザードを起動直後にキャンセルした場合にはWizardDescriptorにDatabaseConnectionは設定されていないので、nullチェックが必須です。
Keyword(s):
References: