|
|
|
@ -15,7 +15,7 @@ import javax.annotation.Resource;
|
|
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
|
|
|
|
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
|
|
import org.apache.commons.lang3.text.WordUtils;
|
|
|
|
|
import org.apache.commons.text.WordUtils;
|
|
|
|
|
import org.apache.tools.ant.util.DateUtils;
|
|
|
|
|
import org.slf4j.Logger;
|
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
@ -67,18 +67,18 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
@Value("${API_SECRET}")
|
|
|
|
|
private String apiSecret;
|
|
|
|
|
|
|
|
|
|
/*同步表,格式:同步设置表列名/同步设置表列名(子表时设置,主表不设置)/主表关联列/子表关联列/数据库实际表/时间列/图片或文件列/数据条件/说明*/
|
|
|
|
|
/*同步表,格式:同步设置表列名/同步设置表列名(子表时设置,主表不设置)/主表唯一列(多列逗号分隔)/主表关联列/子表关联列/数据库实际表/时间列/图片或文件列/数据条件/说明*/
|
|
|
|
|
private final String[] SYNC_TABLES= {
|
|
|
|
|
"entrustAction////////委托验收,basicProducts//basic_udirel///updateTime///耗材字典","/basicProducts/basic_products//////耗材字典信息详情",
|
|
|
|
|
"//company_product_relevance///updateTime///供应商关联信息",
|
|
|
|
|
"basicCorp//basic_corp///updateTime///往来单位","typeThird//thr_bustype_origin///updateTime///第三方单据类型",
|
|
|
|
|
"basicThirdCorp//thr_corp///updateTime///第三方往来单位","//thr_dept///updateTime///第三方部门",
|
|
|
|
|
"//thr_inv_products///updateTime///第三方库存","basicThirdInv//thr_inv_warehouse//////第三方仓库",
|
|
|
|
|
"basicThirdBusOrder//thr_order///updateTime///第三方业务单据","/basicThirdBusOrder/thr_order_detail///updateTime///第三方单据详情",
|
|
|
|
|
"basicThirdProducts//thr_products///updateTime///第三方产品信息","//sup_cert///updateTime/filePath//资质证书信息",
|
|
|
|
|
"//sup_cert_set///updateTime///供应商资质证书设置","companyCert//sup_company///updateTime///配送企业",
|
|
|
|
|
"manufacturerCert//sup_manufacturer///updateTime///生产企业","productCert//sup_product///updateTime///产品资质信息",
|
|
|
|
|
"dbDiProducts//productinfo///updateTime///DI产品信息,//udicompany///updateTime///国际库医疗器械注册人信息"};
|
|
|
|
|
"entrustAction/////////委托验收","basicProducts//basic_udirel/uuid///updateTime///耗材字典","/basicProducts/basic_products/uuid,nameCode/uuid/uuid////耗材字典信息详情",
|
|
|
|
|
"//company_product_relevance////updateTime///供应商关联信息",
|
|
|
|
|
"basicCorp//basic_corp/erpId///updateTime///往来单位","typeThird//thr_bustype_origin/action,thirdSys///updateTime///第三方单据类型",
|
|
|
|
|
"basicThirdCorp//thr_corp/unitId,thirdSysFk///updateTime///第三方往来单位","//thr_dept/code,thirdSysFk///updateTime///第三方部门",
|
|
|
|
|
"//thr_inv_products/inventoryCode,batchNo,warehouseCode,spaceCode,thirdSysFk///updateTime///第三方库存","basicThirdInv//thr_inv_warehouse/code,thirdSysFk//////第三方仓库",
|
|
|
|
|
"basicThirdBusOrder//thr_order/billNo,thirdSysFk///updateTime///第三方业务单据","/basicThirdBusOrder/thr_order_detail/productId,orderIdFk,thirdSysFk///updateTime///第三方单据详情",
|
|
|
|
|
"basicThirdProducts//thr_products/code,thirdSysFk///updateTime///第三方产品信息","//sup_cert////updateTime/filePath//资质证书信息",
|
|
|
|
|
"//sup_cert_set////updateTime///供应商资质证书设置","companyCert//sup_company////updateTime///配送企业",
|
|
|
|
|
"manufacturerCert//sup_manufacturer////updateTime///生产企业","productCert//sup_product/productId,manufacturerIdFk,customerId///updateTime///产品资质信息",
|
|
|
|
|
"dbDiProducts//productinfo/nameCode,uuiddiType///updateTime///DI产品信息//udicompany/tyshxydm///updateTime///国际库医疗器械注册人信息"};
|
|
|
|
|
|
|
|
|
|
private int orderNum=0;
|
|
|
|
|
|
|
|
|
@ -116,11 +116,13 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
/*UDI系统上传自助平台*/
|
|
|
|
|
@Override
|
|
|
|
|
public void asyncUdiTask() {
|
|
|
|
|
logger.info("UDI管理系统同步任务开始--------");
|
|
|
|
|
asyncDataTask(true);
|
|
|
|
|
}
|
|
|
|
|
/*自助平台生成任务,不上传*/
|
|
|
|
|
@Override
|
|
|
|
|
public void asyncSpsTask() {
|
|
|
|
|
logger.info("自助平台同步任务开始--------");
|
|
|
|
|
asyncDataTask(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -164,46 +166,44 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
private void asyncDataTask(boolean isUpload) {
|
|
|
|
|
initTable();
|
|
|
|
|
Map<String,Object> map = dbDao.get("select * from sync_data_set limit 1");
|
|
|
|
|
if(map!=null&&map.get("downstreamEnable")!=null&&map.get("downstreamEnable").toString().equals("1"))
|
|
|
|
|
for(int i=0;i<SYNC_TABLES.length;i++) {
|
|
|
|
|
String[] tnames = SYNC_TABLES[i].split("/");
|
|
|
|
|
if(!StringUtils.isEmpty(tnames[0])&&map!=null&&map.get(tnames[0])!=null&&map.get(tnames[0]).toString().equals("1"))
|
|
|
|
|
syncData(SYNC_TABLES[i],isUpload);
|
|
|
|
|
if(map!=null&&map.get("downstreamEnable")!=null&&map.get("downstreamEnable").toString().equals("1")) {
|
|
|
|
|
for(int i=0;i<SYNC_TABLES.length;i++) {
|
|
|
|
|
String[] tnames = SYNC_TABLES[i].split("/");
|
|
|
|
|
saveIdcLog("---","",map.get(tnames[0])+SYNC_TABLES[i],0,0);
|
|
|
|
|
if(!StringUtils.isEmpty(tnames[0])&&map!=null&&map.get(tnames[0])!=null&&map.get(tnames[0]).toString().equals("1"))
|
|
|
|
|
syncData(SYNC_TABLES[i],isUpload);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void syncData(String t,boolean isUpload) {
|
|
|
|
|
boolean sync = true;
|
|
|
|
|
String[] tnames = t.split("/");
|
|
|
|
|
String[] cnames = {};
|
|
|
|
|
|
|
|
|
|
String lastUpdateTime = getUpdateTime(tnames[0]);
|
|
|
|
|
Date nowUpdateTime = new Date();
|
|
|
|
|
if(!StringUtils.isEmpty(tnames[0])) {
|
|
|
|
|
int n=-1;
|
|
|
|
|
for(int k=0;k<SYNC_TABLES.length;k++) {
|
|
|
|
|
if(SYNC_TABLES[k].contains("/"+tnames[0]+"/")) {
|
|
|
|
|
n++;
|
|
|
|
|
cnames[n] = SYNC_TABLES[k];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
List<Map<String, String>> keyList = dbDao.listKeyMysql(tnames[2]);
|
|
|
|
|
String keyColumn = keyList!=null&&keyList.size()>0 ? keyList.get(0).get("columnName").toString() : "id";
|
|
|
|
|
Map<String,Object> map = new HashMap<String,Object>();
|
|
|
|
|
String sqlWhere = "not exists (select fkId from idc_record where type='"+tnames[2]+"' and fkId="+tnames[2]+"."+keyColumn+")";
|
|
|
|
|
if(!StringUtils.isEmpty(tnames[2])) {
|
|
|
|
|
sqlWhere+=" and "+tnames[5]+">=cast('"+lastUpdateTime+"' as datetime)";
|
|
|
|
|
if(!StringUtils.isEmpty(tnames[6])) {
|
|
|
|
|
sqlWhere+=" and "+tnames[6]+">=cast('"+lastUpdateTime+"' as datetime)";
|
|
|
|
|
} else {
|
|
|
|
|
map.put("isEnd", "1");
|
|
|
|
|
}
|
|
|
|
|
map.put("sqlWhere", sqlWhere);
|
|
|
|
|
map.put("dataWhere", tnames[7]);
|
|
|
|
|
|
|
|
|
|
map.put("tableKey", tnames[0]);
|
|
|
|
|
map.put("tableName", tnames[2]);
|
|
|
|
|
map.put("masterLinkColumn", tnames[3]);
|
|
|
|
|
map.put("subLinkColumn", tnames[4]);
|
|
|
|
|
map.put("filePathColumn", tnames[6]);
|
|
|
|
|
map.put("messageType", tnames[8]);
|
|
|
|
|
map.put("messageName", tnames[8]);
|
|
|
|
|
map.put("uniqueColumn", tnames[3]);
|
|
|
|
|
map.put("masterLinkColumn", tnames[4]);
|
|
|
|
|
map.put("subLinkColumn", tnames[5]);
|
|
|
|
|
map.put("filePathColumn", tnames[7]);
|
|
|
|
|
map.put("dataWhere", tnames[8]);
|
|
|
|
|
map.put("messageType", tnames[9]);
|
|
|
|
|
map.put("messageName", tnames[9]);
|
|
|
|
|
ScheduledRequest scheduledRequest = new ScheduledRequest();
|
|
|
|
|
scheduledRequest.setCronName("sync"+WordUtils.capitalizeFully(tnames[2], new char[]{'_'}).replace("_", ""));
|
|
|
|
|
ScheduledEntity scheduledEntity = scheduledDao.findScheduled(scheduledRequest);
|
|
|
|
@ -403,8 +403,9 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
boolean success=false;
|
|
|
|
|
String tableName = params.get("tableName").toString();
|
|
|
|
|
String tableKey = params.get("tableKey").toString();
|
|
|
|
|
String[] childs = {};
|
|
|
|
|
String[] childs = new String[10];
|
|
|
|
|
int childNum = -1;
|
|
|
|
|
/*子表*/
|
|
|
|
|
for(String str:SYNC_TABLES) {
|
|
|
|
|
if(str.contains("/"+tableKey+"/")) {
|
|
|
|
|
childNum++;
|
|
|
|
@ -417,12 +418,12 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
String sql = "select count(*) from "+tableName;
|
|
|
|
|
Map<String,Object> column = getColumn(tableName);
|
|
|
|
|
|
|
|
|
|
Map<String,Object> whMap = new HashMap<String,Object>();
|
|
|
|
|
whMap.put("sqlWhere", params.get("sqlWhere"));
|
|
|
|
|
whMap.put("dataWhere", params.get("dataWhere"));
|
|
|
|
|
Map<String,Object> whereParams = new HashMap<String,Object>();
|
|
|
|
|
whereParams.put("sqlWhere", params.get("sqlWhere"));
|
|
|
|
|
whereParams.put("dataWhere", params.get("dataWhere"));
|
|
|
|
|
|
|
|
|
|
Map<String,Object> map = new HashMap<String,Object>();
|
|
|
|
|
String where = DBAUtils.convertWhere(column,whMap,"");
|
|
|
|
|
String where = DBAUtils.convertWhere(column,whereParams,"");
|
|
|
|
|
sql+=!StringUtils.isEmpty(where) ? " where "+where : "";
|
|
|
|
|
map.put("sql", sql);
|
|
|
|
|
int total = dbDao.count(map);
|
|
|
|
@ -437,14 +438,16 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
|
|
|
|
|
if(total>0) {
|
|
|
|
|
success = true;
|
|
|
|
|
params.put("page", 0);
|
|
|
|
|
params.put("limit", limit);
|
|
|
|
|
|
|
|
|
|
whereParams.put("page", 0);
|
|
|
|
|
whereParams.put("limit", limit);
|
|
|
|
|
|
|
|
|
|
List<Map<String, String>> keyList = dbDao.listKeyMysql(tableName);
|
|
|
|
|
String keyColumn = keyList!=null&&keyList.size()>0 ? keyList.get(0).get("columnName").toString() : "id";
|
|
|
|
|
for(int i=0;i<Math.ceil(total/limit)+1;i++) {
|
|
|
|
|
params.replace("page", i *limit);
|
|
|
|
|
params.replace("limit",limit);
|
|
|
|
|
Map<String,Object> data = getData(messageType,tableName,params);
|
|
|
|
|
whereParams.replace("page", i *limit);
|
|
|
|
|
whereParams.replace("limit",limit);
|
|
|
|
|
Map<String,Object> data = getData(messageType,tableName,params,whereParams);
|
|
|
|
|
String recordSql = "";
|
|
|
|
|
orderNum++;
|
|
|
|
|
saveIdcLog(messageType,"",tableName +">"+where,i *limit,total);
|
|
|
|
@ -458,7 +461,8 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
}
|
|
|
|
|
recordSql+=!StringUtils.isEmpty(recordSql) ? "," : "";
|
|
|
|
|
recordSql+="('"+UUID.randomUUID().toString().replaceAll("-", "")+"','"+tableName+"','"+list.get(m).get(keyColumn)+"','"+isEnd+"',now())";
|
|
|
|
|
if(childNum>-1&¶ms.get("masterLinkColumn")!=null&¶ms.get("subLinkColumn")!=null) {
|
|
|
|
|
if(childNum>-1&¶ms.get("masterLinkColumn")!=null&&!StringUtils.isEmpty(params.get("masterLinkColumn").toString())&&
|
|
|
|
|
params.get("subLinkColumn")!=null&&!StringUtils.isEmpty(params.get("subLinkColumn").toString())) {
|
|
|
|
|
for(int z=0;z<childNum+1;z++) {
|
|
|
|
|
String[] chidTnames = childs[z].split("/");
|
|
|
|
|
String keyValue = list.get(i).get(params.get("masterLinkColumn")).toString();
|
|
|
|
@ -472,8 +476,14 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
orderNum++;
|
|
|
|
|
|
|
|
|
|
if(isUplaod) {
|
|
|
|
|
String result = relay("",JSON.toJSONString(data),files);
|
|
|
|
|
String result = "";
|
|
|
|
|
try {
|
|
|
|
|
result = relay("",JSON.toJSONString(data),files);
|
|
|
|
|
} catch (Exception ex) {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
if(IDCUtils.isJson(result)) {
|
|
|
|
|
JSONObject json = JSON.parseObject(result);
|
|
|
|
|
if(json.getInteger("code")==20000) {
|
|
|
|
@ -487,9 +497,16 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
logger.error(result);
|
|
|
|
|
saveIdcLog(messageType,"",tableName +">"+result,i *limit,total);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
success = false;
|
|
|
|
|
saveIdcLog(messageType,"",tableName +">fail:上传地址未连通",i *limit,total);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
syncAddTask(data);
|
|
|
|
|
if(!StringUtils.isEmpty(recordSql)) {
|
|
|
|
|
dbDao.save("insert into idc_record (id,type,fkId,isEnd,createTime) values "+recordSql);
|
|
|
|
|
}
|
|
|
|
|
saveIdcLog(messageType,"",tableName +">success",i *limit,total);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -522,19 +539,20 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
private void analyToDB(JSONObject jsonObject,MultipartFile[] files) {
|
|
|
|
|
if(!StringUtils.isEmpty(jsonObject.getString("tableName"))) {
|
|
|
|
|
List<Map<String,Object>> list = jsonObject.getObject("data", List.class);
|
|
|
|
|
analyData(jsonObject.getString("tableName"),list);
|
|
|
|
|
analyData(jsonObject.getString("tableName"),jsonObject.getString("uniqueColumn"),list);
|
|
|
|
|
//图片处理
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*按表名解析数据到数据库,子表暂未处理*/
|
|
|
|
|
private void analyData(String tableName,List<Map<String,Object>> list) {
|
|
|
|
|
private void analyData(String tableName,String uniqueColumn,List<Map<String,Object>> list) {
|
|
|
|
|
|
|
|
|
|
String tName = DBAUtils.tableRealName(tableName);
|
|
|
|
|
String sql="insert into "+tName +"(";
|
|
|
|
|
String del="delete from "+tName+" where ";
|
|
|
|
|
String upd="update "+tName+" set ";
|
|
|
|
|
String[] keyColumn=new String[10];
|
|
|
|
|
String[] keyDataType=new String[10];
|
|
|
|
|
String[] keyColumn=new String[30];
|
|
|
|
|
String[] keyDataType=new String[30];
|
|
|
|
|
List<Map<String,String>> columnList = dbDao.listColumnsMysql(tName);
|
|
|
|
|
int key=0;
|
|
|
|
|
int col=0;
|
|
|
|
@ -545,11 +563,17 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
String extra = columnList.get(i).get("extra")!=null&&columnList.get(i).get("extra").toLowerCase().contains("auto_i") ? "A" : "N";
|
|
|
|
|
sql+=extra.equals("N") ? columnList.get(i).get("columnName").toString() : "";
|
|
|
|
|
col+=extra.equals("N") ? 1 : 0;
|
|
|
|
|
if(columnList.get(i).get("columnKey")!=null&&!StringUtils.isEmpty(columnList.get(i).get("columnKey").toString())&&
|
|
|
|
|
("PRI,UNI,MUL".contains(columnList.get(i).get("columnKey").toString()))&&extra.equals("N")) {
|
|
|
|
|
if(uniqueColumn!=null&&columnList.get(i).get("columnKey")!=null&&(","+uniqueColumn+",").contains(","+columnList.get(i).get("columnKey")+",")) {
|
|
|
|
|
keyColumn[key] = columnList.get(i).get("columnName").toString();
|
|
|
|
|
keyDataType[key]=columnList.get(i).get("dataType").toString().contains("char") ? "C" : "N";
|
|
|
|
|
keyDataType[key]=columnList.get(i).get("dataType").toString().contains("char") ? "C" : columnList.get(i).get("dataType").toString().contains("date") ? "D" : "N";
|
|
|
|
|
key++;
|
|
|
|
|
} else {
|
|
|
|
|
if(columnList.get(i).get("columnKey")!=null&&!StringUtils.isEmpty(columnList.get(i).get("columnKey").toString())&&
|
|
|
|
|
("PRI,UNI,MUL".contains(columnList.get(i).get("columnKey").toString()))&&extra.equals("N")) {
|
|
|
|
|
keyColumn[key] = columnList.get(i).get("columnName").toString();
|
|
|
|
|
keyDataType[key]=columnList.get(i).get("dataType").toString().contains("char") ? "C" : columnList.get(i).get("dataType").toString().contains("date") ? "D" : "N";
|
|
|
|
|
key++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sql+=") values ";
|
|
|
|
@ -565,7 +589,9 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
for(int z=0;z<keyColumn.length;z++ ) {
|
|
|
|
|
if(list.get(i).get(keyColumn[z])!=null&&!StringUtils.isEmpty(list.get(i).get(keyColumn[z]).toString())) {
|
|
|
|
|
updateWhere+=!StringUtils.isEmpty(updateWhere) ? " and " : " ";
|
|
|
|
|
updateWhere+=keyColumn[z]+" = "+(keyDataType[z].equals("C") ? "'" :"") +list.get(i).get(keyColumn[z]) +(keyDataType[z].equals("C") ? "'" :"");
|
|
|
|
|
String value = list.get(i).get(keyColumn[z]) !=null ? list.get(i).get(keyColumn[z]).toString() : "";
|
|
|
|
|
value = keyDataType[z].equals("D") ? "cast('"+DateUtil.formatDate(IDCUtils.parseDate(value),"yyyy-MM-dd HH:mm:ss") +"' as datetime)": value ;
|
|
|
|
|
updateWhere+=keyColumn[z]+" = "+(keyDataType[z].equals("C") ? "'" :"") +value +(keyDataType[z].equals("C") ? "'" :"");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if("A,D".contains(operateMode)&&!StringUtils.isEmpty(updateWhere))
|
|
|
|
@ -625,7 +651,7 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
for (Object o : (List<?>) obj) {
|
|
|
|
|
chList.add((Map<String,Object>)o);
|
|
|
|
|
}
|
|
|
|
|
analyData(list.get(i).get("tableName"+m).toString(),chList);
|
|
|
|
|
analyData(list.get(i).get("tableName"+m).toString(),"",chList);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -715,20 +741,24 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
private List<Map<String,Object>> getList(String tableName,Map<String,Object> params) {
|
|
|
|
|
String sql = "select "+tableName+".*,'A' as operateMode from "+tableName;
|
|
|
|
|
Map<String,Object> column = getColumn(tableName);
|
|
|
|
|
|
|
|
|
|
String where = DBAUtils.convertWhere(column,params,"");
|
|
|
|
|
sql+=!StringUtils.isEmpty(where) ? " where "+where : "";
|
|
|
|
|
params.put("sql", sql);
|
|
|
|
|
List<Map<String,Object>> list = dbDao.list(params);
|
|
|
|
|
Map<String,Object> map = new HashMap<String,Object>();
|
|
|
|
|
map.putAll(params);
|
|
|
|
|
map.put("sql", sql);
|
|
|
|
|
List<Map<String,Object>> list = dbDao.list(map);
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
/*由表名获取数据*/
|
|
|
|
|
private Map<String,Object> getData(String messageType,String tableName,Map<String,Object> params) {
|
|
|
|
|
List<Map<String,Object>> list = getList(tableName,params);
|
|
|
|
|
private Map<String,Object> getData(String messageType,String tableName,Map<String,Object> params,Map<String,Object> whereParams) {
|
|
|
|
|
List<Map<String,Object>> list = getList(tableName,whereParams);
|
|
|
|
|
Map<String,Object> map = new HashMap<String,Object>();
|
|
|
|
|
map.put("messageId", UUID.randomUUID().toString().replaceAll("-", ""));
|
|
|
|
|
map.put("messageType", messageType);
|
|
|
|
|
map.put("apiCode", "common");
|
|
|
|
|
map.put("tableName", DBAUtils.tableAliasName(tableName));
|
|
|
|
|
map.put("uniqueColumn", params.get("uniqueColumn"));
|
|
|
|
|
map.put("sendTime", new Date());
|
|
|
|
|
map.put("version", "1.0");
|
|
|
|
|
map.put("total", list.size());
|
|
|
|
|