Hitachi

Cosminexus V11 BPM/ESB基盤 サービスプラットフォーム 開発ガイド 基本開発編


付録H.4 CSCOwnCodeReaderインターフェース

文字コード変換UOCを開発する場合,CSCOwnCodeReaderインターフェースの実装クラスを作成します。未定義文字をセパレータに使用する場合はこのインターフェースを実装してください。

〈この項の構成〉

(1) インターフェース

CSCOwnCodeReaderインターフェースを次に示します。

図H‒3 CSCOwnCodeReaderインターフェース

[図データ]

インターフェース名

CSCOwnCodeReaderインターフェース

説明

独自文字コードの文字列を読み込むためのインターフェースです。

CSCOwnCodeReaderのパッケージ名は,jp.co.Hitachi.soft.csc.dt.uoc.CSCOwnCodeReaderです。

バイナリ文字列の読み込み処理で,文字コードを変換しないでセパレータを解析することで,バイト数や文字数が変化する変換の制限を緩和したり,変換の性能を向上させたりします。

このインターフェースの実装は任意です。実装していない場合,文字コード変換を実行してセパレータを解析します。

このインターフェースのインスタンスは,複数のスレッドで共用されるため,実装はスレッドセーフにする必要があります。

形式
package jp.co.Hitachi.soft.csc.dt.uoc ;
 
import jp.co.Hitachi.soft.csc.dt.uoc.CSCOwnCodeConverterException ;
 
public interface CSCOwnCodeReader {
 
       CSCOwnCodeReaderContext start( byte[] data, int offset, int length )
              throws CSCOwnCodeConverterException ;
 
       boolean readChar( CSCOwnCodeReaderContext context )
              throws CSCOwnCodeConverterException ;
 
       void end( CSCOwnCodeReaderContext context ) ;
}
メソッド

CSCOwnCodeReaderインターフェースのメソッドを次の表に示します。

メソッド名

説明

startメソッド

独自文字コード文字列の読み込みを開始するためのメソッドです。

readCharメソッド

独自文字コード文字を1文字読み込むメソッドです。

endメソッド

独自文字コード文字列の読み込みを終了するメソッドです。

データ変換の対象が可変長文字列で,かつバイナリフォーマット定義にセパレータが設定されている場合,データ変換はセパレータの解析処理を実行します。CSCOwnCodeReaderおよびCSCOwnCodeReaderContextの各メソッドの呼び出し順序を次の図に示します。

図H‒4 CSCOwnCodeReaderおよびCSCOwnCodeReaderContextの各メソッドの呼び出し順序

[図データ]

  1. インスタンス生成

    データ変換によってCSCOwnCodeReaderのインスタンスを生成します。

  2. CSCOwnCodeReader#startメソッド

    自スレッド専用のCSCOwnCodeReaderContextのインスタンスを生成します。以降,CSCOwnCodeReaderとの値の受け渡しは,自スレッドが保持するCSCOwnCodeReaderContextのインスタンスで実行します。

  3. CSCOwnCodeReader#readCharメソッド

    readCharの実行時,データ変換の処理は引数にCSCOwnCodeReaderContextのインスタンスを渡します。readCharの処理では,解析結果をCSCOwnCodeReaderContextのインスタンスにセットします。セットされた解析結果は,データ変換の処理でセパレータの解析に使用します。

  4. getPositionメソッド,getLengthメソッド,canSeparateメソッド

    それぞれのメソッドは,データ変換から呼ばれます。メソッドの実行順序は電文フォーマットに依存します。

    • getPositionメソッド

      このメソッドで現在の文字位置を返します。

    • getLengthメソッド

      このメソッドで現在の文字長を返します。

    • canSeparateメソッド

      このメソッドで現在の文字をセパレータの解析対象とするかどうかを返します。

  5. CSCOwnCodeReader#endメソッド

    CSCOwnCodeReaderContextの実装クラスの解放処理が必要な場合は,endメソッドを実行します。

(a) startメソッド

説明

独自文字コード文字列の読み込みを開始します。

形式
public CSCOwnCodeReaderContext start( byte[] data, int offset, int length )
パラメタ
data:

読み込み対象データです。

offset:

読み込み開始位置です。

length:

読み込み開始位置からの長さです。

例外
CSCOwnCodeConverterException:

文字コード変換処理中に異常が発生したため,データ変換処理全体を中断しました。

戻り値

CSCOwnCodeReaderContextの実装クラスのインスタンスです。このインスタンスは,ほかのスレッドで使用できません。

(b) readCharメソッド

説明

独自文字コード文字を1文字読み込みます。

文字の位置,長さは,CSCOwnCodeReaderContext#getPosition,CSCOwnCodeReaderContext#getLengthで取得できます。

形式
public boolean readChar( CSCOwnCodeReaderContext context )
パラメタ
context:

#startで返されたCSCOwnCodeReaderContextの実装クラスのインスタンスです。

例外
CSCOwnCodeConverterException:

文字コード変換処理中に異常が発生したため,データ変換処理全体を中断しました。

戻り値

読み込める上限を超えた場合,および文字を変換できない場合,falseを返します。それ以外の場合はtrueを返します。

(c) endメソッド

説明

独自文字コード文字列の読み込みを終了します。

読み込み処理の成功または失敗(エラー)に関係なく必ず呼ばれます。

形式
public void end( CSCOwnCodeReaderContext context )
パラメタ
context:

#startで返されたCSCOwnCodeReaderContextの実装クラスのインスタンスです。

例外
CSCOwnCodeConverterException:

文字コード変換処理中に異常が発生したため,データ変換処理全体を中断しました。

戻り値

なし。

(2) 例外クラス

文字コード変換UOCの開発時に発生する例外クラスを次に示します。

クラス名

CSCOwnCodeConverterExceptionクラス

説明

文字コード変換処理中に異常が発生した場合に送出する例外です。

この例外が発生した場合は,データ変換処理全体を中断します。

(3) 実装例(MS932)

CSCOwnCodeReaderインターフェースの実装例(MS932)を次に示します。

public class CSCOwnCodeReaderImpl implements CSCOwnCodeConverter, CSCOwnCodeReader {
 
    private static final String UNICODE = "ISO-10646-UCS-2" ;
 
    private final HJCOption option ;
 
    private static byte[] charSizeTable = initCharSizeTable() ;
 
    private static byte[] initCharSizeTable() {
 
        final byte[] objTable = new byte[0x100] ;
 
        for ( int i = 0; i <= 0xff; i++ ) {
            if ( i <= 0x80
                || (i >= 0xA0 && i <= 0xDF)
                || (i >= 0xFD && i <= 0xFF) ) {
                objTable[i] = 1 ;
            }
            else {
                objTable[i] = 2 ;
            }
        }
 
        return objTable ;
    }
 
 
    public CSCOwnCodeReaderImpl() {
 
        option = new HJCOption() ;
        try {
            // Unicodeはビッグエンディアン
            option.enableOption( HJCOption.COP_BIGENDIAN ) ;
        }
        catch ( Exception e ) {
            e.printStackTrace() ;
        }
    }
 
 
    @Override
    public void setProperties( Properties properties )
        throws CSCOwnCodeConverterException {
 
        String codetablepath = null ;
        if ( properties != null ) {
            codetablepath = properties.getProperty( "codetablepath" ) ;
        }
 
        try {
            if ( codetablepath == null ) {
                option
                    .setTablePath( "C:\\Program Files\\HITACHI\\Cosminexus\\CSC\\lib\\external\\table" ) ;
            }
            else {
                option.setTablePath( codetablepath ) ;
            }
        }
        catch ( Exception e ) {
            e.printStackTrace() ;
        }
    }
 
 
    @Override
    public int available( byte[] inBuffer ) throws CSCOwnCodeConverterException {
 
        if ( inBuffer == null ) {
            final String message = "空文字列は変換できません。" ;
            throw new CSCOwnCodeConverterException( message ) ;
        }
 
        int retInt = -1 ;
        final HJCResult result = new HJCResult() ;
        final HJCString inStr = new HJCString( inBuffer ) ;
 
        try {
            HJCConverters.cs_ms932tounicode( inStr, result, option ) ;
        }
        catch ( Exception e ) {
            e.printStackTrace() ;
            throw new CSCOwnCodeConverterException( e ) ;
        }
 
        final byte[] resultData = result.getStrResult().getBytes() ;
        final int resultState = result.getConvertState() ;
        if ( resultState == HJCConvertState.CST_NORMAL ) {
            // 変換が正常終了
            if ( resultData != null ) {
                retInt = result.getResultLength() ;
            }
        }
        else {
            // 変換が異常終了
            final byte[] bytes = new byte[result.getResultLength() - 1] ;
            System.arraycopy(
                inBuffer,
                0,
                bytes,
                0,
                result.getResultLength() - 1 ) ;
            retInt = available( bytes ) ;
        }
        return retInt ;
    }
 
 
    @Override
    public char[] ownCodeToUnicode( byte[] inBuffer )
        throws CSCOwnCodeConverterException {
 
        char[] retChar = null ;
        final HJCResult result = new HJCResult() ;
        final HJCString inStr = new HJCString( inBuffer ) ;
 
        try {
            HJCConverters.cs_ms932tounicode( inStr, result, option ) ;
            final byte[] resultData = result.getStrResult().getBytes() ;
            final String retstr = new String( resultData, UNICODE ) ;
            retChar = retstr.toCharArray() ;
        }
        catch ( Exception e ) {
            e.printStackTrace() ;
            throw new CSCOwnCodeConverterException( e ) ;
        }
 
        return retChar ;
    }
 
 
    @Override
    public byte[] unicodeToOwnCode( char[] inBuffer )
        throws CSCOwnCodeConverterException {
 
        byte[] retByte = null ;
        final String data = new String( inBuffer ) ;
        final HJCResult result = new HJCResult() ;
 
        try {
            final HJCString inStr = new HJCString( data.getBytes( UNICODE ) ) ;
            HJCConverters.cs_unicodetoms932( inStr, result, option ) ;
            retByte = result.getStrResult().getBytes() ;
        }
        catch ( Exception e ) {
            e.printStackTrace() ;
            throw new CSCOwnCodeConverterException( e ) ;
        }
 
        return retByte ;
    }
 
 
    @Override
    public CSCOwnCodeReaderContext start( byte[] data, int offset, int length )
        throws CSCOwnCodeConverterException {
 
        return new CSCOwnCodeReaderContextImpl( Arrays.copyOfRange(
            data,
            offset,
            length ) ) ;
    }
 
 
    @Override
    public boolean readChar( CSCOwnCodeReaderContext context )
        throws CSCOwnCodeConverterException {
 
        final CSCOwnCodeReaderContextImpl contextImpl = (CSCOwnCodeReaderContextImpl)context ;
 
        final int offset = contextImpl.getNextPosition() ;
        contextImpl.setPosition( offset ) ;
 
        final byte[] data = contextImpl.getData() ;
 
        // 入力データの最大長を取得(文字のサイズではない)
        final int maxLength = data.length ;
        if ( offset >= maxLength ) {
            // 現在位置が入力データの範囲外である
            return false ;
        }
 
        final int len = charSizeTable[data[offset] & 0xff] ;
 
        contextImpl.setLength( len ) ;
 
        final int next = offset + len ;
        contextImpl.setNextPosition( next ) ;
 
        if ( next > maxLength ) {
            // 変換結果が異常
            // 入力データが不正な場合に発生
            // falseを返して解析を中止する
            return false ;
        }
 
        return true ;
    }
 
 
    @Override
    public void end( CSCOwnCodeReaderContext context )
        throws CSCOwnCodeConverterException {
 
        // 解放すべきリソースがないため,何もしない
    }
 
}

(4) 実装例(IBM漢字コード)

CSCOwnCodeReaderインターフェースの実装例(IBM漢字コード)を次に示します。

public class CSCOwnCodeReaderImpl
    implements
        CSCOwnCodeConverter,
        CSCOwnCodeReader {
 
    private static final String UNICODE = "ISO-10646-UCS-2" ;
 
    private static final byte SHIFT_SINGLEBYTE = (byte)0x0f ;
 
    private static final byte SHIFT_MULTIBYTE = (byte)0x0e ;
 
    private final HJCOption option ;
 
 
    public CSCOwnCodeReaderImpl() {
 
        option = new HJCOption() ;
        try {
            // Unicodeはビッグエンディアン
            option.enableOption( HJCOption.COP_BIGENDIAN ) ;
            // EBCDIC
            option.enableOption( HJCOption.COP_EBCDIC ) ;
        }
        catch ( Exception e ) {
            e.printStackTrace() ;
        }
    }
 
 
    @Override
    public void setProperties( Properties properties )
        throws CSCOwnCodeConverterException {
 
        String codetablepath = null ;
        if ( properties != null ) {
            codetablepath = properties.getProperty( "codetablepath" ) ;
        }
 
        try {
            if ( codetablepath == null ) {
                option
                    .setTablePath( "C:\\Program Files\\HITACHI\\Cosminexus\\CSC\\lib\\external\\table" ) ;
            }
            else {
                option.setTablePath( codetablepath ) ;
            }
        }
        catch ( Exception e ) {
            e.printStackTrace() ;
        }
    }
 
 
    @Override
    public int available( byte[] inBuffer ) throws CSCOwnCodeConverterException {
 
        if ( inBuffer == null ) {
            final String message = "空文字列は変換できません。" ;
            throw new CSCOwnCodeConverterException( message ) ;
        }
 
        int retInt = -1 ;
        final HJCResult result = new HJCResult() ;
        final HJCString inStr = new HJCString( inBuffer ) ;
 
        try {
            HJCConverters.cs_ibmtounicode( inStr, result, option ) ;
        }
        catch ( Exception e ) {
            e.printStackTrace() ;
            throw new CSCOwnCodeConverterException( e ) ;
        }
 
        final byte[] resultData = result.getStrResult().getBytes() ;
        final int resultState = result.getConvertState() ;
        if ( resultState == HJCConvertState.CST_NORMAL ) {
            // 変換が正常終了
            if ( resultData != null ) {
                retInt = result.getResultLength() ;
            }
        }
        else {
            // 変換が異常終了
            final byte[] bytes = new byte[result.getResultLength() - 1] ;
            System.arraycopy(
                inBuffer,
                0,
                bytes,
                0,
                result.getResultLength() - 1 ) ;
            retInt = available( bytes ) ;
        }
        return retInt ;
    }
 
 
    @Override
    public char[] ownCodeToUnicode( byte[] inBuffer )
        throws CSCOwnCodeConverterException {
 
        char[] retChar = null ;
        final HJCResult result = new HJCResult() ;
        final HJCString inStr = new HJCString( inBuffer ) ;
 
        try {
            HJCConverters.cs_ibmtounicode( inStr, result, option ) ;
            final byte[] resultData = result.getStrResult().getBytes() ;
            final String retstr = new String( resultData, UNICODE ) ;
            retChar = retstr.toCharArray() ;
        }
        catch ( Exception e ) {
            e.printStackTrace() ;
            throw new CSCOwnCodeConverterException( e ) ;
        }
 
        return retChar ;
    }
 
 
    @Override
    public byte[] unicodeToOwnCode( char[] inBuffer )
        throws CSCOwnCodeConverterException {
 
        byte[] retByte = null ;
        final String data = new String( inBuffer ) ;
        final HJCResult result = new HJCResult() ;
 
        try {
            final HJCString inStr = new HJCString( data.getBytes( UNICODE ) ) ;
            HJCConverters.cs_unicodetoibm( inStr, result, option ) ;
            retByte = result.getStrResult().getBytes() ;
        }
        catch ( Exception e ) {
            e.printStackTrace() ;
            throw new CSCOwnCodeConverterException( e ) ;
        }
 
        return retByte ;
    }
 
 
    @Override
    public CSCOwnCodeReaderContext start( byte[] data, int offset, int length )
        throws CSCOwnCodeConverterException {
 
        final byte[] tempData = Arrays.copyOfRange( data, offset, length ) ;
 
        // offsetの位置から解析を開始
        return new CSCOwnCodeReaderContextImpl( tempData ) ;
    }
 
 
    @Override
    public boolean readChar( CSCOwnCodeReaderContext context )
        throws CSCOwnCodeConverterException {
 
        final CSCOwnCodeReaderContextImpl contextImpl = (CSCOwnCodeReaderContextImpl)context ;
 
        // 現在位置
        final int position = contextImpl.getNextPosition() ;
 
        // 解析対象の文字列のバイト列
        final byte[] data = contextImpl.getData() ;
 
        // 解析の上限は入力データの最後まで
        final int maxLength = data.length ;
 
        // 現在位置から1バイトずつ解析する
        for ( int i = position; i < maxLength; i++ ) {
 
            // 次の文字を解析
            if ( data[i] == SHIFT_SINGLEBYTE ) {
                // シングルバイトモードに遷移
                contextImpl.setLength( 1 ) ;
                contextImpl.setCanSeparate( true ) ;
                continue ;
            }
            else if ( data[i] == SHIFT_MULTIBYTE ) {
                // マルチバイトモードに遷移
                contextImpl.setLength( 2 ) ;
                contextImpl.setCanSeparate( false ) ;
                continue ;
            }
 
            contextImpl.setPosition( i ) ;
            contextImpl.setNextPosition( i + contextImpl.getLength() ) ;
 
            if ( contextImpl.getNextPosition() > maxLength ) {
                // データが足りない
                return false ;
            }
 
            // 解析に成功した
            return true ;
        }
 
        contextImpl.setPosition( maxLength ) ;
        contextImpl.setNextPosition( maxLength ) ;
 
        return false ;
    }
 
 
    @Override
    public void end( CSCOwnCodeReaderContext context )
        throws CSCOwnCodeConverterException {
 
        // 解放すべきリソースがないため,何もしない
    }
 
}