ビジネス・オブジェクト定義で説明したように、ビジネス・オブジェクト定義 は、集合的単位として扱えるデータ用のテンプレートとなっています。 ODA の目的は、データ・ソース内のオブジェクトに対するビジネス・オブジェクト定義を生成することです。 ODA でビジネス・オブジェクト定義コンテンツを生成するには、その ODA クラスに IGeneratesBoDefs インターフェースを実装する必要があります。
表 37 は、IGeneratesBoDefs インターフェースを実装するために ODA クラスに定義する必要のあるメソッドを示しています。
表 37. IGeneratesBoDefs インターフェース内のメソッド
メソッド | IGeneratesBoDefs メソッド | 説明 |
---|---|---|
ソース・ノード生成メソッド | getTreeNodes() | 次の処理を繰り返し実行します。
|
コンテンツ生成メソッド | generateBoDefs() | ユーザーが選択したソース・データのビジネス・オブジェクト定義を生成し、それを ODA メモリーに書き込みます。 |
コンテンツ取得メソッド | getBoDefs() | 指定したビジネス・オブジェクト定義、またはすべてのビジネス・オブジェクト定義を ODA メモリーから取得します。 |
IGeneratesBoDefs インターフェースを実装している場合、ビジネス・オブジェクト・ウィザードは、表 38 に示すメソッドを呼び出して、ソース・ノードを取得したり、コンテンツを生成および取得したりします。
表 38. ビジネス・オブジェクト・ウィザードと IGeneratesBoDefs メソッド
ビジネス・オブジェクト・ウィザードのステップ | IGeneratesBoDefs メソッド | 詳細情報の参照先 |
---|---|---|
ステップ 3: ソースの選択 | getTreeNodes() | ソース・ノードの生成 |
ステップ 5: ビジネス・オブジェクトの生成中 | generateBoDefs() | ビジネス・オブジェクト定義の生成 |
ステップ 5: ビジネス・オブジェクトの生成中 | getBoDefs() | 生成済みビジネス・オブジェクト定義へのアクセスの提供 |
以降のセクションでは、表 38 に示す各メソッドの実装について説明します。
ビジネス・オブジェクト・ウィザードは、ODA データ・ソース内のソース・ノードを検出してソース・ノード階層を作成するために getTreeNodes() メソッドを呼び出します。ビジネス・オブジェクト・ウィザードは、作成したソース・ノード階層を「ソースの選択」ダイアログ・ボックス (ステップ 3) に表示します。
getTreeNodes() メソッドは IGeneratesBoDefs インターフェースに含まれおり、ODA クラスは、ビジネス・オブジェクト定義の生成をサポートするためにこのメソッドを実装する必要があります。
ソース・データの選択および確認で説明したように、ビジネス・オブジェクト・ウィザードは、getTreeNodes() が戻すツリー・ノード配列を使用して、「ソースの選択」ダイアログ・ボックスを初期化します。このダイアログ・ボックスにはソース・ノード階層が表示され、ユーザーはデータ・ソースから取得されたソース・ノード間を移動したり、ODA がビジネス・オブジェクト定義を生成するソース・ノードを選択したりできます。ソース・ノードが展開されるたびに、ビジネス・オブジェクト・ウィザードは getTreeNodes() メソッドを呼び出します。これにより、展開されたソース・ノードのコンテンツを持つツリー・ノード配列が戻されます。
例えば、サンプル Roman Army ODA の getTreeNodes() メソッドは、サンプルのデータ・ソースである RomanArmy.xml ファイルから取得したトップレベルの army general を使用して、「ソースの選択」ダイアログ・ボックスを初期化します。特定のノードが展開されると、getTreeNodes() はそのノードの army general の子を XML ファイルから取得し、それをツリー・ノード配列に保管します。ビジネス・オブジェクト・ウィザードは、このツリー・ノード配列を使用して、展開されたソース・ノードを表示します。
したがって、getTreeNodes() の目的は、データ・ソース内のソース・ノードを検出してから、ツリー・ノードの配列を作成して戻すことです。
これを行うには、getTreeNodes() で次のタスクを実行する必要があります。
ビジネス・オブジェクト・ウィザードは、getTreeNodes() メソッドを呼び出すときに、親ノード・パス の値をこのメソッドに渡します。このパスは、ユーザーが選択した、getTreeNodes() によって展開されるノードを識別します。このパスは、トップレベルの親からユーザーが選択したノードまでの完全修飾ノード・パスを含む String です。このパス内のノード名は、コロン (:) で区切られています。
例えば、図 59 は、サンプル Roman Army ODA のソース・ノード階層のビューを表示する「ソースの選択」ダイアログ・ボックスを示しています。
図 59 において、Uulius ソース・ノードの親ノード・パスは次のようになります。
Apollo:Tellus:Uulius
ビジネス・オブジェクト・ウィザードは、選択したソース・ノードの親ノード・パスを作成し、このパスを getTreeNodes() に渡します。
親ノード・パスは、getTreeNodes() で指定する親ノード・パスと同じ構文を使用して指定する必要があります。詳しくは、オブジェクトのパスの指定を参照してください。
getTreeNode() メソッドは、ツリー・ノード配列に戻すソース・ノード階層のレベルを、親ノード・パスを使用して決定します。このツリー・ノード配列には、親ノード・パスで識別されるノードの子ノードがすべて保管されます。ソース・ノード階層のトップレベルを戻すように getTreeNodes() に指示する際、ビジネス・オブジェクト・ウィザードは、「空」の親ノード・パスを渡します。したがって、getTreeNodes() メソッドは、最初のステップとして「空」のノード・パスがないかどうかを確認する必要があります。次のコード・フラグメントを参照してください。
if (parentNodePath = null || parentNodePath.length() == 0) //return the top-level of the source-node hierarchy
親ノード・パスが空でない 場合、getTreeNodes() は、指定した親ノード・パスの子のツリー・ノードを構築し、TreeNode オブジェクトの該当する配列をビジネス・オブジェクト・ウィザードに戻す必要があります。
図 60 は、getTreeNodes() メソッド (サンプル Roman Army ODA の ArmyAgent3 クラスで定義) の実装を示しています。
public TreeNode[] getTreeNodes(String parentNodePath, String searchPattern) throws ODKException { if (parentNodePath == null || parentNodePath.length() == 0) return getNodes(m_army, searchPattern); return getNodes(findSon(parentNodePath, searchPattern)); }
図 60 は、getTreeNodes() メソッドの実装における重要な概念を示しています。このメソッドはモジュラー化されることが多く、データ・ソースの実際の検索は個別のメソッド、または個別のクラスに組み込まれます。この getTreeNodes() メソッドは、選択したデータ・ソース・データのツリー・ノード配列を実際に生成する際に getNodes() メソッドを呼び出します。親ノード・パスが空の場合、getTreeNodes() は、(m_army 変数内の) XML ファイルのコンテンツ全体を getNodes() に送ります。親ノード・パスが空でない場合、getTreeNodes() は、データ・ソースを実際に照会する findSon() メソッドの結果を getNodes() に送ります。
検索パターン を使用すると、親ノードを展開したときに、子ノードを表示するために満たす必要のある基準を指定できます。右マウス・ボタンをクリックしてから「項目を検索」をクリックして、検索パターン機能を開始します。検索基準を指定するための「検索パターンの入力」ダイアログ・ボックスが開きます。
ビジネス・オブジェクト・ウィザードは、検索パターンを受け取ると、getTreeNode() を再び呼び出して、データ・ソースから新しいツリー・ノード配列を取得します。ビジネス・オブジェクト・ウィザードは、検索パターンを引き数として getTreeNodes() に渡します。検索パターンには、基盤となるデータ・ソースで認識されるワイルドカードやその他の記号が含まれます。例えば、データ・ソースがデータベースである場合、有効な検索基準には、パーセント (%) や疑問符 (?) などの SQL 検索記号を含めることができます。
getTreeNodes() メソッドは、検索パターンに一致する子ノードがデータ・ソースにあるかどうかを検索し、ビジネス・オブジェクト・ウィザードに戻すツリー・ノード配列に結果の子ノードを保管します。このようにして、ソース・ノードで満たす必要のある新しい条件を動的に指定することができます。
また、searchPatternDesc メンバー変数を、有効な検索基準をユーザーに対して記述するストリングで初期化する必要もあります。
ビジネス・オブジェクト・ウィザードは、「検索パターンの入力」ダイアログ・ボックスのテキストとしてこのストリングを表示します。ODA のメタデータは、getMetaData() メソッドで初期化します。詳しくは、ODA メタデータの初期化を参照してください。
例えば、データ・ソースがデータベースである場合は、データベースの表を照会する SQL ステートメントに検索パターンを含めることができます。
サンプル Roman Army ODA では、検索パターンに検索条件として 1 つの文字を入力できます。 getTreeNodes() メソッドは、ツリー・ノードの実際の生成を処理する getNodes() メソッドを呼び出します。次のコード・フラグメントは、この getNodes() メソッド (ArmyAgent3 内で定義) からのものです。これを見ると、メソッドがデータ・ソースを検索する際にどのように検索パターンを使用しているのかがわかります。
TreeNode[] getNodes(Son parent, String searchPattern) { Vector nodes = new Vector();
if (searchPattern == null || searchPattern.length() == 0) searchPattern = ""; else searchPattern = new String(new char[] {searchPattern.charAt(0)});
XML ファイル (データ・ソース) 内のオブジェクトの名前と親ノード・パス内の現在の名前とを getNodes() メソッドで後で比較するときは、指定された検索パターンでオブジェクトの名前が始まっているかどうかを次のようにして検査します。
if (currSon.name.getValue().startsWith(searchPattern))
検索パターンをこのように使用する状況については、図 61 を参照してください。
getTreeNodes() メソッドの主な目的は、データ・ソースを照会し、ソース・ノード、つまり、ODA がコンテンツを生成できるオブジェクトを検出することです。データ・ソースを照会する仕組みは、ODA が作業の対象とするデータ・ソースのタイプによって異なります。例えば、XML ODA (WebSphere Business Integration Adapters 製品に含まれる事前ビルド済み ODA) は、XML ファイルを照会し、そのファイル内のコンテンツ生成が可能なオブジェクトの名前を戻します。別の例としては、JDBC ODA (WebSphere Business Integration Adapters に含まれる別の事前ビルド済み ODA) は、JDBC データベースを照会し、データベース内のコンテンツ生成が可能な表の名前を戻します。
表 25 で推奨したように、データ・ソースの照会に必要なロジックがかなり複雑な場合は、この対話を処理する特別な Java クラスを開発する必要があります。そうすれば、getTreeNodes() メソッドは、これらのクラスを必要に応じてインスタンス化してアクセスできます。これらのクラスは、ODA ライブラリー・ファイルに含めてください。詳しくは、ODA のコンパイルを参照してください。
サンプル Roman Army ODA では、findSon() メソッド (ArmyAgent3 クラスで定義) はデータ・ソースの照会タスクを実行します。このメソッドは、親ノード・パスによって識別される特定の soldier を Roman-Army XML ファイル内で検索します。このメソッドは、指定された名前の情報を Son オブジェクトとして戻します。サンプルでは、XML ファイル内のオブジェクトを読み取る Son クラスが定義されています。
ODA がソース・ノードについてデータ・ソースを照会するときは、検出した各ソース・ノードを表すための関連するツリー・ノードを生成する必要があります。ODK API は、ツリー・ノードを TreeNode クラスのオブジェクトとして表します。ツリー・ノードには、表 39 に示す情報が含まれています。
ツリー・ノードを作成するには、いずれかの形式の TreeNode() コンストラクターを使用します。
これらの形式については、TreeNode()を参照してください。
ノードが「標準」タイプである場合、ノードは次の構造体のいずれかを持つことができます。
ビジネス・オブジェクト・ウィザードが展開可能ノードを表示するときは、ノード名の左側に正符号 (+) または負符号 (-) が付いています。
正符号 (+) はノードの展開が可能であることを示し、負符号 (-) はノードの縮小が可能であることを示します。次の表は、TreeNode オブジェクトを展開可能ノードとして表示するために必要な初期設定を示しています。
TreeNode メンバー変数 | 値 |
---|---|
isExpandable
| true |
nodes
| 子ノードの配列 |
isGeneratable
| false (通常) |
ソース・ノード階層内の移動方法については、ソース・ノード階層内での移動を参照してください。
ビジネス・オブジェクト・ウィザードは、リーフ (終了) ノードを単にノード名で表示します。次の表は、TreeNode オブジェクトをリーフ・ノードとして表示するために必要な初期設定を示しています。
TreeNode メンバー変数 | 値 |
---|---|
isExpandable
| false |
nodes
| null |
isGeneratable
| true (通常) |
リーフ・ノードと展開可能ノードはどちらも標準タイプ・ノードです。したがって、両方のノードの polymorphicNature メンバー変数には、NODE_NATURE_NORMAL ノード・タイプ定数を設定する必要があります。
この定数は、(TreeNode クラスが実装する) ODKConstant インターフェース内で定義されています。TreeNode() コンストラクターの最初の 2 つの形式では、polymorphicNature メンバー変数は指定しません。したがって、このメンバー変数は、NODE_NATURE_NORMAL にデフォルト設定されています。
図 59 に示すソース・ノード階層を ODA が生成するものと想定しましょう。ユーザーが Uulius ノードを展開した場合、getTreeNodes() メソッドは、Uulius の子ノードを含むツリー・ノード配列を生成する必要があります。親ノード・パスは Apollo:Tellus:Uulius であり、空ではない ため、getTreeNodes() メソッドは、次のように getNodes() メソッドを呼び出します (図 60 を参照)。
getNodes(findSon(parentNodePath), searchPattern))
この getNodes() の呼び出しでは、findSon() メソッドを使用してデータ・ソースに Uulius ノードを照会し、XML ファイルからの情報を含む Son オブジェクトを戻します。この Son オブジェクトのメンバー変数の 1 つは、Uulius の子に関する情報を含む XML オブジェクトのベクトル (XmlObjectVector) です。図 61 は、この XML オブジェクト・ベクトルをループ処理し、それぞれの子ごとに TreeNode オブジェクトを生成する getNodes() メソッドからのコード・フラグメントを示しています。
for (int i=0; i<sons.size(); i++) { Son currSon = (Son) sons.getAt(i); if (currSon.name.getValues().startsWith(searchPattern)) { int age = currSon.age.getIntValue(); int children = currSon.Son == null ? 0 : currSon.Son.size(); int nature = TreeNode.NODE_NATURE_NORMAL;
TreeNode tn = new TreeNode(currSon.name.getValue(), " ", canRecruit(currSon), children > 0, null, nature);
nodes.add(tn); } }
図 61 に示すコード・フラグメントは、それぞれの子 soldier ノードの新しい TreeNode オブジェクトを soldier の名前で、このノードが生成可能であるかどうか (soldier が従軍可能な年齢であるかどうかに基づく)、展開可能であるかどうか (この soldier が所有する子の数に基づく) を設定して初期化します。この TreeNode() コンストラクターの呼び出しでは、ツリー・ノードは説明 ("") で初期化されず、どの子ノードも戻されません。それぞれの新しい TreeNode オブジェクトがインスタンス化されると、コードはそれを Java Vector (nodes) に追加します。 getNodes() によってすべての 子ノードの TreeNode オブジェクトが生成されると、このベクトルの内容が次のコードでツリー・ノード配列にコピーされます。
TreeNode[] tn = new TreeNode[nodes.size()]; System.arraycopy(nodes.toArray(), 0, tn, 0, nodes.size());
getNodes() メソッドは、このツリー・ノード配列を getTreeNodes() 経由で呼び出し側プログラムのビジネス・オブジェクト・ウィザードに戻します。ビジネス・オブジェクト・ウィザードは、この新しいツリー・ノード配列を使用して、展開された Uulius ノードのコンテンツを表示します (図 62 を参照)。
ノードが「ファイル」タイプの場合は、オペレーティング・システム・ファイルとノードを関連付けることができます。
ユーザーがノード名を右マウス・ボタンでクリックすると、ビジネス・オブジェクト・ウィザードは「関連付けられたファイル」メニュー項目を活動化することにより、ノードがファイル・タイプであることを示します。このメニュー項目の使用方法については、オペレーティング・システム・ファイルの関連付けを参照してください。
ファイル・タイプ・ノードの polymorphicNature メンバー変数には、NODE_NATURE_FILE ノード・タイプ定数が設定されています。
この定数は、(TreeNode クラスが実装する) ODKConstant インターフェース内で定義されています。次の表は、TreeNode オブジェクトがファイル・タイプ・ノードとして機能するために必要な初期設定を示しています。
TreeNode メンバー変数 | 値 |
---|---|
polymorphicNature | NODE_NATURE_FILE |
isExpandable | false |
nodes | null |
isGeneratable | false (通常) |
サンプル Roman Army ODA で ArmyAgent4 クラスは、ファイル・タイプ・ノードをサポートする getNode() メソッドを実装しています。このサンプルでは、28 歳 (デフォルトの最小年齢) 以上で自分の子を持たない soldier を表す任意のノードのソース・ノードに対して、ファイルを関連付けることができます。このバージョンの getNode() のコードは、図 61 に示すコードとほぼ同じです。唯一の違いは、polymorphicNature メンバー変数への値の代入にあります。ノードが 28 歳以上で子を持たない soldier を表している場合、ArmyAgent4 バージョンの getNode() は、NODE_NATURE_NORMAL 定数をすべての ノードに割り当てる代わりに、次のコード行を使用してノード・タイプに NODE_NATURE_FILE を設定します。
int nature = m_allowAdoption && canAdopt(currSon) ? TreeNode.NODE_NATURE_FILE : TreeNode.NODE_NATURE_NORMAL;
ユーザーが「ノードを選択」ダイアログ・ボックス (ステップ 3) でソース・ノードを選択すると、ODA は、コンテンツ生成を開始する準備が整います。ビジネス・オブジェクト・ウィザードは、generateBoDefs() コンテンツ生成メソッドを呼び出して、ユーザーが選択したソース・ノードのビジネス・オブジェクト定義を生成します。
ビジネス・オブジェクト・ウィザードは、(ステップ 3 で選択された) ソース・ノードのリストを ODA に送ります。ビジネス・オブジェクト定義の生成プロセスの目的は、選択された各ソース・ノードごとにビジネス・オブジェクト定義を作成することです。 generateBoDefs() メソッドの実行中、ビジネス・オブジェクト・ウィザードは「ビジネス・オブジェクトの生成中」画面 (ステップ 5) を表示します。
したがって、generateBoDefs() は、ビジネス・オブジェクト定義 (BusObjDef オブジェクト) を生成し、それを生成済みコンテンツ構造体に保管して、コンテンツ・メタデータをビジネス・オブジェクト・ウィザードに戻すような処理を行うように実装する必要があります。
このセクションでは、ビジネス・オブジェクト定義を生成する際に generateBoDefs() メソッドで実行する必要のある次のステップについて説明します。
ビジネス・オブジェクト定義の生成を可能にするには、IGeneratesBoDefs インターフェース内で定義されている generateBoDefs() メソッドを、(ODKAgentBase2 から派生した) ODA クラスに実装する必要があります。
generateBoDefs() メソッドは、ユーザーが選択したこれらのソース・ノードを引き数、つまりソース・ノード・パスの配列 (String オブジェクト) として受け取ります。このメソッドは、この配列内の各ソース・ノードごとにビジネス・オブジェクト定義を生成する必要があります。また、このメソッドは、そのパスを使用してデータ・ソース内のソース・ノードを特定することができます。最後のステップとして、generateBoDefs() は、生成したビジネス・オブジェクト定義を記述するコンテンツ・メタデータ (ContentMetaData) オブジェクトを戻します。
サンプル Roman Army ODA は、ビジネス・オブジェクト定義を生成するために、要求時コンテンツ・プロトコルをサポートします (図 58 を参照)。 ArmyAgent3 クラス内のこの generateBoDefs() メソッドの実装には、図 63 に示すコード・フラグメントを含めます。このコード・フラグメントは、生成済みコンテンツ構造体 (m_generatedBOs) の変数を宣言し、generateBoDefs() メソッド自体を定義します。
図 63. generateBoDefs() メソッドの定義
final Vector m_generatedBOs = new Vector();
public ContentMetaData generateBoDefs(String[] nodes) throws ODKException {
コンテンツ生成プロセスの間に ODA で追加情報が必要となった場合は、「BO プロパティー」ダイアログ・ボックスを表示して、ビジネス・オブジェクト・プロパティー の値を入力するようユーザーに求めることができます。
ビジネス・オブジェクト・プロパティーの概要については、ビジネス・オブジェクト・プロパティーの取得を参照してください。
図 64 は、2 つのビジネス・オブジェクト・プロパティーを表示しているサンプルの「BO プロパティー」ダイアログ・ボックスを示しています。
図 64 に示すプロパティーをユーザーに提供するために、generateBoDefs() メソッドは次のステップを実行します。
getBOSpecificProps() メソッドは引き数として、エージェント・プロパティー・オブジェクトの配列を必要とします。この引き数は、ビジネス・オブジェクト・プロパティー配列 であり、「BO プロパティー」ダイアログ・ボックスに表示されるそれぞれのビジネス・オブジェクト・プロパティーごとに、1 つのエージェント・プロパティー・オブジェクトが保持されています。 generateBoDefs() は、getBOSpecificProps() を呼び出す前のステップとして、ビジネス・オブジェクト・プロパティーを定義する配列を作成し、ビジネス・オブジェクト・プロパティーを初期化して、それらのプロパティーを配列に保管する必要があります。
最初のステップでは、Verbs プロパティーと Prefix プロパティーを保持するビジネス・オブジェクト・プロパティー配列を定義します。次のステップでは、AgentProperty() コンストラクターを使用して、ビジネス・オブジェクト・プロパティーを初期化します。
このコンストラクターでは、AgentProperty クラスがサポートする各種のメタデータの値を指定します。AgentProperty クラスは、ビジネス・オブジェクト・プロパティーが次の機能を持つためのサポートを提供します。
Verbs プロパティーと Prefix プロパティーを初期化するには、AgentProperty() コンストラクターに次の情報を指定します。
したがって、このプロパティーは、AgentProperty() コンストラクター内で次のメタデータを必要とします。
AgentProperty() コンストラクターを呼び出す前に、図 65 に示すコードによって最初に validValues 配列と defaultValues 配列が作成および初期化され、それらがコンストラクターで使用できるようになります。
したがって、このプロパティーは、AgentProperty() コンストラクター内で次のメタデータを必要とします。
メタデータ | AgentProperty メンバー変数 | 値 |
---|---|---|
単一カーディナリティー |
cardinality
| ODKConstant.SINGLE_CARD |
ユーザーは複数の値の中から選択できない |
isMultiple
| false |
|
allValidValues
| null |
デフォルト値はない |
allDefaultValues
| null |
ユーザーは値を入力する必要がない |
isRequired
| false |
図 65 に示すコード・フラグメントは、ビジネス・オブジェクト・プロパティー配列を作成して初期化します。
// Create the business-object-property array AgentProperty AgtProps[] = new AgentProperty[2];
// Provide list of valid values for Verbs property Object[] validValues = new Object[4]; validValues[0] = new String("Create"); validValues[1] = new String("Retrieve"); validValues[2] = new String("Delete"); validValues[3] = new String("Update");
// Provide list of default values for Verbs property Object[] defaultValues = new Object[4]; defaultValues[0] = new String("Create"); defaultValues[1] = new String("Retrieve"); defaultValues[2] = new String("Delete"); defaultValues[3] = new String("Update");
// Instantiate the Verbs property AgtProps[0] = new AgentProperty("Verbs", AgentProperty.TYPE_STRING, "Verbs that are applicable to all the selected objects", false, true, ODKConstant.MULTIPLE_CARD, validValues, defaultValues);
// Instantiate the Prefix property AgtProps[1] = new AgentProperty("Prefix", AgentProperty.TYPE_STRING, "Prefix that should be applied to each business object name", false, false, ODKConstant.SINGLE_CARD, null, null);
ビジネス・オブジェクト・プロパティーのメタデータについては、エージェント・プロパティーの使用を参照してください。
ビジネス・オブジェクト・プロパティー配列を初期化すると、ODA は getBOSpecificProps() メソッドを呼び出してこの配列をビジネス・オブジェクト・ウィザードに渡し、「BO プロパティー」ダイアログ・ボックスに表示されるようにします。
このメソッドは ODKUtility クラス内で定義されているため、ODKUtility オブジェクトへのアクセスが必要となります。
通常、このオブジェクトは、ODA 初期設定の一環としてインスタンス化します。詳しくは、ODKUtility オブジェクトへのハンドルの取得を参照してください。
図 66 に示す getBOSpecificProps() の呼び出しでは、(図 65 で初期化された) AgtProps 配列 がビジネス・オブジェクト・ウィザードに送られ、「BO プロパティー」ダイアログ・ボックスに表示されます。
図 66. 「BO プロパティー」ダイアログ・ボックスの表示
// Display BO Properties dialog box, initializing it with AgtProps Util.getBOSpecificProps(AgtProps, "For all the Tables selected");
ユーザーが「BO プロパティー」ダイアログ・ボックスでビジネス・オブジェクト・プロパティーの値を指定して「次へ」をクリックすると、ビジネス・オブジェクト・ウィザードはユーザー指定値を ODA に戻します。 ODA は、これらの値を次のいずれかの方法で取得できます。
図 66 に示す getBOSpecificProps() の呼び出しでは、ビジネス・オブジェクト・ウィザードが作成する Hashtable オブジェクトが保管されませんでした。したがって、このコード・フラグメントは getBOSpecificProperty() メソッドを使用して、動詞および各ビジネス・オブジェクト・プレフィックスに指定されたプロパティーの値を取得します。
// Get the value of the Verbs and the Prefix properties AgentProperty propVerb = Util.getBOSpecificProperty("Verbs"); AgentProperty propPrefix = Util.getBOSpecificProperty("Prefix");
generateBoDefs() メソッドは、ビジネス・オブジェクト・ウィザードから引き数として受け取った配列内の各ソース・ノードごとに、ビジネス・オブジェクト定義を生成する必要があります。ビジネス・オブジェクト定義を生成するために、generateBoDefs() は次のステップを実行する必要があります。
ODK API は、ビジネス・オブジェクト定義をビジネス・オブジェクト定義 (BusObjDef) オブジェクトとして表します。
BusObjDef() コンストラクターを使用すると、新しいビジネス・オブジェクト定義をインスタンス化し、それに名前を提供することができます。
そうすれば、表 40 に示す情報をビジネス・オブジェクト定義に提供できます。
表 40 に示すように、ビジネス・オブジェクト定義にはメタデータとデータの両方が含まれています。以降のセクションでは、ビジネス・オブジェクト定義のこれらの部分にアクセスする方法について説明します。
表 40 に示すように、ビジネス・オブジェクト定義のメタデータは、次の情報から構成されます。
generateBoDefs() メソッドは、ユーザーが選択したソース・ノードのリストを引き数として受け取ります。このリストは、ユーザーが選択したソース・ノードのノード・パスを含む String オブジェクトの配列です (ノード・パスについては、親ノード・パスの決定を参照してください)。この配列を使用して、ODA は各ソース・ノードに関連付けられているビジネス・オブジェクト定義の名前を適切に作成する必要があります。通常 ODA は、ビジネス・オブジェクト定義の名前はソース・ノードが表すデータ・ソース・オブジェクトの名前に一致する (またはそれに基づく) と想定しています。 ODA は、ソース・ノード・パスの構文を解析してソース・ノードの名前を取得し、このソース・ノード名を使用して関連するソース・データ・オブジェクトを特定し、このソース・データ・オブジェクトから名前を取得する必要があります。
例えば、Roman Army サンプルでは、データ・ソース・オブジェクトの名前とビジネス・オブジェクト定義の名前は同じです。したがって、サンプル・コードは、findSon() メソッド (ArmyAgent3 クラスと ArmyAgent4 クラスで定義) を呼び出し、ソース・ノード (nodes) の入力配列内に格納されているソース・ノードのノード・パスを使用して、ソース・ノードが表すデータ・ソース・オブジェクトを取得します (次の例を参照)。
for (int i=0; i<nodes.length; i++) { Son sonNode = findSon(nodes[i]); BusObjDef sonBo = new BusObjDef(sonNode.name.getValue()); ...
findSon() メソッドは、ソース・ノード・パスの構文を解析し、パス内の最後のノード名を取得します。
別の例として、データ・ソースがデータベースであり、そのソース・ノードが表を表しているものと仮定しましょう。ソース・ノード・パスにスキーマ名 (schema:table) が含まれる場合、ODA はソース・ノード・パスの構文を解析し、対応するビジネス・オブジェクト定義に表名のみを割り当てる必要があります。 (構成変数を持つ) ビジネス・オブジェクト定義にユーザーが指定したプレフィックスが ODA でサポートされる場合、ODA は、このプレフィックスを前に付加してから、BusObjDef() コンストラクターを呼び出し、ビジネス・オブジェクト定義オブジェクトを生成する必要があります (次のコード・フラグメントを参照)。
AgentProperty propPrefix = getBOSpecificProperty("Prefix"); for (int i=0; i<names.length; i++) { strToken = new StringTokenizer(names[i], ":"); schemaName = strToken.nextToken(); tableName = strToken.nextToken()
if (propPrefix.allValues != null && propPrefix.allValues[0] != null) boDef = new BusObjDef(propPrefix.allValues[0] + tableName); else boDef = new BusObjDef(tableName); ...
ビジネス・オブジェクト定義に割り当てたい正確な名前がデータ・ソース・オブジェクトに ない 場合、ODA はその名前を必要に応じて構文解析するか、何らかの方法でフォーマットする必要があります。
ビジネス・オブジェクトのアプリケーション固有の情報で説明したように、アプリケーション固有の情報は、アプリケーション固有の処理情報をビジネス・オブジェクト定義に保管するための有効な手段となります。処理プログラム (コネクターなど) からこの情報を移動すれば、処理プログラムをメタデータ主導型にすることができます。つまり、処理プログラムは、より一般的な手法で作成することが可能となり、アプリケーション固有の処理命令をビジネス・オブジェクト定義から取得できるようになります。
したがって、ビジネス・オブジェクト定義をメタデータ主導型の処理プログラムとともに使用する場合は、ビジネス・オブジェクト、属性、および動詞の各レベルのアプリケーション固有の情報を、適切にフォーマットしてビジネス・オブジェクト定義に含める必要があります。
Roman Army サンプルが生成するビジネス・オブジェクト定義は、アプリケーション固有の情報を提供しません。ただし、データ・ソースがそのソース・ノードとして表を持つデータベースであると仮定します。ODA は、ユーザーが選択した表ごとにビジネス・オブジェクト定義を生成します。表の名前は、ビジネス・オブジェクト・レベルのアプリケーション固有の情報として、このビジネス・オブジェクト定義に含めることができます。次のコード・フラグメントは、BusObjDef クラスで定義されている setAppInfo() メソッドを使用して、このビジネス・オブジェクト・レベルのアプリケーション固有の情報に対応する名前と値のペアを適切に作成します。
boDef.setAppInfo("TN=" + tableName + ";SCN=" + schemaName +";");
このコードは、TN および SCH の名前と値のペアを作成して、表名とスキーマ名をそれぞれ表します。この表名とスキーマ名は、要素の命名に使用するタグを用いて連結されます。次にこのコードは、setAppInfo() メソッドを使用して、このストリング全体をビジネス・オブジェクト・レベルのアプリケーション固有の情報として割り当てます。
ビジネス・オブジェクト定義には、属性 が含まれます。属性は、ビジネス・オブジェクト定義で表されるオブジェクトを記述するものです。ビジネス・オブジェクト定義は、その属性リスト 内に属性を保持しています。ODK API は、属性を属性 (BusObjAttr) オブジェクトとして表します。
属性オブジェクトをインスタンス化するには、BusObjAttr() コンストラクターを使用します。
表 41 は、属性オブジェクトのプロパティーをまとめたものです。これらのプロパティーは、属性メタデータに対応しています。
重要 |
---|
ビジネス・オブジェクト定義の生成プロセスでは、ObjectEventId 属性が自動的に作成されます。 ビジネス・オブジェクト・ウィザードがビジネス・オブジェクト定義をファイルに保管する場合は、リポジトリーのバージョンがこのファイルの先頭に自動的に追加されます。 リポジトリーのバージョンは、統合ブローカーが InterChange Server である場合に必要となります。 |
サンプル Roman Army ODA では、各ビジネス・オブジェクト定義はローマの兵士 (soldier) を表します。 generatesBoDefs() メソッドは、ビジネス・オブジェクト定義に対して次の属性を作成します。
図 67 は、ビジネス・オブジェクト定義に対してこれらの属性オブジェクトを生成するコード・フラグメントを示しています。
// 1. Create an attribute object for Age attribute BusObjAttr attr = new BusObjAttr("Age", BusObjAttrType.INTEGER, BusObjAttrType.AttrTypes[BusObjAttrType.INTEGER]);
// Set the Age attribute as the business object definition's key attr.setIsKey(true);
// Add the attribute to the business object definition's attribute list sonBo.insertAttribute(attr);
// 2. Create an attribute object for ChildNo attribute attr = new BusObjAttr("ChildNo", BusObjAttrType.INTEGER, BusObjAttrType.AttrTypes[BusObjAttrType.INTEGER]);
// Set the default value to number of children attr.setDefault(sonNode.Son == null ? "0" : "" + sonNode.Son.size());
// Add the attribute to the business object definition's attribute list boDef.insertAttribute(attr);
Age 属性を作成する際、図 67 に示すコード・フラグメントは次のステップを実行します。
ここでは、このコンストラクターの形式を使用して属性オブジェクトをその名前、タイプ、およびタイプ名で初期化します。
コードは、タイプを初期化する際に Integer (BusObjAttrType.INTEGER) の属性タイプ定数を指定します。
タイプ名を初期化する際は、BusObjAttrType インターフェース内の AttrTypes メンバー変数を使用します。
この静的メンバー変数は、サポートされるすべての属性タイプについてタイプ名を提供し、属性タイプ定数によってインデックスを付けることができます。このようにして、タイプ名ストリングをハードコーディングすることなく、タイプ名を割り当てることができます。
この形式の BusObjAttr() コンストラクターで指定する属性プロパティーは 3 つだけであるため、その他の属性プロパティーはすべて「未定義」としてデフォルト設定されます。したがって、BusObjAttr() を呼び出した後、Primary key 属性プロパティーは false になります。 Age 属性がキー属性である ことを示すために、コード・サンプルは setIsKey() を呼び出します。
図 67 に示すコード・フラグメントは、これらの基本ステップを繰り返して ChildNo 属性を生成します。主な違いは、ChildNo はキー属性ではない ために setIsKey() の呼び出しが不要であることです。ただし、コード・フラグメントは setDefault() メソッドを呼び出して、この属性のデフォルト値を提供します。
Roman Army サンプルが生成するビジネス・オブジェクト定義は非常に単純です。ビジネス・オブジェクト定義内に存在する属性は 2 つだけであり、それらの名前はコンパイル時に既知です。また、設定する必要のある属性プロパティーは数個しかありません。もう少し複雑な例として、データ・ソースが、そのソース・ノードとしての表を持ち、またそのビジネス・オブジェクト定義の名前としての表を持つデータベースであると仮定しましょう。この場合、データベースの列は、ビジネス・オブジェクト定義の属性に対応します。これらの属性に対して、さらに多くの属性プロパティーを設定する必要があります。
次のコード・フラグメントは、データベースの表の列の属性を作成します。
Vector Attributes;
// 1. Retrieve columns from database table into 'rst' result set try{ ResultSet rst = null;
// Retrieve columns from database rst = db.dbmd.getColumns(null, schemaName, tableName, "%"); String colName = null; String colType = null; int cType = 0; int colSize = 0;
// Obtain next column from result set rst.next(); do{ // Get column name & type colName = rst.getString(4); colType = rst.getString("DATA_TYPE"); // Convert database types to supported types. // Load converted types into the cType variable // (steps not shown)
// 2. Create an attribute object for each column in the result set. Attributes = new Vector(1, 10);
try { // Create attribute object for column BusObjAttr attrib = new BusObjAttr(colName, cType);
// Set the cardinality and maxLength attribute properties attrib.setCardinality(BusObjAttr.CARD_SINGLE); colSize = rst.getInt("COLUMN_SIZE"); attrib.setMaxLength(colSize);
// Determine whether it is a primary key in the table: compare // column name against earlier retrieve of table's primary keys // (stored in pKeys -- code not included here) if (pKeys.contains(colName))== true { attrib.setIsKey(true); }else attrib.setIsKey(false);
// Determine whether it is a foreign key in the table: compare // column name against earlier retrieve of table's primary keys // (stored in fKeys -- code not included here) if (fKeys.contains(colName))== true { attrib.setIsForeignKey(true); }else attrib.setIsForeignKey(false);
// Set the isRequired property if ((rst.getString("IS_NULLABLE").equals("NO")) && (attrib.isKey() != true)){ attrib.setIsRequiredKey(true); }
// Create attribute application-specific information: // CN tag provides column name String asi = "CN="+colName; attrib.setAppText(asi); attrib.setDefault("");
// Add attribute object to Attributes vector Attributes.add(attrib); ...
// 3. Save the attribute vector as the business object definition's attribute list boDef.setAttributeList(Attributes);
このプロセスにおけるステップは、次のとおりです。
この形式のコンストラクターは、属性の名前とタイプのみを指定します。
BusObjAttr attrib = new BusObjAttr(LineItems, OrderLineItems); attrib.setCardinality(BusObjAttr.CARD_MULTIPLE);
コード・フラグメントは、データベースから選択した基本キー列 (pKey) および外部キー列 (fKey) を含む既存の配列内の名前と現在の列の名前とを比較します。基本キー列と外部キー列を選択するコードはここでは示しません。
データベースの表に対して生成されたビジネス・オブジェクト定義の場合は、属性レベルのアプリケーション固有の情報として、列名を各属性ごとにビジネス・オブジェクト定義に含めることができます。
このコード・フラグメントは、BusObjAttr クラスで定義されている setAppText() メソッドを使用して、属性レベルのアプリケーション固有の情報に対応した名前と値のペア CN を作成します。
コードは、列名と CN タグを連結します。次に、setAppText() メソッドを使用して、このストリング全体を属性のアプリケーション固有の情報として割り当てます。
ビジネス・オブジェクト定義には、サポートされる動詞 が含まれます。この動詞は、ビジネス・オブジェクト定義のビジネス・オブジェクト上で実行可能な操作を記述します。
ビジネス・オブジェクト定義は、サポートしている動詞をその動詞リスト 内に保持しています。ODK API は、動詞をビジネス・オブジェクト動詞 (BusObjVerb) オブジェクトとして表します。
動詞オブジェクトをインスタンス化するには、BusObjVerb() コンストラクターを使用します。
表 42 は、動詞オブジェクト内のメタデータをまとめたものです。
動詞メタデータ | 説明 | accessor メソッド |
---|---|---|
名前 | サポートされる動詞の名前 (Create、Retrieve、Update、または Delete など) |
getName()、setName()
|
アプリケーション固有の情報 | 動詞レベルのアプリケーション固有の情報。動詞にのみ適用される情報が含まれます。 |
getAppInfo()、setAppInfo()
|
Roman Army サンプルでは、generatesBoDefs() メソッドが、サポートされる単一の動詞である Create を各ビジネス・オブジェクト定義に割り当てます。次のコード・フラグメントは、BusObjDef クラスで定義されている insertVerb() メソッドを使用して、Create 動詞をビジネス・オブジェクト定義の動詞リストに追加します。
sonBo.insertVerb("Create", null);
Roman Army サンプルが生成するビジネス・オブジェクト定義は、アプリケーション固有の情報を提供しません。したがって、この insertVerb() 呼び出しの 2 番目の引き数 (動詞のアプリケーション固有の情報を指定する) は null となります。
ODA は、「BO プロパティー」ダイアログ・ボックスを使用して、生成済みのビジネス・オブジェクト定義の動詞サポートを実現できます。 Verbs と呼ばれるビジネス・オブジェクト・プロパティーを定義し、サポートされる動詞をユーザーが選択できるようにすることで、ODA はよりカスタマイズされた動詞サポートを取得できます。「BO プロパティー」ダイアログ・ボックスの使用方法については、ビジネス・オブジェクト・プロパティーの要求を参照してください。
次のコード・フラグメントでは、ODA が Verbs というビジネス・オブジェクト・プロパティーのユーザー指定値を取得済みで、かつ ODA がこのプロパティーを使用して、ビジネス・オブジェクト定義の動詞リストに追加する動詞を取得するものと想定しています。
Vector Verbs; AgentProperty propVerbs = getBOSpecificProperty("Verbs"); if (propVerbs.allValues[0] != null) { int len = propVerbs.allValues.length; BusObjVerb verb; for(int i=0; i<len; i++) { if(propVerbs.allValues[i] != null) { try { verb = new BusObjVerb(propVerbs.allValues[i].toString(), ""); Verbs.add(verb); } } } ... boDef.setVerbList(Verbs);
このコード・フラグメントは、BusObjVerb() コンストラクターを使用して、タイプ BusObjVerb の verb 変数に動詞をコピーします。
次に、その動詞オブジェクトの String バージョンを Verbs ベクトルにロードします。このコードでは、動詞のアプリケーション固有の情報は指定されません。最後にコード・フラグメントは、BusObjDef クラスで定義されている setVerbList() メソッドを使用して、生成済みの動詞ベクトル (Verbs) をビジネス・オブジェクト定義の動詞リストとして割り当てます。
生成済みコンテンツの提供で説明したように、ODA は生成済みコンテンツを 2 つの部分に分けてビジネス・オブジェクト・ウィザードに戻す必要があります。したがって、ODA がビジネス・オブジェクト定義をコンテンツとして生成する場合は、次のものを戻す必要があります。
ODA は「要求時」にビジネス・オブジェクト定義を生成する必要があるため、generateBoDefs() メソッドは次のようにコンテンツ情報を提供します。
ビジネス・オブジェクト・ウィザードは、このコンテンツ・メタデータ・オブジェクトを受け取ると、getBoDefs() メソッドを必要に応じて使用することにより、(生成済みコンテンツ構造体内の) 生成済みビジネス・オブジェクト定義にアクセスできます。
図 68 のコード・サンプルは、サンプル Roman Army ODA の generateBoDefs() メソッドの最後の部分を示しています。
m_generatedBOs.add(sonBo); } // this for loop terminates when all bus obj defs are generated
return new ContentMetaData(ContentType.BusinessObject, -1, m_generatedBOs.size()); } // end of generateBoDefs()
図 68 のコード・フラグメントは、生成済みコンテンツを次のように処理します。
図 63 に示すように、Roman Army サンプルは m_generatedBOs と呼ばれる Java ベクトルを生成済みコンテンツ構造体として使用します。この構造体は、Roman Army ODA クラスのメソッドに対してグローバルです。生成されたビジネス・オブジェクト定義を保管する際、generateBoDefs() は、それを m_generatedBOs ベクトルに保管します。このステップはループに含まれていますが、このループは、ユーザーが選択したすべての ソース・ノードに対してビジネス・オブジェクト定義が生成された時点で終了します。ビジネス・オブジェクト・ウィザードは、生成済みコンテンツ構造体にアクセスする必要があるときは、コンテンツ取得メソッド (getBoDefs()) を呼び出します。
generateBoDefs() メソッドは、ContentMetaData オブジェクトをインスタンス化し、表 43 に示す情報をこのコンストラクターに渡します。
表 43. ビジネス・オブジェクト定義を生成するためのコンテンツ・メタデータの初期化
ContentMetaData 情報 | コード | 説明 |
---|---|---|
コンテンツ・タイプ | ContentType.BusinessObject |
コンテンツ・タイプがビジネス・オブジェクト定義であることを示します。
|
生成済みコンテンツのサイズ | -1 |
合計サイズが必須でない ことを示します。現在の ContentMetaData オブジェクトの実装では、長さの値は必要ありません。 |
生成済みコンテンツの数 | m_generatedBOs.size() |
size() メソッドは、現在ベクトル内にある要素の数を戻します。
|
generateBoDefs() メソッドは、実際に生成されたビジネス・オブジェクト定義を戻しません。ビジネス・オブジェクト・ウィザードで生成済みコンテンツにアクセスできるようにするには、ビジネス・オブジェクト定義用のコンテンツ取得メソッドを ODA クラスに実装する必要があります。ビジネス・オブジェクト・ウィザードは、generateBoDefs() によって戻される コンテンツ・メタデータ・オブジェクト内の情報を使用して、適切なコンテンツ取得メソッドを呼び出すかどうかを決定します。generateBoDefs() が正常にビジネス・オブジェクトを生成すると、ビジネス・オブジェクト・ウィザードは getBoDefs() メソッドを呼び出して、生成済みのビジネス・オブジェクト定義を取得します。
ODA は、ビジネス・オブジェクト定義の生成において、コールバック・コンテンツ・プロトコルをサポートしてはなりません。
コンテンツ・プロトコルについては、ODA コンテンツ・プロトコルの選択を参照してください。
生成済みのビジネス・オブジェクト定義へのアクセスを可能にするには、ODA クラスに getBoDefs() メソッドを実装する必要があります。このメソッドは、IGeneratesBoDefs インターフェース内で定義されています。
このメソッドは、戻されるビジネス・オブジェクト定義の数を識別するインデックスを引き数として受け入れます。また、このメソッドは、生成済みコンテンツ構造体内のビジネス・オブジェクト定義にアクセスし、取得したビジネス・オブジェクト定義 (BusObjDef) オブジェクトの配列を戻します。この配列内のビジネス・オブジェクト定義の数は、表 44 に示すように、インデックス引き数の値によって異なります。
サンプル Roman Army ODA の場合、generateBoDefs() メソッド (ArmyAgent3 クラスで定義) は、m_generatedBOs ベクトルに生成済みのビジネス・オブジェクト定義を設定します。したがって、getBoDefs() メソッド (これも ArmyAgent3 クラスで定義) は、指定した数のビジネス・オブジェクト定義をこのベクトルから取得し、それを戻り配列内にコピーします。次のコードは、サンプル Roman Army ODA の getBoDefs() メソッドを示しています。
public BusObjDef[] getBoDefs(long index) throws ODKException { BusObjDef[] bos = null;
if (index == ODKConstant.GET_ALL_OBJECTS) { bos = new BusObjDef[m_generatedBOs.size()] System.arraycopy(m_generatedBOs.toArray(), 0, bos, 0, m_generatedBOs.size()); }
else bos = new BusObjDef[] {(BusObjDef)m_generatedBOs.get((int)index)};
return bos; }