/** * PIとの通信時、使う共通機能 * 日付変換、メール送信なの */ global class NFMUtil { public static Integer MaxLogColumnLength = 131072; public static String DummyAssetProfix = '不可用:'; public static String Authorization = 'Basic T0NNX1NGX1VTRVI6b2Ntc2ZkYzg0MDI='; public static final String CBPR_Auth_AWS = 'APPCODE60144b374d314ec2984182046e4ad5fb'; public static final String APP_KEY = '47b829e07dc9512b871a677b383fb716'; // public static final String AWS_DOMAIN = 'http://jzbase.bqbot.com:29990'; public static String AWS_DOMAIN = ''; public static String CLIENT_CERT_NAME = null; public static String NFM001_ENDPOINT = null; public static String NFM007_ENDPOINT = null; public static String NFM008_ENDPOINT = null; public static String NFM103_ENDPOINT = null; public static String NFM106_ENDPOINT = null; //update NFMUtil的NFM401的网站地址修改为使用FQDN。不是IP地址。 // public static String NFM401_ENDPOINT = 'http://161.189.3.104:8088/dojtest/dojInfo/recevie'; public static String NFM401_ENDPOINT = null; // public static String NFM401_ENDPOINT = 'http://192.168.0.173:8088/dojtest/dojInfo/recevie'; //---------- insert by rentongxiao 2020-08-19 public static String NFM402_ENDPOINT = null; //---------- insert by rentongxiao 2020-08-19 public static String NFM501_ENDPOINT = null; public static String NFM502_ENDPOINT = null; //fxk 2021/9/6 Satr public static String NFM504_ENDPOINT = null; //fxk 2021/9/6 end // public static String NFM401_ENDPOINT = 'http://161.189.87.140:8082/doj/dojInfo/recevie'; // LHJ 20180824 CBPR Start //public static String CBPR_Auth_Sap = 'Basic U0ZEQ19XU1VTRVI6cG9kMTIzNDU='; public static String CBPR_Auth_Sap = null; public static String CBPR_Auth_Spo = null; public static String QLM_NFM501_Point = 'application/x-www-form-urlencoded'; public static String QLM_Token = null; //public static String CBPR_Auth_Spo = 'http://cbpr.chinacloudsites.cn/sfdc/token'; //public static String CBPR_Auth_Spo = 'http://cbprproduct.chinacloudsites.cn/sfdc/token1'; public static String CBPR_UserName_Spo = 'int1@olympus.partner.onmschina.cn'; public static String CBPR_Password_Spo = 'Rog618571108'; public static String appKey = '070f00bf-64f1-4720-a8d8-bbe1aa976d22'; public static String appSecret = '67BB2BAFC8AA0BA0CABB37CBF50EC292'; public static String NFM009_ENDPOINT = null; public static String NFM201_ENDPOINT = null; public static String NFM202_ENDPOINT = null; public static String NFM207_ENDPOINT = null; // LHJ 20180824 CBPR End // 智慧医疗&服务新系统通信 LY 20210916 Star public static String NFM621_ENDPOINT = null; // 智慧医疗&服务新系统通信 LY 20210916 End // 智慧医疗&服务新系统通信 客户接口 public static String NFM601_ENDPOINT = null; // 智慧医疗&服务新系统通信 联系人接口 public static String NFM606_ENDPOINT = null; // 智慧医疗&服务新系统通信 学会・活动接口 public static String NFM622_ENDPOINT = null; public static String NFM701_ENDPOINT = null; public static String NFM702_ENDPOINT = null; public static String NFM703_ENDPOINT = null; public static String NFM115_ENDPOINT = null; public static String NFM112_ENDPOINT = null; public static String requestURILMS = null; public static String appSecretLMS = null; public static String appKeyLMS = null; static { if (isSandbox()) { CLIENT_CERT_NAME = 'owdc_test'; NFM001_ENDPOINT = 'https://wdp.olympus.com.cn:44301/RESTAdapter/NFM001'; // NFM007_ENDPOINT = 'https://owdc-test.olympus.co.jp/XISOAPAdapter/MessageServlet?senderParty=&senderService=OCM_SFDC_T&receiverParty=&receiverService=&interface=NFM007_Sync_BC2GPI&interfaceNamespace=http%3A%2F%2Folympus.co.jp%2Fgpi%2FNFM007'; //NFM007_ENDPOINT = 'http://wdp.olympus.com.cn:8089/RESTAdapter/NFM007'; NFM007_ENDPOINT = 'https://wdp.olympus.com.cn:44301/RESTAdapter/NFM007'; NFM008_ENDPOINT = 'https://owdc-test.olympus.co.jp/XISOAPAdapter/MessageServlet?senderParty=&senderService=OCM_SFDC_T&receiverParty=&receiverService=&interface=NFM008_Sync_BC2GPI&interfaceNamespace=http%3A%2F%2Folympus.co.jp%2Fgpi%2FNFM008'; NFM103_ENDPOINT = 'http://wdp.olympus.com.cn:8089/RESTAdapter/NFM103'; // NFM103_ENDPOINT = 'https://sfpi-mebg-test.olympuschina.com/api/nfm/103';//aws 103接口 // NFM106_ENDPOINT = 'https://owdc-test.olympus.co.jp/XISOAPAdapter/MessageServlet?senderParty=&senderService=OCM_SFDC_T&receiverParty=&receiverService=&interface=NFM106_Sync_BC2GPI&interfaceNamespace=http%3A%2F%2Folympus.co.jp%2Fgpi%2FNFM106'; NFM106_ENDPOINT = 'http://wdp.olympus.com.cn:8089/RESTAdapter/NFM106'; //NFM106_ENDPOINT = 'https://sfdc-ocm-test.olympus.co.jp/XISOAPAdapter/MessageServlet?senderParty=&senderService=OCM_SFDC_T&receiverParty=&receiverService=&interface=NFM106_Sync_BC2GPI&interfaceNamespace=http%3A%2F%2Folympus.co.jp%2Fgpi%2FNFM106'; // LHJ 20180824 CBPR Start //NFM009_ENDPOINT = 'http://58.246.66.49:8088/RESTAdapter/SFDC002/'; //NFM009_ENDPOINT = 'https://wstest.olympus.com.cn/RESTAdapter/SFDC002/'; //NFM009_ENDPOINT = 'https://wdp.olympus.com.cn/RESTAdapter/SFDC002/'; NFM009_ENDPOINT = 'https://wdp.olympus.com.cn:44301/RESTAdapter/SFDC002/'; //NFM201_ENDPOINT = 'http://cbpr.chinacloudsites.cn/sfdc/Hospital'; //NFM202_ENDPOINT = 'http://cbpr.chinacloudsites.cn/sfdc/Inquiry'; //NFM207_ENDPOINT = 'http://cbpr.chinacloudsites.cn/sfdc/QIS'; //NFM201_ENDPOINT = 'http://cbprproduct.chinacloudsites.cn/sfdc/Hospital'; //NFM202_ENDPOINT = 'http://cbprproduct.chinacloudsites.cn/sfdc/Inquiry'; //NFM207_ENDPOINT = 'http://cbprproduct.chinacloudsites.cn/sfdc/QIS'; NFM201_ENDPOINT = 'http://cbpr.olympuschina.com/sfdc/Hospital'; NFM202_ENDPOINT = 'http://cbpr.olympuschina.com/sfdc/Inquiry'; NFM207_ENDPOINT = 'http://cbpr.olympuschina.com/sfdc/QIS'; NFM401_ENDPOINT = 'http://ec2-161-189-3-104.cn-northwest-1.compute.amazonaws.com.cn:8088/dojtest/dojInfo/recevie'; NFM402_ENDPOINT = 'http://ec2-161-189-3-104.cn-northwest-1.compute.amazonaws.com.cn:8088/dojtest/dojInfo/getDojInfoByRefNo'; NFM501_ENDPOINT = 'https://sfpi-mebg-test.olympuschina.com/api/nfm/501'; NFM502_ENDPOINT = 'http://cusdata.qianlima.com/v1/info/detailHtml?url='; NFM504_ENDPOINT = 'http://cusdata.qianlima.com/v1/customer/albs/feedback'; CBPR_Auth_Sap = 'Basic U0ZEQ19XU1VTRVI6cG9xMTIzNDU='; // LHJ 20180824 CBPR End //CBPR_Auth_Spo = 'http://cbpr.chinacloudsites.cn/sfdc/token'; CBPR_Auth_Spo = 'http://cbpr.olympuschina.com/sfdc/token'; QLM_Token = 'http://cusdata.qianlima.com/v1/token'; // 智慧医疗&服务新系统通信 客户接口 NFM601_ENDPOINT = 'https://wdp.olympus.com.cn:44301/RESTAdapter/NFM601'; // 智慧医疗&服务新系统通信 联系人接口 NFM606_ENDPOINT = 'https://wdp.olympus.com.cn:44301/RESTAdapter/NFM606'; // 智慧医疗&服务新系统通信 用户接口 NFM621_ENDPOINT = 'https://wdp.olympus.com.cn:44301/RESTAdapter/NFM621'; NFM622_ENDPOINT = 'http://test-platform.olympuschina.com/prod-api/api/sso/sfdc_activitydata'; NFM701_ENDPOINT = 'https://wdp.olympus.com.cn:44301/RESTAdapter/NFM701'; NFM702_ENDPOINT = 'https://wdp.olympus.com.cn:44301/RESTAdapter/NFM702'; NFM703_ENDPOINT = 'https://wdp.olympus.com.cn:44301/RESTAdapter/NFM703'; NFM112_ENDPOINT = 'http://wdp.olympus.com.cn:8089/RESTAdapter/NFM112'; NFM115_ENDPOINT = 'https://wdp.olympus.com.cn:44301/RESTAdapter/NFM115'; // 新服务系统 测试环境 AWS_DOMAIN = 'https://olympus.bqbot.com'; // 新服务系统 本地环境(临时) // AWS_DOMAIN = 'http://114.249.236.98:29990'; // AWS_DOMAIN = 'http://jzbase.bqbot.com:29990'; // AWS_DOMAIN = 'http://114.249.238.243:29990'; requestURILMS = '/v1/uc/user/syncOlympusUnit'; appSecretLMS = 'CAE1D68BE3EB4F7AB5FE97EBDD11B83E'; appKeyLMS = '39111FC57691491190C1D137A1EE3962'; } else { CLIENT_CERT_NAME = 'sfdc_ocm'; NFM001_ENDPOINT = 'https://wdp.olympus.com.cn:44302/RESTAdapter/NFM001'; //NFM007_ENDPOINT = 'https://owdc.olympus.co.jp/XISOAPAdapter/MessageServlet?senderParty=&senderService=OCM_SFDC_P&receiverParty=&receiverService=&interface=NFM007_Sync_BC2GPI&interfaceNamespace=http%3A%2F%2Folympus.co.jp%2Fgpi%2FNFM007'; NFM007_ENDPOINT = 'https://wdp.olympus.com.cn:44302/RESTAdapter/NFM007'; NFM008_ENDPOINT = 'https://owdc.olympus.co.jp/XISOAPAdapter/MessageServlet?senderParty=&senderService=OCM_SFDC_P&receiverParty=&receiverService=&interface=NFM008_Sync_BC2GPI&interfaceNamespace=http%3A%2F%2Folympus.co.jp%2Fgpi%2FNFM008'; //NFM103_ENDPOINT = 'https://owdc.olympus.co.jp/XISOAPAdapter/MessageServlet?senderParty=&senderService=OCM_SFDC_P&receiverParty=&receiverService=&interface=NFM103_Sync_BC2GPI&interfaceNamespace=http%3A%2F%2Folympus.co.jp%2Fgpi%2FNFM103'; NFM103_ENDPOINT = 'https://wdp.olympus.com.cn:44302/RESTAdapter/NFM103'; //NFM106_ENDPOINT = 'https://owdc.olympus.co.jp/XISOAPAdapter/MessageServlet?senderParty=&senderService=OCM_SFDC_P&receiverParty=&receiverService=&interface=NFM106_Sync_BC2GPI&interfaceNamespace=http%3A%2F%2Folympus.co.jp%2Fgpi%2FNFM106'; NFM106_ENDPOINT = 'https://wdp.olympus.com.cn:44302/RESTAdapter/NFM106'; // LHJ 20180824 CBPR Start NFM009_ENDPOINT = 'https://wdp.olympus.com.cn:44302/RESTAdapter/SFDC002/'; //NFM201_ENDPOINT = 'http://cbprproduct.chinacloudsites.cn/sfdc/Hospital'; //NFM202_ENDPOINT = 'http://cbprproduct.chinacloudsites.cn/sfdc/Inquiry'; //NFM207_ENDPOINT = 'http://cbprproduct.chinacloudsites.cn/sfdc/QIS'; NFM201_ENDPOINT = 'http://cbprproduct.olympuschina.com/sfdc/Hospital'; NFM202_ENDPOINT = 'http://cbprproduct.olympuschina.com/sfdc/Inquiry'; NFM207_ENDPOINT = 'http://cbprproduct.olympuschina.com/sfdc/QIS'; NFM401_ENDPOINT = 'http://ec2-161-189-3-104.cn-northwest-1.compute.amazonaws.com.cn:8082/doj/dojInfo/recevie'; NFM402_ENDPOINT = 'http://ec2-161-189-3-104.cn-northwest-1.compute.amazonaws.com.cn:8082/doj/dojInfo/getDojInfoByRefNo'; NFM501_ENDPOINT ='https://sfpi-mebg-test.olympuschina.com/api/nfm/501'; NFM502_ENDPOINT = 'http://cusdata.qianlima.com/v1/info/detailHtml?url='; NFM504_ENDPOINT = 'http://cusdata.qianlima.com/v1/customer/albs/feedback'; CBPR_Auth_Sap = 'Basic U0ZEQ19XU1VTRVI6cG9wMTIzNDU='; //CBPR_Auth_Spo = 'http://cbprproduct.chinacloudsites.cn/sfdc/token'; CBPR_Auth_Spo = 'http://cbprproduct.olympuschina.com/sfdc/token'; // LHJ 20180824 CBPR End QLM_Token = 'http://cusdata.qianlima.com/v1/token'; // 智慧医疗&服务新系统通信 客户接口 NFM601_ENDPOINT = 'https://wdp.olympus.com.cn:44302/RESTAdapter/NFM601'; // 智慧医疗&服务新系统通信 联系人接口 NFM606_ENDPOINT = 'https://wdp.olympus.com.cn:44302/RESTAdapter/NFM606'; // 智慧医疗&服务新系统通信 用户接口 NFM621_ENDPOINT = 'https://wdp.olympus.com.cn:44302/RESTAdapter/NFM621'; NFM622_ENDPOINT = 'https://api-platform.olympuschina.com/prod-api/api/sso/sfdc_activitydata'; NFM701_ENDPOINT = 'https://wdp.olympus.com.cn:44302/RESTAdapter/NFM701'; NFM702_ENDPOINT = 'https://wdp.olympus.com.cn:44302/RESTAdapter/NFM702'; NFM703_ENDPOINT = 'https://wdp.olympus.com.cn:44302/RESTAdapter/NFM703'; //样本管理 NFM115_ENDPOINT = 'https://wdp.olympus.com.cn:44302/RESTAdapter/NFM115'; // 新服务系统 AWS_DOMAIN = 'https://svc-elb.olympuschina.com'; requestURILMS = '/v1/uc/user/syncOlympusUnit'; appSecretLMS = '569117ED8E574BF3A6E4247C1AF8118A'; appKeyLMS = 'B70889DEF6E647EC8A542E3C46925F93'; } } // 受信用 global class Monitoring { webservice String Tag; webservice String Sender; webservice String Receiver; webservice String MessageType; webservice String MessageGroupNumber; webservice String NumberOfRecord; webservice String TransmissionDateTime; webservice String Text; } // NFM622使用 global class MonitoringToOnline { webservice String Tag; webservice String Sender; webservice String Receiver; webservice String MessageType; webservice String MessageGroupNumber; webservice String NumberOfRecord; webservice String TransmissionDateTime; webservice String Text; webservice String username; webservice String password; } // NFM601、NFM606、NFM621使用 global class MonitoringToComPlat { webservice String Tag; webservice String Sender; webservice String Receiver; webservice String MessageType; webservice String MessageGroupNumber; webservice String NumberOfRecord; webservice String TransmissionDateTime; webservice String Text; webservice String API_RANDOM_STR; webservice String API_TIME; webservice String API_TOKEN; webservice String sign; webservice String timestamp; webservice String appKey; } // add to aws response sushanhu 20220224 start global class NFMResponse{ public Boolean SFStatus; public String SFMessage; public StaticResponse staticResponse; } global class StaticResponse{ public string status; public String Message; public StaticResponse(){ status='Success'; Message=''; } } public static NFMResponse getNFMResponse(){ NFMResponse result=new NFMResponse(); result.staticResponse =new StaticResponse(); return result; } // add to aws response sushanhu 20220224 end /** * @return yyyyMMdd の日付文字列 */ public static String formatDate2Str(Date dt) { String rtn = null; if (dt == null) { return rtn; } rtn = String.valueOf(dt); rtn = rtn.replaceAll('-', ''); if (rtn >= '40001231') { rtn = '99991231'; } else if (rtn < '19000101') { rtn = '19000101'; } return rtn; } /** * @return yyyyMMdd の日付文字列 */ public static String formatDate2StrDateTime(Date dt) { String rtn = null; if (dt == null) { return rtn; } rtn = String.valueOf(dt); rtn = rtn.replaceAll('-', ''); if (rtn >= '40001231') { rtn = '99991231'; } else if (rtn < '19000101') { rtn = '19000101'; } return rtn + '000000'; } /** * [formatDate2StrDateNewTime description] * @param dt [日期] * @return [description] * 拼接日期/时间,参数日期(年月日)+ 当前时间(时分秒) */ public static String formatDate2StrDateNewTime(Date dt) { String rtn = null; if (dt == null) { return rtn; } rtn = String.valueOf(dt); rtn = rtn.replaceAll('-', ''); if (rtn >= '40001231') { rtn = '99991231'; } else if (rtn < '19000101') { rtn = '19000101'; } String phourMinuteSecond = String.valueOf(DateTime.now()); if(phourMinuteSecond.length() >= 19){ phourMinuteSecond = phourMinuteSecond.subString(10,19).replaceall(':', ''); } return rtn + phourMinuteSecond; } /** * @return yyyyMMddHHmmss の日付文字列 */ public static String formatDateTime2Str(Datetime dt) { String rtn = null; if (dt == null) { return rtn; } rtn = String.valueOf(dt); rtn = rtn.replaceAll('-', '').replaceall(' ', '').replaceall(':', ''); if (rtn >= '40001231000000') { rtn = '99991231000000'; } else if (rtn < '19000101000000') { rtn = '19000101000000'; } return rtn; } // LHJ Start /** * @return yyyyMMdd の日付文字列 */ public static String formatDate2StrSpo(Date dt) { String rtn = null; if (dt == null) { rtn = '2999-12-31'; } else { rtn = String.valueOf(dt); } return rtn; } // LHJ Start /** * @return yyyy/MM/dd の日付文字列 */ public static String formatDateTime2StrSprit(DateTime dt) { String rtn = null; if (dt == null) { rtn = ''; } else { String pDate = formatDateTime2Str(dt); rtn = Integer.valueOf(pDate.substring(0, 4)) + '/' + Integer.valueOf(pDate.substring(4, 6)) + '/' + Integer.valueOf(pDate.substring(6, 8)); } return rtn; } /** * add wangweipeng 2022/02/11 * [formatDateTime2StrDateTime description] * @param dt [日期/时间] * @return [字符串] * * 此方法用于新建数据时,把 日期/时间 转换成字符串类型,并把 秒 去掉 */ public static String formatDateTime2StrDateTime(DateTime dt){ String rtn = null; if (dt == null) { return rtn; } rtn = String.valueOf(dt); rtn = rtn.replaceAll('-', '/'); if (rtn >= '40001231000000') { rtn = '99991231000000'; } else if (rtn < '19000101000000') { rtn = '19000101000000'; } //去掉 秒 rtn = rtn.substring(0,rtn.length()-3); return rtn; } // LHJ End public static Date parseStr2DateTimeDate(String pDateTime) { if (pDateTime == null || pDateTime.length() != 14) { return null; } return parseStr2Date(pDateTime.substring(0, 8)); } /** * add wangweipeng 2022/02/15 * [parseStr2DateTime description] * @param pDate [日期(不包括时间)] * @return [description] * * 拼接日期/时间,其中日期为真实日期,时间为当前时间 */ public static Datetime parseStr3DateTime(String pDate) { if (String.isBlank(pDate)) { return null; } String phourMinuteSecond = String.valueOf(DateTime.now()); if(phourMinuteSecond.length() >= 19){ phourMinuteSecond = phourMinuteSecond.subString(10,19).replaceall(':', ''); } return parseStr2DateTime(pDate.substring(0, 8), phourMinuteSecond); } public static Datetime parseStr2DateTime(String pDateTime) { if (pDateTime == null || pDateTime.length() != 14) { return null; } return parseStr2DateTime(pDateTime.substring(0, 8), pDateTime.substring(8, 14)); } public static Datetime parseStr2DateTime(String pDate, String pTime) { Datetime rtn = null; try { if (pDate == null || pDate.length() != 8) { return rtn; } else if (pDate > '40001231') { pDate = '40001231'; } else if (pDate < '19000101') { pDate = '19000101'; } if (pDate == '19000101') { return null; } rtn = Datetime.newinstance( Integer.valueOf(pDate.substring(0, 4)), Integer.valueOf(pDate.substring(4, 6)), Integer.valueOf(pDate.substring(6, 8)), Integer.valueOf(pTime.substring(0, 2)), Integer.valueOf(pTime.substring(2, 4)), Integer.valueOf(pTime.substring(4, 6)) ); } catch (Exception ex) { System.debug(Logginglevel.ERROR, 'NFMUtil#parseStr2DateTime(' + pDate + ', ' + pTime + ')' + ex.getMessage()); } return rtn; } /** * @param pStr yyyyMMdd の日付文字列 */ public static Date parseStr2Date(String pStr) { return parseStr2Date(pStr, true); } /** * @param pStr yyyyMMdd の日付文字列 * @param changeToNull 19000101以下の場合 null に変換するかどうか */ public static Date parseStr2Date(String pStr, boolean changeToNull) { Date rtn = null; try { if (pStr == null || pStr.length() != 8 || pStr == '00000000') { return rtn; } else if (pStr > '40001231') { pStr = '40001231'; } else if (pStr < '19000101') { pStr = '19000101'; } if (pStr == '19000101' && changeToNull) { return null; } rtn = Date.newinstance( Integer.valueOf(pStr.substring(0, 4)), Integer.valueOf(pStr.substring(4, 6)), Integer.valueOf(pStr.substring(6, 8)) ); } catch (Exception ex) { System.debug(Logginglevel.ERROR, 'NFMUtil#parseStr2Date(' + pStr + ')' + ex.getMessage()); } return rtn; } /** * @param pStr yyyyMMdd の日付文字列 * @param changeToNull 19000101以下の場合 null に変換するかどうか */ public static Date parseDateTimeStr2Date(String pStr) { if (pStr == null || pStr.length() < 8) { return null; } else { pStr = pStr.replace('-', '').replace('/', ''); String dateStr = pStr.substring(0, 8); return parseStr2Date(dateStr, true); } } /** * もしkeyがmapに存在しない場合、keyをそのまま戻る */ public static String getMapValue(Map < String, String > transferMap, String col, String key, BatchIF_Log__c iflog) { String rtn = key; if (transferMap == null) { return rtn; } if (key == null) { return null; } if (col == null) { col = ''; } rtn = transferMap.get(col + key); if (rtn == null) { iflog.ErrorLog__c += 'Warning! Please check [' + col + '] can not transfer key [' + key + ']\n'; rtn = key; } return rtn; } /** * LMS使用(NFM601使用) * @return [description] */ public static String getSignMD5(){ String signText = appSecretLMS + '|' + requestURILMS + '|' + appSecretLMS; String signMD5 = EncodingUtil.convertToHex(Crypto.generateDigest('MD5', Blob.valueOf(signText))).toUpperCase(); String result = signMD5; return signMD5; } public static String randomUUID(Integer length) { String result = ''; for (Integer i = 0; i < length; i++) { Integer ran = (Math.random() * 16).intValue(); if (ran == 10) { result += 'A'; } else if (ran == 11) { result += 'B'; } else if (ran == 12) { result += 'C'; } else if (ran == 13) { result += 'D'; } else if (ran == 14) { result += 'E'; } else if (ran == 15) { result += 'F'; } else { result += ran.format(); } } return result; } public static String getToken(String randomstr, long timestamp) { if (randomstr == null) { randomstr = randomUUID(16); } System.debug('-------------------randomstr:' + randomstr); System.debug('-------------------timestamp:' + timestamp); String str = 'appkey=' + APP_KEY + '×tamp=' + timestamp + '&random_str=' + randomstr + '&key=' + APP_KEY; String result = EncodingUtil.convertToHex(Crypto.generateDigest('MD5', Blob.valueOf(str))); System.debug('-------------------result:' + result); return result; } /** * 先頭の指定文字をtrim * * @param trimChar 指定したtrim文字 */ public static String trimLeft(String orgStr, String trimChar) { String rtn = orgStr; if (orgStr == null) { return rtn; } if (trimChar == null) { return null; } rtn = orgStr.replaceAll('^' + trimChar + '+(?!$)', ''); return rtn; } public static Boolean isSandbox() { //return URL.getSalesforceBaseUrl().getHost().left(2).equalsignorecase('cs') || URL.getSalesforceBaseUrl().toExternalForm().CONTAINS('.cs'); return [SELECT IsSandbox FROM Organization LIMIT 1].IsSandbox; } public static BatchIF_Log__c makeRowData(NFMUtil.Monitoring Monitoring, String NFMType, Object NFMData) { BatchIF_Log__c rowData = new BatchIF_Log__c(); rowData.Type__c = NFMType; rowData.MessageGroupNumber__c = Monitoring.MessageGroupNumber; rowData.TransmissionDateTime__c = Monitoring.TransmissionDateTime; rowData.RowDataFlg__c = true; rowData.Log__c = ''; rowData.ErrorLog__c = ''; String rowDataStr = JSON.serialize(NFMData); if (rowDataStr.length() > 0) { Integer splitIdx = 1; while (rowDataStr.length() > 0) { if (splitIdx == 1) { rowData.put('Log__c', rowDataStr.substring(0, (rowDataStr.length() > MaxLogColumnLength ? MaxLogColumnLength : rowDataStr.length()))); } else if (splitIdx == 13) { rowData.ErrorLog__c = rowDataStr; break; } else { rowData.put('Log' + splitIdx + '__c', rowDataStr.substring(0, (rowDataStr.length() > MaxLogColumnLength ? MaxLogColumnLength : rowDataStr.length()))); } splitIdx++; rowDataStr = rowDataStr.substring((rowDataStr.length() > MaxLogColumnLength ? MaxLogColumnLength : rowDataStr.length())); } } return rowData; } // public static BatchIF_Log__c makeRowDataToOnline(NFMUtil.MonitoringToOnline Monitoring, String NFMType, Object NFMData) { // BatchIF_Log__c rowData = new BatchIF_Log__c(); // rowData.Type__c = NFMType; // rowData.MessageGroupNumber__c = Monitoring.MessageGroupNumber; // rowData.TransmissionDateTime__c = Monitoring.TransmissionDateTime; // rowData.RowDataFlg__c = true; // rowData.Log__c = ''; // rowData.ErrorLog__c = ''; // String rowDataStr = JSON.serialize(NFMData); // if (rowDataStr.length() > 0) { // Integer splitIdx = 1; // while (rowDataStr.length() > 0) { // if (splitIdx == 1) { // rowData.put('Log__c', rowDataStr.substring(0, (rowDataStr.length() > MaxLogColumnLength ? MaxLogColumnLength : rowDataStr.length()))); // } else if (splitIdx == 13) { // rowData.ErrorLog__c = rowDataStr; // break; // } else { // rowData.put('Log' + splitIdx + '__c', rowDataStr.substring(0, (rowDataStr.length() > MaxLogColumnLength ? MaxLogColumnLength : rowDataStr.length()))); // } // splitIdx++; // rowDataStr = rowDataStr.substring((rowDataStr.length() > MaxLogColumnLength ? MaxLogColumnLength : rowDataStr.length())); // } // } // return rowData; // } public static BatchIF_Log__c makeRowData(BatchIF_Log__c iflog, String NFMType, Object NFMData) { // TransmissionDateTimeの設定 Datetime nowDT = Datetime.now(); String nowStr = nowDT.format('yyyyMMddHHmm'); BatchIF_Log__c rowData = new BatchIF_Log__c(); rowData.Type__c = NFMType; rowData.MessageGroupNumber__c = iflog.Name; rowData.TransmissionDateTime__c = nowStr; rowData.RowDataFlg__c = true; rowData.Log__c = ''; rowData.ErrorLog__c = ''; String rowDataStr = JSON.serialize(NFMData); if (rowDataStr.length() > 0) { Integer splitIdx = 1; while (rowDataStr.length() > 0) { if (splitIdx == 1) { rowData.put('Log__c', rowDataStr.substring(0, (rowDataStr.length() > MaxLogColumnLength ? MaxLogColumnLength : rowDataStr.length()))); } else if (splitIdx == 13) { rowData.ErrorLog__c = rowDataStr; break; } else { rowData.put('Log' + splitIdx + '__c', rowDataStr.substring(0, (rowDataStr.length() > MaxLogColumnLength ? MaxLogColumnLength : rowDataStr.length()))); } splitIdx++; rowDataStr = rowDataStr.substring((rowDataStr.length() > MaxLogColumnLength ? MaxLogColumnLength : rowDataStr.length())); } } return rowData; } public static BatchIF_Log__c saveRowData(NFMUtil.Monitoring Monitoring, String NFMType, Object NFMData) { BatchIF_Log__c rowData = makeRowData(Monitoring, NFMType, NFMData); insert rowData; return rowData; } public static String getRowDataStr(BatchIF_Log__c rowData) { String rowDataStr = rowData.Log__c; Integer splitIdx = 2; while (rowData.get('Log' + splitIdx + '__c') != null && String.isBlank('' + rowData.get('Log' + splitIdx + '__c')) == false) { rowDataStr += rowData.get('Log' + splitIdx + '__c'); splitIdx++; if (splitIdx == 13) break; } if (String.isBlank(rowData.ErrorLog__c) == false) { rowDataStr += rowData.ErrorLog__c; } return rowDataStr; } // 20180823 LHJ C-BPR Spo接口认证 Start public class Token_Response { public String expires_in; public String access_token; } public class AWS_Response { public Integer code; public String msg; public String data; } public static String sendToSpoRet(String rowDataStr, String endpoint) { Http http = new Http(); HttpRequest req = new HttpRequest(); HTTPResponse res; String resb; // 获取token req.setEndpoint(CBPR_Auth_Spo); req.setMethod('POST'); req.setHeader('grant_type', 'password'); req.setHeader('username', CBPR_UserName_Spo); req.setHeader('password', CBPR_Password_Spo); req.setBody(''); res = http.send(req); resb = res.getBody(); Token_Response tr = (Token_Response) JSON.deserialize(resb, Token_Response.class); // 发送接口 Http http2 = new Http(); HttpRequest req2 = new HttpRequest(); HTTPResponse res2; String resb2; req2.setTimeout(110000); req2.setEndpoint(endpoint); req2.setMethod('POST'); req2.setHeader('access_token', tr.access_token); req2.setHeader('Content-Type', 'application/json'); req2.setBody(rowDataStr); res2 = http2.send(req2); resb2 = res2.getStatus(); return resb2; } /* send to AWS */ public static String sendToAWS(String rowDataStr, String endpoint) { Http http = new Http(); HttpRequest req = new HttpRequest(); HTTPResponse res; String resb; system.debug('sendToAWS--->rowDataStr----->'+rowDataStr); // List GeDataList = (List) JSON.deserialize(rowDataStr, List.class); req.setTimeout(120000); req.setEndpoint(AWS_DOMAIN + endpoint); req.setMethod('POST'); //req.setHeader('Authorization', CBPR_Auth_AWS); String randomstr = randomUUID(16); long timestamp = DateTime.now().getTime(); req.setHeader('Content-Type', 'application/json'); req.setHeader('API-RANDOM-STR', randomstr); req.setHeader('API-TIME', timestamp + ''); req.setHeader('API-TOKEN', getToken(randomstr, timestamp)); req.setBody(rowDataStr); system.debug('req--->'+req); //return ''; res = http.send(req); // resb = res.getBody(); resb = res.getStatus(); //AWS_Response tr = (AWS_Response) JSON.deserialize(resb, AWS_Response.class); return resb; } public static void sendToSpo(String rowDataStr, String endpoint) { Http http = new Http(); HttpRequest req = new HttpRequest(); HTTPResponse res; String resb; // 获取token req.setEndpoint(CBPR_Auth_Spo); req.setMethod('POST'); req.setHeader('grant_type', 'password'); req.setHeader('username', CBPR_UserName_Spo); req.setHeader('password', CBPR_Password_Spo); req.setBody(''); res = http.send(req); resb = res.getBody(); Token_Response tr = (Token_Response) JSON.deserialize(resb, Token_Response.class); // 发送接口 Http http2 = new Http(); HttpRequest req2 = new HttpRequest(); HTTPResponse res2; String resb2; req2.setTimeout(120000); req2.setEndpoint(endpoint); req2.setMethod('POST'); req2.setHeader('access_token', tr.access_token); req2.setHeader('Content-Type', 'application/json'); req2.setBody(rowDataStr); res2 = http2.send(req2); resb2 = res2.getStatus(); } // 20180823 LHJ C-BPR Sap接口认证 Start public static void sendToSap(String rowDataStr, String endpoint) { Http http = new Http(); HttpRequest req = new HttpRequest(); HTTPResponse res; String resb; req.setTimeout(120000); req.setEndpoint(endpoint); req.setMethod('POST'); req.setHeader('Authorization', CBPR_Auth_Sap); req.setBody(rowDataStr); res = http.send(req); resb = res.getBody(); } // 20180823 LHJ C-BPR Sap接口认证 Start public static String sendToETQ(String rowDataStr, String endpoint) { Http http = new Http(); HttpRequest req = new HttpRequest(); HTTPResponse res; String resb; req.setTimeout(120000); req.setEndpoint(endpoint); req.setMethod('POST'); req.setHeader('Content-Type', 'application/json'); req.setBody(rowDataStr); res = http.send(req); resb = res.getStatus(); system.debug('resb:' + resb); return resb; } public static String sendToSapRet(String rowDataStr, String endpoint) { Http http = new Http(); HttpRequest req = new HttpRequest(); HTTPResponse res; String resb; req.setTimeout(120000); req.setEndpoint(endpoint); req.setMethod('POST'); req.setHeader('Authorization', CBPR_Auth_Sap); req.setBody(rowDataStr); res = http.send(req); resb = res.getStatus(); system.debug('resb:' + resb); return resb; } // WLIG-BXQBH6 额外接收reponse 的body start public static response sendToSapStatusAndBody(String rowDataStr, String endpoint) { Http http = new Http(); HttpRequest req = new HttpRequest(); HTTPResponse res; String resb; req.setTimeout(120000); req.setEndpoint(endpoint); req.setMethod('POST'); req.setHeader('Authorization', CBPR_Auth_Sap); req.setBody(rowDataStr); res = http.send(req); string ress = res.getStatus(); resb = res.getBody(); system.debug('ress:' + ress); return new response(ress, resb); } // send to aws to sap sushuanhu 20220222 public static response sendToPiAWS(String rowDataStr, String endpoint,String awsToken) { Http http = new Http(); HttpRequest req = new HttpRequest(); HTTPResponse res; String resb; req.setTimeout(120000); req.setEndpoint(endpoint); req.setMethod('POST'); req.setHeader('Content-Type', 'application/json'); req.setHeader('pi-token', awsToken); req.setBody(rowDataStr); res = http.send(req); string ress =String.valueof(res.getStatusCode()); resb = res.getBody(); system.debug('ress:' + ress); return new response(ress, resb); } // 获取aws token sushanhu 20220222 public static response getAwsToken(){ String responseBody = AWSServiceTool.getAWSToken(); return new response('success', responseBody); } public class response { public string status; public string responseBody; public response(string status, string responseBody) { this.status = status; this.responseBody = responseBody; } } // WLIG-BXQBH6 end //---------- insert by rentongxaio 2020-08-19 Start public static String getETQData(String rowDataStr, String endpoint) { HttpRequest req = new HttpRequest(); //endPoint 就是请求路径 req.setEndpoint(endpoint); req.setMethod('POST'); req.setHeader('Content-Type', 'application/json'); //请求参数 req.setBody(rowDataStr); Http http = new Http(); HTTPResponse res = http.send(req); String responseBody = res.getBody(); return responseBody; } //---------- insert by rentongxiao 2020-08-19 End //返回格式: hh:ss:mm //insert by rentongxiao 2020-10-12 start public static Time parseStr2Time(String timeStr) { if (timeStr.length() != 6) { return null; } return Time.newInstance( Integer.valueOf(timeStr.substring(0, 2)), Integer.valueOf(timeStr.substring(2, 4)), Integer.valueOf(timeStr.substring(4, 6)), 0); } //insert by rentongxiao 2020-10-12 end //千里马 //接口1,获取token public class Body { public String msg; public String access_token; public String code; } public class Body502 { public String msg; public String data1; public String code; } public static response receiveToken() { //1、 获取token: Http http = new Http(); HttpRequest req = new HttpRequest(); String content = 'appKey=' + EncodingUtil.urlEncode(appKey, 'UTF-8') + '&appSecret=' + EncodingUtil.urlEncode(appSecret, 'UTF-8'); //请求路径 req.setEndpoint(QLM_Token); req.setHeader('Content-Type', QLM_NFM501_Point); req.setMethod('POST'); //请求参数 req.setBody(content); //两个code分别为: //1.http:code和状态 //2. HTTPResponse response = http.send(req); string ress = response.getStatus(); System.debug('response:' + response); System.debug('Status:' + ress); //`1.http:code和状态 //如果状态不通过,则为他其状态及token = null返回 if (string.isBlank(ress) || !ress.replace('o', 'O').replace('k', 'K').equals('OK')) { return new response(ress, null); } String responseBodyToken = response.getBody(); System.debug('Body:' + responseBodyToken); Body BodyToken = (Body) JSON.deserializeStrict(responseBodyToken, Body.class); System.debug('======1=====' + BodyToken.code); //如果解析时code不为0,则将其错误信息及token = null返回 if (String.isBlank(BodyToken.code) || !BodyToken.code.equals('0')) { System.debug('======12=====' + BodyToken.code); return new response(BodyToken.msg, null); } //正常执行 String token = BodyToken.access_token; return new response(ress, token); } //接口2,获取接口中的数据 和 接口3,获取页面 public static response getQLMData(String endpoint, String token) { //2、获取招标信息:记得使用1中获取的token Http http = new Http(); HttpRequest req = new HttpRequest(); req.setHeader('Content-Type', QLM_NFM501_Point); req.setHeader('open-authorization', 'Bearer' + token); req.setTimeout(120000); req.setEndpoint(endpoint); req.setMethod('GET'); HTTPResponse response = http.send(req); String ress = response.getStatus(); System.debug('response:' + response); //http:状态和code //如果状态不通过 , 则将状态及空的的数据 , 返回 if (string.isBlank(ress) || !ress.replace('o', 'O').replace('k', 'K').equals('OK')) { return new response(ress, null); } System.debug('=====2======' + response.getBody()); //正常执行 return new response(ress, response.getBody()); } // NEW QLM AWS 501 接口 sushanhu 20220223 public static response getAWSQLMData(String endpoint, String token) { //2、获取招标信息:记得使用1中获取的token Http http = new Http(); HttpRequest req = new HttpRequest(); req.setHeader('Content-Type', 'application/json'); req.setHeader('pi-token', token); req.setTimeout(120000); req.setEndpoint(endpoint); req.setMethod('GET'); HTTPResponse response = http.send(req); String statusCode = String.valueof(response.getStatusCode()); System.debug('response:' + response); //http:状态和code //如果状态不通过 , 则将状态及空的的数据 , 返回 // if (String.isNotBlank(statusCode)) { // return new response(statusCode, null); // } System.debug('=====2======' + response.getBody()); //正常执行 return new response(statusCode, response.getBody()); } // NEW QLM AWS 502 503接口 sushanhu 20220223 public static response getAWSQLMData(String endpoint,String jsonStr, String token) { //2、获取招标信息:记得使用1中获取的token Http http = new Http(); HttpRequest req = new HttpRequest(); req.setHeader('Content-Type', 'application/json'); req.setHeader('pi-token', token); req.setTimeout(120000); req.setEndpoint(endpoint); req.setMethod('POST'); req.setBody(jsonStr); HTTPResponse response = http.send(req); String statusCode = String.valueof(response.getStatusCode()); System.debug('response:' + response); //http:状态和code //如果状态不通过 , 则将状态及空的的数据 , 返回 // if (String.isNotBlank(statusCode)) { // return new response(statusCode, null); // } System.debug('=====2======' + response.getBody()); //正常执行 return new response(statusCode, response.getBody()); } //接口3,获取其他附件 public static response503 getFileData(String token503, String endpoint) { //4、获取网页:记得使用1中获取的token,记得EndPoint 使用2中获取的网页 try { Http http503 = new Http(); HttpRequest req503 = new HttpRequest(); req503.setHeader('open-authorization', 'Bearer' + token503); req503.setTimeout(120000); req503.setEndpoint(endpoint); req503.setMethod('GET'); HTTPResponse NFM503response = http503.send(req503); System.debug('NFM503response:' + NFM503response); System.debug('12345678' + NFM503response.getHeader('Content-Disposition')); String ress503 = NFM503response.getStatus(); if (string.isBlank(ress503) || !ress503.replace('o', 'O').replace('k', 'K').equals('OK')) { return new response503(ress503, null, null); } string str = NFM503response.getHeader('Content-Disposition'); string fileName = str.replaceall('filename=', '').replaceall('attachment;', ''); fileName = EncodingUtil.urlDecode(fileName, 'utf-8'); Blob responseBody503 = NFM503response.getBodyAsBlob(); System.debug('=====2======' + NFM503response.getBodyAsBlob()); return new response503(ress503, responseBody503, fileName); } catch (Exception ex) { return new response503('', Blob.valueOf('文件大小超过12M'), '文件大小超过12M'); } } public class response503 { public string status; public Blob responseBody; public String Name; public response503(string status, Blob responseBody, String Name) { this.status = status; this.responseBody = responseBody; this.Name = Name; } } //接口4,发送要删除项目的信息Id。。。2021/9/2,逻辑删除新加接口 fxk public static String sendTenInfo(String token504, String jsonStr, String endpoint) { Http http = new Http(); HttpRequest req = new HttpRequest(); req.setEndpoint(endpoint); req.setHeader('open-authorization', 'Bearer' + token504); req.setHeader('Content-Type', 'application/x-www-form-urlencoded'); req.setMethod('POST'); req.setBody(jsonStr); HTTPResponse response = http.send(req); string ress = response.getStatus(); // if (string.isBlank(ress) || !ress.replace('o', 'O').replace('k', 'K').equals('OK')) { // return new response(ress, null); // } System.debug('Body ' + response.getBody()); System.debug('Status ' + response.getStatus()); System.debug('Status code ' + response.getStatusCode()); return ress; } // 最大值为3,用来作为判断错误的条件(重发三次) public static Integer batch_retry_max_cnt = Integer.valueOf(System.Label.batch_retry_max_cnt); public static void againSendRequest(BatchIF_Log__c iflog, String count, BatchIF_Log__c rowData, String errorStr) { //判断rowdata中数据获取成功与否,如果失败重发三次,如果大于三次则手动操作 System.debug('----====---9-------'); Integer rowDataStr = Integer.valueOf(rowData.get(count)); if (rowDataStr == null) { rowDataStr = 0; } if (rowDataStr < batch_retry_max_cnt) { rowDataStr++; LogAutoSendSchedule.assignOneMinute(); } if (rowDataStr >= batch_retry_max_cnt) { iflog.ErrorLog__c += errorStr; rowData.ErrorLog__c += errorStr; } upsert rowData; upsert iflog; rowData.put(count, rowDataStr); } //因log存入数据有限,所以防止数据太多 public static String QLMgetRowDataStr(BatchIF_Log__c rowData) { String QLMDataStr = rowData.Log__c; Integer splitIdx = 2; while (rowData.get('Log' + splitIdx + '__c') != null && String.isBlank('' + rowData.get('Log' + splitIdx + '__c')) == false) { QLMDataStr += rowData.get('Log' + splitIdx + '__c'); splitIdx++; if (splitIdx == 13) break; } return QLMDataStr; } //创建RowDataFlg类型的日志 // public static BatchIF_Log__c QLMsaveRowData( String NFMType, Object NFMData) { // BatchIF_Log__c rowData = QLMmakeRowData( NFMType, NFMData); // insert rowData; // return rowData; // } public static BatchIF_Log__c QLMmakeRowData(String response, BatchIF_Log__c rowData) { rowData.Log__c = ''; rowData.ErrorLog__c = ''; String rowDataStr = response; Integer MaxLogColumnLength = 131072; if (rowDataStr.length() > 0) { Integer splitIdx = 1; while (rowDataStr.length() > 0) { if (splitIdx == 1) { rowData.put('Log__c', rowDataStr.substring(0, (rowDataStr.length() > MaxLogColumnLength ? MaxLogColumnLength : rowDataStr.length()))); } else if (splitIdx == 13) { rowData.ErrorLog__c = rowDataStr; break; } else { rowData.put('Log' + splitIdx + '__c', rowDataStr.substring(0, (rowDataStr.length() > MaxLogColumnLength ? MaxLogColumnLength : rowDataStr.length()))); } splitIdx++; rowDataStr = rowDataStr.substring((rowDataStr.length() > MaxLogColumnLength ? MaxLogColumnLength : rowDataStr.length())); } } return rowData; } public static BatchIF_Log__c LogAutoSend(BatchIF_Log__c rowDataSFDC, Exception ex, String status) { Integer batch_retry_max_cnt = Integer.valueOf(System.Label.batch_retry_max_cnt); if (rowDataSFDC.retry_cnt__c == null) rowDataSFDC.retry_cnt__c = 0; if (rowDataSFDC.retry_cnt__c < batch_retry_max_cnt) { rowDataSFDC.retry_cnt__c++; LogAutoSendSchedule.assignOneMinute(); } if (rowDataSFDC.retry_cnt__c >= batch_retry_max_cnt) { if (ex == null) { rowDataSFDC.ErrorLog__c = status + '\n错误次数已经超过自动送信设定的最大次数,请手动送信'; } else { rowDataSFDC.ErrorLog__c = ex.getMessage() + '\n' + ex.getStackTraceString() + '\n' + rowDataSFDC.ErrorLog__c + '错误次数已经超过自动送信设定的最大次数,请手动送信'; } } return rowDataSFDC; } // https://oly.ngrok.kunchuangtech.net/api/sso/sfdc_activitydata //发送给共通平台 精琢技术 thh 2021-09-22 start public static String sendToComPlat(String rowDataStr, String endpoint) { Http http = new Http(); HttpRequest req = new HttpRequest(); HTTPResponse res; String resb; req.setTimeout(120000); req.setEndpoint(endpoint); req.setMethod('POST'); req.setHeader('Content-Type', 'application/json'); req.setBody(rowDataStr); res = http.send(req); resb = res.getStatus(); system.debug('resb:' + resb); return resb; } //发送给共通平台 精琢技术 thh 2021-09-22 end public static Integer ControllerUtil() { Integer i = 0; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; return i; } }