You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

826 lines
24 KiB
Java

package cokr.xit.interfaces.smg;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import cokr.xit.base.file.FileInfo;
import cokr.xit.foundation.AbstractEntity;
import cokr.xit.foundation.Assert;
import cokr.xit.foundation.util.Random;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
/**국민 신문고 민원 정보
* @author mjkhan
*/
@Getter
@Setter
@XmlRootElement(name = "dmndinfo")
@XmlAccessorType(XmlAccessType.FIELD)
public class Petition extends AbstractEntity {
/**인터페이스 키: 필수
* PK : number(30) - YYYYMMDDHH24MISSFF+random(9)
*/
@XmlElement(name = "interface_seq_n")
private String interfaceSeqN;
/**시스템 구분: 필수
* char(88)
* EC010008 과태료시스템
*/
@XmlElement(name = "sys_gubun_c")
private String sysGubunC;
/**송신 기관 코드: 필수
* varchar2(7)
* 1140100 / 신청기관코드 / 신청기관코드
* ex)경기도 - 641000
*/
@XmlElement(name = "anc_code_v")
private String ancCodeV;
/**민원 구분: 필수
* char(3)
* 140:민원이송(기관코드-신문고) / 180: 답변 / 140: 반송(기관코드-연계기관)
*/
@XmlElement(name = "peti_gubun_c")
private String petiGubunC;
/**민원 기관 코드: 필수
* varchar2(7)
* 최초 신청기관코드 그대로 사용(절대변경불가)
*/
@XmlElement(name = "peti_anc_code_v")
private String petiAncCodeV;
/**민원 신청 번호: 필수
* varchar2(16)
* 국민신문고에서 생성(국민신문고의 민원 번호), 최초 이송이첩시는 null값 임.
* (신문고에서 생성된 데이터가 있을 경우는 넣어줌)
*/
@XmlElement(name = "peti_no_c")
private String petiNoC;
/**민원 접수 번호: 필수
* varchar2(16)
* 국민신문고에서 생성(국민신문고의 접수 번호), 최초 이송이첩시는 null값 임.
* (신문고에서 생성된 데이터가 있을 경우는 넣어줌)"
*/
@XmlElement(name = "civil_no_c")
private String civilNoC;
/**민원 신청인 명: 이관 / 반송시 필수
* varchar2(128)
*/
@XmlElement(name = "peter_name_v")
private String peterNameV;
/**민원 신청인 우편번호: 이관 / 반송시 필수
* varchar2(7)
*/
@XmlElement(name = "zip_code_c")
private String zipCodeC;
/**민원 신청인 주소: 이관 / 반송시 필수
* varchar2(400)
*/
@XmlElement(name = "address_v")
private String addressV;
/**민원 신청인 이메일
* varchar2(64)
*/
@XmlElement(name = "email_v")
private String emailV;
/**민원 신청인 핸드폰 번호
* varchar2(20)
*/
@XmlElement(name = "cel_no_v")
private String celNoV;
/**민원 신청인 전화 번호
* varchar2(20)
*/
@XmlElement(name = "tel_no_v")
private String telNoV;
/**민원 신청 제목: 이관 / 반송시 필수
* varchar2(500)
*/
@XmlElement(name = "peti_title_v")
private String petiTitleV;
/**민원 신청 내용: 이관 / 반송시 필수
* clob
*/
@XmlElement(name = "peti_reason_l")
private String petiReasonL;
/**민원 공개 여부: 이관 / 반송시 필수
* char(1)
* Y = 공개, N = 비공개 (default N)
* Y로 수신 시에도 내부적용 시에는 비공개로 적용 요함(개인정보보호지침)
* 송신 시는 모두 N으로 송신
*/
@XmlElement(name = "open_yn_c")
private String openYnC;
/**민원 신청일: 이관 / 반송시 필수
* date : YYYYMMDDHH24MISS
*/
@XmlElement(name = "peti_reg_d")
private String petiRegD;
/**민원 신청 내용 첨부 여부: 이관시 필수
* char(1)
* Y = 첨부, N = 미첨부(default)
*/
@XmlElement(name = "peti_reason_attach_yn_c")
private String petiReasonAttachYnC;
/**민원 신청 첨부파일 크기: 이관시 필수
* number(10)
*/
@XmlElement(name = "peti_file_size_n")
private String petiFileSizeN;
//-------------------------------------------------------------
/**민원 신청 첨부파일명1
* varchar2(2000)
*/
@XmlElement(name = "peti_file_path1_v")
private String petiFilePath1V;
/**민원 신청 첨부파일명2
* varchar2(2000)
*/
@XmlElement(name = "peti_file_path2_v")
private String petiFilePath2V;
/**민원 신청 첨부파일명3
* varchar2(2000)
*/
@XmlElement(name = "peti_file_path3_v")
private String petiFilePath3V;
/**민원 신청 첨부파일명4
* varchar2(2000)
*/
@XmlElement(name = "peti_file_path4_v")
private String petiFilePath4V;
/**민원 신청 첨부파일명5
* varchar2(2000)
*/
@XmlElement(name = "peti_file_path5_v")
private String petiFilePath5V;
//-----------------------------------------------------------------------------
/**등록 일자: 필수
* date
* 반영시에 sysdate(YYYYMMDDHH24MISS)로 생성
*/
@XmlElement(name = "reg_d")
private String regD;
/**송신 여부: 필수
* char(1)
* 1:송신 / 2:수신 / 1:송신
*/
@XmlElement(name = "send_yn_c")
private String sendYnC;
/**송신 일자
* date : YYYYMMDDHH24MISS
*/
@XmlElement(name = "send_d")
private String sendD;
/**적용 일자: 필수
* date
* interface DB->XML로 적용 시 sysdate(YYYYMMDDHH24MISS)로 생성
*/
@XmlElement(name = "apply_d")
private String applyD;
/**완료 구분: 필수
* char(1)
* 적용완료:Y OR N (default:N , 각 기관의 실 민원 DB에 반영 후 Y로 변경)
*/
@XmlElement(name = "apply_gubun_c")
private String applyGubunC;
//------------------------------------------------------------------------------------
/**처리 구분1: 필수
* varchar2(400)
* 0 / / 0
*/
@XmlElement(name = "pcd_gubun_v")
private String pcdGubunV;
/**처리 구분2: 필수
* varchar2(400)
*/
@XmlElement(name = "pcd_gubun2_v")
private String pcdGubun2V;
/**처리 구분3: 처리 결과시 필수
* varchar2(400)
*/
@XmlElement(name = "pcd_gubun3_v")
private String pcdGubun3V;
/**xml 인터페이스 아이디: 필수
* varchar2(10)
*/
@XmlElement(name = "ifid")
private String ifid;
/**소스 기관 코드: 필수
* varchar2(7)
* 해당 연계 기관 코드
*/
@XmlElement(name = "srcorgcd")
private String srcorgcd;
/**타겟 기관 코드: 필수
* varchar2(7)
* 연계 기관에서 insert시 무조건 1140100 값을 넣어 준다
*/
@XmlElement(name = "tgtorgcd")
private String tgtorgcd;
@XmlElement(name = "apndfilinfo")
private ApndFileInfo appendFileInfo;
//-------------------------------------------------------------------------------------
@XmlElement(name = "peti_path_gubun_c")
private String petiPathGubunC;
/**처리 부서 코드: 결과 처리시 필수
* varchar2(7)
*/
@XmlElement(name = "pcd_dept_v")
private String pcdDeptV;
/**민원 처리 부서명: 결과 처리시 필수
* varchar2(50)
*/
@XmlElement(name = "pcd_dept_nm_v")
private String pcdDeptNmV;
/**민원 처리 담당자 명: 결과 처리시 필수
* varchar2(50)
*/
@XmlElement(name = "duty_id_v")
private String dutyIdV;
/**담당자 이메일: 결과 처리시 필수
* varchar2(64)
*/
@XmlElement(name = "pcd_email_v")
private String pcdEmailV;
/**담당자 전화 번호: 결과 처리시 필수
* varchar2(20)
*/
@XmlElement(name = "pcd_tel_v")
private String pcdTelV;
/**접수 일자
* date
*/
@XmlElement(name = "anc_reg_d")
private String ancRegD;
/**한마디 더
* varchar2(4000)
*/
@XmlElement(name = "more_again_v")
private String moreAgainV;
/**만족도 항목1
* char(8)
*/
@XmlElement(name = "satisfy_c")
private String satisfyC;
/**만족도 항목2
* char(8)
*/
@XmlElement(name = "satisfy2_c")
private String satisfy2C;
/**만족도 항목3
* char(8)
*/
@XmlElement(name = "satisfy3_c")
private String satisfy3C;
/**만족도 입력일
* date
*/
@XmlElement(name = "satisfy_reg_d")
private String satisfyRegD;
/**민원 실 처리 기관 코드: 처리 결과시 필수
* varchar2(7)
* ex)경기도 6410000
*/
@XmlElement(name = "pcd_anc_code_v")
private String pcdAncCodeV;
/**민원 처리 기간
* number(5)
*/
@XmlElement(name = "peti_proc_dur_n")
private String petiProcDurN;
/**처리 예정일
* date
*/
@XmlElement(name = "peti_end_d")
private String petiEndD;
//----------------------------------------------------------------------------------------------------
// 결과(응답) 처리
//----------------------------------------------------------------------------------------------------
/**민원 요지: 결과 처리시 필수
* varchar2(512)
* 민원요지를 입력하면 민원제목대신 민원요지를 표출
*/
@XmlElement(name = "civil_gist_v")
private String civilGistV;
/**민원 처리 요약: 결과 처리시 필수
* clob
* 처리를 요약하여 표시
*/
@XmlElement(name = "civil_abstract_l")
private String civilAbstractL;
/**민원 처리 결과: 결과 처리시 필수
* clob
*/
@XmlElement(name = "pcd_rst_cont_l")
private String pcdRstContL;
/**민원 처리 완료 일자: 결과 처리시 필수
* varchar2(14) : YYYYMMDDHH24MISS
*/
@XmlElement(name = "do_reg_d")
private String doRegD;
/**민원 처리 결과 첨부 여부: 결과 처리시 필수
* char(1)
* Y = 첨부, N = 미첨부(default)
*/
@XmlElement(name = "pcd_rst_cont_attach_yn_c")
private String pcdRstContAttachYnC;
/**민원 처리 첨부 파일 크기
* number(10)
*/
@XmlElement(name = "pcd_file_size_n")
private String pcdFileSizeN;
/** 민원 처리 첨부파일명 1 */
@XmlTransient
private String pcdFilePath1V;
/** 민원 처리 첨부파일명 2 */
@XmlTransient
private String pcdFilePath2V;
/** 민원 처리 첨부파일명 3 */
@XmlTransient
private String pcdFilePath3V;
/** 민원 처리 첨부파일명 4 */
@XmlTransient
private String pcdFilePath4V;
/** 민원 처리 첨부파일명 5 */
@XmlTransient
private String pcdFilePath5V;
/** 원본 파일 이름 */
@XmlTransient
private String originalFilename;
/** 첨부파일 저장경로1 */
@XmlTransient
private String attachmentPath1;
/** 첨부파일 저장경로2 */
@XmlTransient
private String attachmentPath2;
/** 첨부파일 저장경로3 */
@XmlTransient
private String attachmentPath3;
/** 첨부파일 저장경로4 */
@XmlTransient
private String attachmentPath4;
/** 첨부파일 저장경로5 */
@XmlTransient
private String attachmentPath5;
/**전송 인터페이스 키
* number(30) - YYYYMMDDHH24MISS + 0000000 + random(9)
*/
@XmlTransient
private String sendInterfaceSeqN;
/**전송 상태
*/
@XmlTransient
private String sendStatus;
/**전송 상태 메시지
*/
@XmlTransient
private String sendStatusMsg;
/* yyyy-MM-dd hh:mm:ss -> yyyyMMddhhmmss */
private static String dateText(String str) {
if (str == null) return "";
return str.replaceAll("[-: ]", "");
}
/**일시(yyyy-MM-dd hh:mm:ss) 필드들의 값을 숫자만으로 변환한다.
* @return 현재 Petition
*/
public Petition normalize() {
petiRegD = dateText(petiRegD);
petiEndD = dateText(petiEndD);
ancRegD = dateText(ancRegD);
regD = dateText(regD);
return this;
}
/**민원의 답변/회수를 전송할 파일을 만들 때
* 전송 인터페이스 키를 파일의 인터페이스 키와 파일 이름으로 사용하기 위해
* interfaceSeqN과 sendInterfaceSeqN의 값을 교환한다.
* @return 현재 Petition
*/
public Petition swapInterfaceSeqs() {
String tmp = interfaceSeqN;
interfaceSeqN = sendInterfaceSeqN;
sendInterfaceSeqN = tmp;
return this;
}
/**민원의 답변/회수를 전송할 파일을 만들 때
* <ul><li>지정하는 일시값을 전송일시, 적용일시로 설정</li>
* <li>완료 구분을 완료(Y)로 설정</li>
* <li>소스 기관 코드를 설정</li>
* </ul>
* 한다.
* @param now 일시(yyyyMMddhhmmss)
* @return 현재 Petition
*/
public Petition setNow(String now) {
setSendInterfaceSeqN(now + "0000000" + Random.number(9));
setApplyGubunC("Y");
setSendD(now);
setApplyD(now);
setSrcorgcd(ancCodeV);
setTgtorgcd("");
setIfid("");
return this;
}
/**첨부파일의 갯수를 반환한다.
* @return 첨부파일 갯수
*/
public int getAttachmentCount() {
int count = 0;
for (String path: new String[] {attachmentPath1, attachmentPath2, attachmentPath3, attachmentPath4, attachmentPath5}) {
count += !Assert.isEmpty(path) ? 1 : 0;
}
return count;
}
/**첨부파일 정보로 첨부파일 저장 경로를 설정한다.
* @param attachments 첨부파일 정보
* @return 현재 Petition
*/
public Petition setAttachmentPaths(List<FileInfo> attachments) {
for (int i = 0; i < attachments.size(); ++i) {
FileInfo attachment = attachments.get(i);
String path = attachment.getPath();
switch (i + 1) {
case 1: attachmentPath1 = path; break;
case 2: attachmentPath2 = path; break;
case 3: attachmentPath3 = path; break;
case 4: attachmentPath4 = path; break;
case 5: attachmentPath5 = path; break;
default: break;
}
}
return this;
}
/**전송 파일 이름을 반환한다.
* @return 전송 파일 이름(EPOUGB$ + 전송 인터페이스 순번 + .xml)
*/
public String sendFilename() {
return "EPOUGB$" + getSendInterfaceSeqN() + ".xml";
}
/**민원파일에서 읽은 첨부파일 정보
* @author mjkhan
*/
@Getter
@Setter
@ToString
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name="apndfilinfo")
public static class ApndFileInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**민원 신청 첨부파일명1
* varchar2(2000)
*/
@XmlElement(name = "peti_file_path1_v")
private String petiFilePath1V;
/**민원 신청 첨부파일명2
* varchar2(2000)
*/
@XmlElement(name = "peti_file_path2_v")
private String petiFilePath2V;
/**민원 신청 첨부파일명3
* varchar2(2000)
*/
@XmlElement(name = "peti_file_path3_v")
private String petiFilePath3V;
/**민원 신청 첨부파일명4
* varchar2(2000)
*/
@XmlElement(name = "peti_file_path4_v")
private String petiFilePath4V;
/**민원 신청 첨부파일명5
* varchar2(2000)
*/
@XmlElement(name = "peti_file_path5_v")
private String petiFilePath5V;
@XmlElement(name = "apndfilcount")
private String apndfilcount;
@XmlElement(name = "apndfilcont1")
private String apndfilcont1;
@XmlElement(name = "apndfilcont2")
private String apndfilcont2;
@XmlElement(name = "apndfilcont3")
private String apndfilcont3;
@XmlElement(name = "apndfilcont4")
private String apndfilcont4;
@XmlElement(name = "apndfilcont5")
private String apndfilcont5;
/**민원파일에서 첨부파일 이름과 데이터를 읽어서 파일정보를 만들어 반환한다.
* @param infoType 관련 정보 유형
* @param infoKey 관련 정보 키
* @return 파일정보
*/
public List<FileInfo> getFileInfo(String infoType, String infoKey) {
int count = Integer.valueOf(apndfilcount);
if (count < 1)
return Collections.emptyList();
FileInfo.Relation relation = new FileInfo.Relation()
.setInfoType(infoType)
.setInfoKey(infoKey);
ArrayList<FileInfo.DataHolder> dataHolders = new ArrayList<>();
for (int i = 1; i <= 5; ++i) {
String filename = "";
String filecontent = "";
switch (i) {
case 1:
filename = petiFilePath1V;
filecontent = apndfilcont1;
break;
case 2:
filename = petiFilePath2V;
filecontent = apndfilcont2;
break;
case 3:
filename = petiFilePath3V;
filecontent = apndfilcont3;
break;
case 4:
filename = petiFilePath4V;
filecontent = apndfilcont4;
break;
case 5:
filename = petiFilePath5V;
filecontent = apndfilcont5;
break;
}
FileInfo.DataHolder dataHolder = getDataHolder(relation, filename, filecontent);
if (dataHolder != null)
dataHolders.add(dataHolder);
}
if (count != dataHolders.size())
throw new RuntimeException("첨부파일 수가 다릅니다.");
return new FileInfo.Factory().createFileInfos(dataHolders);
}
private FileInfo.DataHolder getDataHolder(FileInfo.Relation relation, String filename, String filecontent) {
return !Assert.isEmpty(filename) && !Assert.isEmpty(filecontent) ?
new FileInfo.DataHolder(relation, filename, filecontent) : null;
}
}
/**민원파일의 제목과 내용에서 단속 정보를 추출하는 클래스
* @author mjkhan
*/
public static class Violation {
private static RegexPattern
vehicleNoDatetime = new RegexPattern("(\\*\\s\\(\\d.*\\/\\d.*\\)\\s[GCS]:\\s)(.*)(\\s차량번호\\s:\\s)(.*)"),
coordinates = new RegexPattern("(\\*\\s발생지역\\s위도:)(.*)(\\s경도:)(.*)"),
location = new RegexPattern("(\\[사고발생지역\\])(.*)"),
description = new RegexPattern("(\\(.*\\))(.*)(\\s신고입니다.*)"),
entryType = new RegexPattern("(\\[민원 유입 경로\\]:\\s)(.*)");
private String
title,
reason;
/**민원파일의 제목을 설정한다.
* @param title 민원파일의 제목
* @return 현재 Violation
*/
public Violation setTitle(String title) {
this.title = title;
return this;
}
/**민원파일의 내용을 설정한다.
* @param reason 민원파일의 내용
* @return 현재 Violation
*/
public Violation setReason(String reason) {
this.reason = reason;
return this;
}
/**민원파일의 내용에서 단속 차량, 단속 일시 정보를 추출한다.
* @return 단속 차량, 단속 일시
* <ul><li>datetime: 단속 일시</li>
* <li>vehicleNo: 단속 차량 번호</li>
* </ul>
*/
public List<Map<String, String>> getVehicleNoDatetimes() {
Matcher matcher = vehicleNoDatetime.matcher(reason);
ArrayList<Map<String, String>> list = new ArrayList<>();
while (matcher.find()) {
String[] found = matcher.group()
.replaceAll(vehicleNoDatetime.regex, "$2,$4")
.replaceAll("\\(위·변조 없음\\)", "")
.replaceAll("[: /]", "")
.split(",");
HashMap<String, String> info = new HashMap<>();
info.put("datetime", found[0]);
info.put("vehicleNo", found.length > 1 ? found[1] : "");
list.add(info);
}
return list;
}
/**민원파일의 내용에서 단속 위치 정보를 추출한다.
* @return 단속 위치
* <ul><li>latitude: 위도</li>
* <li>longitude: 경도</li>
* </ul>
*/
public Map<String, String> getCoordinates() {
Matcher matcher = coordinates.matcher(reason);
HashMap<String, String> info = new HashMap<>();
while (matcher.find()) {
String[] found = matcher.group()
.replaceAll(coordinates.regex, "$2,$4")
.split(",");
info.put("latitude", found[0]);
info.put("longitude", found[1]);
}
return info;
}
/**민원파일의 내용에서 단속 지역 정보를 추출한다.
* @return 단속 지역 정보
*/
public String getLocation() {
Matcher matcher = location.matcher(reason);
String found = "";
while (matcher.find()) {
found = matcher.group().replaceAll(location.regex, "$2");
}
return found;
}
/**동/읍/면 이름을 추출한다.
* @param location 위치
* @return 동/읍/면 이름
*/
public String getDong(String location) {
if (Assert.isEmpty(location)) return "";
String[] suffix = {"동", "읍", "면"};
for (String token: location.split(" ")) {
for (String tail: suffix) {
if (token.endsWith(tail))
return token;
}
}
return "";
}
/**민원파일의 제목에서 사고 내역 정보를 추출한다.
* @return 사고 내역 정보
*/
public String getDescription() {
Matcher matcher = description.matcher(title);
String found = "";
while (matcher.find()) {
found = matcher.group().replaceAll(description.regex, "$2");
}
return found;
}
/**민원파일의 내역에서 유입 경로 정보를 추출한다.
* @return 유입 경로 정보
*/
public String getEntryType() {
Matcher matcher = entryType.matcher(reason);
String found = "";
while (matcher.find()) {
found = matcher.group().replaceAll(entryType.regex, "$2");
}
return found;
}
/**위반코드를 반환한다.
* @return 위반코드
*/
public String getCode() {
String str = title + " " + reason;
if (str.contains("방해"))
return "03";
if (str.contains("표지"))
return "05";
for (String s: new String[] {"주차", "주정차", "주자"})
if (str.contains(s))
return "01";
return "01";
}
}
private static class RegexPattern {
private String regex;
private Pattern pattern;
private RegexPattern(String regex) {
pattern = Pattern.compile(this.regex = regex);
}
private Matcher matcher(String str) {
return pattern.matcher(str);
}
}
public static void main(String[] args) {
String[] locations = {"경기도 파주시 금촌동 798", "경기도 파주시 문산읍 당동리 892", "경기도 파주시 월롱면 덕은리 1300"};
Violation v = new Violation();
for (String loc: locations)
System.out.println(v.getDong(loc));
}
}