package com.pgf.mqspring.service.impl; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import com.amazonaws.auth.AWSCredentials; import com.amazonaws.auth.AWSStaticCredentialsProvider; import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.regions.Regions; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3ClientBuilder; import com.amazonaws.services.s3.model.GetObjectRequest; import com.pgf.mqspring.model.ReceiveMapVectorRequestModel; import com.pgf.mqspring.service.CommonService; @Service public class CommonServiceImpl implements CommonService { private static final byte SI = 14; private static final byte SO = 15; 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]; 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_DFHPF8[] = {-8, 64, 64, 64}; private static final byte RMVAID_DFHPF10[] = {122, 64, 64, 64}; private static List> telInfoList = new ArrayList>(); public static final HashMap ERR_COLOR_MAP = new HashMap(); //TODO対応方法が検討要 @Value("${aws.bucketname}") private String s3BucketName; @Value("${aws.accesskey}") private String accessKey; @Value("${aws.secretkey}") private String secretKey; Logger logger = LogManager.getLogger(); private CommonServiceImpl() { } /** * */ public String decodeEbcdic(byte data[]) { String result = null; try { result = new String(data, EBCDIC); } catch (UnsupportedEncodingException ex) { result = new String(data); } return result; } /** * */ public byte[] encodeEbcdic(String data) { byte result[] = null; try { result = data.getBytes(EBCDIC); } catch (UnsupportedEncodingException ex) { result = data.getBytes(); } return result; } /** * decodeEbcdicSisoNone */ public 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 this.decodeEbcdic(sisoByte); } /** * encodeEbcdicSisoNone */ public byte[] encodeEbcdicSisoNone(String data) { byte sisoByte[] = this.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; } /** * Stringデータ(指定長)をEBCDICにコード変換する */ public byte[] encodeStringData(String data, int length, boolean isSisoNone) { byte byteData[] = new byte[length]; byte realData[] = null; if (isSisoNone) realData = this.encodeEbcdicSisoNone(data); else realData = this.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 = this.encodeEbcdicSisoNone(data); else realData = this.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] = this.encodeEbcdicSisoNone(" ")[0]; else byteData[idx] = this.encodeEbcdic(" ")[0]; } return byteData; } /** * EBCDICバイナリ配列データをSJISにコード変換する */ public String decodeStringData(byte data[], boolean isSisoNone) { String result = ""; if (isSisoNone) result = this.decodeEbcdicSisoNone(data); else result = this.decodeEbcdic(data); return result; } /** * S3から電文定義マスタファイルをダウンロードする */ public String downloadIbmTelegramInfo() { String downloadFile = "/tmp/ibm_telegram_info.csv"; logger.info("s3BucketName:" + s3BucketName); logger.info("accessKey:" + accessKey); logger.info("secretKey:" + secretKey); AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey); //S3クライアントの生成 AmazonS3 s3Client = AmazonS3ClientBuilder .standard() .withCredentials(new AWSStaticCredentialsProvider(credentials)) .withRegion(Regions.AP_NORTHEAST_1) .build(); // AmazonS3 s3Client = AmazonS3ClientBuilder.defaultClient(); // バケット名とS3のファイルパス(キー値)を指定 GetObjectRequest request = new GetObjectRequest(s3BucketName, "document/ibm_telegram_info.csv"); // ファイル保存先 File file = new File(downloadFile); // ファイルダウンロード s3Client.getObject(request, file); return downloadFile; } /** * csvファイルから電文データ読込み */ public List> getTelInfo(String dispCode) { List> list = new ArrayList>(); List> repeatGroupList = new ArrayList>(); int repeatNumPre = 0; Path path = Paths.get("./src/main/resources/files/ibm_telegram_info.csv"); // downloadIbmTelegramInfo(); // Path path = Paths.get("/tmp/ibm_telegram_info.csv"); try { // CSVファイルの読み込み List lines = Files.readAllLines(path, Charset.forName("Shift-JIS")); for (int i = 1; i < lines.size(); i++) { String[] data = lines.get(i).split(","); if (dispCode.equals(data[0])) { HashMap resultMap = new HashMap(); resultMap.put("DISP_CODE", data[0]); resultMap.put("FIELD_NO", data[1]); resultMap.put("ITEM_NAME", data[2]); resultMap.put("ITEM_LENGTH", data[3]); resultMap.put("CHAR_DIV", data[4]); resultMap.put("REPEAT_NUM", data[5]); resultMap.put("GROUP_NUM", data[6]); resultMap.put("INS_DATE", data[7]); //繰り返す項目対応(ループ回数分) if (Integer.parseInt(data[6]) != 0) { repeatGroupList.add(resultMap); } if (Integer.parseInt(data[6]) == 0 && repeatGroupList.size() != 0) { for (int m = 0; m < repeatNumPre - 1; m++) { list.addAll(repeatGroupList); } //初期化 repeatGroupList = new ArrayList>(); } list.add(resultMap); repeatNumPre = Integer.parseInt(data[5]); } } } catch (IOException e) { logger.info("ファイル読み込みに失敗"); } return list; } /** * AdsデータをSJIS⇒EBCDICにコード変換する */ public byte[] encodeAdsData(String dispCode, String adsData) { //電文定義CSVデータ読込 if (telInfoList == null) { telInfoList = this.getTelInfo(dispCode); } byte[] result = new byte[12]; boolean isSisoNone = false; int charDiv = 0; int length = 0; String ads[] = adsData.split(",", -1); for (int i = 0; i < telInfoList.size(); i++) { HashMap telInfoMap = telInfoList.get(i); charDiv = Integer.parseInt(telInfoMap.get("CHAR_DIV").trim()); if (charDiv == 1) { isSisoNone = true; } else { isSisoNone = false; } length = Integer.parseInt(telInfoMap.get("ITEM_LENGTH").trim()); // SJIS⇒EBCDICにコード変換する byte[] attrLength = paddingByteData(new byte[2], 2); byte[] attrFormat = paddingByteData(DEFAULT_FORMAT, 1); byte[] attrColor = paddingByteData(DEFAULT_COLOR, 1); byte[] attrTurn = paddingByteData(DEFAULT_TURN, 1); byte[] dataPart = null; if (i == telInfoList.size() - 1) { // ERRMSG1のNULL対応 dataPart = new byte[length]; } else { dataPart = encodeStringData(ads[i], length, isSisoNone); } result = concatByteArrays(result, attrLength, attrFormat, attrColor, attrTurn, dataPart); } return result; } /** * AdsデータをEBCDIC⇒SJISにコード変換する */ public String decodeAdsData(String dispCode, byte adsData[]) { String result = ""; boolean isSisoNone = false; int charDiv = 0; int length = 0; int m0 = 12; int m1 = 12; List> list = new ArrayList>(); list = this.getTelInfo(dispCode); for (int i = 0; i < list.size(); i++) { HashMap resultMap = list.get(i); charDiv = Integer.parseInt(resultMap.get("CHAR_DIV").trim()); if (charDiv == 1) { isSisoNone = true; } else { isSisoNone = false; } length = Integer.parseInt(resultMap.get("ITEM_LENGTH").trim()); m1 = m1 + length + ATTRIBUTE_LENGTH; byte[] ads = Arrays.copyOfRange(adsData, m0, m1); m0 = m1; //フィールド長 // String attrLength = decodeEbcdic(paddingByteData(Arrays.copyOfRange(ads, 0, 2), 2)); //フィールド属性 // String attrFormat = decodeEbcdic(paddingByteData(Arrays.copyOfRange(ads, 2, 3), 1)); //カラー属性 byte[] attrColorByteData = Arrays.copyOfRange(ads, 3, 4); // String attrColor = decodeEbcdic(paddingByteData(attrColorByteData, 1)); //強調属性 // String attrTurn = decodeEbcdic(paddingByteData(Arrays.copyOfRange(ads, 4, 5), 1)); //フィールドデータ String fieldData = decodeStringData(Arrays.copyOfRange(ads, 5, length + ATTRIBUTE_LENGTH), isSisoNone); if ("".equals(result)) result = fieldData; else result = result + "," + fieldData; // カラー属性エラー if (attrColorByteData[0] != DEFAULT_COLOR[0]) ERR_COLOR_MAP.put(resultMap.get("ITEM_NAME").trim(), fieldData); } return result; } /** * VectorデータをSJIS⇒EBCDICにコード変換する */ public byte[] encodeVectorData(ReceiveMapVectorRequestModel model, int length) { byte[] vectorLength = this.encodeHexStringData(model.getVectorLength()); byte[] vectorDescriptor = encodeStringData(model.getVectorDescriptor(), 4, false); byte[] vectorType = encodeStringData(model.getVectorType(), 1, false); byte[] vectorVersion = encodeStringData(String.format("%7s", 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(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); } byte[] rmDataLen = this.encodeHexStringData(model.getRmDataLen()); //TODO csvの定義データから合計する予定 byte[] result = concatByteArrays(vectorLength, vectorDescriptor, vectorType, vectorVersion, rmTsa, rmMapset, rmMap, rmAid, rmCposn, rmDataLen); return result; } public byte[] encodeHexStringData(String data) { if (data == null || data.length() <= 0) return null; String tmp = null; int telLen = data.length(); byte res[] = new byte[telLen / 2]; for (int i = 0; i < telLen; i += 2) { tmp = data.substring(i, i + 2); res[i / 2] = (byte) Integer.parseInt(tmp, 16); } return res; } 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("0")).append(tmp).toString(); buff.append(tmp); } return buff.toString().toUpperCase(); } /** * 指定長バイナリ配列の補足処理 */ 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 */ private static byte[] concatByteArrays(byte[]... arrays) { if (arrays.length <= 1) { return arrays[0]; } 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(); } }