From d8351e846682b19b198c2936695e79871737065d Mon Sep 17 00:00:00 2001 From: mjkhan21 Date: Tue, 11 Jul 2023 18:34:01 +0900 Subject: [PATCH] =?UTF-8?q?=EC=A3=BC=EC=84=9D=20=EB=B3=B4=EC=99=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cokr/xit/interfaces/filejob/JobConf.java | 65 ++++++++++++++++++- .../xit/interfaces/filejob/package-info.java | 3 +- .../filejob/service/bean/FileJobBean.java | 22 +++++-- src/main/resources/conf/file-job.conf | 51 +++++++++++++++ 4 files changed, 131 insertions(+), 10 deletions(-) create mode 100644 src/main/resources/conf/file-job.conf diff --git a/src/main/java/cokr/xit/interfaces/filejob/JobConf.java b/src/main/java/cokr/xit/interfaces/filejob/JobConf.java index 3314077..4b07590 100644 --- a/src/main/java/cokr/xit/interfaces/filejob/JobConf.java +++ b/src/main/java/cokr/xit/interfaces/filejob/JobConf.java @@ -12,9 +12,29 @@ import cokr.xit.foundation.AbstractComponent; import cokr.xit.foundation.Assert; import cokr.xit.foundation.data.JSON; -/**파일 작업을 위한 설정 정보. - *

설정 정보는 conf/file-job.conf 파일의 내용을 읽어 적재한다. - * +/**파일 작업을 위한 설정 정보. 설정 정보는 conf/file-job.conf 파일의 내용을 읽어 적재한다. + *

file-job.conf의 설정 정보는 JSON 형식으로 정의하며 다음과 같은 구조를 갖는다. + *

 {
+ *   "dirs": {    //용도별 최상위 디렉토리 경로
+ *     "receive": "수신 파일 최상위 디렉토리",
+ *     "send": "전송 파일 최상위 디렉토리",
+ *     "working": "파일 작업 최상위 디렉토리",
+ *     "success": "작업을 완료한 파일의 최상위 디렉토리",
+ *     "fail": "작업 실패한 파일의 최상위 디렉토리"
+ *   },
+ *   "dirCodes": { // 기관별 디렉토리 코드
+ *     "기관1 키": "기관1 코드",
+ *     "기관2 키": "기관2 코드",
+ *     ...
+ *   },
+ *   "jobs": [    // 작업별 설정 정보
+ *     {
+ *       "name": "작업 이름",
+ *       "dirCode": "기관별 디렉토리 코드, dicCodes에 설정한 키를 설정",
+ *       ... //작업별 설정 정보(key-value pair)
+ *     },
+ *   ]
+ * }
* @author mjkhan */ public class JobConf extends AbstractComponent { @@ -84,10 +104,17 @@ public class JobConf extends AbstractComponent { return ifEmpty(dirCodes != null ? dirCodes.get(key) : null, ""); } + /**key와 매핑한 디렉토리 코드를 설정한다. + * @param dirCodes 디렉토리 코드 + */ public void setDirCodes(Map dirCodes) { this.dirCodes = dirCodes; } + /**지정한 key에 해당하는 작업 설정 정보를 반환한다. + * @param key 작업 설정 정보를 반환한다. + * @return key에 해당하는 작업 설정 정보 + */ public Map getJob(String key) { if (jobMap == null) { if (jobs == null) @@ -99,10 +126,18 @@ public class JobConf extends AbstractComponent { return Assert.ifEmpty(jobMap.get(key), Collections::emptyMap); } + /**key와 매핑한 작업 설정 정보를 지정한다. + * @param jobs key와 매핑한 작업 설정 정보 + */ public void setJobs(List> jobs) { this.jobs = jobs; } + /**지정한 이름의 작업 정보 중 key에 해당하는 값을 반환한다. + * @param jobName 작업 이름 + * @param key 설정 정보 키 + * @return 지정한 이름의 작업 정보 중 key에 해당하는 값 + */ public String getJobConf(String jobName, String key) { Map job = getJob(jobName); return Assert.ifEmpty(job.get(key), () -> getDefault(key)); @@ -112,12 +147,28 @@ public class JobConf extends AbstractComponent { return String.join(File.separator, str); } + /**지정한 이름의 작업이 파일을 읽거나 쓰기 위한 최상위 디렉토리의 경로를 반환한다. + * @param jobName 작업 이름 + * @param dir 디렉토리 종류 + *
  • receive - 수신 파일 디렉토리
  • + *
  • send - 전송 파일 디렉토리
  • + *
+ * @return 파일을 읽거나 쓰기 위한 최상위 디렉토리 + */ public String getDir(String jobName, String dir) { String org = getJob(jobName).get("dirCode"); String code = getDirCode(org); return path(getDir(dir), code); } + /**지정한 이름의 작업이 작업 중 사용하는 디렉토리의 경로를 반환한다. + * @param jobName 작업 이름 + * @param dir 디렉토리 종류 + *
  • receive - 수신 파일 작업 디렉토리
  • + *
  • send - 전송 파일 작업 디렉토리
  • + *
+ * @return 작업 중 사용하는 디렉토리의 경로 + */ public String getWorkingDir(String jobName, String dir) { String org = getJob(jobName).get("dirCode"); String code = getDirCode(org); @@ -127,6 +178,10 @@ public class JobConf extends AbstractComponent { */ } + /**지정한 이름의 작업이 성공한 파일을 위치할 디렉토리 경로를 반환한다. + * @param jobName 작업 이름 + * @return 작업이 성공한 파일을 위치할 디렉토리 경로 + */ public String getSuccessDir(String jobName) { String org = getJob(jobName).get("dirCode"); String code = getDirCode(org); @@ -136,6 +191,10 @@ public class JobConf extends AbstractComponent { */ } + /**지정한 이름의 작업이 실패한 파일을 위치할 디렉토리 경로를 반환한다. + * @param jobName 작업 이름 + * @return 작업이 실패한 파일을 위치할 디렉토리 경로 + */ public String getFailDir(String jobName) { String org = getJob(jobName).get("dirCode"); String code = getDirCode(org); diff --git a/src/main/java/cokr/xit/interfaces/filejob/package-info.java b/src/main/java/cokr/xit/interfaces/filejob/package-info.java index ac406c7..0c1e682 100644 --- a/src/main/java/cokr/xit/interfaces/filejob/package-info.java +++ b/src/main/java/cokr/xit/interfaces/filejob/package-info.java @@ -1,3 +1,4 @@ -/**파일의 수신과 전송을 위한 작업의 설정을 지원하는 클래스를 정의한다. +/**파일의 수신과 전송을 위한 작업을 지원하는 service와 bean 클래스를 정의한다. + *

파일 작업을 정의하는 클래스들은 작업에 필요한 정보를 {@link JobConf conf/file-job.conf}에 정의해야 한다. */ package cokr.xit.interfaces.filejob; \ No newline at end of file diff --git a/src/main/java/cokr/xit/interfaces/filejob/service/bean/FileJobBean.java b/src/main/java/cokr/xit/interfaces/filejob/service/bean/FileJobBean.java index c7a4024..c72bfeb 100644 --- a/src/main/java/cokr/xit/interfaces/filejob/service/bean/FileJobBean.java +++ b/src/main/java/cokr/xit/interfaces/filejob/service/bean/FileJobBean.java @@ -4,16 +4,16 @@ import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.function.Predicate; -import java.util.stream.Collectors; import java.util.stream.Stream; import cokr.xit.foundation.AbstractComponent; import cokr.xit.interfaces.filejob.JobConf; -/**파일 작업을 수행하는 클래스가 상속하는 베이스 클래스 +/**파일 작업을 수행하는 Bean이 상속하는 베이스 클래스 * @author mjkhan */ public abstract class FileJobBean extends AbstractComponent { @@ -142,6 +142,12 @@ public abstract class FileJobBean extends AbstractComponent { this.cause = rootCause(cause); return setSuccess(this.cause == null); } + + public static List getPaths(List fileStatus) { + return !isEmpty(fileStatus) ? + fileStatus.stream().map(FileStatus::getPath).toList() : + Collections.emptyList(); + } } /**수신 파일의 최상위 디렉토리 경로를 반환한다. @@ -201,7 +207,7 @@ public abstract class FileJobBean extends AbstractComponent { */ protected List getFilePaths(String dir, Predicate filter) { try (Stream walk = Files.list(Paths.get(dir))) { - return walk.filter(ifEmpty(filter, path -> true)).collect(Collectors.toList()); + return walk.filter(ifEmpty(filter, path -> true)).toList(); } catch (Exception e) { throw runtimeException(e); } @@ -237,15 +243,19 @@ public abstract class FileJobBean extends AbstractComponent { } /**수신 디렉토리의 파일들을 작업 디렉토리로 이동하고, 경로를 반환한다. + * @param filter 작업 대상 파일에 적용할 필터. 지정하지 않으면 모든 파일을 이동한다. * @return 수신 작업 디렉토리의 파일 경로 목록 */ - protected List getReceivedFilePaths() { + protected List getReceivedFilePaths(Predicate filter) { String receiveDir = receiveDir(), workingDir = receiveWorkingDir(); + Predicate test = ifEmpty(filter, Files::isRegularFile); + + List paths = getFilePaths(receiveDir, test); + if (paths.isEmpty()) return Collections.emptyList(); - List paths = getFilePaths(receiveDir, Files::isRegularFile); move(paths, workingDir); - return getFilePaths(workingDir, null); + return getFilePaths(workingDir, test); } } \ No newline at end of file diff --git a/src/main/resources/conf/file-job.conf b/src/main/resources/conf/file-job.conf new file mode 100644 index 0000000..e35b69c --- /dev/null +++ b/src/main/resources/conf/file-job.conf @@ -0,0 +1,51 @@ +{ + "dirs": { + "receive": "C:\\workspace\\ESB_AGENT\\RCV", /* 수신 파일 최상위 디렉토리 */ + "send": "C:\\workspace\\ESB_AGENT\\SND", /* 전송 파일 최상위 디렉토리 */ + + "working": "C:\\workspace\\xit\\filesite\\work", /* 파일 작업 최상위 디렉토리 */ + "success": "C:\\workspace\\xit\\filesite\\success", /* 작업 완료한 파일의 최상위 디렉토리 */ + "fail": "C:\\workspace\\xit\\filesite\\fail" /* 작업 실패한 파일의 최상위 디렉토리 */ + }, + + "dirCodes": { + "smg": "CG131000000768", /* 국민신문고 기관코드 */ + "epost": "CG144523401150" /* epost 기관코드 */ + }, + + "defaults": { + "charset": "euc-kr", + "fetchSize": 100 + }, + + "jobs": [ + { /* 국민신문고 수신 */ + "name": "smg-in", + "dirCode": "smg", /* <-- dirCodes */ + "infoType": "100", + "alert": "http://localhost:8080/xit-filegate/api/smg/petition/receive.do" /* 업무 통보 url */ + }, + { /* 국민신문고 전송 */ + "name": "smg-out", + "dirCode": "smg", /* <-- dirCodes */ + "alert": "http://localhost:8080/xit-filegate/api/smg/petition/reply.do" /* 업무 통보 url */ + }, + + { /* epost 전자우편 신청 전송 */ + "name": "epost-send-request", + "dirCode": "epost", /* <-- dirCodes */ + + "conOrg": "YICT", /* 외부기관 구분코드 */ + "rceptId": "40219", /* 접수우체국 국기호 */ + "attachmentDir": "", /* 원본 첨부파일 디렉토리 경로 */ + + "txtFilename": "POSDF5$send_{yyyyMMddHHmmssSSS}.txt", + "zipFilename": "POSDF5${conKey}.zip" + }, + + { /* epost 전자우편 신청 수신 결과 */ + "name": "epost-receive-result", + "dirCode": "epost" /* <-- dirCodes */ + } + ] +} \ No newline at end of file