|
|
|
@ -27,6 +27,7 @@ import org.springframework.jdbc.core.JdbcTemplate;
|
|
|
|
|
import org.springframework.scheduling.annotation.Async;
|
|
|
|
|
import org.springframework.scheduling.support.CronSequenceGenerator;
|
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
import org.springframework.web.multipart.MultipartFile;
|
|
|
|
|
|
|
|
|
|
import com.alibaba.fastjson.JSON;
|
|
|
|
@ -58,6 +59,7 @@ import okhttp3.Response;
|
|
|
|
|
/*数据中继数据中心(接收)*/
|
|
|
|
|
@Slf4j
|
|
|
|
|
@Service
|
|
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
|
|
public class IdcServiceImpl implements IdcService {
|
|
|
|
|
private static final Logger logger = LoggerFactory.getLogger(IdcServiceImpl.class);
|
|
|
|
|
@Value("${file_path}")
|
|
|
|
@ -117,11 +119,11 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
BaseResponse response = JSON.parseObject(json,BaseResponse.class);
|
|
|
|
|
return response;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ResultVOUtils.success(object);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*UDI系统上传自助平台*/
|
|
|
|
|
@Override
|
|
|
|
|
public void asyncUdiTask() {
|
|
|
|
@ -134,7 +136,7 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
logger.info("自助平台同步任务开始--------");
|
|
|
|
|
asyncDataTask(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*拉取前一级中继服务数据*/
|
|
|
|
|
@Async
|
|
|
|
|
@Override
|
|
|
|
@ -147,7 +149,7 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
fetchTask(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void fetchTask(boolean isIdc) {
|
|
|
|
|
String host = getNextHost();
|
|
|
|
|
if(!isIdc) {
|
|
|
|
@ -158,7 +160,7 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
logger.info("fetch from ip:"+host);
|
|
|
|
|
if(!StringUtils.isEmpty(host)) {
|
|
|
|
|
String result = post(host+"/spssync/common/list",null);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(IDCUtils.isJson(result)) {
|
|
|
|
|
JSONObject json = JSON.parseObject(result);
|
|
|
|
|
if(json!=null&&json.getInteger("code")==20000&&json.getString("data")!=null) {
|
|
|
|
@ -174,7 +176,7 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Async
|
|
|
|
|
@Override
|
|
|
|
|
public void asyncIdcTask() {
|
|
|
|
@ -184,7 +186,7 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
dbDao.save("insert into idc_var (code,content) values ('system_type','IDC')");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void asyncDataTask(boolean isUpload) {
|
|
|
|
|
initTable();
|
|
|
|
@ -206,15 +208,15 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void syncData(String t,boolean isUpload,String syncIp) {
|
|
|
|
|
boolean sync = true;
|
|
|
|
|
String[] tnames = t.split("/");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String lastUpdateTime = getUpdateTime(tnames[3]);
|
|
|
|
|
Date nowUpdateTime = new Date();
|
|
|
|
|
if(!StringUtils.isEmpty(tnames[0])) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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>();
|
|
|
|
@ -227,7 +229,7 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
map.put("isEnd", "1");
|
|
|
|
|
}
|
|
|
|
|
map.put("sqlWhere", sqlWhere);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
map.put("tableKey", tnames[0]);
|
|
|
|
|
map.put("tableName", tnames[2]);
|
|
|
|
|
map.put("uniqueColumn", tnames[3]);
|
|
|
|
@ -241,7 +243,7 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
scheduledRequest.setCronName("sync"+WordUtils.capitalizeFully(tnames[2], new char[]{'_'}).replace("_", ""));
|
|
|
|
|
ScheduledEntity scheduledEntity = scheduledDao.findScheduled(scheduledRequest);
|
|
|
|
|
String cron = scheduledEntity!=null ? scheduledEntity.getCron() : "";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!StringUtils.isEmpty(cron)) {
|
|
|
|
|
CronSequenceGenerator cronSequenceGenerator = new CronSequenceGenerator(cron);
|
|
|
|
|
Date nextTimePoint = cronSequenceGenerator.next(DateUtil.parseDate(lastUpdateTime));
|
|
|
|
@ -254,8 +256,8 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String fetchData(String host,Map<String,Object> params) {
|
|
|
|
|
OkHttpClient client = new OkHttpClient().newBuilder()
|
|
|
|
@ -274,7 +276,7 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
Response response = client.newCall(request).execute();
|
|
|
|
|
result = response.body().string();
|
|
|
|
|
JSONObject json = JSONObject.parseObject(result);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(isLastLevel()) {
|
|
|
|
|
if(json.get("code")!=null) {
|
|
|
|
|
success = analyToDB(host,json.getJSONObject("data"),files,false);
|
|
|
|
@ -290,12 +292,12 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
syncAddTaskStatus(json,false,success);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(success) {
|
|
|
|
|
String ret = post(host+"/spssync/common/success",params);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
// TODO Auto-generated catch block
|
|
|
|
|
e.printStackTrace();
|
|
|
|
@ -351,7 +353,7 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
IDCUtils.createDirectory(filePath +filePathSlash +datePath+"/");
|
|
|
|
|
if(!FileUtils.makeDirectory(backFilePath +backFileSlash +datePath))
|
|
|
|
|
IDCUtils.createDirectory(filePath +backFileSlash +datePath+"/");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FileUtils.SaveFileAs(content, fileName);
|
|
|
|
|
FileUtils.SaveFileAs(content, backFileName);
|
|
|
|
|
String[] saveFiles= {};
|
|
|
|
@ -391,7 +393,7 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
} else {
|
|
|
|
|
return ResultVOUtils.error(9000, "转发失败");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return ResultVOUtils.success();
|
|
|
|
@ -401,17 +403,17 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
/*数据同步,从数据库获取数据下发或上传下级中继服务*/
|
|
|
|
|
@Override
|
|
|
|
|
public BaseResponse send(Map<String,Object> params) {
|
|
|
|
|
|
|
|
|
|
return send(params.get("messageType").toString(),params.get("tableName").toString(),params);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return send(params.get("messageType").toString(),params.get("tableName").toString(),params);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
@Override
|
|
|
|
|
public BaseResponse send(String messageType,String tableName,Map<String,Object> params) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ResultVOUtils.error(9999, "");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void downloadFile(String fileName,HttpServletResponse response) {
|
|
|
|
|
OutputStream os;
|
|
|
|
@ -438,7 +440,7 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
|
|
|
|
|
dbDao.save(sql);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void saveExportStatus(Map<String,Object> params) {
|
|
|
|
|
Map<String,Object> map = new HashMap<String,Object>();
|
|
|
|
|
map.put("receiveStatus", "0");
|
|
|
|
@ -478,8 +480,8 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
|
|
|
|
|
dbDao.save(sql);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private boolean syncMasterData(Map<String,Object> params,boolean isUpload,String syncIp) {
|
|
|
|
|
boolean success=false;
|
|
|
|
|
String tableName = params.get("tableName").toString();
|
|
|
|
@ -502,13 +504,13 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
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,whereParams,"");
|
|
|
|
|
sql+=!StringUtils.isEmpty(where) ? " where "+where : "";
|
|
|
|
|
map.put("sql", sql);
|
|
|
|
|
int total = dbDao.count(map);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String isEnd = params.get("isEnd")!=null ? params.get("isEnd").toString() : "0";
|
|
|
|
|
int limit = 50;
|
|
|
|
|
String[] files = new String[limit];
|
|
|
|
@ -517,13 +519,13 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
String messageType = params.get("messageType").toString();
|
|
|
|
|
saveIdcLog(messageType,"",tableName +">"+where,0,total);
|
|
|
|
|
String filePathSlash = filePath.substring(filePath.length() -1).equals("/") ? "" : "/";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(total>0) {
|
|
|
|
|
success = true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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++) {
|
|
|
|
@ -559,13 +561,13 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
}
|
|
|
|
|
data.replace("data", list);
|
|
|
|
|
orderNum++;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(isUpload) {
|
|
|
|
|
String result = "";
|
|
|
|
|
try {
|
|
|
|
|
result = relay("",JSON.toJSONString(data),files,syncIp);
|
|
|
|
|
} catch (Exception ex) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
if(IDCUtils.isJson(result)) {
|
|
|
|
|
JSONObject json = JSON.parseObject(result);
|
|
|
|
@ -594,12 +596,12 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return success;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*增加同步任务状态*/
|
|
|
|
|
private void syncAddTaskStatus(Map<String,Object> json,boolean isUpload,boolean success) {
|
|
|
|
|
String content = JSON.toJSONString(json);
|
|
|
|
@ -610,10 +612,10 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
IDCUtils.createDirectory(filePath +datePath+"/");
|
|
|
|
|
if(!FileUtils.makeDirectory(backFilePath +datePath))
|
|
|
|
|
IDCUtils.createDirectory(filePath +datePath+"/");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FileUtils.SaveFileAs(content, fileName);
|
|
|
|
|
FileUtils.SaveFileAs(content, backFileName);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//type,transportType,superiorService,subordinateService,cacheFilePath
|
|
|
|
|
Map<String,Object> map = new HashMap<>();
|
|
|
|
|
map.put("type", json.get("messageType"));
|
|
|
|
@ -622,16 +624,16 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
map.put("taskId", json.get("messageId"));
|
|
|
|
|
map.put("cacheFilePath", fileName);
|
|
|
|
|
map.put("status", success ? "1" : "0");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
saveExportStatus(map);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*解析到数据库*/
|
|
|
|
|
private boolean analyToDB(String host,JSONObject jsonObject,MultipartFile[] files,boolean isUpload) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(jsonObject.get("data")!=null) {
|
|
|
|
|
String tableName = "";
|
|
|
|
|
String uniqueColumn = "";
|
|
|
|
@ -705,7 +707,7 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
if(!StringUtils.isEmpty(filePathColumn)) {
|
|
|
|
|
files[i] = list.get(i).get(filePathColumn) !=null ? list.get(i).get(filePathColumn).toString() : "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if("A,D,U".contains(operateMode)) {
|
|
|
|
|
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())) {
|
|
|
|
@ -715,7 +717,7 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
updateWhere+=keyColumn[z]+" = "+(keyDataType[z].equals("C") ? "'" :"") +value +(keyDataType[z].equals("C") ? "'" :"");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if("A,D".contains(operateMode)&&!StringUtils.isEmpty(updateWhere))
|
|
|
|
|
dbDao.delete(del+updateWhere);
|
|
|
|
|
}
|
|
|
|
@ -732,7 +734,7 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
value = DBAUtils.escape(value);
|
|
|
|
|
String dataType = columnList.get(k).get("dataType").toLowerCase().contains("char") || columnList.get(k).get("dataType").toLowerCase().contains("text") ?
|
|
|
|
|
"C" : columnList.get(k).get("dataType").toLowerCase().contains("date") ? "D" : "N" ;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sql+=m>0 ? "," : "";
|
|
|
|
|
boolean ups = list.get(i).containsKey(attrName) ? true : false ;
|
|
|
|
|
updateSet+=ups&&h>0 ? "," : "";
|
|
|
|
@ -760,11 +762,11 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
dbDao.update(upd + updateSet+" where "+updateWhere);
|
|
|
|
|
h+=ups ? 1 : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sql+=")";
|
|
|
|
|
n++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(int m=0;m<30;m++) {
|
|
|
|
|
if(list.get(i).get("tableName"+m)!=null&&list.get(i).get("data"+m)!=null) {
|
|
|
|
|
Object obj = list.get(i).get("data"+m);
|
|
|
|
@ -777,7 +779,7 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
if(n>0) {
|
|
|
|
|
result = (dbDao.save(sql)>0);
|
|
|
|
@ -864,20 +866,20 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
.addFormDataPart("fileName", fileName)
|
|
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Request request = new Request.Builder()
|
|
|
|
|
.url(syncIp+"/spssync/common/downloadFile")
|
|
|
|
|
.post(requestBody)
|
|
|
|
|
.build();
|
|
|
|
|
try {
|
|
|
|
|
Response result = client.newCall(request).execute();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (MediaType.parse("application/force-download").equals(result.body().contentType())) {
|
|
|
|
|
try (InputStream inputStream = result.body().byteStream()) {
|
|
|
|
|
String filePathSlash = filePath.substring(filePath.length() -1).equals("/") ? "" : "/";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FileOutputStream outputStream =new FileOutputStream(filePath +filePathSlash+fileName);
|
|
|
|
|
|
|
|
|
|
byte b[]=new byte[1024];
|
|
|
|
@ -892,14 +894,14 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
|
|
|
|
|
outputStream.flush();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
// TODO Auto-generated catch block
|
|
|
|
|
e.printStackTrace();
|
|
|
|
@ -907,7 +909,7 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*获取转发服务地址,当前值允许单向,只使用参数upper_server_ip*/
|
|
|
|
|
private String getNextHost() {
|
|
|
|
|
SystemParamConfigEntity systemParamConfigEntity = systemParamConfigService.selectByParamKey("upper_server_ip");
|
|
|
|
@ -921,7 +923,7 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
Map<String,Object> map = dbDao.get("select * from idc_var where code='system_type'");
|
|
|
|
|
return !(map!=null&&map.get("content")!=null&&map.get("content").toString().equals("IDC")) ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*是否需要转发*/
|
|
|
|
|
private boolean isRelay() {
|
|
|
|
|
String relayHost = getNextHost();
|
|
|
|
@ -932,7 +934,7 @@ 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 : "";
|
|
|
|
|
Map<String,Object> map = new HashMap<String,Object>();
|
|
|
|
@ -1032,7 +1034,7 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
} else {
|
|
|
|
|
//国家库数据
|
|
|
|
|
if(id.equals("productinfo")) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
updateTime = "2000-01-01 00:00:00";
|
|
|
|
|
String sql = "insert into idc_status (id,statusTime) values ('"+id+"',cast('"+updateTime+"' as datetime))";
|
|
|
|
@ -1062,7 +1064,7 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
jdbcTemplate.execute("alter table basic_export_status add column cacheFilePath varchar(255)");
|
|
|
|
|
jdbcTemplate.execute("alter table basic_upload_status add column cacheFilePath varchar(255)");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
private void alterTable(String tableName,String sql) {
|
|
|
|
@ -1072,6 +1074,6 @@ public class IdcServiceImpl implements IdcService {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|