データ・ハンドラーを開発するには、DataHandler クラスの次のメソッドをインプリメントします。
カスタム・データ・ハンドラーのメソッドは、データ・ハンドラー基本クラスの拡張で作成した DataHandler クラスの Java ソース・ファイルに入ります。
データ・ハンドラー基本クラス DataHandler には、表 49 にある抽象メソッドがあります。これらは、カスタム・データ・ハンドラーの DataHandler クラス にインプリメントする必要があります。
データ変換 | 直列化データの形式 | DataHandler メソッド |
---|---|---|
ストリングからビジネス・オブジェクトへの変換 | Reader オブジェクトを使用して、直列化データをビジネス・オブジェクトに 変換します。 | getBO() - 抽象 |
ビジネス・オブジェクトからストリングへの変換 | ビジネス・オブジェクトを InputStream オブジェクトに変換します。 | getStreamFromBO() |
| ビジネス・オブジェクトを String オブジェクトに変換します。 | getStringFromBO() |
| ビジネス・オブジェクトをバイト配列に変換します。 | getByteArrayFromBO() |
次のセクションでは、各抽象 DataHandler メソッドのインプリメンテーション情報を提供します。
抽象 getBO() メソッドでは、ストリングからビジネス・オブジェクトへの変換を実行します。つまり、Java Reader オブジェクトから抽出したデータを ビジネス・オブジェクトに取り込みます。 getBO() メソッドには、次のように 2 つのバージョンがあります。
入力引き数には、直列化データとビジネス・オブジェクトへの参照を含む Reader オブジェクトが組み込まれます。メソッドは、theBusObj ビジネス・オブジェクトに、serializedData データを取り込みます。
入力引き数には、直列化データを含む Reader オブジェクトが組み込まれます。このメソッドは、データからビジネス・オブジェクト・タイプ (ビジネス・オブジェクト定義) の名前を判別し、そのタイプのビジネス・オブジェクト・インスタンスを作成および充てんします。
getBO() メソッドを使用すると、呼び出し元は、構成情報 (config パラメーター) が含まれたオプションのオブジェクトを渡すことができます。この情報は、データ・ハンドラーのメタオブジェクトで指定された構成情報に加えられるものです。例として、構成オブジェクトは、テンプレート・ファイルや、データ・ハンドラーが使用する URL を指すことができます。
抽象 getBO() メソッドの目的は、Reader オブジェクトに含まれる直列化データをビジネス・オブジェクトに取り込むことです。これにより、getBO() のパブリック・バージョンはサポートされるいずれかの形式で直列化データを受け取り、そのデータを Reader オブジェクトに変換し、抽象 getBO() メソッドを呼び出して、ストリングからビジネス・オブジェクトへの変換を実際に実行することができます。パブリック getBO() メソッドについての詳細は、getBO() - パブリック を参照してください。
図 34 に、getBO() メソッドの 2 番目の形式の基本的なインプリメンテーションを示します。この例には、固定幅データを含む Reader オブジェクトからのデータをビジネス・オブジェクトに変換するときのステップを示しています。
public BusinessObjectInterface getBO(Reader serializedData, Object config) throws Exception { clear(config); BusinessObjectInterface resultObj = null; // Create a String object from the Reader, then use the string // method int conversionCheck; char[] temp = new char[2000]; StringBuffer tempStringBuffer = new StringBuffer(1000); while ( (conversionCheck = serializedData.read(temp)) != -1 ) tempStringBuffer.append(new String (temp, 0, conversionCheck)); mBOString = new String(tempStringBuffer); mBOStringLength = mBOString.length(); resultObj = getBOFromString(null); return resultObj; } // Gets business object name and verb and creates a bus obj instance private BusinessObjectInterface getBOFromString(String pvBOType) throws Exception { BusinessObjectInterface returnObj = null; String lvBOName = null; String lvVerb = null; lvBOName = this.getNextToken(mBONameSize, true); lvVerb = this.getNextToken(mBOVerbSize, true); if( (pvBOType != null) && (lvBOName.compareTo(pvBOType) != 0) ) { throw new Exception(...); } else { returnObj = JavaConnectorUtil.createBusinessObject(lvBOName); } returnObj.setVerb(lvVerb); parseAttributeList(returnObj); return returnObj; }
// Parse String to populate the attributes in the business object protected void parseAttributeList(BusinessObjectInterface pvBO) throws Exception { if ( mEndOfBOString ) throw new Exception(...); else if( pvBO == null ) throw new Exception(...); int lvAttrNum = pvBO.getAttrCount(); String lvAttrName = null; String lvAttrValue = null; int lvAttrMaxLength = 0; try { for (int lvAttrIndex = 0; lvAttrIndex < lvAttrNum; lvAttrIndex++) { CxObjectAttr lvAttrSpec = pvBO.getAttrDesc(lvAttrIndex); lvAttrName = lvAttrSpec.getName(); // Determine if the attribute is a simple attribute or a // business object container. if (lvAttrSpec.isObjectType()) { // Get the next token based on the BOCountSize lvAttrMaxLength = mBOCountSize; lvAttrValue = this.getNextToken(mBOCountSize, true); String lvBOType = lvAttrSpec.getTypeName(); Object lvAttrBOValue = null; if (lvAttrSpec.isMultipleCard()) { this.getMultipleCard(pvBO,lvAttrIndex,lvBOType, lvAttrValue); } else { this.getSingleCard(pvBO,lvAttrIndex,lvBOType, lvAttrValue); } } else { // Get the next token based on the MaxLength of the attribute lvAttrMaxLength = lvAttrSpec.getMaxLength(); if (lvAttrMaxLength > 0) lvAttrValue = this.getNextToken(lvAttrMaxLength, false); else lvAttrValue = null;
// For simple String attribute, set to null, set to // configured CxIgnore or CxBlank values, or set to the // attribute value if (lvAttrValue == null ) pvBO.setAttrValue(lvAttrIndex, null); else if (lvAttrValue.equals(mCxIgnore)|| lvAttrValue.equals("")) pvBO.setAttrValue(lvAttrIndex, null); else if (lvAttrValue.equals(mCxBlank)|| lvAttrValue.equals(" ")) pvBO.setAttrValue(lvAttrIndex, ""); else pvBO.setAttrValue(lvAttrIndex, lvAttrValue); } } } } // Populates a child container with values in the String protected void getMultipleCard(BusinessObjectInterface pvParentBO, int pvParentAttrIndex, String pvBOType, String pvObjectCountString) throws CW_BOFormatException, Exception { try { if ( pvObjectCountString.equals(mCxIgnore) ) { // trace message } else { int lvObjectCount = Integer.parseInt(pvObjectCountString); if ( lvObjectCount == 0) { // trace message with the number of objects in container } else if (lvObjectCount > 0) { // There is at least one instance of the object in the string BusinessObjectInterface lvChildBO = null; // For each instance of the child object, parse the attribute // list, and then add the object container to the parent. for (int lvObjectIndex = 0; lvObjectIndex < lvObjectCount; lvObjectIndex++) { lvChildBO = getBOFromString(pvBOType); pvParentBO.setAttrValue(pvParentAttrIndex,lvChildBO); } } } } }
// Populates a single cardinality child with values in the String protected void getSingleCard(BusinessObjectInterface pvParentBO, int pvParentAttrIndex, String pvBOType, String pvObjectCountString) throws CW_BOFormatException, Exception { try { BusinessObjectInterface lvChildBO = null; // Check the object count token // If it does not match "1", assume that the child object should // be null if (pvObjectCountString.equals("1")) { // The string contains a single instance of the child lvChildBO = getBOFromString(pvBOType); pvParentBO.setAttrValue(pvParentAttrIndex, lvChildBO); } else if ( pvObjectCountString.equals(mCxIgnore) || pvObjectCountString.equals("0")) { // Validate that the object count token is valid } else throw new CW_BOFormatException(...); } }
表 50 の抽象メソッドは、ビジネス・オブジェクトからストリングへの変換を実行します。つまり、ビジネス・オブジェクトから特定の形式の直列化データを作成します。
表 50. ビジネス・オブジェクトからストリングへの変換をインプリメントするための抽象メソッド
抽象メソッド | 説明 |
---|---|
getStringFromBO() | ビジネス・オブジェクト内のデータを String オブジェクトに変換します。 |
getStreamFromBO() | ビジネス・オブジェクト内のデータを InputStream オブジェクトに変換します。 |
getByteArrayFromBO() | ビジネス・オブジェクト内のデータをバイト配列に変換します。 |
ビジネス・オブジェクトから変換する目的は、ビジネス・オブジェクト内のデータをすべて直列化形式にすることです。ただし、場合によっては、一部のビジネス・オブジェクト・データを直列化データに含めてはならない こともあります。例えば、ビジネス・オブジェクトは、子メタオブジェクトを使用して、コネクターの動的構成情報を保持することがあります。
IBM では、構成メタデータまたは動的メタデータ (あるいはその両方) 用に、プレフィックス cw_mo_label で始まるアプリケーション固有情報をすべて予約しています。 データ・ハンドラーがビジネス・オブジェクトからの変換時に無視する 必要がある属性を示すために、親ビジネス・オブジェクトのビジネス・オブジェクト定義では、そのアプリケーション固有情報内に次のタグを指定します。
cw_mo_label =child_meta-object_attribute_name
label は、cw_mo_ タグの目的を詳細に指定するために定義するストリングです。また、child_meta-object_attribute_name は、無視する属性の名前を表しています。この属性には通常、子メタオブジェクトが含まれています。cw_mo_label タグを複数指定する場合は、セミコロン (;) で区切ります。
getStringFromBO()、getStreamFromBO()、および getByteArrayFromBO() メソッドをカスタム・データ・ハンドラー用にインプリメントするときには、これらのメソッドが次のようにして、データ・ハンドラーにコネクター固有の属性をスキップオーバーさせる必要があります。
次のコードは、属性をスキップオーバーする方法を示しています。
List configObjList = com.crossworlds.DataHandlers.text.namevalue.listMOAttrNames(BusObj); //this list contains attribute names, which are configuration objects for ( attributes in BusObj ) { String attrName = BusObj.getAttrDisc(i).getName(); if ( configObjList.contains(attrName) ) { //skip continue; } }
例えば、MyCustomer という名前のビジネス・オブジェクトが、子メタオブジェクトを使用して、コネクター固有のルーティング情報を保持しているとします。このメタオブジェクトが CustConfig という名前の属性で表されている場合、MyCustomer には、そのアプリケーション固有情報に次のタグが含まれている可能性があります。
cw_mo_cfg=CustConfig
カスタム・データ・ハンドラーは、ビジネス・オブジェクトからの変換時にアプリケーション固有情報を調べて、MyCustomer に関連付けられているビジネス・オブジェクト定義の有無を検査します。次に、cw_mo_cfg タグを検索して、CustConfig 属性のスキップオーバーが必要かどうかを判別します。データ・ハンドラーから結果として生じた直列化データには、CustConfig 子メタオブジェクトは含まれていません。
カスタムのデータ・ハンドラーを開発して cw_mo_label タグを処理することが必要なのは、このデータ・ハンドラーが子メタオブジェクトやその他の動的オブジェクトを使用する場合のみ です。
getStringFromBO() メソッドは、ビジネス・オブジェクトからストリングへの変換を実行します。つまり、ビジネス・オブジェクトのデータを String オブジェクトに変換します。このメソッドの場合、呼び出し元は、変換するビジネス・オブジェクトを受け渡します。図 35 に、FixedWidth データ・ハンドラーによってインプリメントされた getStringFromBO() メソッドを示します。このメソッドは、固定幅フィールドの String を作成します。
この例は、ビジネス・オブジェクトから Reader オブジェクトへのデータ変換のステップを示しています。
図 35. getStringFromBO() メソッドの例
public String getStringFromBO(BusinessObjectInterface theObj, Object config) throws Exception { traceWrite( "Entering getStringFromBO(BusinessObjectInterface, Object) " + " for object type " + theObj.getName(), JavaConnectorUtil.LEVEL4); clear(config); String lvBOString = null; setAttrList(theObj); lvBOString = mBOStringBuffer.toString(); traceWrite( "Exiting getStringFromBO(BusinessObjectInterface, Object) " + " for object type " + theObj.getName(), JavaConnectorUtil.LEVEL4); return lvBOString; } protected void setAttrList(BusinessObjectInterface pvBO) throws Exception { traceWrite( "Entering setAttrList(BusinessObjectInterface) for object " + pvBO.getName(), JavaConnectorUtil.LEVEL4); int lvAttrNum = pvBO.getAttrCount(); String lvAttrName = null; String lvAttrValue = null; int lvAttrMaxLength = 0; // Add the business object name and verb to the fixed width format // String this.setSimpleToken( mBONameSize, pvBO.getName()); this.setSimpleToken( mBOVerbSize, pvBO.getVerb()); try { List moAttrNames = listMOAttrNames( pvBO ); int lvAttrCount = pvBO.getAttrCount(); ATTRIBUTE_WALK: for (int lvAttrIndex = 0; lvAttrIndex < lvAttrCount; ++lvAttrIndex) { CxObjectAttr lvAttrSpec = pvBO.getAttrDesc(lvAttrIndex); lvAttrName = lvAttrSpec.getName(); // Check if the current attribute is a simple (String) type // or a contained object. if (lvAttrSpec.isObjectType()) { //skip child objects designated as meta objects if( moAttrNames.contains( lvAttrName ) ) { continue ATTRIBUTE_WALK; }
if (lvAttrSpec.isMultipleCard()) { CxObjectContainerInterface lvAttrMultiCardBOValue = (CxObjectContainerInterface) pvBO.getAttrValue(lvAttrIndex); if (lvAttrMultiCardBOValue == null) { traceWrite( "setAttrList found empty multiple cardinality container " + lvAttrSpec.getTypeName(), JavaConnectorUtil.LEVEL5); // Add the count to the fixed width String this.setSimpleToken( mBOCountSize, "0"); } else { int lvObjectCount = lvAttrMultiCardBOValue.getObjectCount(); traceWrite( "setAttrList found multiple cardinality container " + lvAttrSpec.getTypeName() + " with " + lvObjectCount + " instances", JavaConnectorUtil.LEVEL5); // Add the count to the fixed width String this.setSimpleToken( mBOCountSize, Integer.toString(lvObjectCount)); // Add each object in the container to the fixed // width String. for (int lvContObjectIndex = 0; lvContObjectIndex < lvObjectCount; ++lvContObjectIndex) setAttrList( lvAttrMultiCardBOValue.getBusinessObject( lvContObjectIndex)); } } else { BusinessObjectInterface lvAttrSingleCardBOValue = (BusinessObjectInterface) pvBO.getAttrValue(lvAttrIndex); if (lvAttrSingleCardBOValue == null) { traceWrite( "setAttrList found empty single cardinality container " + lvAttrSpec.getTypeName(), JavaConnectorUtil.LEVEL5); // Add the count to the fixed width String this.setSimpleToken( mBOCountSize, "0"); }
else { traceWrite( "setAttrList found single cardinality container " + lvAttrSpec.getTypeName(), JavaConnectorUtil.LEVEL5); // Add the count to the fixed width String this.setSimpleToken( mBOCountSize, "1"); setAttrList(lvAttrSingleCardBOValue); } } } else { lvAttrValue = (String) pvBO.getAttrValue(lvAttrIndex); lvAttrMaxLength = lvAttrSpec.getMaxLength(); if (lvAttrMaxLength > 0) this.setSimpleToken(lvAttrMaxLength, lvAttrValue); } } } catch (CxObjectNoSuchAttributeException e) { throw new Exception(e.getMessage()); } traceWrite( "Exiting setAttrList(BusinessObjectInterface) for object " + pvBO.getName(), JavaConnectorUtil.LEVEL4); } protected void setSimpleToken( int pvCellSize, String pvTokenValue) throws Exception { traceWrite( "Entering setSimpleToken(int, String)", JavaConnectorUtil.LEVEL4); StringBuffer lvNewBuffer = new StringBuffer(pvCellSize); int lvTokenLength = 0; int lvCxIgnoreLength = mCxIgnore.length(); int lvCxBlankLength = mCxBlank.length(); int lvPadNumber = 0; // Check the token value to see if it is null if (pvTokenValue == null) { // For this case, we add the configured CxIgnore value to the // fixed width String if it fits in the cell. if (!mTruncation && lvCxIgnoreLength > pvCellSize) throw new Exception( " Null attribute value encountered where cell size is " + pvCellSize + ", size of CxIgnore value is " + lvCxIgnoreLength + "and trucation is not allowed. " + "Please check your MO format configuration.");
else { lvPadNumber = pvCellSize - lvCxIgnoreLength; lvNewBuffer.append(mCxIgnore); } } else if (pvTokenValue.equals("")) { // For this case, the configured CxBlank value is added to the // fixed width String if it fits in the cell. if (! mTruncation && lvCxBlankLength > pvCellSize) throw new Exception( " Blank attribute value encountered where cell size is " + pvCellSize + ", size of CxBlank value is " + lvCxBlankLength + "and trucation is not allowed. " + "Please check your MO format configuration."); else { lvPadNumber = pvCellSize - lvCxBlankLength; lvNewBuffer.append(mCxBlank); } } else { // For this case, actually add the token value to the fixed // width String, unless the data is too long for the cell. lvTokenLength = pvTokenValue.length(); if (!mTruncation && lvTokenLength > pvCellSize ) throw new Exception( " Attribute value encountered where cell size is " + pvCellSize + ", size of token value is " + lvTokenLength + "and trucation is not allowed. " + "Please check your MO format configuration."); else { lvNewBuffer.append(pvTokenValue); lvPadNumber = pvCellSize - lvTokenLength; } } if (lvPadNumber <= 0 && mTruncation) // Token is longer than the cell and truncation is allowed, // so the characters up to pvCellSize are added lvNewBuffer.setLength(pvCellSize); else if (lvPadNumber > 0) { // Pad the cell based on the configuration option chosen if ( mAlignment.equals(fixedwidth.AlignmentLeft) || mAlignment.equals(fixedwidth.AlignmentBoth)) this.padRight(lvNewBuffer, lvPadNumber); else if (mAlignment.equals(fixedwidth.AlignmentRight)) this.padLeft(lvNewBuffer, lvPadNumber); }
String lvNewBuffString = lvNewBuffer.toString(); // Note that this may cause a performance issue when the tracing // level is low, but in most cases it should not as any one token // is *usually* not very long. traceWrite( "Adding the following token to the fixed width String: " + lvNewBuffString, JavaConnectorUtil.LEVEL5); // After the cell has been fully formatted, append to fixed width // String being built mBOStringBuffer.append(lvNewBuffString); traceWrite( "Exiting setSimpleToken(int, String)", JavaConnectorUtil.LEVEL4); }
getStreamFromBO() メソッドは、ビジネス・オブジェクトのデータを InputStream オブジェクトに変換します。図 36 に、getStreamFromBO() メソッドのインプリメンテーションを示します。このインプリメンテーションでは、getStreamFromBO() が getStringFromBO() を呼び出して、ビジネス・オブジェクト・データを含む String オブジェクトを作成し、次に String を InputStream へ変換します。メソッドは、ビジネス・オブジェクト内のデータを表す InputStream オブジェクトを戻します。
図 36. getStreamFromBO() メソッドの例
public InputStream getStreamFromBO(BusinessObjectInterface theObj, Object config) throws Exception { clear(config); String BOstring; BOstring = getStringFromBO(theObj, config); return new ByteArrayInputStream( BOstring.getBytes() ); }
抽象 DataHandler メソッド
(インプリメントする必要がある) に加えて、DataHandler
クラスの一部のパブリック・メソッド (表 51 を参照)
についても、カスタム・データ・ハンドラーで最適に動作するようにオーバーライドする必要があります。
表 51. DataHandler クラスのパブリック・メソッド
パブリック DataHandler メソッド | 説明 |
---|---|
getBO() - パブリック | (いずれかの形式の) 直列化データをビジネス・オブジェクトに変換します。 |
getBOName() | 直列化データからビジネス・オブジェクトの名前を取得します。 |
getBooleanOption() | データ・ハンドラーから Boolean 構成オプションの値を取得します。 |
getOption() | データ・ハンドラーから構成オプションの値を取得します。 |
setOption() | データ・ハンドラーに構成オプションを設定します。 |
traceWrite() | データ・ハンドラーの適切なコンテキスト用にトレース書き込みメソッドを呼び出します。このとき、コンテキストはコネクターまたは Server Access Interface です。 |