/* * 著作権表記 TODO 要否をお客様に確認 */ package com.pgf.mqspring.component.impl; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.List; import javax.xml.bind.DatatypeConverter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.pgf.mqspring.component.CharacterCodeConverterComponent; import com.pgf.mqspring.component.TelegramInfoComponent; import com.pgf.mqspring.constant.MqSpringConst; import com.pgf.mqspring.model.ReceiveMapVectorRequestModel; import com.pgf.mqspring.model.TelegramInfoModel; /** * 文字コード変換クラス *
* SJIS→EBCDICエンコード、EBCDIC→SJISデコード用ユーティリティクラス * */ @Component public class CharacterCodeConverterComponentImpl implements CharacterCodeConverterComponent { /** シフトイン区切り文字 */ private static final byte SI = 14; /** シフトアウト区切り文字 */ private static final byte SO = 15; /** エンコーディング EBCDIC */ private static final String EBCDIC = "Cp930"; /** フィールド長 */ private static final int ATTRIBUTE_LENGTH = 5; /** フィールド属性初期値 */ private static final byte DEFAULT_FORMAT[] = { -52 }; /** カラー属性初期値 */ private static final byte DEFAULT_COLOR[] = new byte[1]; /** 強調属性初期値 */ private static final byte DEFAULT_TURN[] = new byte[1]; /** AIDキー */ private static final String DFHPF1 = "DFHPF1"; private static final String DFHPF5 = "DFHPF5"; private static final String DFHPF8 = "DFHPF8"; private static final String DFHPF10 = "DFHPF10"; private static final String DFHENTER = "DFHENTER"; private static final byte RMVAID_DFHENTER[] = { 125, 64, 64, 64 }; private static final byte RMVAID_DFHPF1[] = { -15, 64, 64, 64 }; private static final byte RMVAID_DFHPF5[] = { -11, 64, 64, 64 }; private static final byte RMVAID_DFHPF8[] = { -8, 64, 64, 64 }; private static final byte RMVAID_DFHPF10[] = { 122, 64, 64, 64 }; /** ベクターバージョンフォーマット */ private static final String VECTOR_VERSION_FORMAT = "%7s"; /** 電文情報クラス */ @Autowired private TelegramInfoComponent telegramInfoComponent; /** * Vectorデータ符号化処理 *
* {@link #encodeStringData(String, int, boolean) encodeStringData}を実行し、ベクター標識を取得する。以下引数
* Adsデータ符号化バイト配列をデータ長12のバイト配列で初期化する。
* 引数の文字列をEBCDICで符号化したバイト配列を返却する。
* 引数のバイト配列をEBCDICで復号して返却する。
* {@link #encodeEbcdic(String) encodeEbcdic}を実行し、バイト配列を取得する。以下引数
* 引数のバイト配列長が2以上の場合
* 開始インデックスを12とする。
* 引数のSISO除去判定がtrueの場合
* 引数のSISO除去判定がtrueの場合
* 引数の復号対象バイト配列の要素数分以下の処理を繰り返す
* 返却用バイト配列にデータ長が引数の指定長の空のバイト配列を設定する。
* 可変長のバイト配列の要素数が0の場合
* ・Vectorデータ.vectorDescriptor
* ・4
* ・false
* {@link #encodeStringData(String, int, boolean) encodeStringData}を実行し、ベクタータイプを取得する。以下引数
* ・Vectorデータ.vectorType
* ・1
* ・false
* {@link #encodeStringData(String, int, boolean) encodeStringData}を実行し、ベクターバージョンを取得する。以下引数
* ・Vectorデータ.vectorVersion(7桁左空白パディング)
* ・7
* ・false
* {@link #encodeStringData(String, int, boolean) encodeStringData}を実行し、SEND域保存フラグを取得する。以下引数
* ・Vectorデータ.rmTransmitSendAreas
* ・4
* ・false
* {@link #encodeStringData(String, int, boolean) encodeStringData}を実行し、MAPSET名を取得する。以下引数
* ・Vectorデータ.rmMapset
* ・8
* ・false
* {@link #encodeStringData(String, int, boolean) encodeStringData}を実行し、MAP名を取得する。以下引数
* ・Vectorデータ.rmMap
* ・8
* ・false
* AIDキーに{ 125, 64, 64, 64 }を設定する
* Vectorデータ.rmAidが"DFHPF8"の場合
* AIDキーに{-8, 64, 64, 64}を設定する
* Vectorデータ.rmAidが"DFHPF5"の場合
* AIDキーに{-11, 64, 64, 64}を設定する
* Vectorデータ.rmAidが"DFHPF1"の場合
* AIDキーに{-15, 64, 64, 64}を設定する
* Vectorデータ.rmAidが"DFHPF10"の場合
* AIDキーに{122, 64, 64, 64}を設定する
* Vectorデータ.rmAidが"DFHENTER"の場合
* AIDキーに{ 125, 64, 64, 64 }を設定する
* カーソルオフセットにデータ長4の空のバイト配列を設定する
* Vectorデータ.rmCposnの文字列長が1以上の場合
* {@link #encodeStringData(String, int, boolean) encodeStringData}を実行し、カーソルオフセットを取得する。以下引数
* ・Vectorデータ.rmCposn
* ・4
* ・false
* Vectorデータ.rmCposnの文字列長が0の場合
* 何もしない
* 全項目長を0で初期化する
* 引数のadsデータ存在フラグがtrueの場合
* 電文情報マップから引数の出力画面コードをキーに電文情報リストを取得する
* 12 + (電文情報リストの各要素.itemLength + 5)の合計値を全項目長とする
* 全項目長を8桁左0パディングの16進文字列に変換し、さらにバイト配列に変換し、データ長文字列とする
* データ長文字列をバイト配列に変換し、データ長とする
* adsデータ存在フラグより電文情報リストの各要素.itemLengthの合計値+引数の指定長を8桁左0パディングの16進文字列に変換し、ベクターデータ長文字列とする
* ベクターデータ長文字列をバイト配列に変換し、ベクターデータ長とする
* 以下のデータを連結し、Vectorデータ符号化バイト配列とする
* ・ベクターデータ長
* ・ベクター標識
* ・ベクタータイプ
* ・ベクターバージョン
* ・SEND域保存フラグ
* ・MAPSET名
* ・MAP名
* ・特殊電文要求区分
* ・カーソルオフセット
* ・データ長
* Vectorデータ符号化バイト配列を返却する。
*
* @param dispCode 出力画面コード
* @param model Vectorデータ
* @param length 指定長
* @param adsExistFlag adsデータ存在フラグ
* @return modelを符号化したバイト配列
*/
@Override
public byte[] encodeVectorData(String dispCode, ReceiveMapVectorRequestModel model, int length, boolean adsExistFlag) {
byte[] vectorDescriptor = encodeStringData(model.getVectorDescriptor(), 4, false);
byte[] vectorType = encodeStringData(model.getVectorType(), 1, false);
byte[] vectorVersion = encodeStringData(String.format(VECTOR_VERSION_FORMAT, model.getVectorVersion()), 7,
false);
byte[] rmTsa = encodeStringData(model.getRmTransmitSendAreas(), 4, false);
byte[] rmMapset = encodeStringData(model.getRmMapset(), 8, false);
byte[] rmMap = encodeStringData(model.getRmMap(), 8, false);
byte[] rmAid = RMVAID_DFHENTER;
if (model.getRmAid().equals(DFHPF8))
rmAid = RMVAID_DFHPF8;
else if (model.getRmAid().equals(DFHPF5))
rmAid = RMVAID_DFHPF5;
else if (model.getRmAid().equals(DFHPF1))
rmAid = RMVAID_DFHPF1;
else if (model.getRmAid().equals(DFHPF10))
rmAid = RMVAID_DFHPF10;
else if (model.getRmAid().equals(DFHENTER))
rmAid = RMVAID_DFHENTER;
byte[] rmCposn = new byte[4];
if (!model.getRmCposn().isEmpty()) {
rmCposn = encodeStringData(model.getRmCposn(), 4, false);
}
Integer itemAllLen = 0;
if (adsExistFlag) {
itemAllLen = 12;
List
* 引数のAdsデータをパイプで分割し、Ads配列とする。
* 電文情報マップから引数の出力画面コードをキーに電文情報リストを取得する
* 電文情報リストの件数分、以下の処理を繰り返す
* 数値変換した電文情報.charDivが1の場合
* SISO除去判定をtrueに設定する。
* その他の場合
* SISO除去判定をfalseに設定する。
* 数値変換した電文情報.itemLengthを指定長に設定する。
* {@link #paddingByteData(byte[], int) paddingByteData}を実行し、取得結果をフィールド長とする。以下引数
* ・データ長2の空のバイト配列
* ・2
* {@link #paddingByteData(byte[], int) paddingByteData}を実行し、取得結果をフィールド属性とする。以下引数
* ・{ -52 }
* ・1
* {@link #paddingByteData(byte[], int) paddingByteData}を実行し、取得結果をカラー属性とする。以下引数
* ・データ長1の空のバイト配列
* ・1
* {@link #paddingByteData(byte[], int) paddingByteData}を実行し、取得結果を強調属性とする。以下引数
* ・データ長1の空のバイト配列
* ・1
* リストの最終行の場合
* フィールドデータを指定長のバイト配列で初期化する。
* それ以外の場合
* {@link #encodeStringData(String, int, boolean) encodeStringData}を実行し、取得結果をフィールドデータとする。以下引数
* ・処理中のリストと同じインデックスのAds配列の値
* ・指定長
* ・SISO除去判定
* 以下の要素を連結し、Adsデータ符号化バイト配列とする。
* ・Adsデータ符号化バイト配列
* ・フィールド長
* ・フィールド属性
* ・カラー属性
* ・強調属性
* ・フィールドデータ
* Adsデータ符号化バイト配列返却する。
*
* @param dispCode 出力画面コード
* @param adsData Adsデータ
* @return adsDataを符号化したバイト配列
*/
@Override
public byte[] encodeAdsData(String dispCode, String adsData) {
byte[] result = new byte[12];
boolean isSisoNone = false;
int charDiv = 0;
int length = 0;
String ads[] = adsData.split(MqSpringConst.PIPE_ESCAPED, -1);
List
* EBCDICで符号化する際にUnsupportedEncodingExceptionが発生した場合
* プラットフォームのデフォルト文字セットで符号化したバイト配列を返却する。
*
* @param data 符号化対象文字列
* @return dataを符号化したバイト配列
*/
private static byte[] encodeEbcdic(String data) {
byte result[] = null;
try {
result = data.getBytes(EBCDIC);
} catch (UnsupportedEncodingException ex) {
result = data.getBytes();
}
return result;
}
/**
* EBCDIC復号処理
*
* EBCDICで復号する際にUnsupportedEncodingExceptionが発生した場合
* プラットフォームのデフォルト文字セットで復号して返却する。
*
* @param data 符号化したバイト配列
* @return dataを復号した文字列
*/
@Override
public String decodeEbcdic(byte data[]) {
String result = null;
try {
result = new String(data, EBCDIC);
} catch (UnsupportedEncodingException ex) {
result = new String(data);
}
return result;
}
/**
* EBCDIC符号化処理(SISO除去)
*
* ・引数の文字列
* バイト配列長が4以上、且つ先頭バイトがシフトイン区切り文字、且つ最終バイトがシフトアウト区切り文字の場合
* バイト配列の先頭バイトと最終バイトを除去する。
* それ以外の場合
* 何もしない
* 上記で編集したバイト配列を返却する。
*
* @param data 符号化対象文字列
* @return dataを符号化したバイト配列
*/
private static byte[] encodeEbcdicSisoNone(String data) {
byte sisoByte[] = encodeEbcdic(data);
int sisoSize = sisoByte.length;
byte result[] = null;
if (sisoSize >= 4 && sisoByte[0] == SI && sisoByte[sisoSize - 1] == SO) {
int size = sisoSize - 2;
result = new byte[size];
for (int i = 0; i < size; i++)
result[i] = sisoByte[i + 1];
} else {
result = sisoByte;
}
return result;
}
/**
* EBCDIC復号処理(SISO付与)
*
* 引数のバイト配列にSISOを付与する。
* それ以外の場合
* 何もしない
* {@link #decodeEbcdic(byte[]) decodeEbcdic}を実行し、実行結果を返却する。以下引数
* ・上記で編集したバイト配列
*
* @param data 符号化したバイト配列
* @return dataを復号した文字列
*
*/
private String decodeEbcdicSisoNone(byte data[]) {
byte sisoByte[] = null;
int dataSize = data.length;
int size = dataSize;
if (dataSize >= 2) {
sisoByte = new byte[size += 2];
int idx = 0;
sisoByte[idx++] = SI;
for (int i = 0; i < dataSize; i++)
sisoByte[idx++] = data[i];
sisoByte[idx] = SO;
} else {
sisoByte = data;
}
return decodeEbcdic(sisoByte);
}
/**
* Adsデータ復号処理
*
* 終了インデックスを12とする。
* 電文情報マップから引数の出力画面コードをキーに電文情報リストを取得する
* 電文情報リストの件数分、以下の処理を繰り返す
* 数値変換した電文情報.charDivが1の場合
* SISO除去判定をtrueに設定する。
* その他の場合
* SISO除去判定をfalseに設定する。
* 数値変換した電文情報.itemLengthを指定長に設定する。
* 終了インデックスに指定長と固定値5を加算する。
* 引数のAdsデータから開始インデックス~終了インデックスまでのバイト配列を取得する。
* 開始インデックスに終了インデックスを設定する。
* {@link #decodeStringData(byte[], boolean) decodeStringData}を実行し、取得結果をフィールドデータとする。以下引数
* ・バイト配列のインデックス5~指定長+固定値5
* ・SISO除去判定
* ループ1回目の場合
* Adsデータ復号文字列にフィールドデータを設定する。
* それ以外の場合
* Adsデータ復号文字列、パイプ、フィールドデータを連結し、Adsデータ復号文字列に設定する。
* {@link #decodeStringData(byte[], boolean) decodeStringData}を実行し、取得結果をAdsデータ属性1とする。以下引数
* ・バイト配列のインデックス0~2
* ・SISO除去判定
* {@link #decodeStringData(byte[], boolean) decodeStringData}を実行し、取得結果をAdsデータ属性2とする。以下引数
* ・バイト配列のインデックス2~3
* ・SISO除去判定
* {@link #decodeStringData(byte[], boolean) decodeStringData}を実行し、取得結果をAdsデータ属性3とする。以下引数
* ・バイト配列のインデックス3~4
* ・SISO除去判定
* {@link #decodeStringData(byte[], boolean) decodeStringData}を実行し、取得結果をAdsデータ属性4とする。以下引数
* ・バイト配列のインデックス4~5
* ・SISO除去判定
* Adsデータ属性1~Adsデータ属性4をカンマ区切りで連結する
* 連結したAdsデータ属性がブランクの場合
* Adsデータ属性復号文字列に連結されたAdsデータ属性を設定する。
* それ以外の場合
* Adsデータ属性復号文字列、パイプ、連結されたAdsデータ属性を連結し、Adsデータ属性復号文字列に設定する。
* Ads復号文字列配列にAdsデータ復号文字列、Adsデータ属性復号文字列を設定し、返却する。
*
* @param dispCode 出力画面コード
* @param adsData Adsデータ
* @return adsDataを復号した文字列配列
*/
@Override
public String[] decodeAdsData(String dispCode, byte adsData[]) {
String result = MqSpringConst.BLANK;
boolean isSisoNone = false;
int charDiv = 0;
int length = 0;
int m0 = 12;
int m1 = m0;
String attr1 = MqSpringConst.BLANK;
String attr2 = MqSpringConst.BLANK;
String attr3 = MqSpringConst.BLANK;
String attr4 = MqSpringConst.BLANK;
String adsAttrs = MqSpringConst.BLANK;
String[] adsDatas = new String[2];
List
* {@link #encodeEbcdicSisoNone(String) encodeEbcdicSisoNone}を実行し、バイト配列を取得する。以下引数
* ・引数の符号化対象文字列
* 引数のSISO除去判定がfalseの場合
* {@link #encodeEbcdic(String) encodeEbcdic}を実行し、バイト配列を取得する。以下引数
* ・引数の符号化対象文字列
*
* 取得したバイト配列長が引数の指定長よりも大きい場合
* バイト配列長が引数の指定長よりも大きい間、以下の処理を繰り返す
* 直前に使用した符号化対象文字列の最終文字を除去する。
* 引数のSISO除去判定がtrueの場合
* {@link #encodeEbcdicSisoNone(String) encodeEbcdicSisoNone}を実行し、バイト配列を取得する。以下引数
* ・編集した符号化対象文字列
* 引数のSISO除去判定がfalseの場合
* {@link #encodeEbcdic(String) encodeEbcdic}を実行し、バイト配列を取得する。以下引数
* ・編集した符号化対象文字列
* 取得したバイト配列長が引数の指定長と等しい場合
* 何もしない
* 取得したバイト配列長が引数の指定長よりも小さい場合
* バイト配列長が引数の指定長よりも小さい間、以下の処理を繰り返す
* 引数のSISO除去判定がtrueの場合
* {@link #encodeEbcdicSisoNone(String) encodeEbcdicSisoNone}を実行し、返却されたバイト配列から先頭バイトを取得する。以下引数
* ・空白スペース
* 引数のSISO除去判定がfalseの場合
* {@link #encodeEbcdic(String) encodeEbcdic}を実行し、返却されたバイト配列から先頭バイトを取得する。以下引数
* ・空白スペース
* 取得した先頭バイトをバイト配列の最終バイトに追加する。
* 上記で編集したバイト配列を返却する。
*
* @param data 符号化対象文字列
* @param length 指定長
* @param isSisoNone SISO除去判定
* @return dataを符号化したバイト配列
*/
private static byte[] encodeStringData(String data, int length, boolean isSisoNone) {
byte byteData[] = new byte[length];
byte realData[] = null;
if (isSisoNone)
realData = encodeEbcdicSisoNone(data);
else
realData = encodeEbcdic(data);
int realSize = realData.length;
int diff = length - realSize;
if (diff < 0)
for (; diff < 0; diff = length - realSize) {
data = data.substring(0, data.length() - 1);
if (isSisoNone)
realData = encodeEbcdicSisoNone(data);
else
realData = encodeEbcdic(data);
realSize = realData.length;
}
if (diff == 0) {
byteData = realData;
} else {
int idx;
for (idx = 0; idx < realSize; idx++)
byteData[idx] = realData[idx];
for (; idx < length; idx++)
if (isSisoNone)
byteData[idx] = encodeEbcdicSisoNone(MqSpringConst.SPACE)[0];
else
byteData[idx] = encodeEbcdic(MqSpringConst.SPACE)[0];
}
return byteData;
}
/**
* 符号化文字データ復号処理
*
* {@link #decodeEbcdicSisoNone(byte[]) decodeEbcdicSisoNone}を実行し、復号文字列を取得する。以下引数
* ・引数の復号対象バイト配列
* それ以外の場合
* {@link #decodeEbcdic(byte[]) decodeEbcdic}を実行し、復号文字列を取得する。
* ・引数の復号対象バイト配列
* 上記で取得した復号文字列を返却する。
*
* @param data 復号対象バイト配列
* @param isSisoNone SISO除去判定
* @return dataを復号した文字列
*
*/
private String decodeStringData(byte data[], boolean isSisoNone) {
String result = MqSpringConst.BLANK;
if (isSisoNone)
result = decodeEbcdicSisoNone(data);
else
result = decodeEbcdic(data);
return result;
}
/**
* 16進文字列復号処理
*
* 要素が0より小さい場合
* 要素に256を加算して16進文字列に変換する
* それ以外の場合
* 要素を16進文字列に変換する
* 変換した16進文字列の文字数が2より小さい場合
* 変換した16進文字列の先頭に"0"を追加する
* 文字列バッファに16進文字列を追加する
* 文字列バッファを大文字に変換し、返却する。
*
* @param data 復号対象バイト配列
* @return dataを復号した文字列
*/
@Override
public String decodeHexStringData(byte data[]) {
int num = data.length;
StringBuilder buff = new StringBuilder();
String tmp = null;
for (int i = 0; i < num; i++) {
if (data[i] < 0)
tmp = Integer.toHexString(data[i] + 256);
else
tmp = Integer.toHexString(data[i]);
if (tmp.length() < 2)
tmp = (new StringBuilder(MqSpringConst.ZERO)).append(tmp).toString();
buff.append(tmp);
}
return buff.toString().toUpperCase();
}
/**
* 指定長バイト配列パディング処理
*
* 引数のパディング対象バイト配列のデータ長が引数の指定長と等しい場合
* 返却用バイト配列に引数のパディング対象バイト配列を設定する
* それ以外の場合
* 引数のパディング対象バイト配列から、引数の指定長までの要素を返却用バイト配列に設定する。
* 引数の指定長が引数のパディング対象バイト配列の要素数よりも大きい場合
* 返却値のバイト配列の未設定の要素に対して0を設定する。
* 返却用バイト配列を返却する
*
* @param data パディング対象バイト配列
* @param length 指定長
* @return パディングしたバイト配列
*/
private static byte[] paddingByteData(byte data[], int length) {
byte result[] = new byte[length];
int num = data.length;
if (num == length) {
result = data;
} else {
int idx = 0;
for (idx = 0; idx < num; idx++) {
if (idx >= length)
break;
result[idx] = data[idx];
}
for (int i = idx; i < length; i++)
result[i] = 0;
}
return result;
}
/**
* バイト配列連結
*
* 空のバイト配列を返却する。
* 可変長のバイト配列の要素を連結したバイト配列を生成する。
* 連結したバイト配列を返却する。
*
* @param arrays 可変長バイト配列
* @return arraysを連結したバイト配列
*/
private static byte[] concatByteArrays(byte[]... arrays) {
int length = 0;
for (byte[] array : arrays) {
length += array.length;
}
ByteBuffer buffer = ByteBuffer.allocate(length);
for (byte[] array : arrays) {
buffer.put(array);
}
return buffer.array();
}
}