package com.taiwanlife.agw.web.controller;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.jasypt.encryption.StringEncryptor;
import org.owasp.esapi.ESAPI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.taiwanlife.agw.jtds.domain.entity.NoticeRead;
import com.taiwanlife.agw.jtds.domain.service.NoticeReadService;
import com.taiwanlife.agw.web.bean.GetMessageDataDetailFormBean;
import com.taiwanlife.agw.web.bean.GetNoticeDataDetailFormBean;
import com.taiwanlife.agw.web.bean.PdfReqFormBean;
import com.taiwanlife.agw.web.bean.ShowMessageDataDetailFormBean;
import com.taiwanlife.agw.web.bean.ShowNoticeDataDetailFormBean;
import com.taiwanlife.agw.web.bean.ShowProgressDataDetailFormBean;
import com.taiwanlife.agw.web.enums.AreaEnum;
import com.taiwanlife.agw.web.enums.MessageDataDetailEnum;
import com.taiwanlife.agw.web.enums.MessageDataOrderingEnum;
import com.taiwanlife.agw.web.enums.MessageDataTypeEnum;
import com.taiwanlife.agw.web.enums.NoticeDataOrderingEnum;
import com.taiwanlife.agw.web.enums.PolicyScheduleTypeEnum;
import com.taiwanlife.agw.web.enums.ProgressNoticeEnum;
import com.taiwanlife.agw.web.util.DateUtil;
import com.taiwanlife.agw.webservice.enums.NoticeDataMessageDataType;
import com.taiwanlife.agw.webservice.exception.ApiException;
import com.taiwanlife.agw.webservice.rest.ChannelApiService;
import com.taiwanlife.agw.webservice.rest.ClamNoteService;
import com.taiwanlife.agw.webservice.rest.CmsApiService;
import com.taiwanlife.agw.webservice.rest.IKashService;
import com.taiwanlife.agw.webservice.rest.LisApiService;
import com.taiwanlife.agw.webservice.rest.NbrApiService;
import com.taiwanlife.agw.webservice.rest.OtherApiService;
import com.taiwanlife.agw.webservice.rest.PDFTemplateService;
import com.taiwanlife.agw.webservice.rest.model.channelApi.req.CmsMessageDataCountReqBean;
import com.taiwanlife.agw.webservice.rest.model.channelApi.req.CmsMessageDataDetailReqBean;
import com.taiwanlife.agw.webservice.rest.model.channelApi.req.DailyInsuranceBenefitsCountReqBean;
import com.taiwanlife.agw.webservice.rest.model.channelApi.req.DailyInsuranceBenefitsDataDetailReqBean;
import com.taiwanlife.agw.webservice.rest.model.channelApi.req.LspMessageDataCountReqBean;
import com.taiwanlife.agw.webservice.rest.model.channelApi.req.LspMessageDataDetailReqBean;
import com.taiwanlife.agw.webservice.rest.model.channelApi.req.LspNoticeDataCountReqBean;
import com.taiwanlife.agw.webservice.rest.model.channelApi.req.LspNoticeDataDetailReqBean;
import com.taiwanlife.agw.webservice.rest.model.claimNote.req.ClamNotePdfReqBean;
import com.taiwanlife.agw.webservice.rest.model.claimNote.req.ClamNoteReqBean;
import com.taiwanlife.agw.webservice.rest.model.claimNote.res.ClamNoticeDataCountResBean;
import com.taiwanlife.agw.webservice.rest.model.claimNote.res.ClamNoticeDataListResBean;
import com.taiwanlife.agw.webservice.rest.model.iKash.req.ChangePolicyScheduleCountReqBean;
import com.taiwanlife.agw.webservice.rest.model.iKash.req.ChangePolicyScheduleDetailReqBean;
import com.taiwanlife.agw.webservice.rest.model.iKash.req.ClaimScheduleCountReqBean;
import com.taiwanlife.agw.webservice.rest.model.iKash.req.ClaimScheduleDetailReqBean;
import com.taiwanlife.agw.webservice.rest.model.iKash.req.MessageDataCountReqBean;
import com.taiwanlife.agw.webservice.rest.model.iKash.req.MessageDataDetailReqBean;
import com.taiwanlife.agw.webservice.rest.model.iKash.req.NewPolicyScheduleCountReqBean;
import com.taiwanlife.agw.webservice.rest.model.iKash.req.NewPolicyScheduleDetailReqBean;
import com.taiwanlife.agw.webservice.rest.model.iKash.req.NewPolicySchedulePDFReqBean;
import com.taiwanlife.agw.webservice.rest.model.iKash.req.NoticeDataCountReqBean;
import com.taiwanlife.agw.webservice.rest.model.iKash.req.NoticeDataDetailReqBean;
import com.taiwanlife.agw.webservice.rest.model.iKash.res.ChangePolicyScheduleCountResBean;
import com.taiwanlife.agw.webservice.rest.model.iKash.res.ChangePolicyScheduleDetailResBean;
import com.taiwanlife.agw.webservice.rest.model.iKash.res.ClaimScheduleCountResBean;
import com.taiwanlife.agw.webservice.rest.model.iKash.res.ClaimScheduleDetailResBean;
import com.taiwanlife.agw.webservice.rest.model.iKash.res.LisNoticeDetailResBean;
import com.taiwanlife.agw.webservice.rest.model.iKash.res.MessageDataCountResBean;
import com.taiwanlife.agw.webservice.rest.model.iKash.res.MessageDataDetailResBean;
import com.taiwanlife.agw.webservice.rest.model.iKash.res.NewPolicyScheduleCountResBean;
import com.taiwanlife.agw.webservice.rest.model.iKash.res.NewPolicyScheduleDetailResBean;
import com.taiwanlife.agw.webservice.rest.model.iKash.res.NoticeBean;
import com.taiwanlife.agw.webservice.rest.model.iKash.res.NoticeDataCountResBean;
import com.taiwanlife.agw.webservice.rest.model.iKash.res.NoticeDataDetailResBean;
import com.taiwanlife.agw.webservice.rest.model.iKash.res.NoticeDataPdfReportReqBean;
import com.taiwanlife.agw.webservice.rest.model.iKash.res.NoticeResBean;
import com.taiwanlife.agw.webservice.rest.model.lis.req.LisExportPdfReqBean;
import com.taiwanlife.agw.webservice.rest.model.lis.req.LisExportPdfReqBean.OperatorInfo;
import com.taiwanlife.agw.webservice.rest.model.lis.req.LisMessageDataCountReqBean;
import com.taiwanlife.agw.webservice.rest.model.lis.req.LisMessageDataDetailReqBean;
import com.taiwanlife.agw.webservice.rest.model.lis.req.LisNoticeDataCountReqBean;
import com.taiwanlife.agw.webservice.rest.model.lis.req.LisNoticeDataDetailReqBean;
import com.taiwanlife.agw.webservice.rest.model.lis.req.LisPolicyScheduleCountReqBean;
import com.taiwanlife.agw.webservice.rest.model.lis.res.LisChangePolicyScheduleResBean;
import com.taiwanlife.agw.webservice.rest.model.lis.res.LisClaimScheduleDetailResBean;
import com.taiwanlife.agw.webservice.rest.model.lis.res.LisExportPdfResBean;
import com.taiwanlife.agw.webservice.rest.model.lis.res.LisMessageDataCountResBean;
import com.taiwanlife.agw.webservice.rest.model.lis.res.LisMessageDataDetailResBean;
import com.taiwanlife.agw.webservice.rest.model.lis.res.LisNewPolicyScheduleDetailResBean;
import com.taiwanlife.agw.webservice.rest.model.lis.res.LisNoticeDataCountResBean;
import com.taiwanlife.agw.webservice.rest.model.lis.res.LisNoticeDataDetailResBean;
import com.taiwanlife.agw.webservice.rest.model.nbr.req.NbrDataReqBean;
import com.taiwanlife.agw.webservice.rest.model.otherApi.req.ENoticeDataReportReqBean;
import com.taiwanlife.agw.webservice.rest.model.otherApi.req.ENoticeDataStatusReqBean;
import com.taiwanlife.agw.webservice.rest.model.otherApi.req.PdfReqBean;
import com.taiwanlife.agw.webservice.rest.model.otherApi.req.PdfTempldateReqBean;
import com.taiwanlife.agw.webservice.rest.model.otherApi.res.ENoticeDataStatusResBean;
import com.taiwanlife.agw.webservice.util.JsonUtil;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
@Controller
public class NoticeDataController extends BaseController {
@Autowired
private IKashService iKashService;
@Autowired
private NbrApiService nbrApiService;
@Autowired
private ChannelApiService channelApiService;
@Autowired
private LisApiService lisApiService;
@Autowired
CmsApiService cmsApiService;
@Autowired
private OtherApiService otherApiService;
@Autowired
private PDFTemplateService pdfTemplateService;
@Autowired
private ClamNoteService clamNoteService;
// 配合測試需求需要整日其區間,因此重新設計 003258
@Value("${notice.period}")
private int period;
@Value("${change.policy.schedule.historyPeriod}")
private int changePolicySchedulePeriod;
@Value("${notice.historyPeriod}")
private int historyPeriod;
@Value("${agw.ip}")
private String ip;
@Value("${eNoticeDataReport.url}")
private String eNoticeDataReportUrl;
@Value("${lis.exportPdf.SID}")
private String exportPdfSID;
@Value("${lis.exportPdf.UID}")
private String exportPdfUID;
// private int period = -30;
//
@Autowired
private NoticeReadService noticeReadService;
@Autowired
private Executor executor;
// private int historyPeriod = -60;
@GetMapping({ "/" })
public String index(HttpServletRequest request, HttpServletResponse response) {
/*
int offline = 9;
if (request.getSession().getAttribute("disclaimerLog") == null) {
// 避免每一次回到首頁的request都會一直call api來確認是否簽屬過同意書
offline = hasLoginEd(this.getAagcode());
}
if (offline != 2) {
return "redirect:/disclaimercontroller?offline=" + String.valueOf(offline);// 蒐集同意說明書功能 ricky update 1081224
} else {
return "redirect:/noticeDataCount";
}
*/
String aud = request.getAttribute(Claims.AUDIENCE) != null ? (String) request.getAttribute(Claims.AUDIENCE)
: null;
boolean nonemenu = request.getSession().getAttribute("nonemenu") != null
? (boolean) request.getSession().getAttribute("nonemenu")
: false;
if ("tapolicy".equals(aud) || nonemenu) {
request.getSession().setAttribute("nonemenu", true);
return "redirect:/tapolicy";
}
return "redirect:/noticeDataCount";
}
@GetMapping({ "/noticeDataCount" })
public String showDataCount(Model model, HttpServletRequest request, HttpServletResponse response,
HttpSession session) throws InterruptedException, ExecutionException {
long t = System.currentTimeMillis();
LOGGER.info("showDataCount /noticeDataCount start!");
LOGGER.info("### [{}][{}] ### isNew1: {}", getClientIp(request), getSessionId(session),
request.getSession(false).isNew());
LOGGER.info("### [{}][{}] ### Entering AGW Home agentId: {} agcode: {} agentcode: {} agname: {}",
getClientIp(request), getSessionId(session), getAgentId(), getAagcode(), getAagcode(), getAagname());
if (session.getAttribute("menuList") == null) {
try {
ESAPI.httpUtilities().setCurrentHTTP(request, response);
ESAPI.currentRequest().getSession().setAttribute("menuList", getMenuList(model));
} catch (Exception e) {
LOGGER.error("{\"menuList\":" + e.toString() + "}", e);
}
}
// Date rightNow = new Date();
// String startDateStr = getStartDateString(rightNow, Calendar.DAY_OF_YEAR, period);
// String endDateStr = getEndDateString(rightNow);
// String changePolicyStartDateStr = getStartDateString(rightNow, Calendar.DAY_OF_YEAR, changePolicySchedulePeriod);
// 呼叫各api取得資料
// CompletableFuture<List<MessageDataCountResBean>>
// messageDataCountResBeansFuture = getMessageDataCountResBeans();
// CompletableFuture<List<NoticeDataCountResBean>> noticeDataCountResBeansFuture
// = getNoticeDataCountResBeans(startDateStr, endDateStr);
// CompletableFuture<List<NewPolicyScheduleCountResBean>>
// newPolicyScheduleCountResBeansFuture = getNewPolicyScheduleCountResBeans();
// CompletableFuture<List<ChangePolicyScheduleCountResBean>>
// changePolicyScheduleCountResBeansFuture =
// getChangePolicyScheduleCountResBeans(changePolicyStartDateStr, endDateStr);
// CompletableFuture<List<ClaimScheduleCountResBean>>
// claimScheduleCountResBeansFuture = getClaimScheduleCountResBean();
// List<MessageDataCountResBean> messageDataCountResBeans =
// messageDataCountResBeansFuture.get();
// List<NoticeDataCountResBean> noticeDataCountResBeans =
// noticeDataCountResBeansFuture.get();
// List<NewPolicyScheduleCountResBean> newPolicyScheduleCountResBeans =
// newPolicyScheduleCountResBeansFuture.get();
// List<ChangePolicyScheduleCountResBean> changePolicyScheduleCountResBeans =
// changePolicyScheduleCountResBeansFuture.get();
// List<ClaimScheduleCountResBean> claimScheduleCountResBeans =
// claimScheduleCountResBeansFuture.get();
// model.addAttribute("messageData", messageDataCountResBeans);
// model.addAttribute("noticeData", noticeDataCountResBeans);
// model.addAttribute("newPolicyScheduleData", newPolicyScheduleCountResBeans);
// model.addAttribute("changePolicyScheduleData",
// changePolicyScheduleCountResBeans);
// model.addAttribute("claimScheduleCountData", claimScheduleCountResBeans);
// getHistoryDataCountResBeans(model);
model.addAttribute("showMessageDataDetailForm", new ShowMessageDataDetailFormBean());
model.addAttribute("showNoticeDataDetailForm", new ShowNoticeDataDetailFormBean());
LOGGER.info("showDataCount /noticeDataCount end! 總共花費時間:{}", (double) (System.currentTimeMillis() - t) / 1000d);
return "SalesInfo";
}
@PostMapping("/getMessageData")
@ResponseBody
public List<NoticeBean> getMessageData() throws InterruptedException, ExecutionException {
return getMessageDataCountResBeans().get().stream().map(e -> {
NoticeBean b = new NoticeBean();
b.setType(e.getAp09Type1());
b.setName(e.getAp09Type1Name());
b.setCount(e.getCount());
return b;
}).collect(Collectors.toList());
}
@PostMapping("/getNoticeData")
@ResponseBody
public List<NoticeBean> getNoticeData() throws InterruptedException, ExecutionException {
Date rightNow = new Date();
String startDateStr = getStartDateString(rightNow, Calendar.DAY_OF_YEAR, period);
String endDateStr = getEndDateString(rightNow);
return getNoticeDataCountResBeans(startDateStr, endDateStr).get().stream().map(e -> {
NoticeBean b = new NoticeBean();
b.setType(e.getUwnmSource());
b.setName(e.getUwnmSourceName());
b.setCount(e.getCount());
return b;
}).collect(Collectors.toList());
}
@PostMapping("/getScheduleData")
@ResponseBody
public List<NoticeBean> getScheduleData() throws InterruptedException, ExecutionException {
Date rightNow = new Date();
String endDateStr = getEndDateString(rightNow);
String changePolicyStartDateStr = getStartDateString(rightNow, Calendar.DAY_OF_YEAR,
changePolicySchedulePeriod);
CompletableFuture<List<NewPolicyScheduleCountResBean>> newPolicyScheduleCountResBeansFuture = getNewPolicyScheduleCountResBeans();
CompletableFuture<List<ChangePolicyScheduleCountResBean>> changePolicyScheduleCountResBeansFuture = getChangePolicyScheduleCountResBeans(
changePolicyStartDateStr, endDateStr);
CompletableFuture<List<ClaimScheduleCountResBean>> claimScheduleCountResBeansFuture = getClaimScheduleCountResBean();
List<NoticeBean> ls = new ArrayList<>();
ls.addAll(newPolicyScheduleCountResBeansFuture.get().stream().filter(e -> e.getCount() != 0).map(e -> {
NoticeBean b = new NoticeBean();
b.setName("新契約");
b.setHref("/newPolicyScheduleDataDetail");
b.setCount(e.getCount());
return b;
}).collect(Collectors.toList()));
ls.addAll(changePolicyScheduleCountResBeansFuture.get().stream().filter(e -> e.getCount() != 0).map(e -> {
NoticeBean b = new NoticeBean();
b.setName("保全");
b.setHref("/changePolicyScheduleDetail");
b.setCount(e.getCount());
return b;
}).collect(Collectors.toList()));
ls.addAll(claimScheduleCountResBeansFuture.get().stream().filter(e -> e.getCount() != 0).map(e -> {
NoticeBean b = new NoticeBean();
b.setName("理賠");
b.setHref("/claimScheduleDetail");
b.setCount(e.getCount());
return b;
}).collect(Collectors.toList()));
return ls;
}
@PostMapping("/noticeDataDetail")
public String showNoticeDataDetail(Model model, @ModelAttribute ShowNoticeDataDetailFormBean formBean)
throws JsonProcessingException, UnsupportedEncodingException {
model.addAttribute("formBean", copyProperties(formBean, ShowNoticeDataDetailFormBean.class));
model.addAttribute("type", MessageDataTypeEnum.LSP.getType());
model.addAttribute("area", AreaEnum.resolve("2"));
model.addAttribute("pdfReqBean", new PdfReqFormBean());
model.addAttribute("noticeDataPdfReportReqBean", new NoticeDataPdfReportReqBean());
if ("NB".equalsIgnoreCase(formBean.getUwnmSource())) {
model.addAttribute("eNoticeDataReportReqBean", new ENoticeDataReportReqBean());
return "NoticeDataDetailNB";
}
return "NoticeDataDetail";
}
@PostMapping("/getNoticeDataDetail")
@ResponseBody
public List<NoticeDataDetailResBean> getNoticeDataDetail(Model model,
@ModelAttribute GetNoticeDataDetailFormBean getNoticeDataDetailFormBean) throws JsonProcessingException {
Date rightNoew = new Date();
String ssoTokenStr = (String) request.getSession().getAttribute("SsoToken");
// System.out.println("ssoTokenStr ==============" + ssoTokenStr);
NoticeDataDetailReqBean noticeDataDetailReqBean = new NoticeDataDetailReqBean();
noticeDataDetailReqBean.setAgentCode(this.getAagcode());
noticeDataDetailReqBean.setUwnmSource(getNoticeDataDetailFormBean.getUwnmSource());
noticeDataDetailReqBean.setStartDate(getStartDateString(rightNoew, Calendar.DAY_OF_YEAR, period));
noticeDataDetailReqBean.setEndDate(getEndDateString(rightNoew));
LisNoticeDataDetailReqBean lisNoticeDataDetailReqBean = new LisNoticeDataDetailReqBean();
lisNoticeDataDetailReqBean.setAgentCode(this.getAagcode());
lisNoticeDataDetailReqBean.setAgentName("");
lisNoticeDataDetailReqBean.setTranType("Y");// agentportal只找電子照會
lisNoticeDataDetailReqBean.setPrintInd("");
lisNoticeDataDetailReqBean.setUwnmSource(getNoticeDataDetailFormBean.getUwnmSource());
lisNoticeDataDetailReqBean.setNoticeStartDate(getStartSlashDateString(rightNoew, Calendar.DAY_OF_YEAR, period));
// lisNoticeDataDetailReqBean.setNoticeStartDate(getStartSlashDateString(rightNoew, Calendar.DAY_OF_YEAR, -99999));//TODO TEST
lisNoticeDataDetailReqBean.setNoticeEndDate(getEndSlashDateString(rightNoew));
// 1120901179-00_Start
lisNoticeDataDetailReqBean.setStatus("('P','N')");
// 1120901179-00_End
List<NoticeDataDetailResBean> noticeDataDetailResBeans = new ArrayList<NoticeDataDetailResBean>();
List<NoticeDataDetailResBean> lspNoticeDataDetailResBeans = new ArrayList<NoticeDataDetailResBean>();
List<NoticeDataDetailResBean> lisNoticeDataDetailResBeans = new ArrayList<NoticeDataDetailResBean>();
List<NoticeDataDetailResBean> clamNoticeDataDetailResBeans = new ArrayList<>();
try {
noticeDataDetailResBeans = iKashService.getNoticeDataDetail(noticeDataDetailReqBean);
if (noticeDataDetailResBeans == null) {
noticeDataDetailReqBean = new NoticeDataDetailReqBean();
}
// else {
// if ("NB".equalsIgnoreCase(getNoticeDataDetailFormBean.getUwnmSource())) {
// for (int i = 0; i < noticeDataDetailResBeans.size(); i++) {
// String uwnmNoStr = noticeDataDetailResBeans.get(i).getUwnmNo();
// String reportFormStr = noticeDataDetailResBeans.get(i).getReportForm();
// // System.out.println("reportFormStr == " + i + "============" + reportFormStr);
// String typeCodeNameStr = null;
// typeCodeNameStr = "-";
// String isUncomplete = "";
// // TEST 使用
// //isUncomplete = "Y";
//
// ENoticeDataStatusReqBean eNoticeDataStatusReqBean = new ENoticeDataStatusReqBean();
// eNoticeDataStatusReqBean.setUwnmno(uwnmNoStr);
// eNoticeDataStatusReqBean.setType(reportFormStr);
// ENoticeDataStatusResBean eNoticeDataStatusResBean = new ENoticeDataStatusResBean();
// if ("1001".equalsIgnoreCase(reportFormStr) || "1002".equalsIgnoreCase(reportFormStr)
// || "1012".equalsIgnoreCase(reportFormStr) || "4001".equalsIgnoreCase(reportFormStr)
// || "5001".equalsIgnoreCase(reportFormStr) || "6001".equalsIgnoreCase(reportFormStr)) {
// // call 電照 API 取 isuncomplete
// eNoticeDataStatusResBean = otherApiService.getENoticeDataReport(eNoticeDataStatusReqBean);
// if (eNoticeDataStatusResBean != null) {
// isUncomplete = eNoticeDataStatusResBean.getIsuncomplete();
// }
// //System.out.println("isUncomplete == " + i + "============" + isUncomplete);
// }
// // TEST 使用
// //reportFormStr = "1002";
// if ("1001".equalsIgnoreCase(reportFormStr) || "1002".equalsIgnoreCase(reportFormStr)
// || "1012".equalsIgnoreCase(reportFormStr)) {
// // call 電照API return ==>isuncomplete 為Y 才需呈現以及產生LINK
// if ("Y".equalsIgnoreCase(isUncomplete.trim())) {
// typeCodeNameStr = "線上回覆";
// noticeDataDetailResBeans.get(i).setSsoToken(ssoTokenStr);
// }
// } else if ("4001".equalsIgnoreCase(reportFormStr) || "5001".equalsIgnoreCase(reportFormStr)
// || "6001".equalsIgnoreCase(reportFormStr)) {
// // call 電照API return ==>isuncomplete 為Y 才需呈現以及產生LINK
// if ("Y".equalsIgnoreCase(isUncomplete.trim())) {
// typeCodeNameStr = "簽名";
// noticeDataDetailResBeans.get(i).setSsoToken(ssoTokenStr);
// }
// }
// //System.out.println("typeCodeNameStr == " + i + "============" + typeCodeNameStr);
// noticeDataDetailResBeans.get(i).setTypeCodeName(typeCodeNameStr);
// }
// }
// }
} catch (ApiException e) {
LOGGER.error("{\"noticeDataDetailReqBean\":" + noticeDataDetailReqBean.toString() + "}", e);
}
try {
LspNoticeDataDetailReqBean lspNoticeDataDetailReqBean = new LspNoticeDataDetailReqBean();
lspNoticeDataDetailReqBean.setAgentCode(this.getAagcode());
lspNoticeDataDetailReqBean.setReportCode(getNoticeDataDetailFormBean.getUwnmSource());
lspNoticeDataDetailReqBean.setStartDate(getStartDateString(rightNoew, Calendar.DAY_OF_YEAR, period));
lspNoticeDataDetailReqBean.setEndDate(getEndDateString(rightNoew));
lspNoticeDataDetailResBeans = channelApiService
.getLspNoticeDataDetailByFileType(lspNoticeDataDetailReqBean);
} catch (ApiException e) {
LOGGER.error("{\"noticeDataDetailReqBean\":" + noticeDataDetailReqBean.toString() + "}", e);
}
try {
LisNoticeDataDetailResBean list = lisApiService
.getLisNoticeDataDetailByFileType(lisNoticeDataDetailReqBean);
if (list != null) {
List<LisNoticeDetailResBean> lislList = list.getLisNoticeDataDetailResBean();
lisNoticeDataDetailResBeans = lislList.stream().map(i -> {
NoticeDataDetailResBean dest = new NoticeDataDetailResBean();
try {
BeanUtils.copyProperties(dest, i);
} catch (IllegalAccessException e) {
LOGGER.error(e.toString());
} catch (InvocationTargetException e) {
LOGGER.error(e.toString());
}
return dest;
}).collect(Collectors.toList());
}
} catch (ApiException e) {
LOGGER.error("{\"lisNoticeDataDetailReqBean\":" + lisNoticeDataDetailReqBean.toString() + "}", e);
}
//114.07.22_1140702268-00理賠通知書_LIS系統串接來源調整(1104會議memo)
//PLNTF 理賠照會
try {
ClamNoteReqBean noticeDataListReqBean = new ClamNoteReqBean();
noticeDataListReqBean.setAgentId(this.getAgentId());
List<ClamNoticeDataListResBean> list = clamNoteService.getClamNoticeList(noticeDataListReqBean);
if (list != null) {
clamNoticeDataDetailResBeans = list.stream().map(i -> {
NoticeDataDetailResBean dest = new NoticeDataDetailResBean();
dest.setInsuredName(i.getAccidentPersonName());
dest.setUwnmNo(i.getClaimNo());
dest.setReferenceNo(String.valueOf(i.getNotifyId()));
dest.setPolicyNo(i.getPolicyNo());
dest.setPolicyNo2("-");
dest.setReportForm("88");
dest.setReportName("給付通知書");
dest.setNoticeDate(i.getSettledDate());
dest.setPendingExpDate("-");
dest.setType(MessageDataTypeEnum.PLNTF.name());
return dest;
}).collect(Collectors.toList());
}
} catch (ApiException e) {
LOGGER.error("{\"lisNoticeDataDetailReqBean\":" + lisNoticeDataDetailReqBean.toString() + "}", e);
}
if (noticeDataDetailResBeans != null) {
noticeDataDetailResBeans.forEach(
noticeDataDetailResBean -> noticeDataDetailResBean.setType(MessageDataTypeEnum.VLIFE.getType()));
}
if (lspNoticeDataDetailResBeans != null) {
lspNoticeDataDetailResBeans.forEach(lspNoticeDataDetailResBean -> lspNoticeDataDetailResBean
.setType(MessageDataTypeEnum.LSP.getType()));
noticeDataDetailResBeans.addAll(lspNoticeDataDetailResBeans);
}
if (!CollectionUtils.isEmpty(lisNoticeDataDetailResBeans)) {
lisNoticeDataDetailResBeans.forEach(lisNoticeDataDetailResBean -> lisNoticeDataDetailResBean
.setType(MessageDataTypeEnum.LIS.getType()));
noticeDataDetailResBeans.addAll(lisNoticeDataDetailResBeans);
}
//114.07.22_1140702268-00理賠通知書_LIS系統串接來源調整(1104會議memo)
//PLNTF 理賠照會
if (!CollectionUtils.isEmpty(clamNoticeDataDetailResBeans)) {
clamNoticeDataDetailResBeans.forEach(noticeDataDetailResBean -> noticeDataDetailResBean
.setType(MessageDataTypeEnum.PLNTF.getType()));
noticeDataDetailResBeans.addAll(clamNoticeDataDetailResBeans);
}
updateNoticeDetailResBean(noticeDataDetailResBeans, AreaEnum.NOTICE_DATA_AREA,
getNoticeDataDetailFormBean.getUwnmSource());
// 由enotify api取得照會回覆狀態
if ("NB".equalsIgnoreCase(getNoticeDataDetailFormBean.getUwnmSource())) {
for (int i = 0; i < noticeDataDetailResBeans.size(); i++) {
noticeDataDetailResBeans.get(i).setTypeCodeName("-");
if (noticeDataDetailResBeans.get(i).getUwnmNo() != null
|| noticeDataDetailResBeans.get(i).getUwnmNo().compareTo("") != 0) {
String isUncomplete = "";
String uwnmNoStr = noticeDataDetailResBeans.get(i).getUwnmNo();
String reportFormStr = noticeDataDetailResBeans.get(i).getReportForm();
ENoticeDataStatusReqBean eNoticeDataStatusReqBean = new ENoticeDataStatusReqBean();
eNoticeDataStatusReqBean.setUwnmno(uwnmNoStr);
eNoticeDataStatusReqBean.setType(reportFormStr);
ENoticeDataStatusResBean eNoticeDataStatusResBean = new ENoticeDataStatusResBean();
try {
if ("1001".equalsIgnoreCase(reportFormStr) || "1002".equalsIgnoreCase(reportFormStr)
|| "1012".equalsIgnoreCase(reportFormStr) || "4001".equalsIgnoreCase(reportFormStr)
|| "5001".equalsIgnoreCase(reportFormStr) || "6001".equalsIgnoreCase(reportFormStr)) {
// call 電照 API 取 isuncomplete
eNoticeDataStatusResBean = otherApiService.getENoticeDataReport(eNoticeDataStatusReqBean);
if (eNoticeDataStatusResBean != null) {
isUncomplete = eNoticeDataStatusResBean.getIsuncomplete();
}
// System.out.println("isUncomplete == " + i + "============" + isUncomplete);
}
} catch (ApiException e) {
LOGGER.error("{\"eNoticeDataStatusReqBean\":" + eNoticeDataStatusReqBean.toString() + "}", e);
}
// TEST 使用
// reportFormStr = "1002";
if ("1001".equalsIgnoreCase(reportFormStr) || "1002".equalsIgnoreCase(reportFormStr)
|| "1012".equalsIgnoreCase(reportFormStr)) {
// call 電照API return ==>isuncomplete 為Y 才需呈現以及產生LINK
if ("Y".equalsIgnoreCase(isUncomplete.trim())) {
// typeCodeNameStr = "線上回覆";
noticeDataDetailResBeans.get(i).setTypeCodeName("線上回覆");
noticeDataDetailResBeans.get(i).setSsoToken(ssoTokenStr);
}
} else if ("4001".equalsIgnoreCase(reportFormStr) || "5001".equalsIgnoreCase(reportFormStr)
|| "6001".equalsIgnoreCase(reportFormStr)) {
// call 電照API return ==>isuncomplete 為Y 才需呈現以及產生LINK
if ("Y".equalsIgnoreCase(isUncomplete.trim())) {
// typeCodeNameStr = "簽名";
noticeDataDetailResBeans.get(i).setTypeCodeName("簽名");
noticeDataDetailResBeans.get(i).setSsoToken(ssoTokenStr);
}
}
}
}
}
return noticeDataDetailResBeans;
}
@PostMapping("/eNoticeDataReport")
public String getENoticeDataReport(@ModelAttribute ENoticeDataReportReqBean eNoticeDataReportReqBean,
HttpServletResponse response) throws Exception {
String token = eNoticeDataReportReqBean.getSsoToken();
String tokenEncodeStr = URLEncoder.encode(token, StandardCharsets.ISO_8859_1.toString());
String uwnmNo = eNoticeDataReportReqBean.getENoticeNo();
String formId = eNoticeDataReportReqBean.getformId();
LOGGER.info("eNotice transfer SsoToken: {} ,uwnmNo: {}, formId: {}", tokenEncodeStr, uwnmNo, formId);
String forwardPath = eNoticeDataReportUrl + "?twlifeToken=" + tokenEncodeStr + "&method=noticeNote&uwnmNo="
+ uwnmNo + "&formId=" + formId;
LOGGER.info("eNotice transfer URL: {} ", forwardPath);
return "redirect:" + forwardPath;
}
@PostMapping("/messageDataDetail")
public String showMessageDataDetail(Model model, @ModelAttribute ShowMessageDataDetailFormBean formBean)
throws JsonProcessingException, UnsupportedEncodingException {
ShowMessageDataDetailFormBean showMessageDataDetailFormBean = copyProperties(formBean,
ShowMessageDataDetailFormBean.class);
model.addAttribute("formBean", showMessageDataDetailFormBean);
model.addAttribute("area", AreaEnum.resolve(showMessageDataDetailFormBean.getArea()));
model.addAttribute("pdfReqBean", new PdfReqFormBean());
return "MessageDataDetail";
}
/*
* @RequestMapping(value = "/HistoryDataDetail", method = RequestMethod.POST)
* public String showHistoryDataDetail(Model model, @ModelAttribute
* ShowMessageDataDetailFormBean formBean) throws JsonProcessingException,
* UnsupportedEncodingException { ShowMessageDataDetailFormBean
* showMessageDataDetailFormBean = copyProperties(formBean,
* ShowMessageDataDetailFormBean.class); model.addAttribute("formBean",
* showMessageDataDetailFormBean); model.addAttribute("area",
* AreaEnum.resolve(showMessageDataDetailFormBean.getArea()));
* model.addAttribute("pdfReqBean", new PdfReqFormBean()); return
* "HistoryDataDetail"; }
*
* @RequestMapping(value = "/getHistoryDataDetail", method = RequestMethod.POST)
*
* @ResponseBody public List<MessageDataDetailResBean>
* getHistoryDataDetail(Model model, @ModelAttribute
* GetMessageDataDetailFormBean getMessageDataDetailFormBean) throws
* JsonProcessingException { Date rightNow = new Date();
* List<MessageDataDetailResBean> messageDataDetailResBeans = new
* ArrayList<MessageDataDetailResBean>(); String messageDataDetailReqBeanStr =
* ""; String historyStartDate = getStartDateString(rightNow,
* Calendar.DAY_OF_YEAR, historyPeriod); String historyEndDate =
* getEndDateString(rightNow); MessageDataTypeEnum messageDataTypeEnum =
* MessageDataTypeEnum.find(getMessageDataDetailFormBean.getType()); if
* (messageDataTypeEnum.equals(MessageDataTypeEnum.CAS)) { try {
* CasMessageDataDetailReqBean casMessageDataDetailReqBean = new
* CasMessageDataDetailReqBean();
* casMessageDataDetailReqBean.setAgentCode(this.getAagcode());
* casMessageDataDetailReqBean.setStartDate(historyStartDate);
* casMessageDataDetailReqBean.setEndDate(historyEndDate);
* casMessageDataDetailReqBean.setReportCode(getMessageDataDetailFormBean.
* getAp09Type1()); messageDataDetailReqBeanStr =
* casMessageDataDetailReqBean.toString(); messageDataDetailResBeans =
* channelApiService.getCasMessageDataDetail(casMessageDataDetailReqBean);
* if(messageDataDetailResBeans != null) {
* messageDataDetailResBeans.forEach(messageDataDetailResBean ->
* messageDataDetailResBean.setType(MessageDataTypeEnum.CAS.getType())); } else
* { messageDataDetailResBeans = new ArrayList<MessageDataDetailResBean>(); } }
* catch (ApiException e) { LOGGER.error("{\"messageDataDetailReqBean\":" +
* messageDataDetailReqBeanStr + "}", e); } } else if
* (messageDataTypeEnum.equals(MessageDataTypeEnum.LSP)) { try {
* LspMessageDataDetailReqBean lspMessageDataDetailReqBean = new
* LspMessageDataDetailReqBean();
* lspMessageDataDetailReqBean.setAgentCode(this.getAagcode());
* lspMessageDataDetailReqBean.setStartDate(historyStartDate);
* lspMessageDataDetailReqBean.setEndDate(historyEndDate);
* lspMessageDataDetailReqBean.setReportCode(getMessageDataDetailFormBean.
* getAp09Type1()); messageDataDetailReqBeanStr =
* lspMessageDataDetailReqBean.toString(); messageDataDetailResBeans =
* channelApiService.getLspHistoryDataDetail(lspMessageDataDetailReqBean);
* if(messageDataDetailResBeans != null) {
* messageDataDetailResBeans.forEach(lspHistoryDataDetailResBean ->
* lspHistoryDataDetailResBean.setType(MessageDataTypeEnum.LSP.getType())); }
* else { messageDataDetailResBeans = new ArrayList<MessageDataDetailResBean>();
* } } catch (ApiException e) { LOGGER.error("{\"messageDataDetailReqBean\":" +
* messageDataDetailReqBeanStr + "}", e); } } return messageDataDetailResBeans;
* }
*/
@PostMapping("/getMessageDataDetailByFileType")
@ResponseBody
public List<MessageDataDetailResBean> getMessageDataDetailByFileType(Model model,
@ModelAttribute GetMessageDataDetailFormBean getMessageDataDetailFormBean) throws JsonProcessingException {
Date rightNow = new Date();
List<MessageDataDetailResBean> messageDataDetailResBeans = new ArrayList<MessageDataDetailResBean>();
String messageDataDetailReqBeanStr = "";
String startDate = getStartDateString(rightNow, Calendar.DAY_OF_YEAR, period);
String endDate = getEndDateString(rightNow);
String endRocDateStr = DateUtil.getCurrentRocDate();// yyy/mm/dd
String starRoctDateStr = DateUtil.addDay(endRocDateStr, period);// yyy/mm/dd
try {
MessageDataDetailReqBean messageDataDetailReqBean = new MessageDataDetailReqBean();
messageDataDetailReqBean.setAgentId(this.getAgentId());
messageDataDetailReqBean.setAp09Type1(getMessageDataDetailFormBean.getAp09Type1());
messageDataDetailReqBean.setStartDate(startDate);
messageDataDetailReqBean.setEndDate(endDate);
messageDataDetailReqBeanStr = messageDataDetailReqBean.toString();
messageDataDetailResBeans = iKashService.getMessageDataDetail(messageDataDetailReqBean);
if (messageDataDetailResBeans != null) {
// 1090601219-02_get accuracy pay dollars from msg notice_Start
// LOGGER.info(messageDataDetailResBeans.size());
// 1090601219-02_get accuracy pay dollars from msg notice_End
messageDataDetailResBeans.forEach(messageDataDetailResBean -> { // 1100500853-00_Start
if (messageDataDetailResBean.getAp09Type1().compareTo("PM") == 0
&& messageDataDetailResBean.getAp09Type2().compareTo("PM") == 0) {
messageDataDetailResBean.setAp09Type2Name("意外險保費調整通知");
} // 1100500853-00_End
messageDataDetailResBean.setType(MessageDataTypeEnum.VLIFE.getType());
});
} else {
messageDataDetailResBeans = new ArrayList<MessageDataDetailResBean>();
}
} catch (ApiException e) {
LOGGER.error("{\"messageDataDetailReqBean\":" + messageDataDetailReqBeanStr + "}", e);
}
try {
LspMessageDataDetailReqBean lspMessageDataDetailReqBean = new LspMessageDataDetailReqBean();
lspMessageDataDetailReqBean.setAgentCode(this.getAagcode());
lspMessageDataDetailReqBean.setReportCode(getMessageDataDetailFormBean.getAp09Type1());
lspMessageDataDetailReqBean.setStartDate(startDate);
lspMessageDataDetailReqBean.setEndDate(endDate);
messageDataDetailReqBeanStr = lspMessageDataDetailReqBean.toString();
List<MessageDataDetailResBean> lspMessageDataDetailResBeans = channelApiService
.getLspMessageDataDetailByFileType(lspMessageDataDetailReqBean);
if (lspMessageDataDetailResBeans != null) {
lspMessageDataDetailResBeans.forEach(lspMessageDataDetailResBean -> {
if (lspMessageDataDetailResBean.getAp09Type1().compareTo("APSSPMIH") == 0 // 1100500853-00_Start
&& lspMessageDataDetailResBean.getAp09Type2().compareTo("APSSPMIH") == 0) {
lspMessageDataDetailResBean.setNoteDesc(
"配合110年7月1日傷害險調降保費,原投保/附加之傷害保險於109/110年度之保險期間屆滿後,次年度起將依法令規範調降保險費率,若保戶願意提高保額(維持原保費),請儘速協助保戶填寫簡易契變書辦理。");
} // 1100500853-00_End
lspMessageDataDetailResBean.setType(MessageDataTypeEnum.LSP.getType());
});
messageDataDetailResBeans.addAll(lspMessageDataDetailResBeans);
}
} catch (ApiException e) {
LOGGER.error("{\"messageDataDetailReqBean\":" + messageDataDetailReqBeanStr + "}", e);
}
try {
CmsMessageDataDetailReqBean cmsMessageDataDetailReqBean = new CmsMessageDataDetailReqBean();
cmsMessageDataDetailReqBean.setAgentCode(this.getAagcode());
cmsMessageDataDetailReqBean.setStartDate(startDate);
cmsMessageDataDetailReqBean.setEndDate(endDate);
cmsMessageDataDetailReqBean.setReportCode(getMessageDataDetailFormBean.getAp09Type1());
messageDataDetailReqBeanStr = cmsMessageDataDetailReqBean.toString();
List<MessageDataDetailResBean> cmsMessageDataDetailResBeans = channelApiService
.getCmsMessageDataDetail(cmsMessageDataDetailReqBean);
if (cmsMessageDataDetailResBeans != null) {
cmsMessageDataDetailResBeans.forEach(cmsMessageDataDetailResBean -> cmsMessageDataDetailResBean
.setType(MessageDataTypeEnum.CAS.getType()));
messageDataDetailResBeans.addAll(cmsMessageDataDetailResBeans);
}
} catch (ApiException e) {
LOGGER.error("{\"messageDataDetailReqBean\":" + messageDataDetailReqBeanStr + "}", e);
}
try {
if (StringUtils.isNotEmpty(getMessageDataDetailFormBean.getAp09Type1())
&& getMessageDataDetailFormBean.getAp09Type1().equals("CL")) {
LspMessageDataDetailReqBean lspMessageDataDetailReqBean = new LspMessageDataDetailReqBean();
lspMessageDataDetailReqBean.setAgentCode(this.getAagcode());
lspMessageDataDetailReqBean.setReportCode(getMessageDataDetailFormBean.getAp09Type1());
lspMessageDataDetailReqBean.setStartDate(startDate);
lspMessageDataDetailReqBean.setEndDate(endDate);
messageDataDetailReqBeanStr = lspMessageDataDetailReqBean.toString();
List<MessageDataDetailResBean> lspMessageDataDetailCl207rResBeans = channelApiService
.getLspMessageDataCl207rDetail(lspMessageDataDetailReqBean);
if (lspMessageDataDetailCl207rResBeans != null) {
lspMessageDataDetailCl207rResBeans
.forEach(lspMessageDataDetailResBean -> lspMessageDataDetailResBean
.setType(MessageDataTypeEnum.VLIFE.getType()));
messageDataDetailResBeans.addAll(lspMessageDataDetailCl207rResBeans);
}
}
} catch (ApiException e) {
LOGGER.error("{\"messageDataDetailCl207rReqBean\":" + messageDataDetailReqBeanStr + "}", e);
}
try {
if (StringUtils.isNotEmpty(getMessageDataDetailFormBean.getAp09Type1()) && StringUtils
.equals(getMessageDataDetailFormBean.getAp09Type1(), MessageDataOrderingEnum.GP.name())) {
DailyInsuranceBenefitsDataDetailReqBean dailyInsuranceBenefitsDataDetailReqBean = new DailyInsuranceBenefitsDataDetailReqBean();
dailyInsuranceBenefitsDataDetailReqBean.setAgentCode(this.getTransagentcode());
dailyInsuranceBenefitsDataDetailReqBean.setStartDate(starRoctDateStr);
dailyInsuranceBenefitsDataDetailReqBean.setEndDate(endRocDateStr);
messageDataDetailReqBeanStr = dailyInsuranceBenefitsDataDetailReqBean.toString();
List<MessageDataDetailResBean> dailyInsuranceBenefitsDataDetailResBeans = channelApiService
.getDailyInsuranceBenefitsDataDetail(dailyInsuranceBenefitsDataDetailReqBean);
if (dailyInsuranceBenefitsDataDetailResBeans != null) {
dailyInsuranceBenefitsDataDetailResBeans
.forEach(bean -> bean.setType(MessageDataTypeEnum.VLIFE.getType()));
messageDataDetailResBeans.addAll(dailyInsuranceBenefitsDataDetailResBeans);
}
}
} catch (ApiException e) {
LOGGER.error("{\"messageDataDetailReqBean\":" + messageDataDetailReqBeanStr + "}", e);
}
try {
if (StringUtils.isNotEmpty(getMessageDataDetailFormBean.getAp09Type1()) && StringUtils
.equals(getMessageDataDetailFormBean.getAp09Type1(), MessageDataOrderingEnum.BL.name())) {
LspMessageDataDetailReqBean lspMessageDataDetailReqBean = new LspMessageDataDetailReqBean();
lspMessageDataDetailReqBean.setAgentCode(this.getAagcode());
lspMessageDataDetailReqBean.setReportCode(getMessageDataDetailFormBean.getAp09Type1());
lspMessageDataDetailReqBean.setStartDate(startDate);
lspMessageDataDetailReqBean.setEndDate(endDate);
messageDataDetailReqBeanStr = lspMessageDataDetailReqBean.toString();
List<MessageDataDetailResBean> lspReminNoticeReturnMessageDataDetailResBeans = channelApiService
.getLspReminNoticeReturnMessageDataDetail(lspMessageDataDetailReqBean);
if (lspReminNoticeReturnMessageDataDetailResBeans != null) {
lspReminNoticeReturnMessageDataDetailResBeans
.forEach(lspMessageDataDetailResBean -> lspMessageDataDetailResBean
.setType(MessageDataTypeEnum.LSP.getType()));
messageDataDetailResBeans.addAll(lspReminNoticeReturnMessageDataDetailResBeans);
}
}
} catch (ApiException e) {
LOGGER.error("{\"lspReminNoticeReturnMessageDataDetailReqBean\":" + messageDataDetailReqBeanStr + "}", e);
}
try {
if (StringUtils.isNotEmpty(getMessageDataDetailFormBean.getAp09Type1()) && StringUtils
.equals(getMessageDataDetailFormBean.getAp09Type1(), MessageDataOrderingEnum.PC.name())) {
LspMessageDataDetailReqBean lspMessageDataDetailReqBean = new LspMessageDataDetailReqBean();
lspMessageDataDetailReqBean.setAgentCode(this.getAagcode());
lspMessageDataDetailReqBean.setReportCode(getMessageDataDetailFormBean.getAp09Type1());
lspMessageDataDetailReqBean.setStartDate(startDate);
lspMessageDataDetailReqBean.setEndDate(endDate);
messageDataDetailReqBeanStr = lspMessageDataDetailReqBean.toString();
List<MessageDataDetailResBean> lspReminNoticeReturnMessageDataDetailResBeans = channelApiService
.getLspReinstatementNoticeMessageDataDetail(lspMessageDataDetailReqBean);
if (lspReminNoticeReturnMessageDataDetailResBeans != null) {
lspReminNoticeReturnMessageDataDetailResBeans
.forEach(lspMessageDataDetailResBean -> lspMessageDataDetailResBean
.setType(MessageDataTypeEnum.LSP.getType()));
messageDataDetailResBeans.addAll(lspReminNoticeReturnMessageDataDetailResBeans);
}
}
} catch (ApiException e) {
LOGGER.error("{\"lspReinstatementNoticeMessageDataDetailReqBean\":" + messageDataDetailReqBeanStr + "}", e);
}
try {
LisMessageDataDetailReqBean lisMessageDataDetailReqBean = new LisMessageDataDetailReqBean();
lisMessageDataDetailReqBean.setAgentId(this.getAgentId());
lisMessageDataDetailReqBean.setAp09Type1(getMessageDataDetailFormBean.getAp09Type1());
lisMessageDataDetailReqBean.setStartDate(startDate);
lisMessageDataDetailReqBean.setEndDate(endDate);
messageDataDetailReqBeanStr = lisMessageDataDetailReqBean.toString();
LisMessageDataDetailResBean list = lisApiService.getMessageDataDetail(lisMessageDataDetailReqBean);
List<MessageDataDetailResBean> lisMessageDataDetailResBeans = list.getMessageDataDetailResBean();
if (lisMessageDataDetailResBeans != null) {
lisMessageDataDetailResBeans.forEach(messageDataDetailResBean -> {
messageDataDetailResBean.setType(MessageDataTypeEnum.LIS.getType());
});
messageDataDetailResBeans.addAll(lisMessageDataDetailResBeans);
}
} catch (ApiException e) {
LOGGER.error("{\"messageDataDetailReqBean\":" + messageDataDetailReqBeanStr + "}", e);
}
updateNoticeDetailResBean(messageDataDetailResBeans, AreaEnum.MESSAGE_DATA_AREA,
getMessageDataDetailFormBean.getAp09Type1());
return messageDataDetailResBeans;
}
@PostMapping("/noticeDataPdfReport")
public void getNoticeDataPdfReport(@ModelAttribute NoticeDataPdfReportReqBean noticeDataPdfReportReqBean,
HttpServletResponse response) throws ApiException, IOException {
byte[] pdf = null;
// Lis 產生照會PDF
if (MessageDataTypeEnum.find(noticeDataPdfReportReqBean.getNoticeDataPdfReportType()).isLis()) {
String uuid = UUID.randomUUID().toString();
LisExportPdfReqBean lisExportPdfReqBean = new LisExportPdfReqBean();
lisExportPdfReqBean.setDocumentId(noticeDataPdfReportReqBean.getDocumentId());// 影像編號
lisExportPdfReqBean.setPage("");// 空白,所有頁次都要匯出
lisExportPdfReqBean.setWatermark("");// 無浮水印
lisExportPdfReqBean.setPassword("");// 無須加密
OperatorInfo operatorInfo = new OperatorInfo();
operatorInfo.setClientIPAddress(ip);
operatorInfo.setTransactionId(uuid);
operatorInfo.setSystemId(exportPdfSID);
operatorInfo.setOperatorUserId(exportPdfUID);
lisExportPdfReqBean.setOperatorInfo(operatorInfo);
LisExportPdfResBean lisExportPdfResBean = lisApiService.getLisxportPdfUrl(lisExportPdfReqBean);
byte[] byteArrray = lisExportPdfResBean.getReturnData().getResult().getBytes();
pdf = java.util.Base64.getDecoder().decode(byteArrray);
//114.07.22_1140702268-00理賠通知書_LIS系統串接來源調整(1104會議memo)
} else if (MessageDataTypeEnum.find(noticeDataPdfReportReqBean.getNoticeDataPdfReportType()).isPlntf()) {
ClamNotePdfReqBean clamNotePdfReqBean = new ClamNotePdfReqBean();
clamNotePdfReqBean.setNotifyId(noticeDataPdfReportReqBean.getDocumentId());
String clamNoticePdfDecryptorStr = clamNoteService.getClamNoticePdf(clamNotePdfReqBean);
if (!StringUtils.isBlank(clamNoticePdfDecryptorStr)) {
pdf = java.util.Base64.getDecoder().decode(clamNoticePdfDecryptorStr);
}
} else {
pdf = nbrApiService.getNbrSingleReport(new NbrDataReqBean(noticeDataPdfReportReqBean.getUwnmNo(), noticeDataPdfReportReqBean.getReportForm())).getReturnReportData();
}
response.setContentType("application/pdf");
IOUtils.write(pdf, response.getOutputStream());
response.flushBuffer();
}
@GetMapping("/newPolicyScheduleDataDetail")
public String showNewPolicyScheduleDetail(Model model) {
final ShowProgressDataDetailFormBean showProgressDataDetailFormBean = new ShowProgressDataDetailFormBean();
showProgressDataDetailFormBean.setArea(AreaEnum.PROGRESS_DATA_AREA.getCode());
showProgressDataDetailFormBean.setCategory(ProgressNoticeEnum.NB.name());
model.addAttribute("formBean", showProgressDataDetailFormBean);
model.addAttribute("area", AreaEnum.PROGRESS_DATA_AREA);
model.addAttribute("newPolicySchedulePDFBean", new NewPolicySchedulePDFReqBean());
return "NewPolicyScheduleDetail";
}
@PostMapping("/getNewPolicyScheduleDataDetail")
@ResponseBody
public List<NewPolicyScheduleDetailResBean> getNewPolicyScheduleDetail(Model model,
ShowProgressDataDetailFormBean showProgressDataDetailFormBean) throws JsonProcessingException {
NewPolicyScheduleDetailReqBean newPolicyScheduleDetailReqBean = new NewPolicyScheduleDetailReqBean();
newPolicyScheduleDetailReqBean.setAgentCode(this.getAagcode());
List<NewPolicyScheduleDetailResBean> newPolicyScheduleDetailResBean = new ArrayList<NewPolicyScheduleDetailResBean>();
List<NewPolicyScheduleDetailResBean> lisNewPolicyScheduleDetailResBean = new ArrayList<NewPolicyScheduleDetailResBean>();
try {
newPolicyScheduleDetailResBean = iKashService.getNewPolicyScheduleDetail(newPolicyScheduleDetailReqBean);
if (newPolicyScheduleDetailResBean == null) {
newPolicyScheduleDetailResBean = new ArrayList<NewPolicyScheduleDetailResBean>();
}
} catch (ApiException e) {
LOGGER.error("{\"newPolicyScheduleDetailReqBean\":" + newPolicyScheduleDetailReqBean.toString() + "}", e);
}
// LIS新契約進度明細
try {
Date endDate = new Date();
String endSlashDateStr = getEndSlashDateString(endDate);
LisNewPolicyScheduleDetailResBean rep = lisApiService
.getNewPolicyScheduleDetail(newPolicyScheduleDetailReqBean);
lisNewPolicyScheduleDetailResBean = rep.getNewPolicyScheduleDetailResBean();
if (lisNewPolicyScheduleDetailResBean != null) {
newPolicyScheduleDetailResBean.addAll(lisNewPolicyScheduleDetailResBean);
}
} catch (ApiException e) {
LOGGER.error("{\"newPolicyScheduleDetailReqBean\":" + newPolicyScheduleDetailReqBean.toString() + "}", e);
}
updateNoticeDetailResBean(newPolicyScheduleDetailResBean, AreaEnum.PROGRESS_DATA_AREA,
showProgressDataDetailFormBean.getCategory());
return newPolicyScheduleDetailResBean;
}
@GetMapping("/changePolicyScheduleDetail")
public String showChangePolicyScheduleDetail(Model model) {
final ShowProgressDataDetailFormBean showProgressDataDetailFormBean = new ShowProgressDataDetailFormBean();
showProgressDataDetailFormBean.setArea(AreaEnum.PROGRESS_DATA_AREA.getCode());
showProgressDataDetailFormBean.setCategory(ProgressNoticeEnum.PC.name());
model.addAttribute("formBean", showProgressDataDetailFormBean);
model.addAttribute("area", AreaEnum.PROGRESS_DATA_AREA);
return "ChangePolicyScheduleDetail";
}
@PostMapping("/getChangePolicyScheduleDetail")
@ResponseBody
public List<ChangePolicyScheduleDetailResBean> getChangePolicyScheduleDetail(Model model,
ShowProgressDataDetailFormBean showProgressDataDetailFormBean) throws JsonProcessingException {
Date endDate = new Date();
String startDateStr = getStartDateString(endDate, Calendar.DAY_OF_YEAR, period);
String endDateStr = getEndDateString(endDate);
String startSlashDateStr = getStartSlashDateString(endDate, Calendar.DAY_OF_YEAR, changePolicySchedulePeriod);
String endSlashDateStr = getEndSlashDateString(endDate);
ChangePolicyScheduleDetailReqBean changePolicyScheduleDetailReqBean = new ChangePolicyScheduleDetailReqBean();
changePolicyScheduleDetailReqBean.setAgentCode(this.getAagcode());
changePolicyScheduleDetailReqBean.setStartDate(startSlashDateStr);
changePolicyScheduleDetailReqBean.setEndDate(endDateStr);
ChangePolicyScheduleDetailReqBean lisChangePolicyScheduleDetailReqBean = new ChangePolicyScheduleDetailReqBean();
lisChangePolicyScheduleDetailReqBean.setAgentCode(this.getAagcode());
lisChangePolicyScheduleDetailReqBean.setStartDate(startSlashDateStr);
lisChangePolicyScheduleDetailReqBean.setEndDate(endSlashDateStr);
List<ChangePolicyScheduleDetailResBean> changePolicyScheduleDetailResBean = new ArrayList<ChangePolicyScheduleDetailResBean>();
List<ChangePolicyScheduleDetailResBean> lisChangePolicyScheduleResBean = new ArrayList<ChangePolicyScheduleDetailResBean>();
try {
changePolicyScheduleDetailResBean = iKashService
.getChangePolicyScheduleDetail(changePolicyScheduleDetailReqBean);
if (changePolicyScheduleDetailResBean == null) {
changePolicyScheduleDetailReqBean = new ChangePolicyScheduleDetailReqBean();
}
} catch (ApiException e) {
LOGGER.error("{\"changePolicyScheduleDetailReqBean\":" + changePolicyScheduleDetailReqBean.toString() + "}",
e);
}
// LIS契約變更=保全進度查詢
try {
LisChangePolicyScheduleResBean rep = lisApiService
.getChangePolicySchedule(lisChangePolicyScheduleDetailReqBean);
lisChangePolicyScheduleResBean = rep.getChangePolicyScheduleDetailResBean();
if (lisChangePolicyScheduleResBean != null) {
changePolicyScheduleDetailResBean.addAll(lisChangePolicyScheduleResBean);
}
} catch (ApiException e) {
LOGGER.error("{\"lisChangePolicyScheduleDetailReqBean\":" + lisChangePolicyScheduleDetailReqBean.toString()
+ "}", e);
}
updateNoticeDetailResBean(changePolicyScheduleDetailResBean, AreaEnum.PROGRESS_DATA_AREA,
showProgressDataDetailFormBean.getCategory());
return changePolicyScheduleDetailResBean;
}
@GetMapping("/claimScheduleDetail")
public String showClaimScheduleDetail(Model model) throws JsonProcessingException {
final ShowProgressDataDetailFormBean showProgressDataDetailFormBean = new ShowProgressDataDetailFormBean();
showProgressDataDetailFormBean.setArea(AreaEnum.PROGRESS_DATA_AREA.getCode());
showProgressDataDetailFormBean.setCategory(ProgressNoticeEnum.CL.name());
model.addAttribute("formBean", showProgressDataDetailFormBean);
model.addAttribute("area", AreaEnum.PROGRESS_DATA_AREA);
return "ClaimScheduleDetail";
}
@PostMapping("/getClaimScheduleDetail")
@ResponseBody
public List<ClaimScheduleDetailResBean> getClaimScheduleDetail(Model model,
ShowProgressDataDetailFormBean showProgressDataDetailFormBean) throws JsonProcessingException {
ClaimScheduleDetailReqBean claimScheduleDetailReqBean = new ClaimScheduleDetailReqBean();
claimScheduleDetailReqBean.setAgentCode(this.getAagcode());
List<ClaimScheduleDetailResBean> claimScheduleDetailResBean = new ArrayList<ClaimScheduleDetailResBean>();
List<ClaimScheduleDetailResBean> lisClaimScheduleDetailResBean = new ArrayList<ClaimScheduleDetailResBean>();
try {
claimScheduleDetailResBean = iKashService.getClaimScheduleDetail(claimScheduleDetailReqBean);
if (claimScheduleDetailResBean == null) {
claimScheduleDetailReqBean = new ClaimScheduleDetailReqBean();
}
} catch (ApiException e) {
LOGGER.error("{\"claimScheduleDetailReqBean\":" + claimScheduleDetailReqBean.toString() + "}", e);
} catch (Exception e) { // 1090900714-00
LOGGER.error("", e);
}
try {
List<ClaimScheduleDetailResBean> claimScheduleDetailResBeans = channelApiService
.getClaimScheduleDetail(claimScheduleDetailReqBean);
if (claimScheduleDetailResBeans != null) {
claimScheduleDetailResBean.addAll(claimScheduleDetailResBeans);
}
} catch (ApiException e) {
LOGGER.error("{\"claimScheduleDetailReqBean\":" + claimScheduleDetailReqBean.toString() + "}", e);
} catch (Exception e) { // 1090900714-00
LOGGER.error("", e);
}
// LIS理賠進度查詢
try {
LisClaimScheduleDetailResBean rep = lisApiService.getClaimScheduleDetail(claimScheduleDetailReqBean);
lisClaimScheduleDetailResBean = rep.getClaimScheduleDetailResBean();
if (lisClaimScheduleDetailResBean != null) {
// 修正西元為民國_20230529_Start
for (int i = 0; i < lisClaimScheduleDetailResBean.size(); i++) {
ClaimScheduleDetailResBean bean = lisClaimScheduleDetailResBean.get(i);
if (bean.getEventDate() != null && DateUtil.checkdateFormat(bean.getEventDate())) {
bean.setEventDate(DateUtil.dateToMinguo(bean.getEventDate()));
}
if (bean.getClaimReceDate() != null && DateUtil.checkdateFormat(bean.getClaimReceDate())) {
bean.setClaimReceDate(DateUtil.dateToMinguo(bean.getClaimReceDate()));
}
if (bean.getClaimSubmitDate() != null && DateUtil.checkdateFormat(bean.getClaimSubmitDate())) {
bean.setClaimSubmitDate(DateUtil.dateToMinguo(bean.getClaimSubmitDate()));
}
lisClaimScheduleDetailResBean.set(i, bean);
}
// 修正西元為民國_20230529_End
claimScheduleDetailResBean.addAll(lisClaimScheduleDetailResBean);
}
} catch (ApiException e) {
LOGGER.error("{\"claimScheduleDetailReqBean\":" + claimScheduleDetailReqBean.toString() + "}", e);
}
updateNoticeDetailResBean(claimScheduleDetailResBean, AreaEnum.PROGRESS_DATA_AREA,
showProgressDataDetailFormBean.getCategory());
return claimScheduleDetailResBean;
}
@PostMapping("/messageDataPdfReport")
public void getMessageDataPdfReport(@ModelAttribute PdfReqFormBean pdfReqBean, HttpServletResponse response)
throws ApiException, IOException {
response.setContentType("application/pdf");
LOGGER.info("type=[{}]", pdfReqBean.getType());
if (MessageDataTypeEnum.find(pdfReqBean.getType()).isCas()) {
IOUtils.write(
otherApiService.getCasPdf(copyProperties(pdfReqBean, PdfReqBean.class), getAagname(), getAgentId()),
response.getOutputStream());
} else if (MessageDataTypeEnum.find(pdfReqBean.getType()).isLsp()) {
IOUtils.write(
otherApiService.getLspPdf(copyProperties(pdfReqBean, PdfReqBean.class), getAagname(), getAgentId()),
response.getOutputStream());
} else if (StringUtils.equals(pdfReqBean.getType(), MessageDataDetailEnum.DailyInsuranceBenefits.name())) {
// 每日保險給付清單PDF
PdfTempldateReqBean pdfReq = pdfTemplateService.getDailyInsuranceBenefitsDataToPDFTemplate(
this.getTransagentcode(), this.getAagcode(), pdfReqBean.getFilename(),
DateUtil.transToRocDateChineseDay(pdfReqBean.getFilename()));
IOUtils.write(channelApiService.getPdfTemplate(pdfReq, getAagname(), getAgentId()),
response.getOutputStream());
}
response.flushBuffer();
}
@PostMapping("/newPolicySchedulePDF")
public void getNewPolicySchedulePDF(@ModelAttribute NewPolicySchedulePDFReqBean newPolicySchedulePDFReqBean,
HttpServletResponse response) throws ApiException, IOException {
response.setContentType("application/pdf");
IOUtils.write(iKashService.getNewPolicySchedulePDF(newPolicySchedulePDFReqBean, getAagname(), getAgentId()),
response.getOutputStream());
response.flushBuffer();
}
private String getStartDateString(Date date, int type, int value) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(type, value);
Date startDate = calendar.getTime();
DateFormat dfStart = new SimpleDateFormat("yyyy-MM-dd'T00:00:00.000'Z");
return dfStart.format(startDate);
}
private String getEndDateString(Date date) {
DateFormat dfEnd = new SimpleDateFormat("yyyy-MM-dd'T23:59:59.999'Z");
return dfEnd.format(date);
}
private String getStartSlashDateString(Date date, int type, int value) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(type, value);
Date startDate = calendar.getTime();
DateFormat dfStart = new SimpleDateFormat("yyyy/MM/dd");
return dfStart.format(startDate);
}
private String getEndSlashDateString(Date date) {
DateFormat dfEnd = new SimpleDateFormat("yyyy/MM/dd");
return dfEnd.format(date);
}
private CompletableFuture<List<MessageDataCountResBean>> getMessageDataCountResBeans() {
Date rightNow = new Date();
String startDateStr = getStartDateString(rightNow, Calendar.DAY_OF_YEAR, period);
String endDateStr = getEndDateString(rightNow);
String endRocDateStr = DateUtil.getCurrentRocDate();// yyy/mm/dd
String starRoctDateStr = DateUtil.addDay(endRocDateStr, period);// yyy/mm/dd
String agentId = this.getAgentId();
String aagcode = this.getAagcode();
String transagentcode = this.getTransagentcode();
CompletableFuture<List<MessageDataCountResBean>> messageDataCountResBeansFuture = CompletableFuture
.supplyAsync(() -> {
List<MessageDataCountResBean> messageDataCountResBeans = new ArrayList<MessageDataCountResBean>();
try {
MessageDataCountReqBean messageDataCountReqBean = new MessageDataCountReqBean();
messageDataCountReqBean.setAgentId(agentId);
messageDataCountReqBean.setStartDate(startDateStr);
messageDataCountReqBean.setEndDate(endDateStr);
messageDataCountResBeans = iKashService.getMessageDataCount(messageDataCountReqBean);
if (messageDataCountResBeans == null) {
messageDataCountResBeans = new ArrayList<MessageDataCountResBean>();
}
} catch (ApiException e) {
LOGGER.error("{'code':'" + e.getCode() + "','message':'" + e.getMessage() + "', 'description':'"
+ e.getDescription() + "'}", e);
}
return messageDataCountResBeans;
}, executor);
CompletableFuture<List<MessageDataCountResBean>> lspMessageDataCountResBeansFuture = CompletableFuture
.supplyAsync(() -> {
List<MessageDataCountResBean> lspMessageDataCountResBeans = new ArrayList<MessageDataCountResBean>();
try {
LspMessageDataCountReqBean lspMessageDataCountReqBean = new LspMessageDataCountReqBean();
lspMessageDataCountReqBean.setAgentCode(aagcode);
lspMessageDataCountReqBean.setStartDate(startDateStr);
lspMessageDataCountReqBean.setEndDate(endDateStr);
lspMessageDataCountResBeans = channelApiService
.getLspMessageDataCount(lspMessageDataCountReqBean);
} catch (ApiException e) {
LOGGER.error("{'code':'" + e.getCode() + "','message':'" + e.getMessage() + "', 'description':'"
+ e.getDescription() + "'}", e);
}
return lspMessageDataCountResBeans;
}, executor);
CompletableFuture<List<MessageDataCountResBean>> cmsMessageDataCountResBeansFuture = CompletableFuture
.supplyAsync(() -> {
List<MessageDataCountResBean> cmsMessageDataCountResBeans = new ArrayList<MessageDataCountResBean>();
try {
CmsMessageDataCountReqBean cmsMessageDataCountReqBean = new CmsMessageDataCountReqBean();
cmsMessageDataCountReqBean.setAgentCode(aagcode);
cmsMessageDataCountReqBean.setStartDate(startDateStr);
cmsMessageDataCountReqBean.setEndDate(endDateStr);
cmsMessageDataCountResBeans = channelApiService
.getCmsMessageDataCount(cmsMessageDataCountReqBean);
} catch (ApiException e) {
LOGGER.error("{'code':'" + e.getCode() + "','message':'" + e.getMessage() + "', 'description':'"
+ e.getDescription() + "'}", e);
}
return cmsMessageDataCountResBeans;
}, executor);
CompletableFuture<List<MessageDataCountResBean>> lspMessageDataCountCl207rResBeansFuture = CompletableFuture
.supplyAsync(() -> {
List<MessageDataCountResBean> lspMessageDataCountCl207rResBeans = new ArrayList<MessageDataCountResBean>();
try {
LspMessageDataCountReqBean lspMessageDataCountReqBean = new LspMessageDataCountReqBean();
lspMessageDataCountReqBean.setAgentCode(aagcode);
lspMessageDataCountReqBean.setStartDate(startDateStr);
lspMessageDataCountReqBean.setEndDate(endDateStr);
lspMessageDataCountCl207rResBeans = channelApiService
.getLspMessageDataCl207rCount(lspMessageDataCountReqBean);
} catch (ApiException e) {
LOGGER.error("{'code':'" + e.getCode() + "','message':'" + e.getMessage() + "', 'description':'"
+ e.getDescription() + "'}", e);
}
return lspMessageDataCountCl207rResBeans;
}, executor);
CompletableFuture<List<MessageDataCountResBean>> vlifeMessageDataCountResBeansFuture = CompletableFuture
.supplyAsync(() -> {
List<MessageDataCountResBean> vlifeMessageDataCountResBeans = new ArrayList<MessageDataCountResBean>();
try {
// 每日給付清單
DailyInsuranceBenefitsCountReqBean dailyInsuranceBenefitsCountReqBean = new DailyInsuranceBenefitsCountReqBean();
dailyInsuranceBenefitsCountReqBean.setAgentCode(transagentcode);
dailyInsuranceBenefitsCountReqBean.setStartDate(starRoctDateStr);
dailyInsuranceBenefitsCountReqBean.setEndDate(endRocDateStr);
MessageDataCountResBean dailyInsuranceBenefitsCount = channelApiService
.getDailyInsuranceBenefitsCount(dailyInsuranceBenefitsCountReqBean);
if (dailyInsuranceBenefitsCount != null && dailyInsuranceBenefitsCount.getCount() > 0) {
vlifeMessageDataCountResBeans.add(dailyInsuranceBenefitsCount);
}
} catch (ApiException e) {
LOGGER.error("{'code':'" + e.getCode() + "','message':'" + e.getMessage() + "', 'description':'"
+ e.getDescription() + "'}", e);
}
return vlifeMessageDataCountResBeans;
}, executor);
CompletableFuture<List<MessageDataCountResBean>> lspReminNoticeReturnResBeansFuture = CompletableFuture
.supplyAsync(() -> {
List<MessageDataCountResBean> lspReminNoticeReturnResBeans = new ArrayList<MessageDataCountResBean>();
try {
LspMessageDataCountReqBean lspMessageDataCountReqBean = new LspMessageDataCountReqBean();
lspMessageDataCountReqBean.setAgentCode(aagcode);
lspMessageDataCountReqBean.setStartDate(startDateStr);
lspMessageDataCountReqBean.setEndDate(endDateStr);
MessageDataCountResBean lspMessageDataCountResBean = channelApiService
.getLspReminNoticeReturnMessageDataCount(lspMessageDataCountReqBean);
if (lspMessageDataCountResBean != null && lspMessageDataCountResBean.getCount() > 0) {
lspReminNoticeReturnResBeans.add(lspMessageDataCountResBean);
}
} catch (ApiException e) {
LOGGER.error("{'code':'" + e.getCode() + "','message':'" + e.getMessage() + "', 'description':'"
+ e.getDescription() + "'}", e);
}
return lspReminNoticeReturnResBeans;
}, executor);
CompletableFuture<List<MessageDataCountResBean>> lspReinstatementNoticeResBeansFuture = CompletableFuture
.supplyAsync(() -> {
List<MessageDataCountResBean> lspReinstatementNoticeResBeans = new ArrayList<MessageDataCountResBean>();
try {
LspMessageDataCountReqBean lspMessageDataCountReqBean = new LspMessageDataCountReqBean();
lspMessageDataCountReqBean.setAgentCode(aagcode);
lspMessageDataCountReqBean.setStartDate(startDateStr);
lspMessageDataCountReqBean.setEndDate(endDateStr);
MessageDataCountResBean lspMessageDataCountResBean = channelApiService
.getLspReinstatementNoticeMessageDataCount(lspMessageDataCountReqBean);
if (lspMessageDataCountResBean != null && lspMessageDataCountResBean.getCount() > 0) {
lspReinstatementNoticeResBeans.add(lspMessageDataCountResBean);
}
} catch (ApiException e) {
LOGGER.error("{'code':'" + e.getCode() + "','message':'" + e.getMessage() + "', 'description':'"
+ e.getDescription() + "'}", e);
}
return lspReinstatementNoticeResBeans;
}, executor);
CompletableFuture<List<MessageDataCountResBean>> lisMessageDataCountResBeansFuture = CompletableFuture
.supplyAsync(() -> {
List<MessageDataCountResBean> lisMessageDataCountResBeans = new ArrayList<MessageDataCountResBean>();
try {
LisMessageDataCountReqBean lisMessageDataCountReqBean = new LisMessageDataCountReqBean();
lisMessageDataCountReqBean.setAgentCode(agentId);
// lisMessageDataCountReqBean.setAgentCode("J220460110");
lisMessageDataCountReqBean.setStartDate(startDateStr);
lisMessageDataCountReqBean.setEndDate(endDateStr);
LisMessageDataCountResBean lisData = lisApiService
.getLisMessageDataCount(lisMessageDataCountReqBean);
if (lisData != null)
lisMessageDataCountResBeans = lisData.getMessageDataCountResBeanlist();
} catch (ApiException e) {
LOGGER.error("{'code':'" + e.getCode() + "','message':'" + e.getMessage() + "', 'description':'"
+ e.getDescription() + "'}", e);
}
return lisMessageDataCountResBeans;
}, executor);
CompletableFuture<List<MessageDataCountResBean>> future = CompletableFuture
.allOf(messageDataCountResBeansFuture, lspMessageDataCountResBeansFuture,
cmsMessageDataCountResBeansFuture, lspMessageDataCountCl207rResBeansFuture,
vlifeMessageDataCountResBeansFuture, lspReminNoticeReturnResBeansFuture,
lspReinstatementNoticeResBeansFuture, lisMessageDataCountResBeansFuture)
.thenApply(x -> {
List<MessageDataCountResBean> messageDataCountResBeans = messageDataCountResBeansFuture.join();
List<MessageDataCountResBean> lspMessageDataCountResBeans = lspMessageDataCountResBeansFuture
.join();
List<MessageDataCountResBean> cmsMessageDataCountResBeans = cmsMessageDataCountResBeansFuture
.join();
List<MessageDataCountResBean> lspMessageDataCountCl207rResBeans = lspMessageDataCountCl207rResBeansFuture
.join();
List<MessageDataCountResBean> vlifeMessageDataCountResBeans = vlifeMessageDataCountResBeansFuture
.join();
List<MessageDataCountResBean> lspReminNoticeReturnResBeans = lspReminNoticeReturnResBeansFuture
.join();
List<MessageDataCountResBean> lspReinstatementNoticeResBeans = lspReinstatementNoticeResBeansFuture
.join();
List<MessageDataCountResBean> lisMessageDataCountResBeans = lisMessageDataCountResBeansFuture
.join();
mergeMessageDataCountList(messageDataCountResBeans, lspMessageDataCountResBeans);
mergeMessageDataCountList(messageDataCountResBeans, cmsMessageDataCountResBeans);
mergeMessageDataCountList(messageDataCountResBeans, lspMessageDataCountCl207rResBeans);
mergeMessageDataCountList(messageDataCountResBeans, vlifeMessageDataCountResBeans);
mergeMessageDataCountList(messageDataCountResBeans, lspReminNoticeReturnResBeans);
mergeMessageDataCountList(messageDataCountResBeans, lspReinstatementNoticeResBeans);
mergeMessageDataCountList(messageDataCountResBeans, lisMessageDataCountResBeans);
if (messageDataCountResBeans != null) {
Collections.sort(messageDataCountResBeans, new Comparator<MessageDataCountResBean>() {
public int compare(MessageDataCountResBean messageDataCountResBean1,
MessageDataCountResBean messageDataCountResBean2) {
String ordering1 = MessageDataOrderingEnum
.resolve(messageDataCountResBean1.getAp09Type1()) != null
? MessageDataOrderingEnum
.resolve(messageDataCountResBean1.getAp09Type1()).getOrdering()
: "99";
String ordering2 = MessageDataOrderingEnum
.resolve(messageDataCountResBean2.getAp09Type1()) != null
? MessageDataOrderingEnum
.resolve(messageDataCountResBean2.getAp09Type1()).getOrdering()
: "99";
return ordering1.compareTo(ordering2);
}
});
}
return messageDataCountResBeans;
});
return future;
}
/*
* private void getHistoryDataCountResBeans(Model model) { Date rightNow = new
* Date(); List<MessageDataCountResBean> casHistoryDataCountResBeans = new
* ArrayList<MessageDataCountResBean>(); List<MessageDataCountResBean>
* lspHistoryDataCountResBeans = new ArrayList<MessageDataCountResBean>();
* String casErrorMessage = ""; String historyStartDate =
* getStartDateString(rightNow, Calendar.DAY_OF_YEAR, historyPeriod); String
* historyEndDate = getEndDateString(rightNow); try { CasMessageDataCountReqBean
* casMessageDataCountReqBean = new CasMessageDataCountReqBean();
* casMessageDataCountReqBean.setAgentCode(this.getAagcode());
* casMessageDataCountReqBean.setStartDate(historyStartDate);
* casMessageDataCountReqBean.setEndDate(historyEndDate);
* casHistoryDataCountResBeans =
* channelApiService.getCasMessageDataCount(casMessageDataCountReqBean);
* if(casHistoryDataCountResBeans != null) {
* casHistoryDataCountResBeans.forEach(messageDataCountResBean ->
* messageDataCountResBean.setType(MessageDataTypeEnum.CAS.getType())); } else {
* casHistoryDataCountResBeans = new ArrayList<MessageDataCountResBean>(); } }
* catch (ApiException e) { casErrorMessage = e.getDescription();
* LOGGER.error("{'code':'" + e.getCode() + "','message':'" + e.getMessage() +
* "', 'description':'" + e.getDescription() + "'}", e); } try {
* LspMessageDataCountReqBean LspMessageDataCountReqBean = new
* LspMessageDataCountReqBean();
* LspMessageDataCountReqBean.setAgentCode(this.getAagcode());
* LspMessageDataCountReqBean.setStartDate(historyStartDate);
* LspMessageDataCountReqBean.setEndDate(historyEndDate);
* lspHistoryDataCountResBeans =
* channelApiService.getLspHistoryDataCount(LspMessageDataCountReqBean);
* if(lspHistoryDataCountResBeans != null) {
* lspHistoryDataCountResBeans.forEach(messageDataCountResBean ->
* messageDataCountResBean.setType(MessageDataTypeEnum.LSP.getType())); } }
* catch (ApiException e) { casErrorMessage = e.getDescription();
* LOGGER.error("{'code':'" + e.getCode() + "','message':'" + e.getMessage() +
* "', 'description':'" + e.getDescription() + "'}", e); }
* if(casHistoryDataCountResBeans != null && lspHistoryDataCountResBeans !=
* null) { casHistoryDataCountResBeans.addAll(lspHistoryDataCountResBeans); }
* model.addAttribute("casErrorMessage", casErrorMessage);
* model.addAttribute("casMessageData", casHistoryDataCountResBeans); }
*/
private CompletableFuture<List<NoticeDataCountResBean>> getNoticeDataCountResBeans(String startDateStr,
String endDateStr) {
String aagCode = this.getAagcode();
String agentID = this.getAgentId();
CompletableFuture<List<NoticeDataCountResBean>> noticeDataCountResBeansFuture = CompletableFuture
.supplyAsync(() -> {
List<NoticeDataCountResBean> noticeDataCountResBeans = new ArrayList<NoticeDataCountResBean>();
try {
NoticeDataCountReqBean noticeDataCountReqBean = new NoticeDataCountReqBean();
noticeDataCountReqBean.setAgentCode(aagCode);
noticeDataCountReqBean.setStartDate(startDateStr);
noticeDataCountReqBean.setEndDate(endDateStr);
noticeDataCountResBeans = iKashService.getNoticeDataCount(noticeDataCountReqBean);
if (noticeDataCountResBeans == null) {
noticeDataCountResBeans = new ArrayList<NoticeDataCountResBean>();
}
} catch (ApiException e) {
LOGGER.error("{'code':'" + e.getCode() + "','message':'" + e.getMessage() + "', 'description':'"
+ e.getDescription() + "'}", e);
}
return noticeDataCountResBeans;
}, executor);
CompletableFuture<List<NoticeDataCountResBean>> lspNoticeDataCountResBeansFuture = CompletableFuture
.supplyAsync(() -> {
List<NoticeDataCountResBean> lspNoticeDataCountResBeans = new ArrayList<NoticeDataCountResBean>();
try {
LspNoticeDataCountReqBean lspNoticeDataCountReqBean = new LspNoticeDataCountReqBean();
lspNoticeDataCountReqBean.setAgentCode(aagCode);
lspNoticeDataCountReqBean.setStartDate(startDateStr);
lspNoticeDataCountReqBean.setEndDate(endDateStr);
lspNoticeDataCountResBeans = channelApiService.getLspNoticeDataCount(lspNoticeDataCountReqBean);
} catch (ApiException e) {
LOGGER.error("{'code':'" + e.getCode() + "','message':'" + e.getMessage() + "', 'description':'"
+ e.getDescription() + "'}", e);
}
return lspNoticeDataCountResBeans;
}, executor);
CompletableFuture<List<NoticeDataCountResBean>> lisNoticeDataCountResBeansFuture = CompletableFuture
.supplyAsync(() -> {
List<NoticeDataCountResBean> lisNoticeDataCountResBeans = new ArrayList<NoticeDataCountResBean>();
try {
LisNoticeDataCountReqBean lisNoticeDataCountReqBean = new LisNoticeDataCountReqBean();
lisNoticeDataCountReqBean.setAgentCode(aagCode);
lisNoticeDataCountReqBean.setStartDate(startDateStr);
lisNoticeDataCountReqBean.setEndDate(endDateStr);
// 1120901179-00_Start
lisNoticeDataCountReqBean.setTranType("Y");
lisNoticeDataCountReqBean.setStatus("('P','N')");
// 1120901179-00_End
LisNoticeDataCountResBean list = lisApiService.getLisNoticeDataCount(lisNoticeDataCountReqBean);
lisNoticeDataCountResBeans = list.getNoticeDataCountResBean();
// 去掉count筆數為0的項目_Start
for (int i = lisNoticeDataCountResBeans.size() - 1; i >= 0; i--) {
NoticeDataCountResBean bean = lisNoticeDataCountResBeans.get(i);
if (bean.getCount() == 0) {
lisNoticeDataCountResBeans.remove(i);
}
}
// 去掉count筆數為0的項目_End
} catch (ApiException e) {
LOGGER.error("{'code':'" + e.getCode() + "','message':'" + e.getMessage() + "', 'description':'"
+ e.getDescription() + "'}", e);
}
return lisNoticeDataCountResBeans;
}, executor);
//114.07.22_1140702268-00理賠通知書_LIS系統串接來源調整(1104會議memo)
CompletableFuture<ClamNoticeDataCountResBean> clamNoteNoticeDataCountResBeanFuture = CompletableFuture
.supplyAsync(() -> {
ClamNoticeDataCountResBean clamNoticeDataCountResBean = new ClamNoticeDataCountResBean();
try {
ClamNoteReqBean clamNoteReqBean = new ClamNoteReqBean();
clamNoteReqBean.setAgentId(agentID);
clamNoticeDataCountResBean = clamNoteService.getClamNoticeDataCount(clamNoteReqBean);
// 去掉count筆數為0的項目_End
} catch (ApiException e) {
LOGGER.error("{'code':'" + e.getCode() + "','message':'" + e.getMessage() + "', 'description':'"
+ e.getDescription() + "'}", e);
}
return clamNoticeDataCountResBean;
}, executor);
CompletableFuture<List<NoticeDataCountResBean>> future = CompletableFuture.allOf(noticeDataCountResBeansFuture,
lspNoticeDataCountResBeansFuture, lisNoticeDataCountResBeansFuture, clamNoteNoticeDataCountResBeanFuture).thenApply(x -> {
List<NoticeDataCountResBean> noticeDataCountResBeans = noticeDataCountResBeansFuture.join();
List<NoticeDataCountResBean> lspNoticeDataCountResBeans = lspNoticeDataCountResBeansFuture.join();
List<NoticeDataCountResBean> lisNoticeDataCountResBeans = lisNoticeDataCountResBeansFuture.join();
ClamNoticeDataCountResBean clamNoticeDataCountResBean = clamNoteNoticeDataCountResBeanFuture.join();
mergeNoticeDataCountList(noticeDataCountResBeans, lspNoticeDataCountResBeans);
mergeNoticeDataCountList(noticeDataCountResBeans, lisNoticeDataCountResBeans);
boolean isEmptyClamData = true;
if (noticeDataCountResBeans != null) {
Collections.sort(noticeDataCountResBeans, new Comparator<NoticeDataCountResBean>() {
@Override
public int compare(NoticeDataCountResBean o1, NoticeDataCountResBean o2) {
String ordering1 = NoticeDataOrderingEnum.resolve(o1.getUwnmSource()) != null
? NoticeDataOrderingEnum.resolve(o1.getUwnmSource()).getOrdeing()
: "99";
String ordering2 = NoticeDataOrderingEnum.resolve(o2.getUwnmSource()) != null
? NoticeDataOrderingEnum.resolve(o2.getUwnmSource()).getOrdeing()
: "99";
return ordering1.compareTo(ordering2);
}
});
//114.07.22_1140702268-00理賠通知書_LIS系統串接來源調整(1104會議memo)
if (clamNoticeDataCountResBean != null && clamNoticeDataCountResBean.getCount() != 0) {
for (NoticeDataCountResBean noticeDataCountResBean : noticeDataCountResBeans) {
NoticeDataMessageDataType currentDataType = NoticeDataMessageDataType
.resolve(noticeDataCountResBean.getUwnmSource());
if (NoticeDataMessageDataType.CL == currentDataType) {
noticeDataCountResBean.setCount(noticeDataCountResBean.getCount() + clamNoticeDataCountResBean.getCount());
isEmptyClamData = false;
break;
}
}
}
}
//114.07.22_1140702268-00理賠通知書_LIS系統串接來源調整(1104會議memo)
if (noticeDataCountResBeans.isEmpty() || isEmptyClamData) {
NoticeDataCountResBean noticeDataCountResBean = new NoticeDataCountResBean();
noticeDataCountResBean.setCount(clamNoticeDataCountResBean.getCount());
noticeDataCountResBean.setUwnmSource(NoticeDataMessageDataType.CL.name());
noticeDataCountResBean.setUwnmSourceName(NoticeDataMessageDataType.CL.getDisplayName());
noticeDataCountResBeans.add(noticeDataCountResBean);
}
return noticeDataCountResBeans;
});
return future;
}
private CompletableFuture<List<NewPolicyScheduleCountResBean>> getNewPolicyScheduleCountResBeans() {
String aagCode = this.getAagcode();
CompletableFuture<List<NewPolicyScheduleCountResBean>> newPolicyScheduleCountResBeansFuture = CompletableFuture
.supplyAsync(() -> {
List<NewPolicyScheduleCountResBean> newPolicyScheduleCountResBeans = new ArrayList<NewPolicyScheduleCountResBean>();
try {
NewPolicyScheduleCountReqBean newPolicyScheduleCountReqBean = new NewPolicyScheduleCountReqBean();
newPolicyScheduleCountReqBean.setAgentCode(aagCode);
newPolicyScheduleCountResBeans = iKashService
.getNewPolicyScheduleCount(newPolicyScheduleCountReqBean);
if (newPolicyScheduleCountResBeans == null || newPolicyScheduleCountResBeans.size() == 0) {
if (newPolicyScheduleCountResBeans == null) {
newPolicyScheduleCountResBeans = new ArrayList<NewPolicyScheduleCountResBean>();
}
}
} catch (ApiException e) {
LOGGER.error("{'code':'" + e.getCode() + "','message':'" + e.getMessage() + "', 'description':'"
+ e.getDescription() + "'}", e);
}
return newPolicyScheduleCountResBeans;
}, executor);
CompletableFuture<NewPolicyScheduleCountResBean> newPolicyScheduleCountResBeanFuture = CompletableFuture
.supplyAsync(() -> {
NewPolicyScheduleCountResBean newPolicyScheduleCountResBean = null;
try {
// LIS 契約進度筆數
LisPolicyScheduleCountReqBean newPolicyScheduleCountReqBean = new LisPolicyScheduleCountReqBean();
newPolicyScheduleCountReqBean.setAgentCode(aagCode);
newPolicyScheduleCountReqBean.setType(PolicyScheduleTypeEnum.NB.getValue());
// newPolicyScheduleCountReqBean.setStartDate(changePolicyStartDateStr);
// newPolicyScheduleCountReqBean.setEndDate(endDateStr);
newPolicyScheduleCountResBean = lisApiService.getLisPolicyScheduleCount(
newPolicyScheduleCountReqBean, NewPolicyScheduleCountResBean.class);
} catch (ApiException e) {
LOGGER.error("{'code':'" + e.getCode() + "','message':'" + e.getMessage() + "', 'description':'"
+ e.getDescription() + "'}", e);
} catch (Exception e) {
LOGGER.error("", e);
}
return newPolicyScheduleCountResBean;
}, executor);
CompletableFuture<List<NewPolicyScheduleCountResBean>> future = CompletableFuture
.allOf(newPolicyScheduleCountResBeansFuture, newPolicyScheduleCountResBeanFuture).thenApply(x -> {
List<NewPolicyScheduleCountResBean> newPolicyScheduleCountResBeans = newPolicyScheduleCountResBeansFuture
.join();
NewPolicyScheduleCountResBean newPolicyScheduleCountResBean = newPolicyScheduleCountResBeanFuture
.join();
if (newPolicyScheduleCountResBean != null) {
if (newPolicyScheduleCountResBeans.size() > 0) {
newPolicyScheduleCountResBeans.get(0).setCount(newPolicyScheduleCountResBeans.get(0).getCount()
+ newPolicyScheduleCountResBean.getCount());
}
}
return newPolicyScheduleCountResBeans;
});
return future;
}
private CompletableFuture<List<ChangePolicyScheduleCountResBean>> getChangePolicyScheduleCountResBeans(
String changePolicyStartDateStr, String endDateStr) {
String aagcode = this.getAagcode();
CompletableFuture<List<ChangePolicyScheduleCountResBean>> changePolicyScheduleCountResBeansFuture = CompletableFuture
.supplyAsync(() -> {
List<ChangePolicyScheduleCountResBean> changePolicyScheduleCountResBeans = new ArrayList<ChangePolicyScheduleCountResBean>();
try {
ChangePolicyScheduleCountReqBean changePolicyScheduleCountReqBean = new ChangePolicyScheduleCountReqBean();
changePolicyScheduleCountReqBean.setAgentCode(aagcode);
changePolicyScheduleCountReqBean.setStartDate(changePolicyStartDateStr);
changePolicyScheduleCountReqBean.setEndDate(endDateStr);
changePolicyScheduleCountResBeans = iKashService
.getChangePolicyScheduleCount(changePolicyScheduleCountReqBean);
if (changePolicyScheduleCountResBeans == null) {
changePolicyScheduleCountResBeans = new ArrayList<>();
}
} catch (ApiException e) {
LOGGER.error("{'code':'" + e.getCode() + "','message':'" + e.getMessage() + "', 'description':'"
+ e.getDescription() + "'}", e);
}
return changePolicyScheduleCountResBeans;
}, executor);
CompletableFuture<ChangePolicyScheduleCountResBean> changePolicyScheduleCountResBeanFuture = CompletableFuture
.supplyAsync(() -> {
ChangePolicyScheduleCountResBean changePolicyScheduleCountResBean = null;
try {
// LIS 保全進度筆數
LisPolicyScheduleCountReqBean changePolicyScheduleCountReqBean = new LisPolicyScheduleCountReqBean();
changePolicyScheduleCountReqBean.setAgentCode(aagcode);
changePolicyScheduleCountReqBean.setType(PolicyScheduleTypeEnum.PC.getValue());
changePolicyScheduleCountReqBean.setStartDate(changePolicyStartDateStr);
changePolicyScheduleCountReqBean.setEndDate(endDateStr);
changePolicyScheduleCountResBean = lisApiService.getLisPolicyScheduleCount(
changePolicyScheduleCountReqBean, ChangePolicyScheduleCountResBean.class);
} catch (ApiException e) {
LOGGER.error("{'code':'" + e.getCode() + "','message':'" + e.getMessage() + "', 'description':'"
+ e.getDescription() + "'}", e);
} catch (Exception e) { // 1090900714-00
LOGGER.error("", e);
}
return changePolicyScheduleCountResBean;
}, executor);
CompletableFuture<List<ChangePolicyScheduleCountResBean>> future = CompletableFuture
.allOf(changePolicyScheduleCountResBeansFuture, changePolicyScheduleCountResBeanFuture).thenApply(x -> {
List<ChangePolicyScheduleCountResBean> changePolicyScheduleCountResBeans = changePolicyScheduleCountResBeansFuture
.join();
ChangePolicyScheduleCountResBean changePolicyScheduleCountResBean = changePolicyScheduleCountResBeanFuture
.join();
if (changePolicyScheduleCountResBean != null) {
if (changePolicyScheduleCountResBeans.size() > 0) {
changePolicyScheduleCountResBeans.get(0)
.setCount(changePolicyScheduleCountResBeans.get(0).getCount()
+ changePolicyScheduleCountResBean.getCount());
}
}
return changePolicyScheduleCountResBeans;
});
return future;
}
private CompletableFuture<List<ClaimScheduleCountResBean>> getClaimScheduleCountResBean() {
String aagcode = this.getAagcode();
CompletableFuture<List<ClaimScheduleCountResBean>> claimScheduleCountResBeansFuture = CompletableFuture
.supplyAsync(() -> {
List<ClaimScheduleCountResBean> claimScheduleCountResBeans = new ArrayList<ClaimScheduleCountResBean>();
try {
ClaimScheduleCountReqBean claimScheduleCountReqBean = new ClaimScheduleCountReqBean();
claimScheduleCountReqBean.setAgentCode(aagcode);
claimScheduleCountResBeans = iKashService.getClaimScheduleCount(claimScheduleCountReqBean);
if (claimScheduleCountResBeans == null) {
claimScheduleCountResBeans = new ArrayList<>();
}
} catch (ApiException e) {
LOGGER.error("{'code':'" + e.getCode() + "','message':'" + e.getMessage() + "', 'description':'"
+ e.getDescription() + "'}", e);
} catch (Exception e) { // 1090900714-00
LOGGER.error("", e);
}
return claimScheduleCountResBeans;
}, executor);
CompletableFuture<ClaimScheduleCountResBean> claimScheduleCountResBeanFuture = CompletableFuture
.supplyAsync(() -> {
ClaimScheduleCountResBean claimScheduleCountResBean = null;
try {
ClaimScheduleCountReqBean claimScheduleCountReqBean = new ClaimScheduleCountReqBean();
claimScheduleCountReqBean.setAgentCode(aagcode);
claimScheduleCountResBean = channelApiService.getClaimScheduleCount(claimScheduleCountReqBean);
} catch (ApiException e) {
LOGGER.error("{'code':'" + e.getCode() + "','message':'" + e.getMessage() + "', 'description':'"
+ e.getDescription() + "'}", e);
} catch (Exception e) { // 1090900714-00
LOGGER.error("", e);
}
return claimScheduleCountResBean;
}, executor);
CompletableFuture<ClaimScheduleCountResBean> claimScheduleCountResBean2Future = CompletableFuture
.supplyAsync(() -> {
ClaimScheduleCountResBean claimScheduleCountResBean2 = null;
try {
// LIS 理賠進度筆數
LisPolicyScheduleCountReqBean claimScheduleCountReqBean = new LisPolicyScheduleCountReqBean();
claimScheduleCountReqBean.setAgentCode(aagcode);
claimScheduleCountReqBean.setType(PolicyScheduleTypeEnum.CL.getValue());
// claimScheduleCountReqBean.setStartDate(changePolicyStartDateStr);
// claimScheduleCountReqBean.setEndDate(endDateStr);
claimScheduleCountResBean2 = lisApiService.getLisPolicyScheduleCount(claimScheduleCountReqBean,
ClaimScheduleCountResBean.class);
} catch (ApiException e) {
LOGGER.error("{'code':'" + e.getCode() + "','message':'" + e.getMessage() + "', 'description':'"
+ e.getDescription() + "'}", e);
} catch (Exception e) {
LOGGER.error("", e);
}
return claimScheduleCountResBean2;
}, executor);
CompletableFuture<List<ClaimScheduleCountResBean>> future = CompletableFuture
.allOf(claimScheduleCountResBeansFuture, claimScheduleCountResBeanFuture,
claimScheduleCountResBean2Future)
.thenApply(x -> {
List<ClaimScheduleCountResBean> claimScheduleCountResBeans = claimScheduleCountResBeansFuture
.join();
ClaimScheduleCountResBean claimScheduleCountResBean = claimScheduleCountResBeanFuture.join();
ClaimScheduleCountResBean claimScheduleCountResBean2 = claimScheduleCountResBean2Future.join();
if (claimScheduleCountResBean != null) {
claimScheduleCountResBeans.get(0).setCount(
claimScheduleCountResBeans.get(0).getCount() + claimScheduleCountResBean.getCount());
}
if (claimScheduleCountResBean2 != null) {
if (claimScheduleCountResBeans.size() > 0) {
claimScheduleCountResBeans.get(0).setCount(
claimScheduleCountResBeans.get(0).getCount() + claimScheduleCountResBean2.getCount());
}
}
return claimScheduleCountResBeans;
});
return future;
}
private void mergeMessageDataCountList(List<MessageDataCountResBean> messageDataCountResBeans1,
List<MessageDataCountResBean> messageDataCountResBeans2) {
if (messageDataCountResBeans2 == null || messageDataCountResBeans1 == null) {
return;
}
List<MessageDataCountResBean> temps = new ArrayList<MessageDataCountResBean>();
for (MessageDataCountResBean messageDataCountResBean2 : messageDataCountResBeans2) {
boolean isDupilicated = false;
for (MessageDataCountResBean messageDataCountResBean1 : messageDataCountResBeans1) {
if (messageDataCountResBean1.getAp09Type1().equals(messageDataCountResBean2.getAp09Type1())) {
messageDataCountResBean1
.setCount(messageDataCountResBean1.getCount() + messageDataCountResBean2.getCount());
isDupilicated = true;
}
}
if (!isDupilicated) {
temps.add(messageDataCountResBean2);
}
}
// 統一訊息通知大分類getAp09Type1之中文命名(follow IKashServiceImpl getMessageDataCount寫法)
changeMessageTypeName(temps);
messageDataCountResBeans1.addAll(temps);
}
private void mergeNoticeDataCountList(List<NoticeDataCountResBean> noticeDataCountResBeans1,
List<NoticeDataCountResBean> noticeDataCountResBeans2) {
if (noticeDataCountResBeans2 == null || noticeDataCountResBeans1 == null) {
return;
}
List<NoticeDataCountResBean> temps = new ArrayList<NoticeDataCountResBean>();
for (NoticeDataCountResBean noticeDataCountResBean2 : noticeDataCountResBeans2) {
boolean isDupilicated = false;
for (NoticeDataCountResBean noticeDataCountResBean1 : noticeDataCountResBeans1) {
if (noticeDataCountResBean1.getUwnmSource().equals(noticeDataCountResBean2.getUwnmSource())) {
noticeDataCountResBean1
.setCount(noticeDataCountResBean1.getCount() + noticeDataCountResBean2.getCount());
isDupilicated = true;
}
}
if (!isDupilicated) {
temps.add(noticeDataCountResBean2);
}
}
// 統一照會通知大分類getAp09Type1之中文命名(follow IKashServiceImpl getNoticeDataCount寫法)
changeNoticeTypeName(temps);
noticeDataCountResBeans1.addAll(temps);
}
private void updateNoticeDetailResBean(final List<? extends NoticeResBean> source, final AreaEnum area,
final String category) {
source.stream().forEach(res -> {
res.setArea(area.getCode());
res.setCategory(category);
});
updateReadStatus(source, area, category);
}
private void updateReadStatus(final List<? extends NoticeResBean> source, final AreaEnum area,
final String category) {
final List<NoticeRead> noticeReadList = noticeReadService.getNoticeReadList(this.getAagcode(), area.getCode(),
category);
// 依 hashCode 分組
final Map<Integer, List<NoticeRead>> noticeReadMap = noticeReadList.stream().collect(
Collectors.groupingBy(NoticeRead::getHashCode, HashMap::new, Collectors.toCollection(ArrayList::new)));
source.stream().forEach(res -> {
if (noticeReadMap.containsKey(res.getHashCode())) {
if (noticeReadMap.get(res.getHashCode()).size() == 1) {
res.setRead(true);
} else {
// 若有多筆資料則逐筆比對原始資料內容
for (NoticeRead noticeRead : noticeReadMap.get(res.getHashCode())) {
try {
NoticeResBean bean = null;
switch (area) {
case MESSAGE_DATA_AREA:
bean = JsonUtil.from(noticeRead.getMessage(), MessageDataDetailResBean.class);
break;
case NOTICE_DATA_AREA:
bean = JsonUtil.from(noticeRead.getMessage(), NoticeDataDetailResBean.class);
break;
case PROGRESS_DATA_AREA:
switch (ProgressNoticeEnum.valueOf(res.getCategory())) {
case NB:
bean = JsonUtil.from(noticeRead.getMessage(), NewPolicyScheduleDetailResBean.class);
break;
case PC:
bean = JsonUtil.from(noticeRead.getMessage(),
ChangePolicyScheduleDetailResBean.class);
break;
case CL:
bean = JsonUtil.from(noticeRead.getMessage(),
ChangePolicyScheduleDetailResBean.class);
break;
}
default:
break;
}
if (res.equals(bean)) {
res.setRead(true);
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
});
}
// 統一訊息通知大分類getAp09Type1之中文命名(follow IKashServiceImpl getMessageDataCount寫法)
protected void changeMessageTypeName(List<MessageDataCountResBean> messageDataCountResBeans) {
for (MessageDataCountResBean messageDataCountResBean : messageDataCountResBeans) {
NoticeDataMessageDataType noticeDataMessageDataType = NoticeDataMessageDataType
.resolve(messageDataCountResBean.getAp09Type1());
if (noticeDataMessageDataType != null && noticeDataMessageDataType.getDisplayName() != null) {
// LOGGER.info("old name-> {}, new name -> {}",
// messageDataCountResBean.getAp09Type1Name(),
// noticeDataMessageDataType.getDisplayName());
messageDataCountResBean.setAp09Type1Name(noticeDataMessageDataType.getDisplayName());
}
}
}
// 統一照會通知大分類getAp09Type1之中文命名(follow IKashServiceImpl
// getNoticeMessageDataCount寫法)
protected void changeNoticeTypeName(List<NoticeDataCountResBean> noticeDataCountResBeans) {
for (NoticeDataCountResBean noticeDataCountResBean : noticeDataCountResBeans) {
NoticeDataMessageDataType noticeDataMessageDataType = NoticeDataMessageDataType
.resolve(noticeDataCountResBean.getUwnmSource());
if (noticeDataMessageDataType != null && noticeDataMessageDataType.getDisplayName() != null) {
// LOGGER.info("old name-> {}, new name -> {}",
// noticeDataCountResBean.getUwnmSourceName(),
// noticeDataMessageDataType.getDisplayName());
noticeDataCountResBean.setUwnmSourceName(noticeDataMessageDataType.getDisplayName());
}
}
}
}
cGFja2FnZSBjb20udGFpd2FubGlmZS5hZ3cud2ViLmNvbnRyb2xsZXI7CgppbXBvcnQgamF2YS5pby5JT0V4Y2VwdGlvbjsKaW1wb3J0IGphdmEuaW8uVW5zdXBwb3J0ZWRFbmNvZGluZ0V4Y2VwdGlvbjsKaW1wb3J0IGphdmEubGFuZy5yZWZsZWN0Lkludm9jYXRpb25UYXJnZXRFeGNlcHRpb247CmltcG9ydCBqYXZhLm5ldC5VUkxFbmNvZGVyOwppbXBvcnQgamF2YS5uaW8uY2hhcnNldC5TdGFuZGFyZENoYXJzZXRzOwppbXBvcnQgamF2YS50ZXh0LkRhdGVGb3JtYXQ7CmltcG9ydCBqYXZhLnRleHQuU2ltcGxlRGF0ZUZvcm1hdDsKaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7CmltcG9ydCBqYXZhLnV0aWwuQ2FsZW5kYXI7CmltcG9ydCBqYXZhLnV0aWwuQ29sbGVjdGlvbnM7CmltcG9ydCBqYXZhLnV0aWwuQ29tcGFyYXRvcjsKaW1wb3J0IGphdmEudXRpbC5EYXRlOwppbXBvcnQgamF2YS51dGlsLkhhc2hNYXA7CmltcG9ydCBqYXZhLnV0aWwuTGlzdDsKaW1wb3J0IGphdmEudXRpbC5NYXA7CmltcG9ydCBqYXZhLnV0aWwuVVVJRDsKaW1wb3J0IGphdmEudXRpbC5jb25jdXJyZW50LkNvbXBsZXRhYmxlRnV0dXJlOwppbXBvcnQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0aW9uRXhjZXB0aW9uOwppbXBvcnQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3I7CmltcG9ydCBqYXZhLnV0aWwuc3RyZWFtLkNvbGxlY3RvcnM7CgppbXBvcnQgb3JnLmFwYWNoZS5jb21tb25zLmJlYW51dGlscy5CZWFuVXRpbHM7CmltcG9ydCBvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuQ29sbGVjdGlvblV0aWxzOwppbXBvcnQgb3JnLmFwYWNoZS5jb21tb25zLmlvLklPVXRpbHM7CmltcG9ydCBvcmcuYXBhY2hlLmNvbW1vbnMubGFuZzMuU3RyaW5nVXRpbHM7CmltcG9ydCBvcmcuamFzeXB0LmVuY3J5cHRpb24uU3RyaW5nRW5jcnlwdG9yOwppbXBvcnQgb3JnLm93YXNwLmVzYXBpLkVTQVBJOwoKaW1wb3J0IG9yZy5zcHJpbmdmcmFtZXdvcmsuYmVhbnMuZmFjdG9yeS5hbm5vdGF0aW9uLkF1dG93aXJlZDsKaW1wb3J0IG9yZy5zcHJpbmdmcmFtZXdvcmsuYmVhbnMuZmFjdG9yeS5hbm5vdGF0aW9uLlF1YWxpZmllcjsKaW1wb3J0IG9yZy5zcHJpbmdmcmFtZXdvcmsuYmVhbnMuZmFjdG9yeS5hbm5vdGF0aW9uLlZhbHVlOwppbXBvcnQgb3JnLnNwcmluZ2ZyYW1ld29yay5zdGVyZW90eXBlLkNvbnRyb2xsZXI7CmltcG9ydCBvcmcuc3ByaW5nZnJhbWV3b3JrLnVpLk1vZGVsOwppbXBvcnQgb3JnLnNwcmluZ2ZyYW1ld29yay53ZWIuYmluZC5hbm5vdGF0aW9uLkdldE1hcHBpbmc7CmltcG9ydCBvcmcuc3ByaW5nZnJhbWV3b3JrLndlYi5iaW5kLmFubm90YXRpb24uTW9kZWxBdHRyaWJ1dGU7CmltcG9ydCBvcmcuc3ByaW5nZnJhbWV3b3JrLndlYi5iaW5kLmFubm90YXRpb24uUG9zdE1hcHBpbmc7CmltcG9ydCBvcmcuc3ByaW5nZnJhbWV3b3JrLndlYi5iaW5kLmFubm90YXRpb24uUmVzcG9uc2VCb2R5OwoKaW1wb3J0IGNvbS5mYXN0ZXJ4bWwuamFja3Nvbi5jb3JlLkpzb25Qcm9jZXNzaW5nRXhjZXB0aW9uOwoKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy5qdGRzLmRvbWFpbi5lbnRpdHkuTm90aWNlUmVhZDsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy5qdGRzLmRvbWFpbi5zZXJ2aWNlLk5vdGljZVJlYWRTZXJ2aWNlOwppbXBvcnQgY29tLnRhaXdhbmxpZmUuYWd3LndlYi5iZWFuLkdldE1lc3NhZ2VEYXRhRGV0YWlsRm9ybUJlYW47CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2ViLmJlYW4uR2V0Tm90aWNlRGF0YURldGFpbEZvcm1CZWFuOwppbXBvcnQgY29tLnRhaXdhbmxpZmUuYWd3LndlYi5iZWFuLlBkZlJlcUZvcm1CZWFuOwppbXBvcnQgY29tLnRhaXdhbmxpZmUuYWd3LndlYi5iZWFuLlNob3dNZXNzYWdlRGF0YURldGFpbEZvcm1CZWFuOwppbXBvcnQgY29tLnRhaXdhbmxpZmUuYWd3LndlYi5iZWFuLlNob3dOb3RpY2VEYXRhRGV0YWlsRm9ybUJlYW47CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2ViLmJlYW4uU2hvd1Byb2dyZXNzRGF0YURldGFpbEZvcm1CZWFuOwppbXBvcnQgY29tLnRhaXdhbmxpZmUuYWd3LndlYi5lbnVtcy5BcmVhRW51bTsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWIuZW51bXMuTWVzc2FnZURhdGFEZXRhaWxFbnVtOwppbXBvcnQgY29tLnRhaXdhbmxpZmUuYWd3LndlYi5lbnVtcy5NZXNzYWdlRGF0YU9yZGVyaW5nRW51bTsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWIuZW51bXMuTWVzc2FnZURhdGFUeXBlRW51bTsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWIuZW51bXMuTm90aWNlRGF0YU9yZGVyaW5nRW51bTsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWIuZW51bXMuUG9saWN5U2NoZWR1bGVUeXBlRW51bTsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWIuZW51bXMuUHJvZ3Jlc3NOb3RpY2VFbnVtOwppbXBvcnQgY29tLnRhaXdhbmxpZmUuYWd3LndlYi51dGlsLkRhdGVVdGlsOwppbXBvcnQgY29tLnRhaXdhbmxpZmUuYWd3LndlYnNlcnZpY2UuZW51bXMuTm90aWNlRGF0YU1lc3NhZ2VEYXRhVHlwZTsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWJzZXJ2aWNlLmV4Y2VwdGlvbi5BcGlFeGNlcHRpb247CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0LkNoYW5uZWxBcGlTZXJ2aWNlOwppbXBvcnQgY29tLnRhaXdhbmxpZmUuYWd3LndlYnNlcnZpY2UucmVzdC5DbGFtTm90ZVNlcnZpY2U7CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0LkNtc0FwaVNlcnZpY2U7CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0LklLYXNoU2VydmljZTsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWJzZXJ2aWNlLnJlc3QuTGlzQXBpU2VydmljZTsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWJzZXJ2aWNlLnJlc3QuTmJyQXBpU2VydmljZTsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWJzZXJ2aWNlLnJlc3QuT3RoZXJBcGlTZXJ2aWNlOwppbXBvcnQgY29tLnRhaXdhbmxpZmUuYWd3LndlYnNlcnZpY2UucmVzdC5QREZUZW1wbGF0ZVNlcnZpY2U7CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0Lm1vZGVsLmNoYW5uZWxBcGkucmVxLkNtc01lc3NhZ2VEYXRhQ291bnRSZXFCZWFuOwppbXBvcnQgY29tLnRhaXdhbmxpZmUuYWd3LndlYnNlcnZpY2UucmVzdC5tb2RlbC5jaGFubmVsQXBpLnJlcS5DbXNNZXNzYWdlRGF0YURldGFpbFJlcUJlYW47CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0Lm1vZGVsLmNoYW5uZWxBcGkucmVxLkRhaWx5SW5zdXJhbmNlQmVuZWZpdHNDb3VudFJlcUJlYW47CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0Lm1vZGVsLmNoYW5uZWxBcGkucmVxLkRhaWx5SW5zdXJhbmNlQmVuZWZpdHNEYXRhRGV0YWlsUmVxQmVhbjsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWJzZXJ2aWNlLnJlc3QubW9kZWwuY2hhbm5lbEFwaS5yZXEuTHNwTWVzc2FnZURhdGFDb3VudFJlcUJlYW47CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0Lm1vZGVsLmNoYW5uZWxBcGkucmVxLkxzcE1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbjsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWJzZXJ2aWNlLnJlc3QubW9kZWwuY2hhbm5lbEFwaS5yZXEuTHNwTm90aWNlRGF0YUNvdW50UmVxQmVhbjsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWJzZXJ2aWNlLnJlc3QubW9kZWwuY2hhbm5lbEFwaS5yZXEuTHNwTm90aWNlRGF0YURldGFpbFJlcUJlYW47CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0Lm1vZGVsLmNsYWltTm90ZS5yZXEuQ2xhbU5vdGVQZGZSZXFCZWFuOwppbXBvcnQgY29tLnRhaXdhbmxpZmUuYWd3LndlYnNlcnZpY2UucmVzdC5tb2RlbC5jbGFpbU5vdGUucmVxLkNsYW1Ob3RlUmVxQmVhbjsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWJzZXJ2aWNlLnJlc3QubW9kZWwuY2xhaW1Ob3RlLnJlcy5DbGFtTm90aWNlRGF0YUNvdW50UmVzQmVhbjsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWJzZXJ2aWNlLnJlc3QubW9kZWwuY2xhaW1Ob3RlLnJlcy5DbGFtTm90aWNlRGF0YUxpc3RSZXNCZWFuOwppbXBvcnQgY29tLnRhaXdhbmxpZmUuYWd3LndlYnNlcnZpY2UucmVzdC5tb2RlbC5pS2FzaC5yZXEuQ2hhbmdlUG9saWN5U2NoZWR1bGVDb3VudFJlcUJlYW47CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0Lm1vZGVsLmlLYXNoLnJlcS5DaGFuZ2VQb2xpY3lTY2hlZHVsZURldGFpbFJlcUJlYW47CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0Lm1vZGVsLmlLYXNoLnJlcS5DbGFpbVNjaGVkdWxlQ291bnRSZXFCZWFuOwppbXBvcnQgY29tLnRhaXdhbmxpZmUuYWd3LndlYnNlcnZpY2UucmVzdC5tb2RlbC5pS2FzaC5yZXEuQ2xhaW1TY2hlZHVsZURldGFpbFJlcUJlYW47CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0Lm1vZGVsLmlLYXNoLnJlcS5NZXNzYWdlRGF0YUNvdW50UmVxQmVhbjsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWJzZXJ2aWNlLnJlc3QubW9kZWwuaUthc2gucmVxLk1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbjsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWJzZXJ2aWNlLnJlc3QubW9kZWwuaUthc2gucmVxLk5ld1BvbGljeVNjaGVkdWxlQ291bnRSZXFCZWFuOwppbXBvcnQgY29tLnRhaXdhbmxpZmUuYWd3LndlYnNlcnZpY2UucmVzdC5tb2RlbC5pS2FzaC5yZXEuTmV3UG9saWN5U2NoZWR1bGVEZXRhaWxSZXFCZWFuOwppbXBvcnQgY29tLnRhaXdhbmxpZmUuYWd3LndlYnNlcnZpY2UucmVzdC5tb2RlbC5pS2FzaC5yZXEuTmV3UG9saWN5U2NoZWR1bGVQREZSZXFCZWFuOwppbXBvcnQgY29tLnRhaXdhbmxpZmUuYWd3LndlYnNlcnZpY2UucmVzdC5tb2RlbC5pS2FzaC5yZXEuTm90aWNlRGF0YUNvdW50UmVxQmVhbjsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWJzZXJ2aWNlLnJlc3QubW9kZWwuaUthc2gucmVxLk5vdGljZURhdGFEZXRhaWxSZXFCZWFuOwppbXBvcnQgY29tLnRhaXdhbmxpZmUuYWd3LndlYnNlcnZpY2UucmVzdC5tb2RlbC5pS2FzaC5yZXMuQ2hhbmdlUG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW47CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0Lm1vZGVsLmlLYXNoLnJlcy5DaGFuZ2VQb2xpY3lTY2hlZHVsZURldGFpbFJlc0JlYW47CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0Lm1vZGVsLmlLYXNoLnJlcy5DbGFpbVNjaGVkdWxlQ291bnRSZXNCZWFuOwppbXBvcnQgY29tLnRhaXdhbmxpZmUuYWd3LndlYnNlcnZpY2UucmVzdC5tb2RlbC5pS2FzaC5yZXMuQ2xhaW1TY2hlZHVsZURldGFpbFJlc0JlYW47CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0Lm1vZGVsLmlLYXNoLnJlcy5MaXNOb3RpY2VEZXRhaWxSZXNCZWFuOwppbXBvcnQgY29tLnRhaXdhbmxpZmUuYWd3LndlYnNlcnZpY2UucmVzdC5tb2RlbC5pS2FzaC5yZXMuTWVzc2FnZURhdGFDb3VudFJlc0JlYW47CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0Lm1vZGVsLmlLYXNoLnJlcy5NZXNzYWdlRGF0YURldGFpbFJlc0JlYW47CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0Lm1vZGVsLmlLYXNoLnJlcy5OZXdQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbjsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWJzZXJ2aWNlLnJlc3QubW9kZWwuaUthc2gucmVzLk5ld1BvbGljeVNjaGVkdWxlRGV0YWlsUmVzQmVhbjsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWJzZXJ2aWNlLnJlc3QubW9kZWwuaUthc2gucmVzLk5vdGljZUJlYW47CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0Lm1vZGVsLmlLYXNoLnJlcy5Ob3RpY2VEYXRhQ291bnRSZXNCZWFuOwppbXBvcnQgY29tLnRhaXdhbmxpZmUuYWd3LndlYnNlcnZpY2UucmVzdC5tb2RlbC5pS2FzaC5yZXMuTm90aWNlRGF0YURldGFpbFJlc0JlYW47CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0Lm1vZGVsLmlLYXNoLnJlcy5Ob3RpY2VEYXRhUGRmUmVwb3J0UmVxQmVhbjsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWJzZXJ2aWNlLnJlc3QubW9kZWwuaUthc2gucmVzLk5vdGljZVJlc0JlYW47CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0Lm1vZGVsLmxpcy5yZXEuTGlzRXhwb3J0UGRmUmVxQmVhbjsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWJzZXJ2aWNlLnJlc3QubW9kZWwubGlzLnJlcS5MaXNFeHBvcnRQZGZSZXFCZWFuLk9wZXJhdG9ySW5mbzsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWJzZXJ2aWNlLnJlc3QubW9kZWwubGlzLnJlcS5MaXNNZXNzYWdlRGF0YUNvdW50UmVxQmVhbjsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWJzZXJ2aWNlLnJlc3QubW9kZWwubGlzLnJlcS5MaXNNZXNzYWdlRGF0YURldGFpbFJlcUJlYW47CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0Lm1vZGVsLmxpcy5yZXEuTGlzTm90aWNlRGF0YUNvdW50UmVxQmVhbjsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWJzZXJ2aWNlLnJlc3QubW9kZWwubGlzLnJlcS5MaXNOb3RpY2VEYXRhRGV0YWlsUmVxQmVhbjsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWJzZXJ2aWNlLnJlc3QubW9kZWwubGlzLnJlcS5MaXNQb2xpY3lTY2hlZHVsZUNvdW50UmVxQmVhbjsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWJzZXJ2aWNlLnJlc3QubW9kZWwubGlzLnJlcy5MaXNDaGFuZ2VQb2xpY3lTY2hlZHVsZVJlc0JlYW47CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0Lm1vZGVsLmxpcy5yZXMuTGlzQ2xhaW1TY2hlZHVsZURldGFpbFJlc0JlYW47CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0Lm1vZGVsLmxpcy5yZXMuTGlzRXhwb3J0UGRmUmVzQmVhbjsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWJzZXJ2aWNlLnJlc3QubW9kZWwubGlzLnJlcy5MaXNNZXNzYWdlRGF0YUNvdW50UmVzQmVhbjsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWJzZXJ2aWNlLnJlc3QubW9kZWwubGlzLnJlcy5MaXNNZXNzYWdlRGF0YURldGFpbFJlc0JlYW47CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0Lm1vZGVsLmxpcy5yZXMuTGlzTmV3UG9saWN5U2NoZWR1bGVEZXRhaWxSZXNCZWFuOwppbXBvcnQgY29tLnRhaXdhbmxpZmUuYWd3LndlYnNlcnZpY2UucmVzdC5tb2RlbC5saXMucmVzLkxpc05vdGljZURhdGFDb3VudFJlc0JlYW47CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0Lm1vZGVsLmxpcy5yZXMuTGlzTm90aWNlRGF0YURldGFpbFJlc0JlYW47CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0Lm1vZGVsLm5ici5yZXEuTmJyRGF0YVJlcUJlYW47CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0Lm1vZGVsLm90aGVyQXBpLnJlcS5FTm90aWNlRGF0YVJlcG9ydFJlcUJlYW47CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0Lm1vZGVsLm90aGVyQXBpLnJlcS5FTm90aWNlRGF0YVN0YXR1c1JlcUJlYW47CmltcG9ydCBjb20udGFpd2FubGlmZS5hZ3cud2Vic2VydmljZS5yZXN0Lm1vZGVsLm90aGVyQXBpLnJlcS5QZGZSZXFCZWFuOwppbXBvcnQgY29tLnRhaXdhbmxpZmUuYWd3LndlYnNlcnZpY2UucmVzdC5tb2RlbC5vdGhlckFwaS5yZXEuUGRmVGVtcGxkYXRlUmVxQmVhbjsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWJzZXJ2aWNlLnJlc3QubW9kZWwub3RoZXJBcGkucmVzLkVOb3RpY2VEYXRhU3RhdHVzUmVzQmVhbjsKaW1wb3J0IGNvbS50YWl3YW5saWZlLmFndy53ZWJzZXJ2aWNlLnV0aWwuSnNvblV0aWw7CgppbXBvcnQgaW8uanNvbndlYnRva2VuLkNsYWltczsKCmltcG9ydCBqYWthcnRhLnNlcnZsZXQuaHR0cC5IdHRwU2VydmxldFJlcXVlc3Q7CmltcG9ydCBqYWthcnRhLnNlcnZsZXQuaHR0cC5IdHRwU2VydmxldFJlc3BvbnNlOwppbXBvcnQgamFrYXJ0YS5zZXJ2bGV0Lmh0dHAuSHR0cFNlc3Npb247CgpAQ29udHJvbGxlcgpwdWJsaWMgY2xhc3MgTm90aWNlRGF0YUNvbnRyb2xsZXIgZXh0ZW5kcyBCYXNlQ29udHJvbGxlciB7CgoJQEF1dG93aXJlZAoJcHJpdmF0ZSBJS2FzaFNlcnZpY2UgaUthc2hTZXJ2aWNlOwoJCglAQXV0b3dpcmVkCglwcml2YXRlIE5ickFwaVNlcnZpY2UgbmJyQXBpU2VydmljZTsKCglAQXV0b3dpcmVkCglwcml2YXRlIENoYW5uZWxBcGlTZXJ2aWNlIGNoYW5uZWxBcGlTZXJ2aWNlOwoKCUBBdXRvd2lyZWQKCXByaXZhdGUgTGlzQXBpU2VydmljZSBsaXNBcGlTZXJ2aWNlOwoKCUBBdXRvd2lyZWQKCUNtc0FwaVNlcnZpY2UgY21zQXBpU2VydmljZTsKCglAQXV0b3dpcmVkCglwcml2YXRlIE90aGVyQXBpU2VydmljZSBvdGhlckFwaVNlcnZpY2U7CgoJQEF1dG93aXJlZAoJcHJpdmF0ZSBQREZUZW1wbGF0ZVNlcnZpY2UgcGRmVGVtcGxhdGVTZXJ2aWNlOwoJCglAQXV0b3dpcmVkCglwcml2YXRlIENsYW1Ob3RlU2VydmljZSBjbGFtTm90ZVNlcnZpY2U7CgoJLy8g6YWN5ZCI5ris6Kmm6ZyA5rGC6ZyA6KaB5pW05pel5YW25Y2A6ZaT77yM5Zug5q2k6YeN5paw6Kit6KiIIDAwMzI1OAoJQFZhbHVlKCIke25vdGljZS5wZXJpb2R9IikKCXByaXZhdGUgaW50IHBlcmlvZDsKCglAVmFsdWUoIiR7Y2hhbmdlLnBvbGljeS5zY2hlZHVsZS5oaXN0b3J5UGVyaW9kfSIpCglwcml2YXRlIGludCBjaGFuZ2VQb2xpY3lTY2hlZHVsZVBlcmlvZDsKCglAVmFsdWUoIiR7bm90aWNlLmhpc3RvcnlQZXJpb2R9IikKCXByaXZhdGUgaW50IGhpc3RvcnlQZXJpb2Q7CgoJQFZhbHVlKCIke2Fndy5pcH0iKQoJcHJpdmF0ZSBTdHJpbmcgaXA7CgoJQFZhbHVlKCIke2VOb3RpY2VEYXRhUmVwb3J0LnVybH0iKQoJcHJpdmF0ZSBTdHJpbmcgZU5vdGljZURhdGFSZXBvcnRVcmw7CgoJQFZhbHVlKCIke2xpcy5leHBvcnRQZGYuU0lEfSIpCglwcml2YXRlIFN0cmluZyBleHBvcnRQZGZTSUQ7CgoJQFZhbHVlKCIke2xpcy5leHBvcnRQZGYuVUlEfSIpCglwcml2YXRlIFN0cmluZyBleHBvcnRQZGZVSUQ7CgovLwlwcml2YXRlIGludCBwZXJpb2QgPSAtMzA7Ci8vCgoJQEF1dG93aXJlZAoJcHJpdmF0ZSBOb3RpY2VSZWFkU2VydmljZSBub3RpY2VSZWFkU2VydmljZTsKCglAQXV0b3dpcmVkCglwcml2YXRlIEV4ZWN1dG9yIGV4ZWN1dG9yOwoKLy8JcHJpdmF0ZSBpbnQgaGlzdG9yeVBlcmlvZCA9IC02MDsKCglAR2V0TWFwcGluZyh7ICIvIiB9KQoJcHVibGljIFN0cmluZyBpbmRleChIdHRwU2VydmxldFJlcXVlc3QgcmVxdWVzdCwgSHR0cFNlcnZsZXRSZXNwb25zZSByZXNwb25zZSkgewoJCS8qCgkJaW50IG9mZmxpbmUgPSA5OwoJCWlmIChyZXF1ZXN0LmdldFNlc3Npb24oKS5nZXRBdHRyaWJ1dGUoImRpc2NsYWltZXJMb2ciKSA9PSBudWxsKSB7CgkJCS8vIOmBv+WFjeavj+S4gOasoeWbnuWIsOmmlumggeeahHJlcXVlc3Tpg73mnIPkuIDnm7RjYWxsIGFwaeS+hueiuuiqjeaYr+WQpuewveWxrOmBjuWQjOaEj+abuAoJCQlvZmZsaW5lID0gaGFzTG9naW5FZCh0aGlzLmdldEFhZ2NvZGUoKSk7CgkJfQoJCWlmIChvZmZsaW5lICE9IDIpIHsKCQkJcmV0dXJuICJyZWRpcmVjdDovZGlzY2xhaW1lcmNvbnRyb2xsZXI/b2ZmbGluZT0iICsgU3RyaW5nLnZhbHVlT2Yob2ZmbGluZSk7Ly8g6JKQ6ZuG5ZCM5oSP6Kqq5piO5pu45Yqf6IO9IHJpY2t5IHVwZGF0ZSAxMDgxMjI0CgkJfSBlbHNlIHsKCQkJcmV0dXJuICJyZWRpcmVjdDovbm90aWNlRGF0YUNvdW50IjsKCQl9CgkJKi8KCgkJU3RyaW5nIGF1ZCA9IHJlcXVlc3QuZ2V0QXR0cmlidXRlKENsYWltcy5BVURJRU5DRSkgIT0gbnVsbCA/IChTdHJpbmcpIHJlcXVlc3QuZ2V0QXR0cmlidXRlKENsYWltcy5BVURJRU5DRSkKCQkJCTogbnVsbDsKCQlib29sZWFuIG5vbmVtZW51ID0gcmVxdWVzdC5nZXRTZXNzaW9uKCkuZ2V0QXR0cmlidXRlKCJub25lbWVudSIpICE9IG51bGwKCQkJCT8gKGJvb2xlYW4pIHJlcXVlc3QuZ2V0U2Vzc2lvbigpLmdldEF0dHJpYnV0ZSgibm9uZW1lbnUiKQoJCQkJOiBmYWxzZTsKCQlpZiAoInRhcG9saWN5Ii5lcXVhbHMoYXVkKSB8fCBub25lbWVudSkgewoJCQlyZXF1ZXN0LmdldFNlc3Npb24oKS5zZXRBdHRyaWJ1dGUoIm5vbmVtZW51IiwgdHJ1ZSk7CgkJCXJldHVybiAicmVkaXJlY3Q6L3RhcG9saWN5IjsKCQl9CgkJcmV0dXJuICJyZWRpcmVjdDovbm90aWNlRGF0YUNvdW50IjsKCX0KCglAR2V0TWFwcGluZyh7ICIvbm90aWNlRGF0YUNvdW50IiB9KQoJcHVibGljIFN0cmluZyBzaG93RGF0YUNvdW50KE1vZGVsIG1vZGVsLCBIdHRwU2VydmxldFJlcXVlc3QgcmVxdWVzdCwgSHR0cFNlcnZsZXRSZXNwb25zZSByZXNwb25zZSwKCQkJSHR0cFNlc3Npb24gc2Vzc2lvbikgdGhyb3dzIEludGVycnVwdGVkRXhjZXB0aW9uLCBFeGVjdXRpb25FeGNlcHRpb24gewoJCWxvbmcgdCA9IFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCUxPR0dFUi5pbmZvKCJzaG93RGF0YUNvdW50IC9ub3RpY2VEYXRhQ291bnQgc3RhcnQhIik7CgkJTE9HR0VSLmluZm8oIiMjIyBbe31dW3t9XSAjIyMgaXNOZXcxOiB7fSIsIGdldENsaWVudElwKHJlcXVlc3QpLCBnZXRTZXNzaW9uSWQoc2Vzc2lvbiksCgkJCQlyZXF1ZXN0LmdldFNlc3Npb24oZmFsc2UpLmlzTmV3KCkpOwoJCUxPR0dFUi5pbmZvKCIjIyMgW3t9XVt7fV0gIyMjIEVudGVyaW5nIEFHVyBIb21lIGFnZW50SWQ6IHt9IGFnY29kZToge30gYWdlbnRjb2RlOiB7fSBhZ25hbWU6IHt9IiwKCQkJCWdldENsaWVudElwKHJlcXVlc3QpLCBnZXRTZXNzaW9uSWQoc2Vzc2lvbiksIGdldEFnZW50SWQoKSwgZ2V0QWFnY29kZSgpLCBnZXRBYWdjb2RlKCksIGdldEFhZ25hbWUoKSk7CgkJaWYgKHNlc3Npb24uZ2V0QXR0cmlidXRlKCJtZW51TGlzdCIpID09IG51bGwpIHsKCQkJdHJ5IHsKCQkJCUVTQVBJLmh0dHBVdGlsaXRpZXMoKS5zZXRDdXJyZW50SFRUUChyZXF1ZXN0LCByZXNwb25zZSk7CgkJCQlFU0FQSS5jdXJyZW50UmVxdWVzdCgpLmdldFNlc3Npb24oKS5zZXRBdHRyaWJ1dGUoIm1lbnVMaXN0IiwgZ2V0TWVudUxpc3QobW9kZWwpKTsKCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCUxPR0dFUi5lcnJvcigie1wibWVudUxpc3RcIjoiICsgZS50b1N0cmluZygpICsgIn0iLCBlKTsKCQkJfQoJCX0KLy8JCURhdGUgcmlnaHROb3cgPSBuZXcgRGF0ZSgpOwovLwkJU3RyaW5nIHN0YXJ0RGF0ZVN0ciA9IGdldFN0YXJ0RGF0ZVN0cmluZyhyaWdodE5vdywgQ2FsZW5kYXIuREFZX09GX1lFQVIsIHBlcmlvZCk7Ci8vCQlTdHJpbmcgZW5kRGF0ZVN0ciA9IGdldEVuZERhdGVTdHJpbmcocmlnaHROb3cpOwovLwkJU3RyaW5nIGNoYW5nZVBvbGljeVN0YXJ0RGF0ZVN0ciA9IGdldFN0YXJ0RGF0ZVN0cmluZyhyaWdodE5vdywgQ2FsZW5kYXIuREFZX09GX1lFQVIsIGNoYW5nZVBvbGljeVNjaGVkdWxlUGVyaW9kKTsKCQkvLyDlkbzlj6vlkIRhcGnlj5blvpfos4fmlpkKCgkJLy8gQ29tcGxldGFibGVGdXR1cmU8TGlzdDxNZXNzYWdlRGF0YUNvdW50UmVzQmVhbj4+CgkJLy8gbWVzc2FnZURhdGFDb3VudFJlc0JlYW5zRnV0dXJlID0gZ2V0TWVzc2FnZURhdGFDb3VudFJlc0JlYW5zKCk7CgkJLy8gQ29tcGxldGFibGVGdXR1cmU8TGlzdDxOb3RpY2VEYXRhQ291bnRSZXNCZWFuPj4gbm90aWNlRGF0YUNvdW50UmVzQmVhbnNGdXR1cmUKCQkvLyA9IGdldE5vdGljZURhdGFDb3VudFJlc0JlYW5zKHN0YXJ0RGF0ZVN0ciwgZW5kRGF0ZVN0cik7CgkJLy8gQ29tcGxldGFibGVGdXR1cmU8TGlzdDxOZXdQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbj4+CgkJLy8gbmV3UG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW5zRnV0dXJlID0gZ2V0TmV3UG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW5zKCk7CgkJLy8gQ29tcGxldGFibGVGdXR1cmU8TGlzdDxDaGFuZ2VQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbj4+CgkJLy8gY2hhbmdlUG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW5zRnV0dXJlID0KCQkvLyBnZXRDaGFuZ2VQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbnMoY2hhbmdlUG9saWN5U3RhcnREYXRlU3RyLCBlbmREYXRlU3RyKTsKCQkvLyBDb21wbGV0YWJsZUZ1dHVyZTxMaXN0PENsYWltU2NoZWR1bGVDb3VudFJlc0JlYW4+PgoJCS8vIGNsYWltU2NoZWR1bGVDb3VudFJlc0JlYW5zRnV0dXJlID0gZ2V0Q2xhaW1TY2hlZHVsZUNvdW50UmVzQmVhbigpOwoKCQkvLyBMaXN0PE1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuPiBtZXNzYWdlRGF0YUNvdW50UmVzQmVhbnMgPQoJCS8vIG1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuc0Z1dHVyZS5nZXQoKTsKCQkvLyBMaXN0PE5vdGljZURhdGFDb3VudFJlc0JlYW4+IG5vdGljZURhdGFDb3VudFJlc0JlYW5zID0KCQkvLyBub3RpY2VEYXRhQ291bnRSZXNCZWFuc0Z1dHVyZS5nZXQoKTsKCQkvLyBMaXN0PE5ld1BvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFuPiBuZXdQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbnMgPQoJCS8vIG5ld1BvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFuc0Z1dHVyZS5nZXQoKTsKCQkvLyBMaXN0PENoYW5nZVBvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFuPiBjaGFuZ2VQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbnMgPQoJCS8vIGNoYW5nZVBvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFuc0Z1dHVyZS5nZXQoKTsKCQkvLyBMaXN0PENsYWltU2NoZWR1bGVDb3VudFJlc0JlYW4+IGNsYWltU2NoZWR1bGVDb3VudFJlc0JlYW5zID0KCQkvLyBjbGFpbVNjaGVkdWxlQ291bnRSZXNCZWFuc0Z1dHVyZS5nZXQoKTsKCgkJLy8gbW9kZWwuYWRkQXR0cmlidXRlKCJtZXNzYWdlRGF0YSIsIG1lc3NhZ2VEYXRhQ291bnRSZXNCZWFucyk7CgkJLy8gbW9kZWwuYWRkQXR0cmlidXRlKCJub3RpY2VEYXRhIiwgbm90aWNlRGF0YUNvdW50UmVzQmVhbnMpOwoJCS8vIG1vZGVsLmFkZEF0dHJpYnV0ZSgibmV3UG9saWN5U2NoZWR1bGVEYXRhIiwgbmV3UG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW5zKTsKCQkvLyBtb2RlbC5hZGRBdHRyaWJ1dGUoImNoYW5nZVBvbGljeVNjaGVkdWxlRGF0YSIsCgkJLy8gY2hhbmdlUG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW5zKTsKCQkvLyBtb2RlbC5hZGRBdHRyaWJ1dGUoImNsYWltU2NoZWR1bGVDb3VudERhdGEiLCBjbGFpbVNjaGVkdWxlQ291bnRSZXNCZWFucyk7CgovLwkJZ2V0SGlzdG9yeURhdGFDb3VudFJlc0JlYW5zKG1vZGVsKTsKCQltb2RlbC5hZGRBdHRyaWJ1dGUoInNob3dNZXNzYWdlRGF0YURldGFpbEZvcm0iLCBuZXcgU2hvd01lc3NhZ2VEYXRhRGV0YWlsRm9ybUJlYW4oKSk7CgkJbW9kZWwuYWRkQXR0cmlidXRlKCJzaG93Tm90aWNlRGF0YURldGFpbEZvcm0iLCBuZXcgU2hvd05vdGljZURhdGFEZXRhaWxGb3JtQmVhbigpKTsKCQlMT0dHRVIuaW5mbygic2hvd0RhdGFDb3VudCAvbm90aWNlRGF0YUNvdW50IGVuZCEg57i95YWx6Iqx6LK75pmC6ZaTOnt9IiwgKGRvdWJsZSkgKFN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpIC0gdCkgLyAxMDAwZCk7CgkJcmV0dXJuICJTYWxlc0luZm8iOwoJfQoKCUBQb3N0TWFwcGluZygiL2dldE1lc3NhZ2VEYXRhIikKCUBSZXNwb25zZUJvZHkKCXB1YmxpYyBMaXN0PE5vdGljZUJlYW4+IGdldE1lc3NhZ2VEYXRhKCkgdGhyb3dzIEludGVycnVwdGVkRXhjZXB0aW9uLCBFeGVjdXRpb25FeGNlcHRpb24gewoJCXJldHVybiBnZXRNZXNzYWdlRGF0YUNvdW50UmVzQmVhbnMoKS5nZXQoKS5zdHJlYW0oKS5tYXAoZSAtPiB7CgkJCU5vdGljZUJlYW4gYiA9IG5ldyBOb3RpY2VCZWFuKCk7CgkJCWIuc2V0VHlwZShlLmdldEFwMDlUeXBlMSgpKTsKCQkJYi5zZXROYW1lKGUuZ2V0QXAwOVR5cGUxTmFtZSgpKTsKCQkJYi5zZXRDb3VudChlLmdldENvdW50KCkpOwoJCQlyZXR1cm4gYjsKCQl9KS5jb2xsZWN0KENvbGxlY3RvcnMudG9MaXN0KCkpOwoJfQoKCUBQb3N0TWFwcGluZygiL2dldE5vdGljZURhdGEiKQoJQFJlc3BvbnNlQm9keQoJcHVibGljIExpc3Q8Tm90aWNlQmVhbj4gZ2V0Tm90aWNlRGF0YSgpIHRocm93cyBJbnRlcnJ1cHRlZEV4Y2VwdGlvbiwgRXhlY3V0aW9uRXhjZXB0aW9uIHsKCQlEYXRlIHJpZ2h0Tm93ID0gbmV3IERhdGUoKTsKCQlTdHJpbmcgc3RhcnREYXRlU3RyID0gZ2V0U3RhcnREYXRlU3RyaW5nKHJpZ2h0Tm93LCBDYWxlbmRhci5EQVlfT0ZfWUVBUiwgcGVyaW9kKTsKCQlTdHJpbmcgZW5kRGF0ZVN0ciA9IGdldEVuZERhdGVTdHJpbmcocmlnaHROb3cpOwoJCXJldHVybiBnZXROb3RpY2VEYXRhQ291bnRSZXNCZWFucyhzdGFydERhdGVTdHIsIGVuZERhdGVTdHIpLmdldCgpLnN0cmVhbSgpLm1hcChlIC0+IHsKCQkJTm90aWNlQmVhbiBiID0gbmV3IE5vdGljZUJlYW4oKTsKCQkJYi5zZXRUeXBlKGUuZ2V0VXdubVNvdXJjZSgpKTsKCQkJYi5zZXROYW1lKGUuZ2V0VXdubVNvdXJjZU5hbWUoKSk7CgkJCWIuc2V0Q291bnQoZS5nZXRDb3VudCgpKTsKCQkJcmV0dXJuIGI7CgkJfSkuY29sbGVjdChDb2xsZWN0b3JzLnRvTGlzdCgpKTsKCX0KCglAUG9zdE1hcHBpbmcoIi9nZXRTY2hlZHVsZURhdGEiKQoJQFJlc3BvbnNlQm9keQoJcHVibGljIExpc3Q8Tm90aWNlQmVhbj4gZ2V0U2NoZWR1bGVEYXRhKCkgdGhyb3dzIEludGVycnVwdGVkRXhjZXB0aW9uLCBFeGVjdXRpb25FeGNlcHRpb24gewoJCURhdGUgcmlnaHROb3cgPSBuZXcgRGF0ZSgpOwoJCVN0cmluZyBlbmREYXRlU3RyID0gZ2V0RW5kRGF0ZVN0cmluZyhyaWdodE5vdyk7CgkJU3RyaW5nIGNoYW5nZVBvbGljeVN0YXJ0RGF0ZVN0ciA9IGdldFN0YXJ0RGF0ZVN0cmluZyhyaWdodE5vdywgQ2FsZW5kYXIuREFZX09GX1lFQVIsCgkJCQljaGFuZ2VQb2xpY3lTY2hlZHVsZVBlcmlvZCk7CgkJQ29tcGxldGFibGVGdXR1cmU8TGlzdDxOZXdQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbj4+IG5ld1BvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFuc0Z1dHVyZSA9IGdldE5ld1BvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFucygpOwoJCUNvbXBsZXRhYmxlRnV0dXJlPExpc3Q8Q2hhbmdlUG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW4+PiBjaGFuZ2VQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbnNGdXR1cmUgPSBnZXRDaGFuZ2VQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbnMoCgkJCQljaGFuZ2VQb2xpY3lTdGFydERhdGVTdHIsIGVuZERhdGVTdHIpOwoJCUNvbXBsZXRhYmxlRnV0dXJlPExpc3Q8Q2xhaW1TY2hlZHVsZUNvdW50UmVzQmVhbj4+IGNsYWltU2NoZWR1bGVDb3VudFJlc0JlYW5zRnV0dXJlID0gZ2V0Q2xhaW1TY2hlZHVsZUNvdW50UmVzQmVhbigpOwoJCUxpc3Q8Tm90aWNlQmVhbj4gbHMgPSBuZXcgQXJyYXlMaXN0PD4oKTsKCQlscy5hZGRBbGwobmV3UG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW5zRnV0dXJlLmdldCgpLnN0cmVhbSgpLmZpbHRlcihlIC0+IGUuZ2V0Q291bnQoKSAhPSAwKS5tYXAoZSAtPiB7CgkJCU5vdGljZUJlYW4gYiA9IG5ldyBOb3RpY2VCZWFuKCk7CgkJCWIuc2V0TmFtZSgi5paw5aWR57SEIik7CgkJCWIuc2V0SHJlZigiL25ld1BvbGljeVNjaGVkdWxlRGF0YURldGFpbCIpOwoJCQliLnNldENvdW50KGUuZ2V0Q291bnQoKSk7CgkJCXJldHVybiBiOwoJCX0pLmNvbGxlY3QoQ29sbGVjdG9ycy50b0xpc3QoKSkpOwoJCWxzLmFkZEFsbChjaGFuZ2VQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbnNGdXR1cmUuZ2V0KCkuc3RyZWFtKCkuZmlsdGVyKGUgLT4gZS5nZXRDb3VudCgpICE9IDApLm1hcChlIC0+IHsKCQkJTm90aWNlQmVhbiBiID0gbmV3IE5vdGljZUJlYW4oKTsKCQkJYi5zZXROYW1lKCLkv53lhagiKTsKCQkJYi5zZXRIcmVmKCIvY2hhbmdlUG9saWN5U2NoZWR1bGVEZXRhaWwiKTsKCQkJYi5zZXRDb3VudChlLmdldENvdW50KCkpOwoJCQlyZXR1cm4gYjsKCQl9KS5jb2xsZWN0KENvbGxlY3RvcnMudG9MaXN0KCkpKTsKCQlscy5hZGRBbGwoY2xhaW1TY2hlZHVsZUNvdW50UmVzQmVhbnNGdXR1cmUuZ2V0KCkuc3RyZWFtKCkuZmlsdGVyKGUgLT4gZS5nZXRDb3VudCgpICE9IDApLm1hcChlIC0+IHsKCQkJTm90aWNlQmVhbiBiID0gbmV3IE5vdGljZUJlYW4oKTsKCQkJYi5zZXROYW1lKCLnkIbos6AiKTsKCQkJYi5zZXRIcmVmKCIvY2xhaW1TY2hlZHVsZURldGFpbCIpOwoJCQliLnNldENvdW50KGUuZ2V0Q291bnQoKSk7CgkJCXJldHVybiBiOwoJCX0pLmNvbGxlY3QoQ29sbGVjdG9ycy50b0xpc3QoKSkpOwoKCQlyZXR1cm4gbHM7Cgl9CgoJQFBvc3RNYXBwaW5nKCIvbm90aWNlRGF0YURldGFpbCIpCglwdWJsaWMgU3RyaW5nIHNob3dOb3RpY2VEYXRhRGV0YWlsKE1vZGVsIG1vZGVsLCBATW9kZWxBdHRyaWJ1dGUgU2hvd05vdGljZURhdGFEZXRhaWxGb3JtQmVhbiBmb3JtQmVhbikKCQkJdGhyb3dzIEpzb25Qcm9jZXNzaW5nRXhjZXB0aW9uLCBVbnN1cHBvcnRlZEVuY29kaW5nRXhjZXB0aW9uIHsKCQltb2RlbC5hZGRBdHRyaWJ1dGUoImZvcm1CZWFuIiwgY29weVByb3BlcnRpZXMoZm9ybUJlYW4sIFNob3dOb3RpY2VEYXRhRGV0YWlsRm9ybUJlYW4uY2xhc3MpKTsKCQltb2RlbC5hZGRBdHRyaWJ1dGUoInR5cGUiLCBNZXNzYWdlRGF0YVR5cGVFbnVtLkxTUC5nZXRUeXBlKCkpOwoJCW1vZGVsLmFkZEF0dHJpYnV0ZSgiYXJlYSIsIEFyZWFFbnVtLnJlc29sdmUoIjIiKSk7CgkJbW9kZWwuYWRkQXR0cmlidXRlKCJwZGZSZXFCZWFuIiwgbmV3IFBkZlJlcUZvcm1CZWFuKCkpOwoJCW1vZGVsLmFkZEF0dHJpYnV0ZSgibm90aWNlRGF0YVBkZlJlcG9ydFJlcUJlYW4iLCBuZXcgTm90aWNlRGF0YVBkZlJlcG9ydFJlcUJlYW4oKSk7CgoJCWlmICgiTkIiLmVxdWFsc0lnbm9yZUNhc2UoZm9ybUJlYW4uZ2V0VXdubVNvdXJjZSgpKSkgewoJCQltb2RlbC5hZGRBdHRyaWJ1dGUoImVOb3RpY2VEYXRhUmVwb3J0UmVxQmVhbiIsIG5ldyBFTm90aWNlRGF0YVJlcG9ydFJlcUJlYW4oKSk7CgkJCXJldHVybiAiTm90aWNlRGF0YURldGFpbE5CIjsKCQl9CgoJCXJldHVybiAiTm90aWNlRGF0YURldGFpbCI7Cgl9CgoJQFBvc3RNYXBwaW5nKCIvZ2V0Tm90aWNlRGF0YURldGFpbCIpCglAUmVzcG9uc2VCb2R5CglwdWJsaWMgTGlzdDxOb3RpY2VEYXRhRGV0YWlsUmVzQmVhbj4gZ2V0Tm90aWNlRGF0YURldGFpbChNb2RlbCBtb2RlbCwKCQkJQE1vZGVsQXR0cmlidXRlIEdldE5vdGljZURhdGFEZXRhaWxGb3JtQmVhbiBnZXROb3RpY2VEYXRhRGV0YWlsRm9ybUJlYW4pIHRocm93cyBKc29uUHJvY2Vzc2luZ0V4Y2VwdGlvbiB7CgkJRGF0ZSByaWdodE5vZXcgPSBuZXcgRGF0ZSgpOwoKCQlTdHJpbmcgc3NvVG9rZW5TdHIgPSAoU3RyaW5nKSByZXF1ZXN0LmdldFNlc3Npb24oKS5nZXRBdHRyaWJ1dGUoIlNzb1Rva2VuIik7CgkJLy8gU3lzdGVtLm91dC5wcmludGxuKCJzc29Ub2tlblN0ciA9PT09PT09PT09PT09PSIgKyBzc29Ub2tlblN0cik7CgkJTm90aWNlRGF0YURldGFpbFJlcUJlYW4gbm90aWNlRGF0YURldGFpbFJlcUJlYW4gPSBuZXcgTm90aWNlRGF0YURldGFpbFJlcUJlYW4oKTsKCQlub3RpY2VEYXRhRGV0YWlsUmVxQmVhbi5zZXRBZ2VudENvZGUodGhpcy5nZXRBYWdjb2RlKCkpOwoJCW5vdGljZURhdGFEZXRhaWxSZXFCZWFuLnNldFV3bm1Tb3VyY2UoZ2V0Tm90aWNlRGF0YURldGFpbEZvcm1CZWFuLmdldFV3bm1Tb3VyY2UoKSk7CgkJbm90aWNlRGF0YURldGFpbFJlcUJlYW4uc2V0U3RhcnREYXRlKGdldFN0YXJ0RGF0ZVN0cmluZyhyaWdodE5vZXcsIENhbGVuZGFyLkRBWV9PRl9ZRUFSLCBwZXJpb2QpKTsKCQlub3RpY2VEYXRhRGV0YWlsUmVxQmVhbi5zZXRFbmREYXRlKGdldEVuZERhdGVTdHJpbmcocmlnaHROb2V3KSk7CgkJTGlzTm90aWNlRGF0YURldGFpbFJlcUJlYW4gbGlzTm90aWNlRGF0YURldGFpbFJlcUJlYW4gPSBuZXcgTGlzTm90aWNlRGF0YURldGFpbFJlcUJlYW4oKTsKCQlsaXNOb3RpY2VEYXRhRGV0YWlsUmVxQmVhbi5zZXRBZ2VudENvZGUodGhpcy5nZXRBYWdjb2RlKCkpOwoJCWxpc05vdGljZURhdGFEZXRhaWxSZXFCZWFuLnNldEFnZW50TmFtZSgiIik7CgkJbGlzTm90aWNlRGF0YURldGFpbFJlcUJlYW4uc2V0VHJhblR5cGUoIlkiKTsvLyBhZ2VudHBvcnRhbOWPquaJvumbu+WtkOeFp+acgwoJCWxpc05vdGljZURhdGFEZXRhaWxSZXFCZWFuLnNldFByaW50SW5kKCIiKTsKCQlsaXNOb3RpY2VEYXRhRGV0YWlsUmVxQmVhbi5zZXRVd25tU291cmNlKGdldE5vdGljZURhdGFEZXRhaWxGb3JtQmVhbi5nZXRVd25tU291cmNlKCkpOwoJCWxpc05vdGljZURhdGFEZXRhaWxSZXFCZWFuLnNldE5vdGljZVN0YXJ0RGF0ZShnZXRTdGFydFNsYXNoRGF0ZVN0cmluZyhyaWdodE5vZXcsIENhbGVuZGFyLkRBWV9PRl9ZRUFSLCBwZXJpb2QpKTsKLy8JCWxpc05vdGljZURhdGFEZXRhaWxSZXFCZWFuLnNldE5vdGljZVN0YXJ0RGF0ZShnZXRTdGFydFNsYXNoRGF0ZVN0cmluZyhyaWdodE5vZXcsIENhbGVuZGFyLkRBWV9PRl9ZRUFSLCAtOTk5OTkpKTsvL1RPRE8gVEVTVAoJCWxpc05vdGljZURhdGFEZXRhaWxSZXFCZWFuLnNldE5vdGljZUVuZERhdGUoZ2V0RW5kU2xhc2hEYXRlU3RyaW5nKHJpZ2h0Tm9ldykpOwoJCS8vIDExMjA5MDExNzktMDBfU3RhcnQKCQlsaXNOb3RpY2VEYXRhRGV0YWlsUmVxQmVhbi5zZXRTdGF0dXMoIignUCcsJ04nKSIpOwoJCS8vIDExMjA5MDExNzktMDBfRW5kCgkJTGlzdDxOb3RpY2VEYXRhRGV0YWlsUmVzQmVhbj4gbm90aWNlRGF0YURldGFpbFJlc0JlYW5zID0gbmV3IEFycmF5TGlzdDxOb3RpY2VEYXRhRGV0YWlsUmVzQmVhbj4oKTsKCQlMaXN0PE5vdGljZURhdGFEZXRhaWxSZXNCZWFuPiBsc3BOb3RpY2VEYXRhRGV0YWlsUmVzQmVhbnMgPSBuZXcgQXJyYXlMaXN0PE5vdGljZURhdGFEZXRhaWxSZXNCZWFuPigpOwoJCUxpc3Q8Tm90aWNlRGF0YURldGFpbFJlc0JlYW4+IGxpc05vdGljZURhdGFEZXRhaWxSZXNCZWFucyA9IG5ldyBBcnJheUxpc3Q8Tm90aWNlRGF0YURldGFpbFJlc0JlYW4+KCk7CgkJTGlzdDxOb3RpY2VEYXRhRGV0YWlsUmVzQmVhbj4gY2xhbU5vdGljZURhdGFEZXRhaWxSZXNCZWFucyA9IG5ldyBBcnJheUxpc3Q8PigpOwoJCXRyeSB7CgkJCW5vdGljZURhdGFEZXRhaWxSZXNCZWFucyA9IGlLYXNoU2VydmljZS5nZXROb3RpY2VEYXRhRGV0YWlsKG5vdGljZURhdGFEZXRhaWxSZXFCZWFuKTsKCQkJaWYgKG5vdGljZURhdGFEZXRhaWxSZXNCZWFucyA9PSBudWxsKSB7CgkJCQlub3RpY2VEYXRhRGV0YWlsUmVxQmVhbiA9IG5ldyBOb3RpY2VEYXRhRGV0YWlsUmVxQmVhbigpOwoJCQl9Ci8vCQkJZWxzZSB7Ci8vCQkJCWlmICgiTkIiLmVxdWFsc0lnbm9yZUNhc2UoZ2V0Tm90aWNlRGF0YURldGFpbEZvcm1CZWFuLmdldFV3bm1Tb3VyY2UoKSkpIHsKLy8JCQkJCWZvciAoaW50IGkgPSAwOyBpIDwgbm90aWNlRGF0YURldGFpbFJlc0JlYW5zLnNpemUoKTsgaSsrKSB7Ci8vCQkJCQkJU3RyaW5nIHV3bm1Ob1N0ciA9IG5vdGljZURhdGFEZXRhaWxSZXNCZWFucy5nZXQoaSkuZ2V0VXdubU5vKCk7Ci8vCQkJCQkJU3RyaW5nIHJlcG9ydEZvcm1TdHIgPSBub3RpY2VEYXRhRGV0YWlsUmVzQmVhbnMuZ2V0KGkpLmdldFJlcG9ydEZvcm0oKTsKLy8JCQkJCQkvLyBTeXN0ZW0ub3V0LnByaW50bG4oInJlcG9ydEZvcm1TdHIgPT0gIiArIGkgKyAiPT09PT09PT09PT09IiArIHJlcG9ydEZvcm1TdHIpOwovLwkJCQkJCVN0cmluZyB0eXBlQ29kZU5hbWVTdHIgPSBudWxsOwovLwkJCQkJCXR5cGVDb2RlTmFtZVN0ciA9ICItIjsJCQkJCQkKLy8JCQkJCQlTdHJpbmcgaXNVbmNvbXBsZXRlID0gIiI7Ci8vCQkJCQkJLy8gVEVTVCDkvb/nlKgKLy8JCQkJCQkvL2lzVW5jb21wbGV0ZSA9ICJZIjsJCQkJCQkKLy8JCQkJCQkKLy8JCQkJCQlFTm90aWNlRGF0YVN0YXR1c1JlcUJlYW4gZU5vdGljZURhdGFTdGF0dXNSZXFCZWFuID0gbmV3IEVOb3RpY2VEYXRhU3RhdHVzUmVxQmVhbigpOwovLwkJCQkJCWVOb3RpY2VEYXRhU3RhdHVzUmVxQmVhbi5zZXRVd25tbm8odXdubU5vU3RyKTsKLy8JCQkJCQllTm90aWNlRGF0YVN0YXR1c1JlcUJlYW4uc2V0VHlwZShyZXBvcnRGb3JtU3RyKTsJCQkJCQkKLy8JCQkJCQlFTm90aWNlRGF0YVN0YXR1c1Jlc0JlYW4gZU5vdGljZURhdGFTdGF0dXNSZXNCZWFuID0gbmV3IEVOb3RpY2VEYXRhU3RhdHVzUmVzQmVhbigpOwkKLy8JCQkJCQlpZiAoIjEwMDEiLmVxdWFsc0lnbm9yZUNhc2UocmVwb3J0Rm9ybVN0cikgfHwgIjEwMDIiLmVxdWFsc0lnbm9yZUNhc2UocmVwb3J0Rm9ybVN0cikKLy8JCQkJCQkJCXx8ICIxMDEyIi5lcXVhbHNJZ25vcmVDYXNlKHJlcG9ydEZvcm1TdHIpIHx8ICI0MDAxIi5lcXVhbHNJZ25vcmVDYXNlKHJlcG9ydEZvcm1TdHIpCi8vCQkJCQkJCQl8fCAiNTAwMSIuZXF1YWxzSWdub3JlQ2FzZShyZXBvcnRGb3JtU3RyKSB8fCAiNjAwMSIuZXF1YWxzSWdub3JlQ2FzZShyZXBvcnRGb3JtU3RyKSkgewovLwkJCQkJCQkvLyBjYWxsIOmbu+eFpyBBUEkg5Y+WIGlzdW5jb21wbGV0ZQovLwkJCQkJCQllTm90aWNlRGF0YVN0YXR1c1Jlc0JlYW4gPSBvdGhlckFwaVNlcnZpY2UuZ2V0RU5vdGljZURhdGFSZXBvcnQoZU5vdGljZURhdGFTdGF0dXNSZXFCZWFuKTsKLy8JCQkJCQkJaWYgKGVOb3RpY2VEYXRhU3RhdHVzUmVzQmVhbiAhPSBudWxsKSB7Ci8vCQkJCQkJCQlpc1VuY29tcGxldGUgPSBlTm90aWNlRGF0YVN0YXR1c1Jlc0JlYW4uZ2V0SXN1bmNvbXBsZXRlKCk7Ci8vCQkJCQkJCX0KLy8JCQkJCQkJLy9TeXN0ZW0ub3V0LnByaW50bG4oImlzVW5jb21wbGV0ZSA9PSAiICsgaSArICI9PT09PT09PT09PT0iICsgaXNVbmNvbXBsZXRlKTsKLy8JCQkJCQl9Ci8vCQkJCQkJLy8gVEVTVCDkvb/nlKggIAovLwkJCQkJCS8vcmVwb3J0Rm9ybVN0ciA9ICIxMDAyIjsKLy8JCQkJCQlpZiAoIjEwMDEiLmVxdWFsc0lnbm9yZUNhc2UocmVwb3J0Rm9ybVN0cikgfHwgIjEwMDIiLmVxdWFsc0lnbm9yZUNhc2UocmVwb3J0Rm9ybVN0cikKLy8JCQkJCQkJCXx8ICIxMDEyIi5lcXVhbHNJZ25vcmVDYXNlKHJlcG9ydEZvcm1TdHIpKSB7Ci8vCQkJCQkJCS8vIGNhbGwg6Zu754WnQVBJIHJldHVybiA9PT5pc3VuY29tcGxldGUg54K6WSDmiY3pnIDlkYjnj77ku6Xlj4rnlKLnlJ9MSU5LCi8vCQkJCQkJCWlmICgiWSIuZXF1YWxzSWdub3JlQ2FzZShpc1VuY29tcGxldGUudHJpbSgpKSkgewovLwkJCQkJCQkJdHlwZUNvZGVOYW1lU3RyID0gIue3muS4iuWbnuimhiI7Ci8vCQkJCQkJCQlub3RpY2VEYXRhRGV0YWlsUmVzQmVhbnMuZ2V0KGkpLnNldFNzb1Rva2VuKHNzb1Rva2VuU3RyKTsKLy8JCQkJCQkJfQovLwkJCQkJCX0gZWxzZSBpZiAoIjQwMDEiLmVxdWFsc0lnbm9yZUNhc2UocmVwb3J0Rm9ybVN0cikgfHwgIjUwMDEiLmVxdWFsc0lnbm9yZUNhc2UocmVwb3J0Rm9ybVN0cikKLy8JCQkJCQkJCXx8ICI2MDAxIi5lcXVhbHNJZ25vcmVDYXNlKHJlcG9ydEZvcm1TdHIpKSB7Ci8vCQkJCQkJCS8vIGNhbGwg6Zu754WnQVBJIHJldHVybiA9PT5pc3VuY29tcGxldGUg54K6WSDmiY3pnIDlkYjnj77ku6Xlj4rnlKLnlJ9MSU5LCi8vCQkJCQkJCWlmICgiWSIuZXF1YWxzSWdub3JlQ2FzZShpc1VuY29tcGxldGUudHJpbSgpKSkgewovLwkJCQkJCQkJdHlwZUNvZGVOYW1lU3RyID0gIuewveWQjSI7Ci8vCQkJCQkJCQlub3RpY2VEYXRhRGV0YWlsUmVzQmVhbnMuZ2V0KGkpLnNldFNzb1Rva2VuKHNzb1Rva2VuU3RyKTsKLy8JCQkJCQkJfQovLwkJCQkJCX0KLy8JCQkJCQkvL1N5c3RlbS5vdXQucHJpbnRsbigidHlwZUNvZGVOYW1lU3RyID09ICIgKyBpICsgIj09PT09PT09PT09PSIgKyB0eXBlQ29kZU5hbWVTdHIpOwovLwkJCQkJCW5vdGljZURhdGFEZXRhaWxSZXNCZWFucy5nZXQoaSkuc2V0VHlwZUNvZGVOYW1lKHR5cGVDb2RlTmFtZVN0cik7Ci8vCQkJCQl9Ci8vCQkJCX0KLy8JCQl9CQkJCgkJfSBjYXRjaCAoQXBpRXhjZXB0aW9uIGUpIHsKCQkJTE9HR0VSLmVycm9yKCJ7XCJub3RpY2VEYXRhRGV0YWlsUmVxQmVhblwiOiIgKyBub3RpY2VEYXRhRGV0YWlsUmVxQmVhbi50b1N0cmluZygpICsgIn0iLCBlKTsKCQl9CgkJdHJ5IHsKCQkJTHNwTm90aWNlRGF0YURldGFpbFJlcUJlYW4gbHNwTm90aWNlRGF0YURldGFpbFJlcUJlYW4gPSBuZXcgTHNwTm90aWNlRGF0YURldGFpbFJlcUJlYW4oKTsKCQkJbHNwTm90aWNlRGF0YURldGFpbFJlcUJlYW4uc2V0QWdlbnRDb2RlKHRoaXMuZ2V0QWFnY29kZSgpKTsKCQkJbHNwTm90aWNlRGF0YURldGFpbFJlcUJlYW4uc2V0UmVwb3J0Q29kZShnZXROb3RpY2VEYXRhRGV0YWlsRm9ybUJlYW4uZ2V0VXdubVNvdXJjZSgpKTsKCQkJbHNwTm90aWNlRGF0YURldGFpbFJlcUJlYW4uc2V0U3RhcnREYXRlKGdldFN0YXJ0RGF0ZVN0cmluZyhyaWdodE5vZXcsIENhbGVuZGFyLkRBWV9PRl9ZRUFSLCBwZXJpb2QpKTsKCQkJbHNwTm90aWNlRGF0YURldGFpbFJlcUJlYW4uc2V0RW5kRGF0ZShnZXRFbmREYXRlU3RyaW5nKHJpZ2h0Tm9ldykpOwoJCQlsc3BOb3RpY2VEYXRhRGV0YWlsUmVzQmVhbnMgPSBjaGFubmVsQXBpU2VydmljZQoJCQkJCS5nZXRMc3BOb3RpY2VEYXRhRGV0YWlsQnlGaWxlVHlwZShsc3BOb3RpY2VEYXRhRGV0YWlsUmVxQmVhbik7CgkJfSBjYXRjaCAoQXBpRXhjZXB0aW9uIGUpIHsKCQkJTE9HR0VSLmVycm9yKCJ7XCJub3RpY2VEYXRhRGV0YWlsUmVxQmVhblwiOiIgKyBub3RpY2VEYXRhRGV0YWlsUmVxQmVhbi50b1N0cmluZygpICsgIn0iLCBlKTsKCQl9CgkJdHJ5IHsKCQkJTGlzTm90aWNlRGF0YURldGFpbFJlc0JlYW4gbGlzdCA9IGxpc0FwaVNlcnZpY2UKCQkJCQkuZ2V0TGlzTm90aWNlRGF0YURldGFpbEJ5RmlsZVR5cGUobGlzTm90aWNlRGF0YURldGFpbFJlcUJlYW4pOwoJCQlpZiAobGlzdCAhPSBudWxsKSB7CgkJCQlMaXN0PExpc05vdGljZURldGFpbFJlc0JlYW4+IGxpc2xMaXN0ID0gbGlzdC5nZXRMaXNOb3RpY2VEYXRhRGV0YWlsUmVzQmVhbigpOwoJCQkJbGlzTm90aWNlRGF0YURldGFpbFJlc0JlYW5zID0gbGlzbExpc3Quc3RyZWFtKCkubWFwKGkgLT4gewoJCQkJCU5vdGljZURhdGFEZXRhaWxSZXNCZWFuIGRlc3QgPSBuZXcgTm90aWNlRGF0YURldGFpbFJlc0JlYW4oKTsKCQkJCQl0cnkgewoJCQkJCQlCZWFuVXRpbHMuY29weVByb3BlcnRpZXMoZGVzdCwgaSk7CgkJCQkJfSBjYXRjaCAoSWxsZWdhbEFjY2Vzc0V4Y2VwdGlvbiBlKSB7CgkJCQkJCUxPR0dFUi5lcnJvcihlLnRvU3RyaW5nKCkpOwoJCQkJCX0gY2F0Y2ggKEludm9jYXRpb25UYXJnZXRFeGNlcHRpb24gZSkgewoJCQkJCQlMT0dHRVIuZXJyb3IoZS50b1N0cmluZygpKTsKCQkJCQl9CgkJCQkJcmV0dXJuIGRlc3Q7CgkJCQl9KS5jb2xsZWN0KENvbGxlY3RvcnMudG9MaXN0KCkpOwoJCQl9CgkJfSBjYXRjaCAoQXBpRXhjZXB0aW9uIGUpIHsKCQkJTE9HR0VSLmVycm9yKCJ7XCJsaXNOb3RpY2VEYXRhRGV0YWlsUmVxQmVhblwiOiIgKyBsaXNOb3RpY2VEYXRhRGV0YWlsUmVxQmVhbi50b1N0cmluZygpICsgIn0iLCBlKTsKCQl9CgkJLy8xMTQuMDcuMjJfMTE0MDcwMjI2OC0wMOeQhuizoOmAmuefpeabuF9MSVPns7vntbHkuLLmjqXkvobmupDoqr/mlbQoMTEwNOacg+itsG1lbW8pCgkJLy9QTE5URiDnkIbos6DnhafmnIMKCQl0cnkgewoJCQlDbGFtTm90ZVJlcUJlYW4gbm90aWNlRGF0YUxpc3RSZXFCZWFuID0gbmV3IENsYW1Ob3RlUmVxQmVhbigpOwoJCQlub3RpY2VEYXRhTGlzdFJlcUJlYW4uc2V0QWdlbnRJZCh0aGlzLmdldEFnZW50SWQoKSk7CgkJCUxpc3Q8Q2xhbU5vdGljZURhdGFMaXN0UmVzQmVhbj4gbGlzdCA9IGNsYW1Ob3RlU2VydmljZS5nZXRDbGFtTm90aWNlTGlzdChub3RpY2VEYXRhTGlzdFJlcUJlYW4pOwoJCQlpZiAobGlzdCAhPSBudWxsKSB7CgkJCQljbGFtTm90aWNlRGF0YURldGFpbFJlc0JlYW5zID0gbGlzdC5zdHJlYW0oKS5tYXAoaSAtPiB7CgkJCQkJTm90aWNlRGF0YURldGFpbFJlc0JlYW4gZGVzdCA9IG5ldyBOb3RpY2VEYXRhRGV0YWlsUmVzQmVhbigpOwoJCQkJCWRlc3Quc2V0SW5zdXJlZE5hbWUoaS5nZXRBY2NpZGVudFBlcnNvbk5hbWUoKSk7CgkJCQkJZGVzdC5zZXRVd25tTm8oaS5nZXRDbGFpbU5vKCkpOwoJCQkJCWRlc3Quc2V0UmVmZXJlbmNlTm8oU3RyaW5nLnZhbHVlT2YoaS5nZXROb3RpZnlJZCgpKSk7CgkJCQkJZGVzdC5zZXRQb2xpY3lObyhpLmdldFBvbGljeU5vKCkpOwoJCQkJCWRlc3Quc2V0UG9saWN5Tm8yKCItIik7CgkJCQkJZGVzdC5zZXRSZXBvcnRGb3JtKCI4OCIpOwoJCQkJCWRlc3Quc2V0UmVwb3J0TmFtZSgi57Wm5LuY6YCa55+l5pu4Iik7CgkJCQkJZGVzdC5zZXROb3RpY2VEYXRlKGkuZ2V0U2V0dGxlZERhdGUoKSk7CgkJCQkJZGVzdC5zZXRQZW5kaW5nRXhwRGF0ZSgiLSIpOwoJCQkJCWRlc3Quc2V0VHlwZShNZXNzYWdlRGF0YVR5cGVFbnVtLlBMTlRGLm5hbWUoKSk7CgkJCQkJcmV0dXJuIGRlc3Q7CgkJCQl9KS5jb2xsZWN0KENvbGxlY3RvcnMudG9MaXN0KCkpOwoJCQl9CgkJfSBjYXRjaCAoQXBpRXhjZXB0aW9uIGUpIHsKCQkJTE9HR0VSLmVycm9yKCJ7XCJsaXNOb3RpY2VEYXRhRGV0YWlsUmVxQmVhblwiOiIgKyBsaXNOb3RpY2VEYXRhRGV0YWlsUmVxQmVhbi50b1N0cmluZygpICsgIn0iLCBlKTsKCQl9CgkJCgkJaWYgKG5vdGljZURhdGFEZXRhaWxSZXNCZWFucyAhPSBudWxsKSB7CgkJCW5vdGljZURhdGFEZXRhaWxSZXNCZWFucy5mb3JFYWNoKAoJCQkJCW5vdGljZURhdGFEZXRhaWxSZXNCZWFuIC0+IG5vdGljZURhdGFEZXRhaWxSZXNCZWFuLnNldFR5cGUoTWVzc2FnZURhdGFUeXBlRW51bS5WTElGRS5nZXRUeXBlKCkpKTsKCQl9CgkJaWYgKGxzcE5vdGljZURhdGFEZXRhaWxSZXNCZWFucyAhPSBudWxsKSB7CgkJCWxzcE5vdGljZURhdGFEZXRhaWxSZXNCZWFucy5mb3JFYWNoKGxzcE5vdGljZURhdGFEZXRhaWxSZXNCZWFuIC0+IGxzcE5vdGljZURhdGFEZXRhaWxSZXNCZWFuCgkJCQkJLnNldFR5cGUoTWVzc2FnZURhdGFUeXBlRW51bS5MU1AuZ2V0VHlwZSgpKSk7CgkJCW5vdGljZURhdGFEZXRhaWxSZXNCZWFucy5hZGRBbGwobHNwTm90aWNlRGF0YURldGFpbFJlc0JlYW5zKTsKCQl9CgkJaWYgKCFDb2xsZWN0aW9uVXRpbHMuaXNFbXB0eShsaXNOb3RpY2VEYXRhRGV0YWlsUmVzQmVhbnMpKSB7CgkJCWxpc05vdGljZURhdGFEZXRhaWxSZXNCZWFucy5mb3JFYWNoKGxpc05vdGljZURhdGFEZXRhaWxSZXNCZWFuIC0+IGxpc05vdGljZURhdGFEZXRhaWxSZXNCZWFuCgkJCQkJLnNldFR5cGUoTWVzc2FnZURhdGFUeXBlRW51bS5MSVMuZ2V0VHlwZSgpKSk7CgkJCW5vdGljZURhdGFEZXRhaWxSZXNCZWFucy5hZGRBbGwobGlzTm90aWNlRGF0YURldGFpbFJlc0JlYW5zKTsKCQl9CgkJLy8xMTQuMDcuMjJfMTE0MDcwMjI2OC0wMOeQhuizoOmAmuefpeabuF9MSVPns7vntbHkuLLmjqXkvobmupDoqr/mlbQoMTEwNOacg+itsG1lbW8pCgkJLy9QTE5URiDnkIbos6DnhafmnIMKCQlpZiAoIUNvbGxlY3Rpb25VdGlscy5pc0VtcHR5KGNsYW1Ob3RpY2VEYXRhRGV0YWlsUmVzQmVhbnMpKSB7CgkJCWNsYW1Ob3RpY2VEYXRhRGV0YWlsUmVzQmVhbnMuZm9yRWFjaChub3RpY2VEYXRhRGV0YWlsUmVzQmVhbiAtPiBub3RpY2VEYXRhRGV0YWlsUmVzQmVhbgoJCQkJCS5zZXRUeXBlKE1lc3NhZ2VEYXRhVHlwZUVudW0uUExOVEYuZ2V0VHlwZSgpKSk7CgkJCW5vdGljZURhdGFEZXRhaWxSZXNCZWFucy5hZGRBbGwoY2xhbU5vdGljZURhdGFEZXRhaWxSZXNCZWFucyk7CgkJfQoJCXVwZGF0ZU5vdGljZURldGFpbFJlc0JlYW4obm90aWNlRGF0YURldGFpbFJlc0JlYW5zLCBBcmVhRW51bS5OT1RJQ0VfREFUQV9BUkVBLAoJCQkJZ2V0Tm90aWNlRGF0YURldGFpbEZvcm1CZWFuLmdldFV3bm1Tb3VyY2UoKSk7CgkJLy8g55SxZW5vdGlmeSBhcGnlj5blvpfnhafmnIPlm57opobni4DmhYsKCQlpZiAoIk5CIi5lcXVhbHNJZ25vcmVDYXNlKGdldE5vdGljZURhdGFEZXRhaWxGb3JtQmVhbi5nZXRVd25tU291cmNlKCkpKSB7CgkJCWZvciAoaW50IGkgPSAwOyBpIDwgbm90aWNlRGF0YURldGFpbFJlc0JlYW5zLnNpemUoKTsgaSsrKSB7CgkJCQlub3RpY2VEYXRhRGV0YWlsUmVzQmVhbnMuZ2V0KGkpLnNldFR5cGVDb2RlTmFtZSgiLSIpOwoJCQkJaWYgKG5vdGljZURhdGFEZXRhaWxSZXNCZWFucy5nZXQoaSkuZ2V0VXdubU5vKCkgIT0gbnVsbAoJCQkJCQl8fCBub3RpY2VEYXRhRGV0YWlsUmVzQmVhbnMuZ2V0KGkpLmdldFV3bm1ObygpLmNvbXBhcmVUbygiIikgIT0gMCkgewoJCQkJCVN0cmluZyBpc1VuY29tcGxldGUgPSAiIjsKCQkJCQlTdHJpbmcgdXdubU5vU3RyID0gbm90aWNlRGF0YURldGFpbFJlc0JlYW5zLmdldChpKS5nZXRVd25tTm8oKTsKCQkJCQlTdHJpbmcgcmVwb3J0Rm9ybVN0ciA9IG5vdGljZURhdGFEZXRhaWxSZXNCZWFucy5nZXQoaSkuZ2V0UmVwb3J0Rm9ybSgpOwoJCQkJCUVOb3RpY2VEYXRhU3RhdHVzUmVxQmVhbiBlTm90aWNlRGF0YVN0YXR1c1JlcUJlYW4gPSBuZXcgRU5vdGljZURhdGFTdGF0dXNSZXFCZWFuKCk7CgkJCQkJZU5vdGljZURhdGFTdGF0dXNSZXFCZWFuLnNldFV3bm1ubyh1d25tTm9TdHIpOwoJCQkJCWVOb3RpY2VEYXRhU3RhdHVzUmVxQmVhbi5zZXRUeXBlKHJlcG9ydEZvcm1TdHIpOwoJCQkJCUVOb3RpY2VEYXRhU3RhdHVzUmVzQmVhbiBlTm90aWNlRGF0YVN0YXR1c1Jlc0JlYW4gPSBuZXcgRU5vdGljZURhdGFTdGF0dXNSZXNCZWFuKCk7CgkJCQkJdHJ5IHsKCQkJCQkJaWYgKCIxMDAxIi5lcXVhbHNJZ25vcmVDYXNlKHJlcG9ydEZvcm1TdHIpIHx8ICIxMDAyIi5lcXVhbHNJZ25vcmVDYXNlKHJlcG9ydEZvcm1TdHIpCgkJCQkJCQkJfHwgIjEwMTIiLmVxdWFsc0lnbm9yZUNhc2UocmVwb3J0Rm9ybVN0cikgfHwgIjQwMDEiLmVxdWFsc0lnbm9yZUNhc2UocmVwb3J0Rm9ybVN0cikKCQkJCQkJCQl8fCAiNTAwMSIuZXF1YWxzSWdub3JlQ2FzZShyZXBvcnRGb3JtU3RyKSB8fCAiNjAwMSIuZXF1YWxzSWdub3JlQ2FzZShyZXBvcnRGb3JtU3RyKSkgewoJCQkJCQkJLy8gY2FsbCDpm7vnhacgQVBJIOWPliBpc3VuY29tcGxldGUKCQkJCQkJCWVOb3RpY2VEYXRhU3RhdHVzUmVzQmVhbiA9IG90aGVyQXBpU2VydmljZS5nZXRFTm90aWNlRGF0YVJlcG9ydChlTm90aWNlRGF0YVN0YXR1c1JlcUJlYW4pOwoJCQkJCQkJaWYgKGVOb3RpY2VEYXRhU3RhdHVzUmVzQmVhbiAhPSBudWxsKSB7CgkJCQkJCQkJaXNVbmNvbXBsZXRlID0gZU5vdGljZURhdGFTdGF0dXNSZXNCZWFuLmdldElzdW5jb21wbGV0ZSgpOwoJCQkJCQkJfQoJCQkJCQkJLy8gU3lzdGVtLm91dC5wcmludGxuKCJpc1VuY29tcGxldGUgPT0gIiArIGkgKyAiPT09PT09PT09PT09IiArIGlzVW5jb21wbGV0ZSk7CgkJCQkJCX0KCQkJCQl9IGNhdGNoIChBcGlFeGNlcHRpb24gZSkgewoJCQkJCQlMT0dHRVIuZXJyb3IoIntcImVOb3RpY2VEYXRhU3RhdHVzUmVxQmVhblwiOiIgKyBlTm90aWNlRGF0YVN0YXR1c1JlcUJlYW4udG9TdHJpbmcoKSArICJ9IiwgZSk7CgkJCQkJfQoJCQkJCS8vIFRFU1Qg5L2/55SoCgkJCQkJLy8gcmVwb3J0Rm9ybVN0ciA9ICIxMDAyIjsKCQkJCQlpZiAoIjEwMDEiLmVxdWFsc0lnbm9yZUNhc2UocmVwb3J0Rm9ybVN0cikgfHwgIjEwMDIiLmVxdWFsc0lnbm9yZUNhc2UocmVwb3J0Rm9ybVN0cikKCQkJCQkJCXx8ICIxMDEyIi5lcXVhbHNJZ25vcmVDYXNlKHJlcG9ydEZvcm1TdHIpKSB7CgkJCQkJCS8vIGNhbGwg6Zu754WnQVBJIHJldHVybiA9PT5pc3VuY29tcGxldGUg54K6WSDmiY3pnIDlkYjnj77ku6Xlj4rnlKLnlJ9MSU5LCgkJCQkJCWlmICgiWSIuZXF1YWxzSWdub3JlQ2FzZShpc1VuY29tcGxldGUudHJpbSgpKSkgewoJCQkJCQkJLy8gdHlwZUNvZGVOYW1lU3RyID0gIue3muS4iuWbnuimhiI7CgkJCQkJCQlub3RpY2VEYXRhRGV0YWlsUmVzQmVhbnMuZ2V0KGkpLnNldFR5cGVDb2RlTmFtZSgi57ea5LiK5Zue6KaGIik7CgkJCQkJCQlub3RpY2VEYXRhRGV0YWlsUmVzQmVhbnMuZ2V0KGkpLnNldFNzb1Rva2VuKHNzb1Rva2VuU3RyKTsKCQkJCQkJfQoJCQkJCX0gZWxzZSBpZiAoIjQwMDEiLmVxdWFsc0lnbm9yZUNhc2UocmVwb3J0Rm9ybVN0cikgfHwgIjUwMDEiLmVxdWFsc0lnbm9yZUNhc2UocmVwb3J0Rm9ybVN0cikKCQkJCQkJCXx8ICI2MDAxIi5lcXVhbHNJZ25vcmVDYXNlKHJlcG9ydEZvcm1TdHIpKSB7CgkJCQkJCS8vIGNhbGwg6Zu754WnQVBJIHJldHVybiA9PT5pc3VuY29tcGxldGUg54K6WSDmiY3pnIDlkYjnj77ku6Xlj4rnlKLnlJ9MSU5LCgkJCQkJCWlmICgiWSIuZXF1YWxzSWdub3JlQ2FzZShpc1VuY29tcGxldGUudHJpbSgpKSkgewoJCQkJCQkJLy8gdHlwZUNvZGVOYW1lU3RyID0gIuewveWQjSI7CgkJCQkJCQlub3RpY2VEYXRhRGV0YWlsUmVzQmVhbnMuZ2V0KGkpLnNldFR5cGVDb2RlTmFtZSgi57C95ZCNIik7CgkJCQkJCQlub3RpY2VEYXRhRGV0YWlsUmVzQmVhbnMuZ2V0KGkpLnNldFNzb1Rva2VuKHNzb1Rva2VuU3RyKTsKCQkJCQkJfQoJCQkJCX0KCQkJCX0KCQkJfQoJCX0KCQlyZXR1cm4gbm90aWNlRGF0YURldGFpbFJlc0JlYW5zOwoJfQoKCUBQb3N0TWFwcGluZygiL2VOb3RpY2VEYXRhUmVwb3J0IikKCXB1YmxpYyBTdHJpbmcgZ2V0RU5vdGljZURhdGFSZXBvcnQoQE1vZGVsQXR0cmlidXRlIEVOb3RpY2VEYXRhUmVwb3J0UmVxQmVhbiBlTm90aWNlRGF0YVJlcG9ydFJlcUJlYW4sCgkJCUh0dHBTZXJ2bGV0UmVzcG9uc2UgcmVzcG9uc2UpIHRocm93cyBFeGNlcHRpb24gewoKCQlTdHJpbmcgdG9rZW4gPSBlTm90aWNlRGF0YVJlcG9ydFJlcUJlYW4uZ2V0U3NvVG9rZW4oKTsKCQlTdHJpbmcgdG9rZW5FbmNvZGVTdHIgPSBVUkxFbmNvZGVyLmVuY29kZSh0b2tlbiwgU3RhbmRhcmRDaGFyc2V0cy5JU09fODg1OV8xLnRvU3RyaW5nKCkpOwoJCVN0cmluZyB1d25tTm8gPSBlTm90aWNlRGF0YVJlcG9ydFJlcUJlYW4uZ2V0RU5vdGljZU5vKCk7CgkJU3RyaW5nIGZvcm1JZCA9IGVOb3RpY2VEYXRhUmVwb3J0UmVxQmVhbi5nZXRmb3JtSWQoKTsKCQlMT0dHRVIuaW5mbygiZU5vdGljZSB0cmFuc2ZlciBTc29Ub2tlbjoge30gLHV3bm1Obzoge30sIGZvcm1JZDoge30iLCB0b2tlbkVuY29kZVN0ciwgdXdubU5vLCBmb3JtSWQpOwoJCVN0cmluZyBmb3J3YXJkUGF0aCA9IGVOb3RpY2VEYXRhUmVwb3J0VXJsICsgIj90d2xpZmVUb2tlbj0iICsgdG9rZW5FbmNvZGVTdHIgKyAiJm1ldGhvZD1ub3RpY2VOb3RlJnV3bm1Obz0iCgkJCQkrIHV3bm1ObyArICImZm9ybUlkPSIgKyBmb3JtSWQ7CgkJTE9HR0VSLmluZm8oImVOb3RpY2UgdHJhbnNmZXIgVVJMOiB7fSAiLCBmb3J3YXJkUGF0aCk7CgkJcmV0dXJuICJyZWRpcmVjdDoiICsgZm9yd2FyZFBhdGg7Cgl9CgoJQFBvc3RNYXBwaW5nKCIvbWVzc2FnZURhdGFEZXRhaWwiKQoJcHVibGljIFN0cmluZyBzaG93TWVzc2FnZURhdGFEZXRhaWwoTW9kZWwgbW9kZWwsIEBNb2RlbEF0dHJpYnV0ZSBTaG93TWVzc2FnZURhdGFEZXRhaWxGb3JtQmVhbiBmb3JtQmVhbikKCQkJdGhyb3dzIEpzb25Qcm9jZXNzaW5nRXhjZXB0aW9uLCBVbnN1cHBvcnRlZEVuY29kaW5nRXhjZXB0aW9uIHsKCQlTaG93TWVzc2FnZURhdGFEZXRhaWxGb3JtQmVhbiBzaG93TWVzc2FnZURhdGFEZXRhaWxGb3JtQmVhbiA9IGNvcHlQcm9wZXJ0aWVzKGZvcm1CZWFuLAoJCQkJU2hvd01lc3NhZ2VEYXRhRGV0YWlsRm9ybUJlYW4uY2xhc3MpOwoJCW1vZGVsLmFkZEF0dHJpYnV0ZSgiZm9ybUJlYW4iLCBzaG93TWVzc2FnZURhdGFEZXRhaWxGb3JtQmVhbik7CgkJbW9kZWwuYWRkQXR0cmlidXRlKCJhcmVhIiwgQXJlYUVudW0ucmVzb2x2ZShzaG93TWVzc2FnZURhdGFEZXRhaWxGb3JtQmVhbi5nZXRBcmVhKCkpKTsKCQltb2RlbC5hZGRBdHRyaWJ1dGUoInBkZlJlcUJlYW4iLCBuZXcgUGRmUmVxRm9ybUJlYW4oKSk7CgkJcmV0dXJuICJNZXNzYWdlRGF0YURldGFpbCI7Cgl9CgoJLyoKCSAqIEBSZXF1ZXN0TWFwcGluZyh2YWx1ZSA9ICIvSGlzdG9yeURhdGFEZXRhaWwiLCBtZXRob2QgPSBSZXF1ZXN0TWV0aG9kLlBPU1QpCgkgKiBwdWJsaWMgU3RyaW5nIHNob3dIaXN0b3J5RGF0YURldGFpbChNb2RlbCBtb2RlbCwgQE1vZGVsQXR0cmlidXRlCgkgKiBTaG93TWVzc2FnZURhdGFEZXRhaWxGb3JtQmVhbiBmb3JtQmVhbikgdGhyb3dzIEpzb25Qcm9jZXNzaW5nRXhjZXB0aW9uLAoJICogVW5zdXBwb3J0ZWRFbmNvZGluZ0V4Y2VwdGlvbiB7IFNob3dNZXNzYWdlRGF0YURldGFpbEZvcm1CZWFuCgkgKiBzaG93TWVzc2FnZURhdGFEZXRhaWxGb3JtQmVhbiA9IGNvcHlQcm9wZXJ0aWVzKGZvcm1CZWFuLAoJICogU2hvd01lc3NhZ2VEYXRhRGV0YWlsRm9ybUJlYW4uY2xhc3MpOyBtb2RlbC5hZGRBdHRyaWJ1dGUoImZvcm1CZWFuIiwKCSAqIHNob3dNZXNzYWdlRGF0YURldGFpbEZvcm1CZWFuKTsgbW9kZWwuYWRkQXR0cmlidXRlKCJhcmVhIiwKCSAqIEFyZWFFbnVtLnJlc29sdmUoc2hvd01lc3NhZ2VEYXRhRGV0YWlsRm9ybUJlYW4uZ2V0QXJlYSgpKSk7CgkgKiBtb2RlbC5hZGRBdHRyaWJ1dGUoInBkZlJlcUJlYW4iLCBuZXcgUGRmUmVxRm9ybUJlYW4oKSk7IHJldHVybgoJICogIkhpc3RvcnlEYXRhRGV0YWlsIjsgfQoJICogCgkgKiBAUmVxdWVzdE1hcHBpbmcodmFsdWUgPSAiL2dldEhpc3RvcnlEYXRhRGV0YWlsIiwgbWV0aG9kID0gUmVxdWVzdE1ldGhvZC5QT1NUKQoJICogCgkgKiBAUmVzcG9uc2VCb2R5IHB1YmxpYyBMaXN0PE1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbj4KCSAqIGdldEhpc3RvcnlEYXRhRGV0YWlsKE1vZGVsIG1vZGVsLCBATW9kZWxBdHRyaWJ1dGUKCSAqIEdldE1lc3NhZ2VEYXRhRGV0YWlsRm9ybUJlYW4gZ2V0TWVzc2FnZURhdGFEZXRhaWxGb3JtQmVhbikgdGhyb3dzCgkgKiBKc29uUHJvY2Vzc2luZ0V4Y2VwdGlvbiB7IERhdGUgcmlnaHROb3cgPSBuZXcgRGF0ZSgpOwoJICogTGlzdDxNZXNzYWdlRGF0YURldGFpbFJlc0JlYW4+IG1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbnMgPSBuZXcKCSAqIEFycmF5TGlzdDxNZXNzYWdlRGF0YURldGFpbFJlc0JlYW4+KCk7IFN0cmluZyBtZXNzYWdlRGF0YURldGFpbFJlcUJlYW5TdHIgPQoJICogIiI7IFN0cmluZyBoaXN0b3J5U3RhcnREYXRlID0gZ2V0U3RhcnREYXRlU3RyaW5nKHJpZ2h0Tm93LAoJICogQ2FsZW5kYXIuREFZX09GX1lFQVIsIGhpc3RvcnlQZXJpb2QpOyBTdHJpbmcgaGlzdG9yeUVuZERhdGUgPQoJICogZ2V0RW5kRGF0ZVN0cmluZyhyaWdodE5vdyk7IE1lc3NhZ2VEYXRhVHlwZUVudW0gbWVzc2FnZURhdGFUeXBlRW51bSA9CgkgKiBNZXNzYWdlRGF0YVR5cGVFbnVtLmZpbmQoZ2V0TWVzc2FnZURhdGFEZXRhaWxGb3JtQmVhbi5nZXRUeXBlKCkpOyBpZgoJICogKG1lc3NhZ2VEYXRhVHlwZUVudW0uZXF1YWxzKE1lc3NhZ2VEYXRhVHlwZUVudW0uQ0FTKSkgeyB0cnkgewoJICogQ2FzTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuIGNhc01lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbiA9IG5ldwoJICogQ2FzTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuKCk7CgkgKiBjYXNNZXNzYWdlRGF0YURldGFpbFJlcUJlYW4uc2V0QWdlbnRDb2RlKHRoaXMuZ2V0QWFnY29kZSgpKTsKCSAqIGNhc01lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbi5zZXRTdGFydERhdGUoaGlzdG9yeVN0YXJ0RGF0ZSk7CgkgKiBjYXNNZXNzYWdlRGF0YURldGFpbFJlcUJlYW4uc2V0RW5kRGF0ZShoaXN0b3J5RW5kRGF0ZSk7CgkgKiBjYXNNZXNzYWdlRGF0YURldGFpbFJlcUJlYW4uc2V0UmVwb3J0Q29kZShnZXRNZXNzYWdlRGF0YURldGFpbEZvcm1CZWFuLgoJICogZ2V0QXAwOVR5cGUxKCkpOyBtZXNzYWdlRGF0YURldGFpbFJlcUJlYW5TdHIgPQoJICogY2FzTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuLnRvU3RyaW5nKCk7IG1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbnMgPQoJICogY2hhbm5lbEFwaVNlcnZpY2UuZ2V0Q2FzTWVzc2FnZURhdGFEZXRhaWwoY2FzTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuKTsKCSAqIGlmKG1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbnMgIT0gbnVsbCkgewoJICogbWVzc2FnZURhdGFEZXRhaWxSZXNCZWFucy5mb3JFYWNoKG1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbiAtPgoJICogbWVzc2FnZURhdGFEZXRhaWxSZXNCZWFuLnNldFR5cGUoTWVzc2FnZURhdGFUeXBlRW51bS5DQVMuZ2V0VHlwZSgpKSk7IH0gZWxzZQoJICogeyBtZXNzYWdlRGF0YURldGFpbFJlc0JlYW5zID0gbmV3IEFycmF5TGlzdDxNZXNzYWdlRGF0YURldGFpbFJlc0JlYW4+KCk7IH0gfQoJICogY2F0Y2ggKEFwaUV4Y2VwdGlvbiBlKSB7IExPR0dFUi5lcnJvcigie1wibWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuXCI6IiArCgkgKiBtZXNzYWdlRGF0YURldGFpbFJlcUJlYW5TdHIgKyAifSIsIGUpOyB9IH0gZWxzZSBpZgoJICogKG1lc3NhZ2VEYXRhVHlwZUVudW0uZXF1YWxzKE1lc3NhZ2VEYXRhVHlwZUVudW0uTFNQKSkgeyB0cnkgewoJICogTHNwTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuIGxzcE1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbiA9IG5ldwoJICogTHNwTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuKCk7CgkgKiBsc3BNZXNzYWdlRGF0YURldGFpbFJlcUJlYW4uc2V0QWdlbnRDb2RlKHRoaXMuZ2V0QWFnY29kZSgpKTsKCSAqIGxzcE1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbi5zZXRTdGFydERhdGUoaGlzdG9yeVN0YXJ0RGF0ZSk7CgkgKiBsc3BNZXNzYWdlRGF0YURldGFpbFJlcUJlYW4uc2V0RW5kRGF0ZShoaXN0b3J5RW5kRGF0ZSk7CgkgKiBsc3BNZXNzYWdlRGF0YURldGFpbFJlcUJlYW4uc2V0UmVwb3J0Q29kZShnZXRNZXNzYWdlRGF0YURldGFpbEZvcm1CZWFuLgoJICogZ2V0QXAwOVR5cGUxKCkpOyBtZXNzYWdlRGF0YURldGFpbFJlcUJlYW5TdHIgPQoJICogbHNwTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuLnRvU3RyaW5nKCk7IG1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbnMgPQoJICogY2hhbm5lbEFwaVNlcnZpY2UuZ2V0THNwSGlzdG9yeURhdGFEZXRhaWwobHNwTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuKTsKCSAqIGlmKG1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbnMgIT0gbnVsbCkgewoJICogbWVzc2FnZURhdGFEZXRhaWxSZXNCZWFucy5mb3JFYWNoKGxzcEhpc3RvcnlEYXRhRGV0YWlsUmVzQmVhbiAtPgoJICogbHNwSGlzdG9yeURhdGFEZXRhaWxSZXNCZWFuLnNldFR5cGUoTWVzc2FnZURhdGFUeXBlRW51bS5MU1AuZ2V0VHlwZSgpKSk7IH0KCSAqIGVsc2UgeyBtZXNzYWdlRGF0YURldGFpbFJlc0JlYW5zID0gbmV3IEFycmF5TGlzdDxNZXNzYWdlRGF0YURldGFpbFJlc0JlYW4+KCk7CgkgKiB9IH0gY2F0Y2ggKEFwaUV4Y2VwdGlvbiBlKSB7IExPR0dFUi5lcnJvcigie1wibWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuXCI6IiArCgkgKiBtZXNzYWdlRGF0YURldGFpbFJlcUJlYW5TdHIgKyAifSIsIGUpOyB9IH0gcmV0dXJuIG1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbnM7CgkgKiB9CgkgKi8KCglAUG9zdE1hcHBpbmcoIi9nZXRNZXNzYWdlRGF0YURldGFpbEJ5RmlsZVR5cGUiKQoJQFJlc3BvbnNlQm9keQoJcHVibGljIExpc3Q8TWVzc2FnZURhdGFEZXRhaWxSZXNCZWFuPiBnZXRNZXNzYWdlRGF0YURldGFpbEJ5RmlsZVR5cGUoTW9kZWwgbW9kZWwsCgkJCUBNb2RlbEF0dHJpYnV0ZSBHZXRNZXNzYWdlRGF0YURldGFpbEZvcm1CZWFuIGdldE1lc3NhZ2VEYXRhRGV0YWlsRm9ybUJlYW4pIHRocm93cyBKc29uUHJvY2Vzc2luZ0V4Y2VwdGlvbiB7CgkJRGF0ZSByaWdodE5vdyA9IG5ldyBEYXRlKCk7CgkJTGlzdDxNZXNzYWdlRGF0YURldGFpbFJlc0JlYW4+IG1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbnMgPSBuZXcgQXJyYXlMaXN0PE1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbj4oKTsKCQlTdHJpbmcgbWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuU3RyID0gIiI7CgkJU3RyaW5nIHN0YXJ0RGF0ZSA9IGdldFN0YXJ0RGF0ZVN0cmluZyhyaWdodE5vdywgQ2FsZW5kYXIuREFZX09GX1lFQVIsIHBlcmlvZCk7CgkJU3RyaW5nIGVuZERhdGUgPSBnZXRFbmREYXRlU3RyaW5nKHJpZ2h0Tm93KTsKCgkJU3RyaW5nIGVuZFJvY0RhdGVTdHIgPSBEYXRlVXRpbC5nZXRDdXJyZW50Um9jRGF0ZSgpOy8vIHl5eS9tbS9kZAoJCVN0cmluZyBzdGFyUm9jdERhdGVTdHIgPSBEYXRlVXRpbC5hZGREYXkoZW5kUm9jRGF0ZVN0ciwgcGVyaW9kKTsvLyB5eXkvbW0vZGQKCQl0cnkgewoJCQlNZXNzYWdlRGF0YURldGFpbFJlcUJlYW4gbWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuID0gbmV3IE1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbigpOwoJCQltZXNzYWdlRGF0YURldGFpbFJlcUJlYW4uc2V0QWdlbnRJZCh0aGlzLmdldEFnZW50SWQoKSk7CgkJCW1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbi5zZXRBcDA5VHlwZTEoZ2V0TWVzc2FnZURhdGFEZXRhaWxGb3JtQmVhbi5nZXRBcDA5VHlwZTEoKSk7CgkJCW1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbi5zZXRTdGFydERhdGUoc3RhcnREYXRlKTsKCQkJbWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuLnNldEVuZERhdGUoZW5kRGF0ZSk7CgkJCW1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhblN0ciA9IG1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbi50b1N0cmluZygpOwoJCQltZXNzYWdlRGF0YURldGFpbFJlc0JlYW5zID0gaUthc2hTZXJ2aWNlLmdldE1lc3NhZ2VEYXRhRGV0YWlsKG1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbik7CgkJCWlmIChtZXNzYWdlRGF0YURldGFpbFJlc0JlYW5zICE9IG51bGwpIHsKCQkJCS8vIDEwOTA2MDEyMTktMDJfZ2V0IGFjY3VyYWN5IHBheSBkb2xsYXJzIGZyb20gbXNnIG5vdGljZV9TdGFydAoJCQkJLy8gTE9HR0VSLmluZm8obWVzc2FnZURhdGFEZXRhaWxSZXNCZWFucy5zaXplKCkpOwoJCQkJLy8gMTA5MDYwMTIxOS0wMl9nZXQgYWNjdXJhY3kgcGF5IGRvbGxhcnMgZnJvbSBtc2cgbm90aWNlX0VuZAoJCQkJbWVzc2FnZURhdGFEZXRhaWxSZXNCZWFucy5mb3JFYWNoKG1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbiAtPiB7IC8vIDExMDA1MDA4NTMtMDBfU3RhcnQKCQkJCQlpZiAobWVzc2FnZURhdGFEZXRhaWxSZXNCZWFuLmdldEFwMDlUeXBlMSgpLmNvbXBhcmVUbygiUE0iKSA9PSAwCgkJCQkJCQkmJiBtZXNzYWdlRGF0YURldGFpbFJlc0JlYW4uZ2V0QXAwOVR5cGUyKCkuY29tcGFyZVRvKCJQTSIpID09IDApIHsKCQkJCQkJbWVzc2FnZURhdGFEZXRhaWxSZXNCZWFuLnNldEFwMDlUeXBlMk5hbWUoIuaEj+WklumaquS/neiyu+iqv+aVtOmAmuefpSIpOwoJCQkJCX0gLy8gMTEwMDUwMDg1My0wMF9FbmQKCQkJCQltZXNzYWdlRGF0YURldGFpbFJlc0JlYW4uc2V0VHlwZShNZXNzYWdlRGF0YVR5cGVFbnVtLlZMSUZFLmdldFR5cGUoKSk7CgkJCQl9KTsKCQkJfSBlbHNlIHsKCQkJCW1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbnMgPSBuZXcgQXJyYXlMaXN0PE1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbj4oKTsKCQkJfQoJCX0gY2F0Y2ggKEFwaUV4Y2VwdGlvbiBlKSB7CgkJCUxPR0dFUi5lcnJvcigie1wibWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuXCI6IiArIG1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhblN0ciArICJ9IiwgZSk7CgkJfQoJCXRyeSB7CgkJCUxzcE1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbiBsc3BNZXNzYWdlRGF0YURldGFpbFJlcUJlYW4gPSBuZXcgTHNwTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuKCk7CgkJCWxzcE1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbi5zZXRBZ2VudENvZGUodGhpcy5nZXRBYWdjb2RlKCkpOwoJCQlsc3BNZXNzYWdlRGF0YURldGFpbFJlcUJlYW4uc2V0UmVwb3J0Q29kZShnZXRNZXNzYWdlRGF0YURldGFpbEZvcm1CZWFuLmdldEFwMDlUeXBlMSgpKTsKCQkJbHNwTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuLnNldFN0YXJ0RGF0ZShzdGFydERhdGUpOwoJCQlsc3BNZXNzYWdlRGF0YURldGFpbFJlcUJlYW4uc2V0RW5kRGF0ZShlbmREYXRlKTsKCQkJbWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuU3RyID0gbHNwTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuLnRvU3RyaW5nKCk7CgkJCUxpc3Q8TWVzc2FnZURhdGFEZXRhaWxSZXNCZWFuPiBsc3BNZXNzYWdlRGF0YURldGFpbFJlc0JlYW5zID0gY2hhbm5lbEFwaVNlcnZpY2UKCQkJCQkuZ2V0THNwTWVzc2FnZURhdGFEZXRhaWxCeUZpbGVUeXBlKGxzcE1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbik7CgkJCWlmIChsc3BNZXNzYWdlRGF0YURldGFpbFJlc0JlYW5zICE9IG51bGwpIHsKCQkJCWxzcE1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbnMuZm9yRWFjaChsc3BNZXNzYWdlRGF0YURldGFpbFJlc0JlYW4gLT4gewoJCQkJCWlmIChsc3BNZXNzYWdlRGF0YURldGFpbFJlc0JlYW4uZ2V0QXAwOVR5cGUxKCkuY29tcGFyZVRvKCJBUFNTUE1JSCIpID09IDAgLy8gMTEwMDUwMDg1My0wMF9TdGFydAoJCQkJCQkJJiYgbHNwTWVzc2FnZURhdGFEZXRhaWxSZXNCZWFuLmdldEFwMDlUeXBlMigpLmNvbXBhcmVUbygiQVBTU1BNSUgiKSA9PSAwKSB7CgkJCQkJCWxzcE1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbi5zZXROb3RlRGVzYygKCQkJCQkJCQki6YWN5ZCIMTEw5bm0N+aciDHml6XlgrflrrPpmqroqr/pmY3kv53osrvvvIzljp/mipXkv50v6ZmE5Yqg5LmL5YK35a6z5L+d6Zqq5pa8MTA5LzExMOW5tOW6puS5i+S/nemaquacn+mWk+Wxhua7v+W+jO+8jOasoeW5tOW6pui1t+Wwh+S+neazleS7pOimj+evhOiqv+mZjeS/nemaquiyu+eOh++8jOiLpeS/neaItumhmOaEj+aPkOmrmOS/nemhjSjntq3mjIHljp/kv53osrsp77yM6KuL5YSY6YCf5Y2U5Yqp5L+d5oi25aGr5a+r57Ch5piT5aWR6K6K5pu46L6m55CG44CCIik7CgkJCQkJfSAvLyAxMTAwNTAwODUzLTAwX0VuZAoJCQkJCWxzcE1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbi5zZXRUeXBlKE1lc3NhZ2VEYXRhVHlwZUVudW0uTFNQLmdldFR5cGUoKSk7CgkJCQl9KTsKCQkJCW1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbnMuYWRkQWxsKGxzcE1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbnMpOwoJCQl9CgkJfSBjYXRjaCAoQXBpRXhjZXB0aW9uIGUpIHsKCQkJTE9HR0VSLmVycm9yKCJ7XCJtZXNzYWdlRGF0YURldGFpbFJlcUJlYW5cIjoiICsgbWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuU3RyICsgIn0iLCBlKTsKCQl9CgkJdHJ5IHsKCQkJQ21zTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuIGNtc01lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbiA9IG5ldyBDbXNNZXNzYWdlRGF0YURldGFpbFJlcUJlYW4oKTsKCQkJY21zTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuLnNldEFnZW50Q29kZSh0aGlzLmdldEFhZ2NvZGUoKSk7CgkJCWNtc01lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbi5zZXRTdGFydERhdGUoc3RhcnREYXRlKTsKCQkJY21zTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuLnNldEVuZERhdGUoZW5kRGF0ZSk7CgkJCWNtc01lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbi5zZXRSZXBvcnRDb2RlKGdldE1lc3NhZ2VEYXRhRGV0YWlsRm9ybUJlYW4uZ2V0QXAwOVR5cGUxKCkpOwoJCQltZXNzYWdlRGF0YURldGFpbFJlcUJlYW5TdHIgPSBjbXNNZXNzYWdlRGF0YURldGFpbFJlcUJlYW4udG9TdHJpbmcoKTsKCQkJTGlzdDxNZXNzYWdlRGF0YURldGFpbFJlc0JlYW4+IGNtc01lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbnMgPSBjaGFubmVsQXBpU2VydmljZQoJCQkJCS5nZXRDbXNNZXNzYWdlRGF0YURldGFpbChjbXNNZXNzYWdlRGF0YURldGFpbFJlcUJlYW4pOwoJCQlpZiAoY21zTWVzc2FnZURhdGFEZXRhaWxSZXNCZWFucyAhPSBudWxsKSB7CgkJCQljbXNNZXNzYWdlRGF0YURldGFpbFJlc0JlYW5zLmZvckVhY2goY21zTWVzc2FnZURhdGFEZXRhaWxSZXNCZWFuIC0+IGNtc01lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbgoJCQkJCQkuc2V0VHlwZShNZXNzYWdlRGF0YVR5cGVFbnVtLkNBUy5nZXRUeXBlKCkpKTsKCQkJCW1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbnMuYWRkQWxsKGNtc01lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbnMpOwoJCQl9CgkJfSBjYXRjaCAoQXBpRXhjZXB0aW9uIGUpIHsKCQkJTE9HR0VSLmVycm9yKCJ7XCJtZXNzYWdlRGF0YURldGFpbFJlcUJlYW5cIjoiICsgbWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuU3RyICsgIn0iLCBlKTsKCQl9CgkJdHJ5IHsKCQkJaWYgKFN0cmluZ1V0aWxzLmlzTm90RW1wdHkoZ2V0TWVzc2FnZURhdGFEZXRhaWxGb3JtQmVhbi5nZXRBcDA5VHlwZTEoKSkKCQkJCQkmJiBnZXRNZXNzYWdlRGF0YURldGFpbEZvcm1CZWFuLmdldEFwMDlUeXBlMSgpLmVxdWFscygiQ0wiKSkgewoJCQkJTHNwTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuIGxzcE1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbiA9IG5ldyBMc3BNZXNzYWdlRGF0YURldGFpbFJlcUJlYW4oKTsKCQkJCWxzcE1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbi5zZXRBZ2VudENvZGUodGhpcy5nZXRBYWdjb2RlKCkpOwoJCQkJbHNwTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuLnNldFJlcG9ydENvZGUoZ2V0TWVzc2FnZURhdGFEZXRhaWxGb3JtQmVhbi5nZXRBcDA5VHlwZTEoKSk7CgkJCQlsc3BNZXNzYWdlRGF0YURldGFpbFJlcUJlYW4uc2V0U3RhcnREYXRlKHN0YXJ0RGF0ZSk7CgkJCQlsc3BNZXNzYWdlRGF0YURldGFpbFJlcUJlYW4uc2V0RW5kRGF0ZShlbmREYXRlKTsKCQkJCW1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhblN0ciA9IGxzcE1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbi50b1N0cmluZygpOwoJCQkJTGlzdDxNZXNzYWdlRGF0YURldGFpbFJlc0JlYW4+IGxzcE1lc3NhZ2VEYXRhRGV0YWlsQ2wyMDdyUmVzQmVhbnMgPSBjaGFubmVsQXBpU2VydmljZQoJCQkJCQkuZ2V0THNwTWVzc2FnZURhdGFDbDIwN3JEZXRhaWwobHNwTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuKTsKCQkJCWlmIChsc3BNZXNzYWdlRGF0YURldGFpbENsMjA3clJlc0JlYW5zICE9IG51bGwpIHsKCQkJCQlsc3BNZXNzYWdlRGF0YURldGFpbENsMjA3clJlc0JlYW5zCgkJCQkJCQkuZm9yRWFjaChsc3BNZXNzYWdlRGF0YURldGFpbFJlc0JlYW4gLT4gbHNwTWVzc2FnZURhdGFEZXRhaWxSZXNCZWFuCgkJCQkJCQkJCS5zZXRUeXBlKE1lc3NhZ2VEYXRhVHlwZUVudW0uVkxJRkUuZ2V0VHlwZSgpKSk7CgkJCQkJbWVzc2FnZURhdGFEZXRhaWxSZXNCZWFucy5hZGRBbGwobHNwTWVzc2FnZURhdGFEZXRhaWxDbDIwN3JSZXNCZWFucyk7CgkJCQl9CgkJCX0KCQl9IGNhdGNoIChBcGlFeGNlcHRpb24gZSkgewoJCQlMT0dHRVIuZXJyb3IoIntcIm1lc3NhZ2VEYXRhRGV0YWlsQ2wyMDdyUmVxQmVhblwiOiIgKyBtZXNzYWdlRGF0YURldGFpbFJlcUJlYW5TdHIgKyAifSIsIGUpOwoJCX0KCQl0cnkgewoJCQlpZiAoU3RyaW5nVXRpbHMuaXNOb3RFbXB0eShnZXRNZXNzYWdlRGF0YURldGFpbEZvcm1CZWFuLmdldEFwMDlUeXBlMSgpKSAmJiBTdHJpbmdVdGlscwoJCQkJCS5lcXVhbHMoZ2V0TWVzc2FnZURhdGFEZXRhaWxGb3JtQmVhbi5nZXRBcDA5VHlwZTEoKSwgTWVzc2FnZURhdGFPcmRlcmluZ0VudW0uR1AubmFtZSgpKSkgewoJCQkJRGFpbHlJbnN1cmFuY2VCZW5lZml0c0RhdGFEZXRhaWxSZXFCZWFuIGRhaWx5SW5zdXJhbmNlQmVuZWZpdHNEYXRhRGV0YWlsUmVxQmVhbiA9IG5ldyBEYWlseUluc3VyYW5jZUJlbmVmaXRzRGF0YURldGFpbFJlcUJlYW4oKTsKCQkJCWRhaWx5SW5zdXJhbmNlQmVuZWZpdHNEYXRhRGV0YWlsUmVxQmVhbi5zZXRBZ2VudENvZGUodGhpcy5nZXRUcmFuc2FnZW50Y29kZSgpKTsKCQkJCWRhaWx5SW5zdXJhbmNlQmVuZWZpdHNEYXRhRGV0YWlsUmVxQmVhbi5zZXRTdGFydERhdGUoc3RhclJvY3REYXRlU3RyKTsKCQkJCWRhaWx5SW5zdXJhbmNlQmVuZWZpdHNEYXRhRGV0YWlsUmVxQmVhbi5zZXRFbmREYXRlKGVuZFJvY0RhdGVTdHIpOwoJCQkJbWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuU3RyID0gZGFpbHlJbnN1cmFuY2VCZW5lZml0c0RhdGFEZXRhaWxSZXFCZWFuLnRvU3RyaW5nKCk7CgkJCQlMaXN0PE1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbj4gZGFpbHlJbnN1cmFuY2VCZW5lZml0c0RhdGFEZXRhaWxSZXNCZWFucyA9IGNoYW5uZWxBcGlTZXJ2aWNlCgkJCQkJCS5nZXREYWlseUluc3VyYW5jZUJlbmVmaXRzRGF0YURldGFpbChkYWlseUluc3VyYW5jZUJlbmVmaXRzRGF0YURldGFpbFJlcUJlYW4pOwoJCQkJaWYgKGRhaWx5SW5zdXJhbmNlQmVuZWZpdHNEYXRhRGV0YWlsUmVzQmVhbnMgIT0gbnVsbCkgewoJCQkJCWRhaWx5SW5zdXJhbmNlQmVuZWZpdHNEYXRhRGV0YWlsUmVzQmVhbnMKCQkJCQkJCS5mb3JFYWNoKGJlYW4gLT4gYmVhbi5zZXRUeXBlKE1lc3NhZ2VEYXRhVHlwZUVudW0uVkxJRkUuZ2V0VHlwZSgpKSk7CgkJCQkJbWVzc2FnZURhdGFEZXRhaWxSZXNCZWFucy5hZGRBbGwoZGFpbHlJbnN1cmFuY2VCZW5lZml0c0RhdGFEZXRhaWxSZXNCZWFucyk7CgkJCQl9CgkJCX0KCQl9IGNhdGNoIChBcGlFeGNlcHRpb24gZSkgewoJCQlMT0dHRVIuZXJyb3IoIntcIm1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhblwiOiIgKyBtZXNzYWdlRGF0YURldGFpbFJlcUJlYW5TdHIgKyAifSIsIGUpOwoJCX0KCgkJdHJ5IHsKCQkJaWYgKFN0cmluZ1V0aWxzLmlzTm90RW1wdHkoZ2V0TWVzc2FnZURhdGFEZXRhaWxGb3JtQmVhbi5nZXRBcDA5VHlwZTEoKSkgJiYgU3RyaW5nVXRpbHMKCQkJCQkuZXF1YWxzKGdldE1lc3NhZ2VEYXRhRGV0YWlsRm9ybUJlYW4uZ2V0QXAwOVR5cGUxKCksIE1lc3NhZ2VEYXRhT3JkZXJpbmdFbnVtLkJMLm5hbWUoKSkpIHsKCQkJCUxzcE1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbiBsc3BNZXNzYWdlRGF0YURldGFpbFJlcUJlYW4gPSBuZXcgTHNwTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuKCk7CgkJCQlsc3BNZXNzYWdlRGF0YURldGFpbFJlcUJlYW4uc2V0QWdlbnRDb2RlKHRoaXMuZ2V0QWFnY29kZSgpKTsKCQkJCWxzcE1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbi5zZXRSZXBvcnRDb2RlKGdldE1lc3NhZ2VEYXRhRGV0YWlsRm9ybUJlYW4uZ2V0QXAwOVR5cGUxKCkpOwoJCQkJbHNwTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuLnNldFN0YXJ0RGF0ZShzdGFydERhdGUpOwoJCQkJbHNwTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuLnNldEVuZERhdGUoZW5kRGF0ZSk7CgkJCQltZXNzYWdlRGF0YURldGFpbFJlcUJlYW5TdHIgPSBsc3BNZXNzYWdlRGF0YURldGFpbFJlcUJlYW4udG9TdHJpbmcoKTsKCQkJCUxpc3Q8TWVzc2FnZURhdGFEZXRhaWxSZXNCZWFuPiBsc3BSZW1pbk5vdGljZVJldHVybk1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbnMgPSBjaGFubmVsQXBpU2VydmljZQoJCQkJCQkuZ2V0THNwUmVtaW5Ob3RpY2VSZXR1cm5NZXNzYWdlRGF0YURldGFpbChsc3BNZXNzYWdlRGF0YURldGFpbFJlcUJlYW4pOwoJCQkJaWYgKGxzcFJlbWluTm90aWNlUmV0dXJuTWVzc2FnZURhdGFEZXRhaWxSZXNCZWFucyAhPSBudWxsKSB7CgkJCQkJbHNwUmVtaW5Ob3RpY2VSZXR1cm5NZXNzYWdlRGF0YURldGFpbFJlc0JlYW5zCgkJCQkJCQkuZm9yRWFjaChsc3BNZXNzYWdlRGF0YURldGFpbFJlc0JlYW4gLT4gbHNwTWVzc2FnZURhdGFEZXRhaWxSZXNCZWFuCgkJCQkJCQkJCS5zZXRUeXBlKE1lc3NhZ2VEYXRhVHlwZUVudW0uTFNQLmdldFR5cGUoKSkpOwoJCQkJCW1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbnMuYWRkQWxsKGxzcFJlbWluTm90aWNlUmV0dXJuTWVzc2FnZURhdGFEZXRhaWxSZXNCZWFucyk7CgkJCQl9CgkJCX0KCQl9IGNhdGNoIChBcGlFeGNlcHRpb24gZSkgewoJCQlMT0dHRVIuZXJyb3IoIntcImxzcFJlbWluTm90aWNlUmV0dXJuTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuXCI6IiArIG1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhblN0ciArICJ9IiwgZSk7CgkJfQoKCQl0cnkgewoJCQlpZiAoU3RyaW5nVXRpbHMuaXNOb3RFbXB0eShnZXRNZXNzYWdlRGF0YURldGFpbEZvcm1CZWFuLmdldEFwMDlUeXBlMSgpKSAmJiBTdHJpbmdVdGlscwoJCQkJCS5lcXVhbHMoZ2V0TWVzc2FnZURhdGFEZXRhaWxGb3JtQmVhbi5nZXRBcDA5VHlwZTEoKSwgTWVzc2FnZURhdGFPcmRlcmluZ0VudW0uUEMubmFtZSgpKSkgewoJCQkJTHNwTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuIGxzcE1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbiA9IG5ldyBMc3BNZXNzYWdlRGF0YURldGFpbFJlcUJlYW4oKTsKCQkJCWxzcE1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbi5zZXRBZ2VudENvZGUodGhpcy5nZXRBYWdjb2RlKCkpOwoJCQkJbHNwTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuLnNldFJlcG9ydENvZGUoZ2V0TWVzc2FnZURhdGFEZXRhaWxGb3JtQmVhbi5nZXRBcDA5VHlwZTEoKSk7CgkJCQlsc3BNZXNzYWdlRGF0YURldGFpbFJlcUJlYW4uc2V0U3RhcnREYXRlKHN0YXJ0RGF0ZSk7CgkJCQlsc3BNZXNzYWdlRGF0YURldGFpbFJlcUJlYW4uc2V0RW5kRGF0ZShlbmREYXRlKTsKCQkJCW1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhblN0ciA9IGxzcE1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbi50b1N0cmluZygpOwoJCQkJTGlzdDxNZXNzYWdlRGF0YURldGFpbFJlc0JlYW4+IGxzcFJlbWluTm90aWNlUmV0dXJuTWVzc2FnZURhdGFEZXRhaWxSZXNCZWFucyA9IGNoYW5uZWxBcGlTZXJ2aWNlCgkJCQkJCS5nZXRMc3BSZWluc3RhdGVtZW50Tm90aWNlTWVzc2FnZURhdGFEZXRhaWwobHNwTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuKTsKCQkJCWlmIChsc3BSZW1pbk5vdGljZVJldHVybk1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbnMgIT0gbnVsbCkgewoJCQkJCWxzcFJlbWluTm90aWNlUmV0dXJuTWVzc2FnZURhdGFEZXRhaWxSZXNCZWFucwoJCQkJCQkJLmZvckVhY2gobHNwTWVzc2FnZURhdGFEZXRhaWxSZXNCZWFuIC0+IGxzcE1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbgoJCQkJCQkJCQkuc2V0VHlwZShNZXNzYWdlRGF0YVR5cGVFbnVtLkxTUC5nZXRUeXBlKCkpKTsKCQkJCQltZXNzYWdlRGF0YURldGFpbFJlc0JlYW5zLmFkZEFsbChsc3BSZW1pbk5vdGljZVJldHVybk1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbnMpOwoJCQkJfQoJCQl9CgkJfSBjYXRjaCAoQXBpRXhjZXB0aW9uIGUpIHsKCQkJTE9HR0VSLmVycm9yKCJ7XCJsc3BSZWluc3RhdGVtZW50Tm90aWNlTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuXCI6IiArIG1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhblN0ciArICJ9IiwgZSk7CgkJfQoKCQl0cnkgewoJCQlMaXNNZXNzYWdlRGF0YURldGFpbFJlcUJlYW4gbGlzTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuID0gbmV3IExpc01lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbigpOwoJCQlsaXNNZXNzYWdlRGF0YURldGFpbFJlcUJlYW4uc2V0QWdlbnRJZCh0aGlzLmdldEFnZW50SWQoKSk7CgkJCWxpc01lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbi5zZXRBcDA5VHlwZTEoZ2V0TWVzc2FnZURhdGFEZXRhaWxGb3JtQmVhbi5nZXRBcDA5VHlwZTEoKSk7CgkJCWxpc01lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbi5zZXRTdGFydERhdGUoc3RhcnREYXRlKTsKCQkJbGlzTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuLnNldEVuZERhdGUoZW5kRGF0ZSk7CgkJCW1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhblN0ciA9IGxpc01lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhbi50b1N0cmluZygpOwoJCQlMaXNNZXNzYWdlRGF0YURldGFpbFJlc0JlYW4gbGlzdCA9IGxpc0FwaVNlcnZpY2UuZ2V0TWVzc2FnZURhdGFEZXRhaWwobGlzTWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuKTsKCQkJTGlzdDxNZXNzYWdlRGF0YURldGFpbFJlc0JlYW4+IGxpc01lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbnMgPSBsaXN0LmdldE1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbigpOwoJCQlpZiAobGlzTWVzc2FnZURhdGFEZXRhaWxSZXNCZWFucyAhPSBudWxsKSB7CgkJCQlsaXNNZXNzYWdlRGF0YURldGFpbFJlc0JlYW5zLmZvckVhY2gobWVzc2FnZURhdGFEZXRhaWxSZXNCZWFuIC0+IHsKCQkJCQltZXNzYWdlRGF0YURldGFpbFJlc0JlYW4uc2V0VHlwZShNZXNzYWdlRGF0YVR5cGVFbnVtLkxJUy5nZXRUeXBlKCkpOwoJCQkJfSk7CgkJCQltZXNzYWdlRGF0YURldGFpbFJlc0JlYW5zLmFkZEFsbChsaXNNZXNzYWdlRGF0YURldGFpbFJlc0JlYW5zKTsKCQkJfQoJCX0gY2F0Y2ggKEFwaUV4Y2VwdGlvbiBlKSB7CgkJCUxPR0dFUi5lcnJvcigie1wibWVzc2FnZURhdGFEZXRhaWxSZXFCZWFuXCI6IiArIG1lc3NhZ2VEYXRhRGV0YWlsUmVxQmVhblN0ciArICJ9IiwgZSk7CgkJfQoJCXVwZGF0ZU5vdGljZURldGFpbFJlc0JlYW4obWVzc2FnZURhdGFEZXRhaWxSZXNCZWFucywgQXJlYUVudW0uTUVTU0FHRV9EQVRBX0FSRUEsCgkJCQlnZXRNZXNzYWdlRGF0YURldGFpbEZvcm1CZWFuLmdldEFwMDlUeXBlMSgpKTsKCQlyZXR1cm4gbWVzc2FnZURhdGFEZXRhaWxSZXNCZWFuczsKCX0KCglAUG9zdE1hcHBpbmcoIi9ub3RpY2VEYXRhUGRmUmVwb3J0IikKCXB1YmxpYyB2b2lkIGdldE5vdGljZURhdGFQZGZSZXBvcnQoQE1vZGVsQXR0cmlidXRlIE5vdGljZURhdGFQZGZSZXBvcnRSZXFCZWFuIG5vdGljZURhdGFQZGZSZXBvcnRSZXFCZWFuLAoJCQlIdHRwU2VydmxldFJlc3BvbnNlIHJlc3BvbnNlKSB0aHJvd3MgQXBpRXhjZXB0aW9uLCBJT0V4Y2VwdGlvbiB7CgkJYnl0ZVtdIHBkZiA9IG51bGw7CgkJLy8gTGlzIOeUoueUn+eFp+acg1BERgoJCWlmIChNZXNzYWdlRGF0YVR5cGVFbnVtLmZpbmQobm90aWNlRGF0YVBkZlJlcG9ydFJlcUJlYW4uZ2V0Tm90aWNlRGF0YVBkZlJlcG9ydFR5cGUoKSkuaXNMaXMoKSkgewoJCQlTdHJpbmcgdXVpZCA9IFVVSUQucmFuZG9tVVVJRCgpLnRvU3RyaW5nKCk7CgkJCUxpc0V4cG9ydFBkZlJlcUJlYW4gbGlzRXhwb3J0UGRmUmVxQmVhbiA9IG5ldyBMaXNFeHBvcnRQZGZSZXFCZWFuKCk7CgkJCWxpc0V4cG9ydFBkZlJlcUJlYW4uc2V0RG9jdW1lbnRJZChub3RpY2VEYXRhUGRmUmVwb3J0UmVxQmVhbi5nZXREb2N1bWVudElkKCkpOy8vIOW9seWDj+e3qOiZnwoJCQlsaXNFeHBvcnRQZGZSZXFCZWFuLnNldFBhZ2UoIiIpOy8vIOepuueZve+8jOaJgOaciemggeasoemDveimgeWMr+WHugoJCQlsaXNFeHBvcnRQZGZSZXFCZWFuLnNldFdhdGVybWFyaygiIik7Ly8g54Sh5rWu5rC05Y2wCgkJCWxpc0V4cG9ydFBkZlJlcUJlYW4uc2V0UGFzc3dvcmQoIiIpOy8vIOeEoemgiOWKoOWvhgoJCQlPcGVyYXRvckluZm8gb3BlcmF0b3JJbmZvID0gbmV3IE9wZXJhdG9ySW5mbygpOwoJCQlvcGVyYXRvckluZm8uc2V0Q2xpZW50SVBBZGRyZXNzKGlwKTsKCQkJb3BlcmF0b3JJbmZvLnNldFRyYW5zYWN0aW9uSWQodXVpZCk7CgkJCW9wZXJhdG9ySW5mby5zZXRTeXN0ZW1JZChleHBvcnRQZGZTSUQpOwoJCQlvcGVyYXRvckluZm8uc2V0T3BlcmF0b3JVc2VySWQoZXhwb3J0UGRmVUlEKTsKCQkJbGlzRXhwb3J0UGRmUmVxQmVhbi5zZXRPcGVyYXRvckluZm8ob3BlcmF0b3JJbmZvKTsKCQkJTGlzRXhwb3J0UGRmUmVzQmVhbiBsaXNFeHBvcnRQZGZSZXNCZWFuID0gbGlzQXBpU2VydmljZS5nZXRMaXN4cG9ydFBkZlVybChsaXNFeHBvcnRQZGZSZXFCZWFuKTsKCQkJYnl0ZVtdIGJ5dGVBcnJyYXkgPSBsaXNFeHBvcnRQZGZSZXNCZWFuLmdldFJldHVybkRhdGEoKS5nZXRSZXN1bHQoKS5nZXRCeXRlcygpOwoJCQlwZGYgPSBqYXZhLnV0aWwuQmFzZTY0LmdldERlY29kZXIoKS5kZWNvZGUoYnl0ZUFycnJheSk7CgkJLy8xMTQuMDcuMjJfMTE0MDcwMjI2OC0wMOeQhuizoOmAmuefpeabuF9MSVPns7vntbHkuLLmjqXkvobmupDoqr/mlbQoMTEwNOacg+itsG1lbW8pCgkJfSBlbHNlIGlmIChNZXNzYWdlRGF0YVR5cGVFbnVtLmZpbmQobm90aWNlRGF0YVBkZlJlcG9ydFJlcUJlYW4uZ2V0Tm90aWNlRGF0YVBkZlJlcG9ydFR5cGUoKSkuaXNQbG50ZigpKSB7CgkJCUNsYW1Ob3RlUGRmUmVxQmVhbiBjbGFtTm90ZVBkZlJlcUJlYW4gPSBuZXcgQ2xhbU5vdGVQZGZSZXFCZWFuKCk7CgkJCWNsYW1Ob3RlUGRmUmVxQmVhbi5zZXROb3RpZnlJZChub3RpY2VEYXRhUGRmUmVwb3J0UmVxQmVhbi5nZXREb2N1bWVudElkKCkpOwoJCQlTdHJpbmcgY2xhbU5vdGljZVBkZkRlY3J5cHRvclN0ciA9IGNsYW1Ob3RlU2VydmljZS5nZXRDbGFtTm90aWNlUGRmKGNsYW1Ob3RlUGRmUmVxQmVhbik7CgkJCWlmICghU3RyaW5nVXRpbHMuaXNCbGFuayhjbGFtTm90aWNlUGRmRGVjcnlwdG9yU3RyKSkgewoJCQkJcGRmID0gamF2YS51dGlsLkJhc2U2NC5nZXREZWNvZGVyKCkuZGVjb2RlKGNsYW1Ob3RpY2VQZGZEZWNyeXB0b3JTdHIpOwoJCQl9CgkJfSBlbHNlIHsKCQkJcGRmID0gbmJyQXBpU2VydmljZS5nZXROYnJTaW5nbGVSZXBvcnQobmV3IE5ickRhdGFSZXFCZWFuKG5vdGljZURhdGFQZGZSZXBvcnRSZXFCZWFuLmdldFV3bm1ObygpLCBub3RpY2VEYXRhUGRmUmVwb3J0UmVxQmVhbi5nZXRSZXBvcnRGb3JtKCkpKS5nZXRSZXR1cm5SZXBvcnREYXRhKCk7CgkJfQoKCQlyZXNwb25zZS5zZXRDb250ZW50VHlwZSgiYXBwbGljYXRpb24vcGRmIik7CgkJSU9VdGlscy53cml0ZShwZGYsIHJlc3BvbnNlLmdldE91dHB1dFN0cmVhbSgpKTsKCQlyZXNwb25zZS5mbHVzaEJ1ZmZlcigpOwoJfQoKCUBHZXRNYXBwaW5nKCIvbmV3UG9saWN5U2NoZWR1bGVEYXRhRGV0YWlsIikKCXB1YmxpYyBTdHJpbmcgc2hvd05ld1BvbGljeVNjaGVkdWxlRGV0YWlsKE1vZGVsIG1vZGVsKSB7CgkJZmluYWwgU2hvd1Byb2dyZXNzRGF0YURldGFpbEZvcm1CZWFuIHNob3dQcm9ncmVzc0RhdGFEZXRhaWxGb3JtQmVhbiA9IG5ldyBTaG93UHJvZ3Jlc3NEYXRhRGV0YWlsRm9ybUJlYW4oKTsKCQlzaG93UHJvZ3Jlc3NEYXRhRGV0YWlsRm9ybUJlYW4uc2V0QXJlYShBcmVhRW51bS5QUk9HUkVTU19EQVRBX0FSRUEuZ2V0Q29kZSgpKTsKCQlzaG93UHJvZ3Jlc3NEYXRhRGV0YWlsRm9ybUJlYW4uc2V0Q2F0ZWdvcnkoUHJvZ3Jlc3NOb3RpY2VFbnVtLk5CLm5hbWUoKSk7CgkJbW9kZWwuYWRkQXR0cmlidXRlKCJmb3JtQmVhbiIsIHNob3dQcm9ncmVzc0RhdGFEZXRhaWxGb3JtQmVhbik7CgkJbW9kZWwuYWRkQXR0cmlidXRlKCJhcmVhIiwgQXJlYUVudW0uUFJPR1JFU1NfREFUQV9BUkVBKTsKCQltb2RlbC5hZGRBdHRyaWJ1dGUoIm5ld1BvbGljeVNjaGVkdWxlUERGQmVhbiIsIG5ldyBOZXdQb2xpY3lTY2hlZHVsZVBERlJlcUJlYW4oKSk7CgkJcmV0dXJuICJOZXdQb2xpY3lTY2hlZHVsZURldGFpbCI7Cgl9CgoJQFBvc3RNYXBwaW5nKCIvZ2V0TmV3UG9saWN5U2NoZWR1bGVEYXRhRGV0YWlsIikKCUBSZXNwb25zZUJvZHkKCXB1YmxpYyBMaXN0PE5ld1BvbGljeVNjaGVkdWxlRGV0YWlsUmVzQmVhbj4gZ2V0TmV3UG9saWN5U2NoZWR1bGVEZXRhaWwoTW9kZWwgbW9kZWwsCgkJCVNob3dQcm9ncmVzc0RhdGFEZXRhaWxGb3JtQmVhbiBzaG93UHJvZ3Jlc3NEYXRhRGV0YWlsRm9ybUJlYW4pIHRocm93cyBKc29uUHJvY2Vzc2luZ0V4Y2VwdGlvbiB7CgkJTmV3UG9saWN5U2NoZWR1bGVEZXRhaWxSZXFCZWFuIG5ld1BvbGljeVNjaGVkdWxlRGV0YWlsUmVxQmVhbiA9IG5ldyBOZXdQb2xpY3lTY2hlZHVsZURldGFpbFJlcUJlYW4oKTsKCQluZXdQb2xpY3lTY2hlZHVsZURldGFpbFJlcUJlYW4uc2V0QWdlbnRDb2RlKHRoaXMuZ2V0QWFnY29kZSgpKTsKCQlMaXN0PE5ld1BvbGljeVNjaGVkdWxlRGV0YWlsUmVzQmVhbj4gbmV3UG9saWN5U2NoZWR1bGVEZXRhaWxSZXNCZWFuID0gbmV3IEFycmF5TGlzdDxOZXdQb2xpY3lTY2hlZHVsZURldGFpbFJlc0JlYW4+KCk7CgkJTGlzdDxOZXdQb2xpY3lTY2hlZHVsZURldGFpbFJlc0JlYW4+IGxpc05ld1BvbGljeVNjaGVkdWxlRGV0YWlsUmVzQmVhbiA9IG5ldyBBcnJheUxpc3Q8TmV3UG9saWN5U2NoZWR1bGVEZXRhaWxSZXNCZWFuPigpOwoJCXRyeSB7CgkJCW5ld1BvbGljeVNjaGVkdWxlRGV0YWlsUmVzQmVhbiA9IGlLYXNoU2VydmljZS5nZXROZXdQb2xpY3lTY2hlZHVsZURldGFpbChuZXdQb2xpY3lTY2hlZHVsZURldGFpbFJlcUJlYW4pOwoJCQlpZiAobmV3UG9saWN5U2NoZWR1bGVEZXRhaWxSZXNCZWFuID09IG51bGwpIHsKCQkJCW5ld1BvbGljeVNjaGVkdWxlRGV0YWlsUmVzQmVhbiA9IG5ldyBBcnJheUxpc3Q8TmV3UG9saWN5U2NoZWR1bGVEZXRhaWxSZXNCZWFuPigpOwoJCQl9CgkJfSBjYXRjaCAoQXBpRXhjZXB0aW9uIGUpIHsKCQkJTE9HR0VSLmVycm9yKCJ7XCJuZXdQb2xpY3lTY2hlZHVsZURldGFpbFJlcUJlYW5cIjoiICsgbmV3UG9saWN5U2NoZWR1bGVEZXRhaWxSZXFCZWFuLnRvU3RyaW5nKCkgKyAifSIsIGUpOwoJCX0KLy8JCUxJU+aWsOWlkee0hOmAsuW6puaYjue0sAoJCXRyeSB7CgkJCURhdGUgZW5kRGF0ZSA9IG5ldyBEYXRlKCk7CgkJCVN0cmluZyBlbmRTbGFzaERhdGVTdHIgPSBnZXRFbmRTbGFzaERhdGVTdHJpbmcoZW5kRGF0ZSk7CgkJCUxpc05ld1BvbGljeVNjaGVkdWxlRGV0YWlsUmVzQmVhbiByZXAgPSBsaXNBcGlTZXJ2aWNlCgkJCQkJLmdldE5ld1BvbGljeVNjaGVkdWxlRGV0YWlsKG5ld1BvbGljeVNjaGVkdWxlRGV0YWlsUmVxQmVhbik7CgkJCWxpc05ld1BvbGljeVNjaGVkdWxlRGV0YWlsUmVzQmVhbiA9IHJlcC5nZXROZXdQb2xpY3lTY2hlZHVsZURldGFpbFJlc0JlYW4oKTsKCQkJaWYgKGxpc05ld1BvbGljeVNjaGVkdWxlRGV0YWlsUmVzQmVhbiAhPSBudWxsKSB7CgkJCQluZXdQb2xpY3lTY2hlZHVsZURldGFpbFJlc0JlYW4uYWRkQWxsKGxpc05ld1BvbGljeVNjaGVkdWxlRGV0YWlsUmVzQmVhbik7CgkJCX0KCQl9IGNhdGNoIChBcGlFeGNlcHRpb24gZSkgewoJCQlMT0dHRVIuZXJyb3IoIntcIm5ld1BvbGljeVNjaGVkdWxlRGV0YWlsUmVxQmVhblwiOiIgKyBuZXdQb2xpY3lTY2hlZHVsZURldGFpbFJlcUJlYW4udG9TdHJpbmcoKSArICJ9IiwgZSk7CgkJfQoJCXVwZGF0ZU5vdGljZURldGFpbFJlc0JlYW4obmV3UG9saWN5U2NoZWR1bGVEZXRhaWxSZXNCZWFuLCBBcmVhRW51bS5QUk9HUkVTU19EQVRBX0FSRUEsCgkJCQlzaG93UHJvZ3Jlc3NEYXRhRGV0YWlsRm9ybUJlYW4uZ2V0Q2F0ZWdvcnkoKSk7CgkJcmV0dXJuIG5ld1BvbGljeVNjaGVkdWxlRGV0YWlsUmVzQmVhbjsKCX0KCglAR2V0TWFwcGluZygiL2NoYW5nZVBvbGljeVNjaGVkdWxlRGV0YWlsIikKCXB1YmxpYyBTdHJpbmcgc2hvd0NoYW5nZVBvbGljeVNjaGVkdWxlRGV0YWlsKE1vZGVsIG1vZGVsKSB7CgkJZmluYWwgU2hvd1Byb2dyZXNzRGF0YURldGFpbEZvcm1CZWFuIHNob3dQcm9ncmVzc0RhdGFEZXRhaWxGb3JtQmVhbiA9IG5ldyBTaG93UHJvZ3Jlc3NEYXRhRGV0YWlsRm9ybUJlYW4oKTsKCQlzaG93UHJvZ3Jlc3NEYXRhRGV0YWlsRm9ybUJlYW4uc2V0QXJlYShBcmVhRW51bS5QUk9HUkVTU19EQVRBX0FSRUEuZ2V0Q29kZSgpKTsKCQlzaG93UHJvZ3Jlc3NEYXRhRGV0YWlsRm9ybUJlYW4uc2V0Q2F0ZWdvcnkoUHJvZ3Jlc3NOb3RpY2VFbnVtLlBDLm5hbWUoKSk7CgkJbW9kZWwuYWRkQXR0cmlidXRlKCJmb3JtQmVhbiIsIHNob3dQcm9ncmVzc0RhdGFEZXRhaWxGb3JtQmVhbik7CgkJbW9kZWwuYWRkQXR0cmlidXRlKCJhcmVhIiwgQXJlYUVudW0uUFJPR1JFU1NfREFUQV9BUkVBKTsKCQlyZXR1cm4gIkNoYW5nZVBvbGljeVNjaGVkdWxlRGV0YWlsIjsKCX0KCglAUG9zdE1hcHBpbmcoIi9nZXRDaGFuZ2VQb2xpY3lTY2hlZHVsZURldGFpbCIpCglAUmVzcG9uc2VCb2R5CglwdWJsaWMgTGlzdDxDaGFuZ2VQb2xpY3lTY2hlZHVsZURldGFpbFJlc0JlYW4+IGdldENoYW5nZVBvbGljeVNjaGVkdWxlRGV0YWlsKE1vZGVsIG1vZGVsLAoJCQlTaG93UHJvZ3Jlc3NEYXRhRGV0YWlsRm9ybUJlYW4gc2hvd1Byb2dyZXNzRGF0YURldGFpbEZvcm1CZWFuKSB0aHJvd3MgSnNvblByb2Nlc3NpbmdFeGNlcHRpb24gewoJCURhdGUgZW5kRGF0ZSA9IG5ldyBEYXRlKCk7CgkJU3RyaW5nIHN0YXJ0RGF0ZVN0ciA9IGdldFN0YXJ0RGF0ZVN0cmluZyhlbmREYXRlLCBDYWxlbmRhci5EQVlfT0ZfWUVBUiwgcGVyaW9kKTsKCQlTdHJpbmcgZW5kRGF0ZVN0ciA9IGdldEVuZERhdGVTdHJpbmcoZW5kRGF0ZSk7CgkJU3RyaW5nIHN0YXJ0U2xhc2hEYXRlU3RyID0gZ2V0U3RhcnRTbGFzaERhdGVTdHJpbmcoZW5kRGF0ZSwgQ2FsZW5kYXIuREFZX09GX1lFQVIsIGNoYW5nZVBvbGljeVNjaGVkdWxlUGVyaW9kKTsKCQlTdHJpbmcgZW5kU2xhc2hEYXRlU3RyID0gZ2V0RW5kU2xhc2hEYXRlU3RyaW5nKGVuZERhdGUpOwoJCUNoYW5nZVBvbGljeVNjaGVkdWxlRGV0YWlsUmVxQmVhbiBjaGFuZ2VQb2xpY3lTY2hlZHVsZURldGFpbFJlcUJlYW4gPSBuZXcgQ2hhbmdlUG9saWN5U2NoZWR1bGVEZXRhaWxSZXFCZWFuKCk7CgkJY2hhbmdlUG9saWN5U2NoZWR1bGVEZXRhaWxSZXFCZWFuLnNldEFnZW50Q29kZSh0aGlzLmdldEFhZ2NvZGUoKSk7CgkJY2hhbmdlUG9saWN5U2NoZWR1bGVEZXRhaWxSZXFCZWFuLnNldFN0YXJ0RGF0ZShzdGFydFNsYXNoRGF0ZVN0cik7CgkJY2hhbmdlUG9saWN5U2NoZWR1bGVEZXRhaWxSZXFCZWFuLnNldEVuZERhdGUoZW5kRGF0ZVN0cik7CgkJQ2hhbmdlUG9saWN5U2NoZWR1bGVEZXRhaWxSZXFCZWFuIGxpc0NoYW5nZVBvbGljeVNjaGVkdWxlRGV0YWlsUmVxQmVhbiA9IG5ldyBDaGFuZ2VQb2xpY3lTY2hlZHVsZURldGFpbFJlcUJlYW4oKTsKCQlsaXNDaGFuZ2VQb2xpY3lTY2hlZHVsZURldGFpbFJlcUJlYW4uc2V0QWdlbnRDb2RlKHRoaXMuZ2V0QWFnY29kZSgpKTsKCQlsaXNDaGFuZ2VQb2xpY3lTY2hlZHVsZURldGFpbFJlcUJlYW4uc2V0U3RhcnREYXRlKHN0YXJ0U2xhc2hEYXRlU3RyKTsKCQlsaXNDaGFuZ2VQb2xpY3lTY2hlZHVsZURldGFpbFJlcUJlYW4uc2V0RW5kRGF0ZShlbmRTbGFzaERhdGVTdHIpOwoJCUxpc3Q8Q2hhbmdlUG9saWN5U2NoZWR1bGVEZXRhaWxSZXNCZWFuPiBjaGFuZ2VQb2xpY3lTY2hlZHVsZURldGFpbFJlc0JlYW4gPSBuZXcgQXJyYXlMaXN0PENoYW5nZVBvbGljeVNjaGVkdWxlRGV0YWlsUmVzQmVhbj4oKTsKCQlMaXN0PENoYW5nZVBvbGljeVNjaGVkdWxlRGV0YWlsUmVzQmVhbj4gbGlzQ2hhbmdlUG9saWN5U2NoZWR1bGVSZXNCZWFuID0gbmV3IEFycmF5TGlzdDxDaGFuZ2VQb2xpY3lTY2hlZHVsZURldGFpbFJlc0JlYW4+KCk7CgkJdHJ5IHsKCQkJY2hhbmdlUG9saWN5U2NoZWR1bGVEZXRhaWxSZXNCZWFuID0gaUthc2hTZXJ2aWNlCgkJCQkJLmdldENoYW5nZVBvbGljeVNjaGVkdWxlRGV0YWlsKGNoYW5nZVBvbGljeVNjaGVkdWxlRGV0YWlsUmVxQmVhbik7CgkJCWlmIChjaGFuZ2VQb2xpY3lTY2hlZHVsZURldGFpbFJlc0JlYW4gPT0gbnVsbCkgewoJCQkJY2hhbmdlUG9saWN5U2NoZWR1bGVEZXRhaWxSZXFCZWFuID0gbmV3IENoYW5nZVBvbGljeVNjaGVkdWxlRGV0YWlsUmVxQmVhbigpOwoJCQl9CgkJfSBjYXRjaCAoQXBpRXhjZXB0aW9uIGUpIHsKCQkJTE9HR0VSLmVycm9yKCJ7XCJjaGFuZ2VQb2xpY3lTY2hlZHVsZURldGFpbFJlcUJlYW5cIjoiICsgY2hhbmdlUG9saWN5U2NoZWR1bGVEZXRhaWxSZXFCZWFuLnRvU3RyaW5nKCkgKyAifSIsCgkJCQkJZSk7CgkJfQoJCS8vIExJU+Wlkee0hOiuiuabtD3kv53lhajpgLLluqbmn6XoqaIKCQl0cnkgewoJCQlMaXNDaGFuZ2VQb2xpY3lTY2hlZHVsZVJlc0JlYW4gcmVwID0gbGlzQXBpU2VydmljZQoJCQkJCS5nZXRDaGFuZ2VQb2xpY3lTY2hlZHVsZShsaXNDaGFuZ2VQb2xpY3lTY2hlZHVsZURldGFpbFJlcUJlYW4pOwoKCQkJbGlzQ2hhbmdlUG9saWN5U2NoZWR1bGVSZXNCZWFuID0gcmVwLmdldENoYW5nZVBvbGljeVNjaGVkdWxlRGV0YWlsUmVzQmVhbigpOwoJCQlpZiAobGlzQ2hhbmdlUG9saWN5U2NoZWR1bGVSZXNCZWFuICE9IG51bGwpIHsKCQkJCWNoYW5nZVBvbGljeVNjaGVkdWxlRGV0YWlsUmVzQmVhbi5hZGRBbGwobGlzQ2hhbmdlUG9saWN5U2NoZWR1bGVSZXNCZWFuKTsKCQkJfQoJCX0gY2F0Y2ggKEFwaUV4Y2VwdGlvbiBlKSB7CgkJCUxPR0dFUi5lcnJvcigie1wibGlzQ2hhbmdlUG9saWN5U2NoZWR1bGVEZXRhaWxSZXFCZWFuXCI6IiArIGxpc0NoYW5nZVBvbGljeVNjaGVkdWxlRGV0YWlsUmVxQmVhbi50b1N0cmluZygpCgkJCQkJKyAifSIsIGUpOwoJCX0KCQl1cGRhdGVOb3RpY2VEZXRhaWxSZXNCZWFuKGNoYW5nZVBvbGljeVNjaGVkdWxlRGV0YWlsUmVzQmVhbiwgQXJlYUVudW0uUFJPR1JFU1NfREFUQV9BUkVBLAoJCQkJc2hvd1Byb2dyZXNzRGF0YURldGFpbEZvcm1CZWFuLmdldENhdGVnb3J5KCkpOwoJCXJldHVybiBjaGFuZ2VQb2xpY3lTY2hlZHVsZURldGFpbFJlc0JlYW47Cgl9CgoJQEdldE1hcHBpbmcoIi9jbGFpbVNjaGVkdWxlRGV0YWlsIikKCXB1YmxpYyBTdHJpbmcgc2hvd0NsYWltU2NoZWR1bGVEZXRhaWwoTW9kZWwgbW9kZWwpIHRocm93cyBKc29uUHJvY2Vzc2luZ0V4Y2VwdGlvbiB7CgkJZmluYWwgU2hvd1Byb2dyZXNzRGF0YURldGFpbEZvcm1CZWFuIHNob3dQcm9ncmVzc0RhdGFEZXRhaWxGb3JtQmVhbiA9IG5ldyBTaG93UHJvZ3Jlc3NEYXRhRGV0YWlsRm9ybUJlYW4oKTsKCQlzaG93UHJvZ3Jlc3NEYXRhRGV0YWlsRm9ybUJlYW4uc2V0QXJlYShBcmVhRW51bS5QUk9HUkVTU19EQVRBX0FSRUEuZ2V0Q29kZSgpKTsKCQlzaG93UHJvZ3Jlc3NEYXRhRGV0YWlsRm9ybUJlYW4uc2V0Q2F0ZWdvcnkoUHJvZ3Jlc3NOb3RpY2VFbnVtLkNMLm5hbWUoKSk7CgkJbW9kZWwuYWRkQXR0cmlidXRlKCJmb3JtQmVhbiIsIHNob3dQcm9ncmVzc0RhdGFEZXRhaWxGb3JtQmVhbik7CgkJbW9kZWwuYWRkQXR0cmlidXRlKCJhcmVhIiwgQXJlYUVudW0uUFJPR1JFU1NfREFUQV9BUkVBKTsKCQlyZXR1cm4gIkNsYWltU2NoZWR1bGVEZXRhaWwiOwoJfQoKCUBQb3N0TWFwcGluZygiL2dldENsYWltU2NoZWR1bGVEZXRhaWwiKQoJQFJlc3BvbnNlQm9keQoJcHVibGljIExpc3Q8Q2xhaW1TY2hlZHVsZURldGFpbFJlc0JlYW4+IGdldENsYWltU2NoZWR1bGVEZXRhaWwoTW9kZWwgbW9kZWwsCgkJCVNob3dQcm9ncmVzc0RhdGFEZXRhaWxGb3JtQmVhbiBzaG93UHJvZ3Jlc3NEYXRhRGV0YWlsRm9ybUJlYW4pIHRocm93cyBKc29uUHJvY2Vzc2luZ0V4Y2VwdGlvbiB7CgkJQ2xhaW1TY2hlZHVsZURldGFpbFJlcUJlYW4gY2xhaW1TY2hlZHVsZURldGFpbFJlcUJlYW4gPSBuZXcgQ2xhaW1TY2hlZHVsZURldGFpbFJlcUJlYW4oKTsKCQljbGFpbVNjaGVkdWxlRGV0YWlsUmVxQmVhbi5zZXRBZ2VudENvZGUodGhpcy5nZXRBYWdjb2RlKCkpOwoJCUxpc3Q8Q2xhaW1TY2hlZHVsZURldGFpbFJlc0JlYW4+IGNsYWltU2NoZWR1bGVEZXRhaWxSZXNCZWFuID0gbmV3IEFycmF5TGlzdDxDbGFpbVNjaGVkdWxlRGV0YWlsUmVzQmVhbj4oKTsKCQlMaXN0PENsYWltU2NoZWR1bGVEZXRhaWxSZXNCZWFuPiBsaXNDbGFpbVNjaGVkdWxlRGV0YWlsUmVzQmVhbiA9IG5ldyBBcnJheUxpc3Q8Q2xhaW1TY2hlZHVsZURldGFpbFJlc0JlYW4+KCk7CgkJdHJ5IHsKCQkJY2xhaW1TY2hlZHVsZURldGFpbFJlc0JlYW4gPSBpS2FzaFNlcnZpY2UuZ2V0Q2xhaW1TY2hlZHVsZURldGFpbChjbGFpbVNjaGVkdWxlRGV0YWlsUmVxQmVhbik7CgkJCWlmIChjbGFpbVNjaGVkdWxlRGV0YWlsUmVzQmVhbiA9PSBudWxsKSB7CgkJCQljbGFpbVNjaGVkdWxlRGV0YWlsUmVxQmVhbiA9IG5ldyBDbGFpbVNjaGVkdWxlRGV0YWlsUmVxQmVhbigpOwoJCQl9CgkJfSBjYXRjaCAoQXBpRXhjZXB0aW9uIGUpIHsKCQkJTE9HR0VSLmVycm9yKCJ7XCJjbGFpbVNjaGVkdWxlRGV0YWlsUmVxQmVhblwiOiIgKyBjbGFpbVNjaGVkdWxlRGV0YWlsUmVxQmVhbi50b1N0cmluZygpICsgIn0iLCBlKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgeyAvLyAxMDkwOTAwNzE0LTAwCgkJCUxPR0dFUi5lcnJvcigiIiwgZSk7CgkJfQoJCXRyeSB7CgkJCUxpc3Q8Q2xhaW1TY2hlZHVsZURldGFpbFJlc0JlYW4+IGNsYWltU2NoZWR1bGVEZXRhaWxSZXNCZWFucyA9IGNoYW5uZWxBcGlTZXJ2aWNlCgkJCQkJLmdldENsYWltU2NoZWR1bGVEZXRhaWwoY2xhaW1TY2hlZHVsZURldGFpbFJlcUJlYW4pOwoJCQlpZiAoY2xhaW1TY2hlZHVsZURldGFpbFJlc0JlYW5zICE9IG51bGwpIHsKCQkJCWNsYWltU2NoZWR1bGVEZXRhaWxSZXNCZWFuLmFkZEFsbChjbGFpbVNjaGVkdWxlRGV0YWlsUmVzQmVhbnMpOwoJCQl9CgkJfSBjYXRjaCAoQXBpRXhjZXB0aW9uIGUpIHsKCQkJTE9HR0VSLmVycm9yKCJ7XCJjbGFpbVNjaGVkdWxlRGV0YWlsUmVxQmVhblwiOiIgKyBjbGFpbVNjaGVkdWxlRGV0YWlsUmVxQmVhbi50b1N0cmluZygpICsgIn0iLCBlKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgeyAvLyAxMDkwOTAwNzE0LTAwCgkJCUxPR0dFUi5lcnJvcigiIiwgZSk7CgkJfQoJCS8vIExJU+eQhuizoOmAsuW6puafpeipogoJCXRyeSB7CgkJCUxpc0NsYWltU2NoZWR1bGVEZXRhaWxSZXNCZWFuIHJlcCA9IGxpc0FwaVNlcnZpY2UuZ2V0Q2xhaW1TY2hlZHVsZURldGFpbChjbGFpbVNjaGVkdWxlRGV0YWlsUmVxQmVhbik7CgkJCWxpc0NsYWltU2NoZWR1bGVEZXRhaWxSZXNCZWFuID0gcmVwLmdldENsYWltU2NoZWR1bGVEZXRhaWxSZXNCZWFuKCk7CgkJCWlmIChsaXNDbGFpbVNjaGVkdWxlRGV0YWlsUmVzQmVhbiAhPSBudWxsKSB7CgkJCQkvLyDkv67mraPopb/lhYPngrrmsJHlnItfMjAyMzA1MjlfU3RhcnQKCQkJCWZvciAoaW50IGkgPSAwOyBpIDwgbGlzQ2xhaW1TY2hlZHVsZURldGFpbFJlc0JlYW4uc2l6ZSgpOyBpKyspIHsKCQkJCQlDbGFpbVNjaGVkdWxlRGV0YWlsUmVzQmVhbiBiZWFuID0gbGlzQ2xhaW1TY2hlZHVsZURldGFpbFJlc0JlYW4uZ2V0KGkpOwoJCQkJCWlmIChiZWFuLmdldEV2ZW50RGF0ZSgpICE9IG51bGwgJiYgRGF0ZVV0aWwuY2hlY2tkYXRlRm9ybWF0KGJlYW4uZ2V0RXZlbnREYXRlKCkpKSB7CgkJCQkJCWJlYW4uc2V0RXZlbnREYXRlKERhdGVVdGlsLmRhdGVUb01pbmd1byhiZWFuLmdldEV2ZW50RGF0ZSgpKSk7CgkJCQkJfQoJCQkJCWlmIChiZWFuLmdldENsYWltUmVjZURhdGUoKSAhPSBudWxsICYmIERhdGVVdGlsLmNoZWNrZGF0ZUZvcm1hdChiZWFuLmdldENsYWltUmVjZURhdGUoKSkpIHsKCQkJCQkJYmVhbi5zZXRDbGFpbVJlY2VEYXRlKERhdGVVdGlsLmRhdGVUb01pbmd1byhiZWFuLmdldENsYWltUmVjZURhdGUoKSkpOwoJCQkJCX0KCQkJCQlpZiAoYmVhbi5nZXRDbGFpbVN1Ym1pdERhdGUoKSAhPSBudWxsICYmIERhdGVVdGlsLmNoZWNrZGF0ZUZvcm1hdChiZWFuLmdldENsYWltU3VibWl0RGF0ZSgpKSkgewoJCQkJCQliZWFuLnNldENsYWltU3VibWl0RGF0ZShEYXRlVXRpbC5kYXRlVG9NaW5ndW8oYmVhbi5nZXRDbGFpbVN1Ym1pdERhdGUoKSkpOwoJCQkJCX0KCQkJCQlsaXNDbGFpbVNjaGVkdWxlRGV0YWlsUmVzQmVhbi5zZXQoaSwgYmVhbik7CgkJCQl9CgkJCQkvLyDkv67mraPopb/lhYPngrrmsJHlnItfMjAyMzA1MjlfRW5kCgkJCQljbGFpbVNjaGVkdWxlRGV0YWlsUmVzQmVhbi5hZGRBbGwobGlzQ2xhaW1TY2hlZHVsZURldGFpbFJlc0JlYW4pOwoJCQl9CgkJfSBjYXRjaCAoQXBpRXhjZXB0aW9uIGUpIHsKCQkJTE9HR0VSLmVycm9yKCJ7XCJjbGFpbVNjaGVkdWxlRGV0YWlsUmVxQmVhblwiOiIgKyBjbGFpbVNjaGVkdWxlRGV0YWlsUmVxQmVhbi50b1N0cmluZygpICsgIn0iLCBlKTsKCQl9CgkJdXBkYXRlTm90aWNlRGV0YWlsUmVzQmVhbihjbGFpbVNjaGVkdWxlRGV0YWlsUmVzQmVhbiwgQXJlYUVudW0uUFJPR1JFU1NfREFUQV9BUkVBLAoJCQkJc2hvd1Byb2dyZXNzRGF0YURldGFpbEZvcm1CZWFuLmdldENhdGVnb3J5KCkpOwoJCXJldHVybiBjbGFpbVNjaGVkdWxlRGV0YWlsUmVzQmVhbjsKCX0KCglAUG9zdE1hcHBpbmcoIi9tZXNzYWdlRGF0YVBkZlJlcG9ydCIpCglwdWJsaWMgdm9pZCBnZXRNZXNzYWdlRGF0YVBkZlJlcG9ydChATW9kZWxBdHRyaWJ1dGUgUGRmUmVxRm9ybUJlYW4gcGRmUmVxQmVhbiwgSHR0cFNlcnZsZXRSZXNwb25zZSByZXNwb25zZSkKCQkJdGhyb3dzIEFwaUV4Y2VwdGlvbiwgSU9FeGNlcHRpb24gewoJCXJlc3BvbnNlLnNldENvbnRlbnRUeXBlKCJhcHBsaWNhdGlvbi9wZGYiKTsKCQlMT0dHRVIuaW5mbygidHlwZT1be31dIiwgcGRmUmVxQmVhbi5nZXRUeXBlKCkpOwoJCWlmIChNZXNzYWdlRGF0YVR5cGVFbnVtLmZpbmQocGRmUmVxQmVhbi5nZXRUeXBlKCkpLmlzQ2FzKCkpIHsKCQkJSU9VdGlscy53cml0ZSgKCQkJCQlvdGhlckFwaVNlcnZpY2UuZ2V0Q2FzUGRmKGNvcHlQcm9wZXJ0aWVzKHBkZlJlcUJlYW4sIFBkZlJlcUJlYW4uY2xhc3MpLCBnZXRBYWduYW1lKCksIGdldEFnZW50SWQoKSksCgkJCQkJcmVzcG9uc2UuZ2V0T3V0cHV0U3RyZWFtKCkpOwoJCX0gZWxzZSBpZiAoTWVzc2FnZURhdGFUeXBlRW51bS5maW5kKHBkZlJlcUJlYW4uZ2V0VHlwZSgpKS5pc0xzcCgpKSB7CgkJCUlPVXRpbHMud3JpdGUoCgkJCQkJb3RoZXJBcGlTZXJ2aWNlLmdldExzcFBkZihjb3B5UHJvcGVydGllcyhwZGZSZXFCZWFuLCBQZGZSZXFCZWFuLmNsYXNzKSwgZ2V0QWFnbmFtZSgpLCBnZXRBZ2VudElkKCkpLAoJCQkJCXJlc3BvbnNlLmdldE91dHB1dFN0cmVhbSgpKTsKCQl9IGVsc2UgaWYgKFN0cmluZ1V0aWxzLmVxdWFscyhwZGZSZXFCZWFuLmdldFR5cGUoKSwgTWVzc2FnZURhdGFEZXRhaWxFbnVtLkRhaWx5SW5zdXJhbmNlQmVuZWZpdHMubmFtZSgpKSkgewovLwkJCeavj+aXpeS/nemaque1puS7mOa4heWWrlBERgoJCQlQZGZUZW1wbGRhdGVSZXFCZWFuIHBkZlJlcSA9IHBkZlRlbXBsYXRlU2VydmljZS5nZXREYWlseUluc3VyYW5jZUJlbmVmaXRzRGF0YVRvUERGVGVtcGxhdGUoCgkJCQkJdGhpcy5nZXRUcmFuc2FnZW50Y29kZSgpLCB0aGlzLmdldEFhZ2NvZGUoKSwgcGRmUmVxQmVhbi5nZXRGaWxlbmFtZSgpLAoJCQkJCURhdGVVdGlsLnRyYW5zVG9Sb2NEYXRlQ2hpbmVzZURheShwZGZSZXFCZWFuLmdldEZpbGVuYW1lKCkpKTsKCQkJSU9VdGlscy53cml0ZShjaGFubmVsQXBpU2VydmljZS5nZXRQZGZUZW1wbGF0ZShwZGZSZXEsIGdldEFhZ25hbWUoKSwgZ2V0QWdlbnRJZCgpKSwKCQkJCQlyZXNwb25zZS5nZXRPdXRwdXRTdHJlYW0oKSk7CgkJfQoJCXJlc3BvbnNlLmZsdXNoQnVmZmVyKCk7Cgl9CgoJQFBvc3RNYXBwaW5nKCIvbmV3UG9saWN5U2NoZWR1bGVQREYiKQoJcHVibGljIHZvaWQgZ2V0TmV3UG9saWN5U2NoZWR1bGVQREYoQE1vZGVsQXR0cmlidXRlIE5ld1BvbGljeVNjaGVkdWxlUERGUmVxQmVhbiBuZXdQb2xpY3lTY2hlZHVsZVBERlJlcUJlYW4sCgkJCUh0dHBTZXJ2bGV0UmVzcG9uc2UgcmVzcG9uc2UpIHRocm93cyBBcGlFeGNlcHRpb24sIElPRXhjZXB0aW9uIHsKCQlyZXNwb25zZS5zZXRDb250ZW50VHlwZSgiYXBwbGljYXRpb24vcGRmIik7CiAgICAgICAgSU9VdGlscy53cml0ZShpS2FzaFNlcnZpY2UuZ2V0TmV3UG9saWN5U2NoZWR1bGVQREYobmV3UG9saWN5U2NoZWR1bGVQREZSZXFCZWFuLCBnZXRBYWduYW1lKCksIGdldEFnZW50SWQoKSksCiAgICAgICAgICAgICAgICByZXNwb25zZS5nZXRPdXRwdXRTdHJlYW0oKSk7CgkJcmVzcG9uc2UuZmx1c2hCdWZmZXIoKTsKCX0KCglwcml2YXRlIFN0cmluZyBnZXRTdGFydERhdGVTdHJpbmcoRGF0ZSBkYXRlLCBpbnQgdHlwZSwgaW50IHZhbHVlKSB7CgkJQ2FsZW5kYXIgY2FsZW5kYXIgPSBDYWxlbmRhci5nZXRJbnN0YW5jZSgpOwoJCWNhbGVuZGFyLnNldFRpbWUoZGF0ZSk7CgkJY2FsZW5kYXIuYWRkKHR5cGUsIHZhbHVlKTsKCQlEYXRlIHN0YXJ0RGF0ZSA9IGNhbGVuZGFyLmdldFRpbWUoKTsKCQlEYXRlRm9ybWF0IGRmU3RhcnQgPSBuZXcgU2ltcGxlRGF0ZUZvcm1hdCgieXl5eS1NTS1kZCdUMDA6MDA6MDAuMDAwJ1oiKTsKCQlyZXR1cm4gZGZTdGFydC5mb3JtYXQoc3RhcnREYXRlKTsKCX0KCglwcml2YXRlIFN0cmluZyBnZXRFbmREYXRlU3RyaW5nKERhdGUgZGF0ZSkgewoJCURhdGVGb3JtYXQgZGZFbmQgPSBuZXcgU2ltcGxlRGF0ZUZvcm1hdCgieXl5eS1NTS1kZCdUMjM6NTk6NTkuOTk5J1oiKTsKCQlyZXR1cm4gZGZFbmQuZm9ybWF0KGRhdGUpOwoJfQoKCXByaXZhdGUgU3RyaW5nIGdldFN0YXJ0U2xhc2hEYXRlU3RyaW5nKERhdGUgZGF0ZSwgaW50IHR5cGUsIGludCB2YWx1ZSkgewoJCUNhbGVuZGFyIGNhbGVuZGFyID0gQ2FsZW5kYXIuZ2V0SW5zdGFuY2UoKTsKCQljYWxlbmRhci5zZXRUaW1lKGRhdGUpOwoJCWNhbGVuZGFyLmFkZCh0eXBlLCB2YWx1ZSk7CgkJRGF0ZSBzdGFydERhdGUgPSBjYWxlbmRhci5nZXRUaW1lKCk7CgkJRGF0ZUZvcm1hdCBkZlN0YXJ0ID0gbmV3IFNpbXBsZURhdGVGb3JtYXQoInl5eXkvTU0vZGQiKTsKCQlyZXR1cm4gZGZTdGFydC5mb3JtYXQoc3RhcnREYXRlKTsKCX0KCglwcml2YXRlIFN0cmluZyBnZXRFbmRTbGFzaERhdGVTdHJpbmcoRGF0ZSBkYXRlKSB7CgkJRGF0ZUZvcm1hdCBkZkVuZCA9IG5ldyBTaW1wbGVEYXRlRm9ybWF0KCJ5eXl5L01NL2RkIik7CgkJcmV0dXJuIGRmRW5kLmZvcm1hdChkYXRlKTsKCX0KCglwcml2YXRlIENvbXBsZXRhYmxlRnV0dXJlPExpc3Q8TWVzc2FnZURhdGFDb3VudFJlc0JlYW4+PiBnZXRNZXNzYWdlRGF0YUNvdW50UmVzQmVhbnMoKSB7CgkJRGF0ZSByaWdodE5vdyA9IG5ldyBEYXRlKCk7CgkJU3RyaW5nIHN0YXJ0RGF0ZVN0ciA9IGdldFN0YXJ0RGF0ZVN0cmluZyhyaWdodE5vdywgQ2FsZW5kYXIuREFZX09GX1lFQVIsIHBlcmlvZCk7CgkJU3RyaW5nIGVuZERhdGVTdHIgPSBnZXRFbmREYXRlU3RyaW5nKHJpZ2h0Tm93KTsKCgkJU3RyaW5nIGVuZFJvY0RhdGVTdHIgPSBEYXRlVXRpbC5nZXRDdXJyZW50Um9jRGF0ZSgpOy8vIHl5eS9tbS9kZAoJCVN0cmluZyBzdGFyUm9jdERhdGVTdHIgPSBEYXRlVXRpbC5hZGREYXkoZW5kUm9jRGF0ZVN0ciwgcGVyaW9kKTsvLyB5eXkvbW0vZGQKCQlTdHJpbmcgYWdlbnRJZCA9IHRoaXMuZ2V0QWdlbnRJZCgpOwoJCVN0cmluZyBhYWdjb2RlID0gdGhpcy5nZXRBYWdjb2RlKCk7CgkJU3RyaW5nIHRyYW5zYWdlbnRjb2RlID0gdGhpcy5nZXRUcmFuc2FnZW50Y29kZSgpOwoKCQlDb21wbGV0YWJsZUZ1dHVyZTxMaXN0PE1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuPj4gbWVzc2FnZURhdGFDb3VudFJlc0JlYW5zRnV0dXJlID0gQ29tcGxldGFibGVGdXR1cmUKCQkJCS5zdXBwbHlBc3luYygoKSAtPiB7CgkJCQkJTGlzdDxNZXNzYWdlRGF0YUNvdW50UmVzQmVhbj4gbWVzc2FnZURhdGFDb3VudFJlc0JlYW5zID0gbmV3IEFycmF5TGlzdDxNZXNzYWdlRGF0YUNvdW50UmVzQmVhbj4oKTsKCQkJCQl0cnkgewoJCQkJCQlNZXNzYWdlRGF0YUNvdW50UmVxQmVhbiBtZXNzYWdlRGF0YUNvdW50UmVxQmVhbiA9IG5ldyBNZXNzYWdlRGF0YUNvdW50UmVxQmVhbigpOwoJCQkJCQltZXNzYWdlRGF0YUNvdW50UmVxQmVhbi5zZXRBZ2VudElkKGFnZW50SWQpOwoJCQkJCQltZXNzYWdlRGF0YUNvdW50UmVxQmVhbi5zZXRTdGFydERhdGUoc3RhcnREYXRlU3RyKTsKCQkJCQkJbWVzc2FnZURhdGFDb3VudFJlcUJlYW4uc2V0RW5kRGF0ZShlbmREYXRlU3RyKTsKCQkJCQkJbWVzc2FnZURhdGFDb3VudFJlc0JlYW5zID0gaUthc2hTZXJ2aWNlLmdldE1lc3NhZ2VEYXRhQ291bnQobWVzc2FnZURhdGFDb3VudFJlcUJlYW4pOwoJCQkJCQlpZiAobWVzc2FnZURhdGFDb3VudFJlc0JlYW5zID09IG51bGwpIHsKCQkJCQkJCW1lc3NhZ2VEYXRhQ291bnRSZXNCZWFucyA9IG5ldyBBcnJheUxpc3Q8TWVzc2FnZURhdGFDb3VudFJlc0JlYW4+KCk7CgkJCQkJCX0KCQkJCQl9IGNhdGNoIChBcGlFeGNlcHRpb24gZSkgewoJCQkJCQlMT0dHRVIuZXJyb3IoInsnY29kZSc6JyIgKyBlLmdldENvZGUoKSArICInLCdtZXNzYWdlJzonIiArIGUuZ2V0TWVzc2FnZSgpICsgIicsICdkZXNjcmlwdGlvbic6JyIKCQkJCQkJCQkrIGUuZ2V0RGVzY3JpcHRpb24oKSArICInfSIsIGUpOwoJCQkJCX0KCQkJCQlyZXR1cm4gbWVzc2FnZURhdGFDb3VudFJlc0JlYW5zOwoJCQkJfSwgZXhlY3V0b3IpOwoKCQlDb21wbGV0YWJsZUZ1dHVyZTxMaXN0PE1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuPj4gbHNwTWVzc2FnZURhdGFDb3VudFJlc0JlYW5zRnV0dXJlID0gQ29tcGxldGFibGVGdXR1cmUKCQkJCS5zdXBwbHlBc3luYygoKSAtPiB7CgkJCQkJTGlzdDxNZXNzYWdlRGF0YUNvdW50UmVzQmVhbj4gbHNwTWVzc2FnZURhdGFDb3VudFJlc0JlYW5zID0gbmV3IEFycmF5TGlzdDxNZXNzYWdlRGF0YUNvdW50UmVzQmVhbj4oKTsKCQkJCQl0cnkgewoJCQkJCQlMc3BNZXNzYWdlRGF0YUNvdW50UmVxQmVhbiBsc3BNZXNzYWdlRGF0YUNvdW50UmVxQmVhbiA9IG5ldyBMc3BNZXNzYWdlRGF0YUNvdW50UmVxQmVhbigpOwoJCQkJCQlsc3BNZXNzYWdlRGF0YUNvdW50UmVxQmVhbi5zZXRBZ2VudENvZGUoYWFnY29kZSk7CgkJCQkJCWxzcE1lc3NhZ2VEYXRhQ291bnRSZXFCZWFuLnNldFN0YXJ0RGF0ZShzdGFydERhdGVTdHIpOwoJCQkJCQlsc3BNZXNzYWdlRGF0YUNvdW50UmVxQmVhbi5zZXRFbmREYXRlKGVuZERhdGVTdHIpOwoJCQkJCQlsc3BNZXNzYWdlRGF0YUNvdW50UmVzQmVhbnMgPSBjaGFubmVsQXBpU2VydmljZQoJCQkJCQkJCS5nZXRMc3BNZXNzYWdlRGF0YUNvdW50KGxzcE1lc3NhZ2VEYXRhQ291bnRSZXFCZWFuKTsKCQkJCQl9IGNhdGNoIChBcGlFeGNlcHRpb24gZSkgewoJCQkJCQlMT0dHRVIuZXJyb3IoInsnY29kZSc6JyIgKyBlLmdldENvZGUoKSArICInLCdtZXNzYWdlJzonIiArIGUuZ2V0TWVzc2FnZSgpICsgIicsICdkZXNjcmlwdGlvbic6JyIKCQkJCQkJCQkrIGUuZ2V0RGVzY3JpcHRpb24oKSArICInfSIsIGUpOwoJCQkJCX0KCQkJCQlyZXR1cm4gbHNwTWVzc2FnZURhdGFDb3VudFJlc0JlYW5zOwoJCQkJfSwgZXhlY3V0b3IpOwoJCUNvbXBsZXRhYmxlRnV0dXJlPExpc3Q8TWVzc2FnZURhdGFDb3VudFJlc0JlYW4+PiBjbXNNZXNzYWdlRGF0YUNvdW50UmVzQmVhbnNGdXR1cmUgPSBDb21wbGV0YWJsZUZ1dHVyZQoJCQkJLnN1cHBseUFzeW5jKCgpIC0+IHsKCQkJCQlMaXN0PE1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuPiBjbXNNZXNzYWdlRGF0YUNvdW50UmVzQmVhbnMgPSBuZXcgQXJyYXlMaXN0PE1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuPigpOwoJCQkJCXRyeSB7CgkJCQkJCUNtc01lc3NhZ2VEYXRhQ291bnRSZXFCZWFuIGNtc01lc3NhZ2VEYXRhQ291bnRSZXFCZWFuID0gbmV3IENtc01lc3NhZ2VEYXRhQ291bnRSZXFCZWFuKCk7CgkJCQkJCWNtc01lc3NhZ2VEYXRhQ291bnRSZXFCZWFuLnNldEFnZW50Q29kZShhYWdjb2RlKTsKCQkJCQkJY21zTWVzc2FnZURhdGFDb3VudFJlcUJlYW4uc2V0U3RhcnREYXRlKHN0YXJ0RGF0ZVN0cik7CgkJCQkJCWNtc01lc3NhZ2VEYXRhQ291bnRSZXFCZWFuLnNldEVuZERhdGUoZW5kRGF0ZVN0cik7CgkJCQkJCWNtc01lc3NhZ2VEYXRhQ291bnRSZXNCZWFucyA9IGNoYW5uZWxBcGlTZXJ2aWNlCgkJCQkJCQkJLmdldENtc01lc3NhZ2VEYXRhQ291bnQoY21zTWVzc2FnZURhdGFDb3VudFJlcUJlYW4pOwoJCQkJCX0gY2F0Y2ggKEFwaUV4Y2VwdGlvbiBlKSB7CgkJCQkJCUxPR0dFUi5lcnJvcigieydjb2RlJzonIiArIGUuZ2V0Q29kZSgpICsgIicsJ21lc3NhZ2UnOiciICsgZS5nZXRNZXNzYWdlKCkgKyAiJywgJ2Rlc2NyaXB0aW9uJzonIgoJCQkJCQkJCSsgZS5nZXREZXNjcmlwdGlvbigpICsgIid9IiwgZSk7CgkJCQkJfQoJCQkJCXJldHVybiBjbXNNZXNzYWdlRGF0YUNvdW50UmVzQmVhbnM7CgkJCQl9LCBleGVjdXRvcik7CgoJCUNvbXBsZXRhYmxlRnV0dXJlPExpc3Q8TWVzc2FnZURhdGFDb3VudFJlc0JlYW4+PiBsc3BNZXNzYWdlRGF0YUNvdW50Q2wyMDdyUmVzQmVhbnNGdXR1cmUgPSBDb21wbGV0YWJsZUZ1dHVyZQoJCQkJLnN1cHBseUFzeW5jKCgpIC0+IHsKCQkJCQlMaXN0PE1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuPiBsc3BNZXNzYWdlRGF0YUNvdW50Q2wyMDdyUmVzQmVhbnMgPSBuZXcgQXJyYXlMaXN0PE1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuPigpOwoJCQkJCXRyeSB7CgkJCQkJCUxzcE1lc3NhZ2VEYXRhQ291bnRSZXFCZWFuIGxzcE1lc3NhZ2VEYXRhQ291bnRSZXFCZWFuID0gbmV3IExzcE1lc3NhZ2VEYXRhQ291bnRSZXFCZWFuKCk7CgkJCQkJCWxzcE1lc3NhZ2VEYXRhQ291bnRSZXFCZWFuLnNldEFnZW50Q29kZShhYWdjb2RlKTsKCQkJCQkJbHNwTWVzc2FnZURhdGFDb3VudFJlcUJlYW4uc2V0U3RhcnREYXRlKHN0YXJ0RGF0ZVN0cik7CgkJCQkJCWxzcE1lc3NhZ2VEYXRhQ291bnRSZXFCZWFuLnNldEVuZERhdGUoZW5kRGF0ZVN0cik7CgkJCQkJCWxzcE1lc3NhZ2VEYXRhQ291bnRDbDIwN3JSZXNCZWFucyA9IGNoYW5uZWxBcGlTZXJ2aWNlCgkJCQkJCQkJLmdldExzcE1lc3NhZ2VEYXRhQ2wyMDdyQ291bnQobHNwTWVzc2FnZURhdGFDb3VudFJlcUJlYW4pOwoJCQkJCX0gY2F0Y2ggKEFwaUV4Y2VwdGlvbiBlKSB7CgkJCQkJCUxPR0dFUi5lcnJvcigieydjb2RlJzonIiArIGUuZ2V0Q29kZSgpICsgIicsJ21lc3NhZ2UnOiciICsgZS5nZXRNZXNzYWdlKCkgKyAiJywgJ2Rlc2NyaXB0aW9uJzonIgoJCQkJCQkJCSsgZS5nZXREZXNjcmlwdGlvbigpICsgIid9IiwgZSk7CgkJCQkJfQoJCQkJCXJldHVybiBsc3BNZXNzYWdlRGF0YUNvdW50Q2wyMDdyUmVzQmVhbnM7CgkJCQl9LCBleGVjdXRvcik7CgkJQ29tcGxldGFibGVGdXR1cmU8TGlzdDxNZXNzYWdlRGF0YUNvdW50UmVzQmVhbj4+IHZsaWZlTWVzc2FnZURhdGFDb3VudFJlc0JlYW5zRnV0dXJlID0gQ29tcGxldGFibGVGdXR1cmUKCQkJCS5zdXBwbHlBc3luYygoKSAtPiB7CgkJCQkJTGlzdDxNZXNzYWdlRGF0YUNvdW50UmVzQmVhbj4gdmxpZmVNZXNzYWdlRGF0YUNvdW50UmVzQmVhbnMgPSBuZXcgQXJyYXlMaXN0PE1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuPigpOwoJCQkJCXRyeSB7CgkJCQkJCS8vIOavj+aXpee1puS7mOa4heWWrgoJCQkJCQlEYWlseUluc3VyYW5jZUJlbmVmaXRzQ291bnRSZXFCZWFuIGRhaWx5SW5zdXJhbmNlQmVuZWZpdHNDb3VudFJlcUJlYW4gPSBuZXcgRGFpbHlJbnN1cmFuY2VCZW5lZml0c0NvdW50UmVxQmVhbigpOwoJCQkJCQlkYWlseUluc3VyYW5jZUJlbmVmaXRzQ291bnRSZXFCZWFuLnNldEFnZW50Q29kZSh0cmFuc2FnZW50Y29kZSk7CgkJCQkJCWRhaWx5SW5zdXJhbmNlQmVuZWZpdHNDb3VudFJlcUJlYW4uc2V0U3RhcnREYXRlKHN0YXJSb2N0RGF0ZVN0cik7CgkJCQkJCWRhaWx5SW5zdXJhbmNlQmVuZWZpdHNDb3VudFJlcUJlYW4uc2V0RW5kRGF0ZShlbmRSb2NEYXRlU3RyKTsKCQkJCQkJTWVzc2FnZURhdGFDb3VudFJlc0JlYW4gZGFpbHlJbnN1cmFuY2VCZW5lZml0c0NvdW50ID0gY2hhbm5lbEFwaVNlcnZpY2UKCQkJCQkJCQkuZ2V0RGFpbHlJbnN1cmFuY2VCZW5lZml0c0NvdW50KGRhaWx5SW5zdXJhbmNlQmVuZWZpdHNDb3VudFJlcUJlYW4pOwoJCQkJCQlpZiAoZGFpbHlJbnN1cmFuY2VCZW5lZml0c0NvdW50ICE9IG51bGwgJiYgZGFpbHlJbnN1cmFuY2VCZW5lZml0c0NvdW50LmdldENvdW50KCkgPiAwKSB7CgkJCQkJCQl2bGlmZU1lc3NhZ2VEYXRhQ291bnRSZXNCZWFucy5hZGQoZGFpbHlJbnN1cmFuY2VCZW5lZml0c0NvdW50KTsKCQkJCQkJfQoJCQkJCX0gY2F0Y2ggKEFwaUV4Y2VwdGlvbiBlKSB7CgkJCQkJCUxPR0dFUi5lcnJvcigieydjb2RlJzonIiArIGUuZ2V0Q29kZSgpICsgIicsJ21lc3NhZ2UnOiciICsgZS5nZXRNZXNzYWdlKCkgKyAiJywgJ2Rlc2NyaXB0aW9uJzonIgoJCQkJCQkJCSsgZS5nZXREZXNjcmlwdGlvbigpICsgIid9IiwgZSk7CgkJCQkJfQoJCQkJCXJldHVybiB2bGlmZU1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuczsKCQkJCX0sIGV4ZWN1dG9yKTsKCgkJQ29tcGxldGFibGVGdXR1cmU8TGlzdDxNZXNzYWdlRGF0YUNvdW50UmVzQmVhbj4+IGxzcFJlbWluTm90aWNlUmV0dXJuUmVzQmVhbnNGdXR1cmUgPSBDb21wbGV0YWJsZUZ1dHVyZQoJCQkJLnN1cHBseUFzeW5jKCgpIC0+IHsKCQkJCQlMaXN0PE1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuPiBsc3BSZW1pbk5vdGljZVJldHVyblJlc0JlYW5zID0gbmV3IEFycmF5TGlzdDxNZXNzYWdlRGF0YUNvdW50UmVzQmVhbj4oKTsKCQkJCQl0cnkgewoJCQkJCQlMc3BNZXNzYWdlRGF0YUNvdW50UmVxQmVhbiBsc3BNZXNzYWdlRGF0YUNvdW50UmVxQmVhbiA9IG5ldyBMc3BNZXNzYWdlRGF0YUNvdW50UmVxQmVhbigpOwoJCQkJCQlsc3BNZXNzYWdlRGF0YUNvdW50UmVxQmVhbi5zZXRBZ2VudENvZGUoYWFnY29kZSk7CgkJCQkJCWxzcE1lc3NhZ2VEYXRhQ291bnRSZXFCZWFuLnNldFN0YXJ0RGF0ZShzdGFydERhdGVTdHIpOwoJCQkJCQlsc3BNZXNzYWdlRGF0YUNvdW50UmVxQmVhbi5zZXRFbmREYXRlKGVuZERhdGVTdHIpOwoKCQkJCQkJTWVzc2FnZURhdGFDb3VudFJlc0JlYW4gbHNwTWVzc2FnZURhdGFDb3VudFJlc0JlYW4gPSBjaGFubmVsQXBpU2VydmljZQoJCQkJCQkJCS5nZXRMc3BSZW1pbk5vdGljZVJldHVybk1lc3NhZ2VEYXRhQ291bnQobHNwTWVzc2FnZURhdGFDb3VudFJlcUJlYW4pOwoKCQkJCQkJaWYgKGxzcE1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuICE9IG51bGwgJiYgbHNwTWVzc2FnZURhdGFDb3VudFJlc0JlYW4uZ2V0Q291bnQoKSA+IDApIHsKCQkJCQkJCWxzcFJlbWluTm90aWNlUmV0dXJuUmVzQmVhbnMuYWRkKGxzcE1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuKTsKCQkJCQkJfQoKCQkJCQl9IGNhdGNoIChBcGlFeGNlcHRpb24gZSkgewoJCQkJCQlMT0dHRVIuZXJyb3IoInsnY29kZSc6JyIgKyBlLmdldENvZGUoKSArICInLCdtZXNzYWdlJzonIiArIGUuZ2V0TWVzc2FnZSgpICsgIicsICdkZXNjcmlwdGlvbic6JyIKCQkJCQkJCQkrIGUuZ2V0RGVzY3JpcHRpb24oKSArICInfSIsIGUpOwoJCQkJCX0KCQkJCQlyZXR1cm4gbHNwUmVtaW5Ob3RpY2VSZXR1cm5SZXNCZWFuczsKCQkJCX0sIGV4ZWN1dG9yKTsKCgkJQ29tcGxldGFibGVGdXR1cmU8TGlzdDxNZXNzYWdlRGF0YUNvdW50UmVzQmVhbj4+IGxzcFJlaW5zdGF0ZW1lbnROb3RpY2VSZXNCZWFuc0Z1dHVyZSA9IENvbXBsZXRhYmxlRnV0dXJlCgkJCQkuc3VwcGx5QXN5bmMoKCkgLT4gewoJCQkJCUxpc3Q8TWVzc2FnZURhdGFDb3VudFJlc0JlYW4+IGxzcFJlaW5zdGF0ZW1lbnROb3RpY2VSZXNCZWFucyA9IG5ldyBBcnJheUxpc3Q8TWVzc2FnZURhdGFDb3VudFJlc0JlYW4+KCk7CgkJCQkJdHJ5IHsKCQkJCQkJTHNwTWVzc2FnZURhdGFDb3VudFJlcUJlYW4gbHNwTWVzc2FnZURhdGFDb3VudFJlcUJlYW4gPSBuZXcgTHNwTWVzc2FnZURhdGFDb3VudFJlcUJlYW4oKTsKCQkJCQkJbHNwTWVzc2FnZURhdGFDb3VudFJlcUJlYW4uc2V0QWdlbnRDb2RlKGFhZ2NvZGUpOwoJCQkJCQlsc3BNZXNzYWdlRGF0YUNvdW50UmVxQmVhbi5zZXRTdGFydERhdGUoc3RhcnREYXRlU3RyKTsKCQkJCQkJbHNwTWVzc2FnZURhdGFDb3VudFJlcUJlYW4uc2V0RW5kRGF0ZShlbmREYXRlU3RyKTsKCgkJCQkJCU1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuIGxzcE1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuID0gY2hhbm5lbEFwaVNlcnZpY2UKCQkJCQkJCQkuZ2V0THNwUmVpbnN0YXRlbWVudE5vdGljZU1lc3NhZ2VEYXRhQ291bnQobHNwTWVzc2FnZURhdGFDb3VudFJlcUJlYW4pOwoKCQkJCQkJaWYgKGxzcE1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuICE9IG51bGwgJiYgbHNwTWVzc2FnZURhdGFDb3VudFJlc0JlYW4uZ2V0Q291bnQoKSA+IDApIHsKCQkJCQkJCWxzcFJlaW5zdGF0ZW1lbnROb3RpY2VSZXNCZWFucy5hZGQobHNwTWVzc2FnZURhdGFDb3VudFJlc0JlYW4pOwoJCQkJCQl9CgoJCQkJCX0gY2F0Y2ggKEFwaUV4Y2VwdGlvbiBlKSB7CgkJCQkJCUxPR0dFUi5lcnJvcigieydjb2RlJzonIiArIGUuZ2V0Q29kZSgpICsgIicsJ21lc3NhZ2UnOiciICsgZS5nZXRNZXNzYWdlKCkgKyAiJywgJ2Rlc2NyaXB0aW9uJzonIgoJCQkJCQkJCSsgZS5nZXREZXNjcmlwdGlvbigpICsgIid9IiwgZSk7CgkJCQkJfQoJCQkJCXJldHVybiBsc3BSZWluc3RhdGVtZW50Tm90aWNlUmVzQmVhbnM7CgkJCQl9LCBleGVjdXRvcik7CgoJCUNvbXBsZXRhYmxlRnV0dXJlPExpc3Q8TWVzc2FnZURhdGFDb3VudFJlc0JlYW4+PiBsaXNNZXNzYWdlRGF0YUNvdW50UmVzQmVhbnNGdXR1cmUgPSBDb21wbGV0YWJsZUZ1dHVyZQoJCQkJLnN1cHBseUFzeW5jKCgpIC0+IHsKCQkJCQlMaXN0PE1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuPiBsaXNNZXNzYWdlRGF0YUNvdW50UmVzQmVhbnMgPSBuZXcgQXJyYXlMaXN0PE1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuPigpOwoJCQkJCXRyeSB7CgoJCQkJCQlMaXNNZXNzYWdlRGF0YUNvdW50UmVxQmVhbiBsaXNNZXNzYWdlRGF0YUNvdW50UmVxQmVhbiA9IG5ldyBMaXNNZXNzYWdlRGF0YUNvdW50UmVxQmVhbigpOwoJCQkJCQlsaXNNZXNzYWdlRGF0YUNvdW50UmVxQmVhbi5zZXRBZ2VudENvZGUoYWdlbnRJZCk7CgkJCQkJCS8vIGxpc01lc3NhZ2VEYXRhQ291bnRSZXFCZWFuLnNldEFnZW50Q29kZSgiSjIyMDQ2MDExMCIpOwoJCQkJCQlsaXNNZXNzYWdlRGF0YUNvdW50UmVxQmVhbi5zZXRTdGFydERhdGUoc3RhcnREYXRlU3RyKTsKCQkJCQkJbGlzTWVzc2FnZURhdGFDb3VudFJlcUJlYW4uc2V0RW5kRGF0ZShlbmREYXRlU3RyKTsKCQkJCQkJTGlzTWVzc2FnZURhdGFDb3VudFJlc0JlYW4gbGlzRGF0YSA9IGxpc0FwaVNlcnZpY2UKCQkJCQkJCQkuZ2V0TGlzTWVzc2FnZURhdGFDb3VudChsaXNNZXNzYWdlRGF0YUNvdW50UmVxQmVhbik7CgkJCQkJCWlmIChsaXNEYXRhICE9IG51bGwpCgkJCQkJCQlsaXNNZXNzYWdlRGF0YUNvdW50UmVzQmVhbnMgPSBsaXNEYXRhLmdldE1lc3NhZ2VEYXRhQ291bnRSZXNCZWFubGlzdCgpOwoJCQkJCX0gY2F0Y2ggKEFwaUV4Y2VwdGlvbiBlKSB7CgkJCQkJCUxPR0dFUi5lcnJvcigieydjb2RlJzonIiArIGUuZ2V0Q29kZSgpICsgIicsJ21lc3NhZ2UnOiciICsgZS5nZXRNZXNzYWdlKCkgKyAiJywgJ2Rlc2NyaXB0aW9uJzonIgoJCQkJCQkJCSsgZS5nZXREZXNjcmlwdGlvbigpICsgIid9IiwgZSk7CgkJCQkJfQoJCQkJCXJldHVybiBsaXNNZXNzYWdlRGF0YUNvdW50UmVzQmVhbnM7CgkJCQl9LCBleGVjdXRvcik7CgoJCUNvbXBsZXRhYmxlRnV0dXJlPExpc3Q8TWVzc2FnZURhdGFDb3VudFJlc0JlYW4+PiBmdXR1cmUgPSBDb21wbGV0YWJsZUZ1dHVyZQoJCQkJLmFsbE9mKG1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuc0Z1dHVyZSwgbHNwTWVzc2FnZURhdGFDb3VudFJlc0JlYW5zRnV0dXJlLAoJCQkJCQljbXNNZXNzYWdlRGF0YUNvdW50UmVzQmVhbnNGdXR1cmUsIGxzcE1lc3NhZ2VEYXRhQ291bnRDbDIwN3JSZXNCZWFuc0Z1dHVyZSwKCQkJCQkJdmxpZmVNZXNzYWdlRGF0YUNvdW50UmVzQmVhbnNGdXR1cmUsIGxzcFJlbWluTm90aWNlUmV0dXJuUmVzQmVhbnNGdXR1cmUsCgkJCQkJCWxzcFJlaW5zdGF0ZW1lbnROb3RpY2VSZXNCZWFuc0Z1dHVyZSwgbGlzTWVzc2FnZURhdGFDb3VudFJlc0JlYW5zRnV0dXJlKQoJCQkJLnRoZW5BcHBseSh4IC0+IHsKCQkJCQlMaXN0PE1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuPiBtZXNzYWdlRGF0YUNvdW50UmVzQmVhbnMgPSBtZXNzYWdlRGF0YUNvdW50UmVzQmVhbnNGdXR1cmUuam9pbigpOwoJCQkJCUxpc3Q8TWVzc2FnZURhdGFDb3VudFJlc0JlYW4+IGxzcE1lc3NhZ2VEYXRhQ291bnRSZXNCZWFucyA9IGxzcE1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuc0Z1dHVyZQoJCQkJCQkJLmpvaW4oKTsKCQkJCQlMaXN0PE1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuPiBjbXNNZXNzYWdlRGF0YUNvdW50UmVzQmVhbnMgPSBjbXNNZXNzYWdlRGF0YUNvdW50UmVzQmVhbnNGdXR1cmUKCQkJCQkJCS5qb2luKCk7CgkJCQkJTGlzdDxNZXNzYWdlRGF0YUNvdW50UmVzQmVhbj4gbHNwTWVzc2FnZURhdGFDb3VudENsMjA3clJlc0JlYW5zID0gbHNwTWVzc2FnZURhdGFDb3VudENsMjA3clJlc0JlYW5zRnV0dXJlCgkJCQkJCQkuam9pbigpOwoJCQkJCUxpc3Q8TWVzc2FnZURhdGFDb3VudFJlc0JlYW4+IHZsaWZlTWVzc2FnZURhdGFDb3VudFJlc0JlYW5zID0gdmxpZmVNZXNzYWdlRGF0YUNvdW50UmVzQmVhbnNGdXR1cmUKCQkJCQkJCS5qb2luKCk7CgkJCQkJTGlzdDxNZXNzYWdlRGF0YUNvdW50UmVzQmVhbj4gbHNwUmVtaW5Ob3RpY2VSZXR1cm5SZXNCZWFucyA9IGxzcFJlbWluTm90aWNlUmV0dXJuUmVzQmVhbnNGdXR1cmUKCQkJCQkJCS5qb2luKCk7CgkJCQkJTGlzdDxNZXNzYWdlRGF0YUNvdW50UmVzQmVhbj4gbHNwUmVpbnN0YXRlbWVudE5vdGljZVJlc0JlYW5zID0gbHNwUmVpbnN0YXRlbWVudE5vdGljZVJlc0JlYW5zRnV0dXJlCgkJCQkJCQkuam9pbigpOwoJCQkJCUxpc3Q8TWVzc2FnZURhdGFDb3VudFJlc0JlYW4+IGxpc01lc3NhZ2VEYXRhQ291bnRSZXNCZWFucyA9IGxpc01lc3NhZ2VEYXRhQ291bnRSZXNCZWFuc0Z1dHVyZQoJCQkJCQkJLmpvaW4oKTsKCgkJCQkJbWVyZ2VNZXNzYWdlRGF0YUNvdW50TGlzdChtZXNzYWdlRGF0YUNvdW50UmVzQmVhbnMsIGxzcE1lc3NhZ2VEYXRhQ291bnRSZXNCZWFucyk7CgkJCQkJbWVyZ2VNZXNzYWdlRGF0YUNvdW50TGlzdChtZXNzYWdlRGF0YUNvdW50UmVzQmVhbnMsIGNtc01lc3NhZ2VEYXRhQ291bnRSZXNCZWFucyk7CgkJCQkJbWVyZ2VNZXNzYWdlRGF0YUNvdW50TGlzdChtZXNzYWdlRGF0YUNvdW50UmVzQmVhbnMsIGxzcE1lc3NhZ2VEYXRhQ291bnRDbDIwN3JSZXNCZWFucyk7CgkJCQkJbWVyZ2VNZXNzYWdlRGF0YUNvdW50TGlzdChtZXNzYWdlRGF0YUNvdW50UmVzQmVhbnMsIHZsaWZlTWVzc2FnZURhdGFDb3VudFJlc0JlYW5zKTsKCQkJCQltZXJnZU1lc3NhZ2VEYXRhQ291bnRMaXN0KG1lc3NhZ2VEYXRhQ291bnRSZXNCZWFucywgbHNwUmVtaW5Ob3RpY2VSZXR1cm5SZXNCZWFucyk7CgkJCQkJbWVyZ2VNZXNzYWdlRGF0YUNvdW50TGlzdChtZXNzYWdlRGF0YUNvdW50UmVzQmVhbnMsIGxzcFJlaW5zdGF0ZW1lbnROb3RpY2VSZXNCZWFucyk7CgkJCQkJbWVyZ2VNZXNzYWdlRGF0YUNvdW50TGlzdChtZXNzYWdlRGF0YUNvdW50UmVzQmVhbnMsIGxpc01lc3NhZ2VEYXRhQ291bnRSZXNCZWFucyk7CgkJCQkJaWYgKG1lc3NhZ2VEYXRhQ291bnRSZXNCZWFucyAhPSBudWxsKSB7CgkJCQkJCUNvbGxlY3Rpb25zLnNvcnQobWVzc2FnZURhdGFDb3VudFJlc0JlYW5zLCBuZXcgQ29tcGFyYXRvcjxNZXNzYWdlRGF0YUNvdW50UmVzQmVhbj4oKSB7CgkJCQkJCQlwdWJsaWMgaW50IGNvbXBhcmUoTWVzc2FnZURhdGFDb3VudFJlc0JlYW4gbWVzc2FnZURhdGFDb3VudFJlc0JlYW4xLAoJCQkJCQkJCQlNZXNzYWdlRGF0YUNvdW50UmVzQmVhbiBtZXNzYWdlRGF0YUNvdW50UmVzQmVhbjIpIHsKCQkJCQkJCQlTdHJpbmcgb3JkZXJpbmcxID0gTWVzc2FnZURhdGFPcmRlcmluZ0VudW0KCQkJCQkJCQkJCS5yZXNvbHZlKG1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuMS5nZXRBcDA5VHlwZTEoKSkgIT0gbnVsbAoJCQkJCQkJCQkJCQk/IE1lc3NhZ2VEYXRhT3JkZXJpbmdFbnVtCgkJCQkJCQkJCQkJCQkJLnJlc29sdmUobWVzc2FnZURhdGFDb3VudFJlc0JlYW4xLmdldEFwMDlUeXBlMSgpKS5nZXRPcmRlcmluZygpCgkJCQkJCQkJCQkJCTogIjk5IjsKCQkJCQkJCQlTdHJpbmcgb3JkZXJpbmcyID0gTWVzc2FnZURhdGFPcmRlcmluZ0VudW0KCQkJCQkJCQkJCS5yZXNvbHZlKG1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuMi5nZXRBcDA5VHlwZTEoKSkgIT0gbnVsbAoJCQkJCQkJCQkJCQk/IE1lc3NhZ2VEYXRhT3JkZXJpbmdFbnVtCgkJCQkJCQkJCQkJCQkJLnJlc29sdmUobWVzc2FnZURhdGFDb3VudFJlc0JlYW4yLmdldEFwMDlUeXBlMSgpKS5nZXRPcmRlcmluZygpCgkJCQkJCQkJCQkJCTogIjk5IjsKCQkJCQkJCQlyZXR1cm4gb3JkZXJpbmcxLmNvbXBhcmVUbyhvcmRlcmluZzIpOwoJCQkJCQkJfQoJCQkJCQl9KTsKCQkJCQl9CgoJCQkJCXJldHVybiBtZXNzYWdlRGF0YUNvdW50UmVzQmVhbnM7CgkJCQl9KTsKCgkJcmV0dXJuIGZ1dHVyZTsKCX0KCgkvKgoJICogcHJpdmF0ZSB2b2lkIGdldEhpc3RvcnlEYXRhQ291bnRSZXNCZWFucyhNb2RlbCBtb2RlbCkgeyBEYXRlIHJpZ2h0Tm93ID0gbmV3CgkgKiBEYXRlKCk7IExpc3Q8TWVzc2FnZURhdGFDb3VudFJlc0JlYW4+IGNhc0hpc3RvcnlEYXRhQ291bnRSZXNCZWFucyA9IG5ldwoJICogQXJyYXlMaXN0PE1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuPigpOyBMaXN0PE1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuPgoJICogbHNwSGlzdG9yeURhdGFDb3VudFJlc0JlYW5zID0gbmV3IEFycmF5TGlzdDxNZXNzYWdlRGF0YUNvdW50UmVzQmVhbj4oKTsKCSAqIFN0cmluZyBjYXNFcnJvck1lc3NhZ2UgPSAiIjsgU3RyaW5nIGhpc3RvcnlTdGFydERhdGUgPQoJICogZ2V0U3RhcnREYXRlU3RyaW5nKHJpZ2h0Tm93LCBDYWxlbmRhci5EQVlfT0ZfWUVBUiwgaGlzdG9yeVBlcmlvZCk7IFN0cmluZwoJICogaGlzdG9yeUVuZERhdGUgPSBnZXRFbmREYXRlU3RyaW5nKHJpZ2h0Tm93KTsgdHJ5IHsgQ2FzTWVzc2FnZURhdGFDb3VudFJlcUJlYW4KCSAqIGNhc01lc3NhZ2VEYXRhQ291bnRSZXFCZWFuID0gbmV3IENhc01lc3NhZ2VEYXRhQ291bnRSZXFCZWFuKCk7CgkgKiBjYXNNZXNzYWdlRGF0YUNvdW50UmVxQmVhbi5zZXRBZ2VudENvZGUodGhpcy5nZXRBYWdjb2RlKCkpOwoJICogY2FzTWVzc2FnZURhdGFDb3VudFJlcUJlYW4uc2V0U3RhcnREYXRlKGhpc3RvcnlTdGFydERhdGUpOwoJICogY2FzTWVzc2FnZURhdGFDb3VudFJlcUJlYW4uc2V0RW5kRGF0ZShoaXN0b3J5RW5kRGF0ZSk7CgkgKiBjYXNIaXN0b3J5RGF0YUNvdW50UmVzQmVhbnMgPQoJICogY2hhbm5lbEFwaVNlcnZpY2UuZ2V0Q2FzTWVzc2FnZURhdGFDb3VudChjYXNNZXNzYWdlRGF0YUNvdW50UmVxQmVhbik7CgkgKiBpZihjYXNIaXN0b3J5RGF0YUNvdW50UmVzQmVhbnMgIT0gbnVsbCkgewoJICogY2FzSGlzdG9yeURhdGFDb3VudFJlc0JlYW5zLmZvckVhY2gobWVzc2FnZURhdGFDb3VudFJlc0JlYW4gLT4KCSAqIG1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuLnNldFR5cGUoTWVzc2FnZURhdGFUeXBlRW51bS5DQVMuZ2V0VHlwZSgpKSk7IH0gZWxzZSB7CgkgKiBjYXNIaXN0b3J5RGF0YUNvdW50UmVzQmVhbnMgPSBuZXcgQXJyYXlMaXN0PE1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuPigpOyB9IH0KCSAqIGNhdGNoIChBcGlFeGNlcHRpb24gZSkgeyBjYXNFcnJvck1lc3NhZ2UgPSBlLmdldERlc2NyaXB0aW9uKCk7CgkgKiBMT0dHRVIuZXJyb3IoInsnY29kZSc6JyIgKyBlLmdldENvZGUoKSArICInLCdtZXNzYWdlJzonIiArIGUuZ2V0TWVzc2FnZSgpICsKCSAqICInLCAnZGVzY3JpcHRpb24nOiciICsgZS5nZXREZXNjcmlwdGlvbigpICsgIid9IiwgZSk7IH0gdHJ5IHsKCSAqIExzcE1lc3NhZ2VEYXRhQ291bnRSZXFCZWFuIExzcE1lc3NhZ2VEYXRhQ291bnRSZXFCZWFuID0gbmV3CgkgKiBMc3BNZXNzYWdlRGF0YUNvdW50UmVxQmVhbigpOwoJICogTHNwTWVzc2FnZURhdGFDb3VudFJlcUJlYW4uc2V0QWdlbnRDb2RlKHRoaXMuZ2V0QWFnY29kZSgpKTsKCSAqIExzcE1lc3NhZ2VEYXRhQ291bnRSZXFCZWFuLnNldFN0YXJ0RGF0ZShoaXN0b3J5U3RhcnREYXRlKTsKCSAqIExzcE1lc3NhZ2VEYXRhQ291bnRSZXFCZWFuLnNldEVuZERhdGUoaGlzdG9yeUVuZERhdGUpOwoJICogbHNwSGlzdG9yeURhdGFDb3VudFJlc0JlYW5zID0KCSAqIGNoYW5uZWxBcGlTZXJ2aWNlLmdldExzcEhpc3RvcnlEYXRhQ291bnQoTHNwTWVzc2FnZURhdGFDb3VudFJlcUJlYW4pOwoJICogaWYobHNwSGlzdG9yeURhdGFDb3VudFJlc0JlYW5zICE9IG51bGwpIHsKCSAqIGxzcEhpc3RvcnlEYXRhQ291bnRSZXNCZWFucy5mb3JFYWNoKG1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuIC0+CgkgKiBtZXNzYWdlRGF0YUNvdW50UmVzQmVhbi5zZXRUeXBlKE1lc3NhZ2VEYXRhVHlwZUVudW0uTFNQLmdldFR5cGUoKSkpOyB9IH0KCSAqIGNhdGNoIChBcGlFeGNlcHRpb24gZSkgeyBjYXNFcnJvck1lc3NhZ2UgPSBlLmdldERlc2NyaXB0aW9uKCk7CgkgKiBMT0dHRVIuZXJyb3IoInsnY29kZSc6JyIgKyBlLmdldENvZGUoKSArICInLCdtZXNzYWdlJzonIiArIGUuZ2V0TWVzc2FnZSgpICsKCSAqICInLCAnZGVzY3JpcHRpb24nOiciICsgZS5nZXREZXNjcmlwdGlvbigpICsgIid9IiwgZSk7IH0KCSAqIGlmKGNhc0hpc3RvcnlEYXRhQ291bnRSZXNCZWFucyAhPSBudWxsICYmIGxzcEhpc3RvcnlEYXRhQ291bnRSZXNCZWFucyAhPQoJICogbnVsbCkgeyBjYXNIaXN0b3J5RGF0YUNvdW50UmVzQmVhbnMuYWRkQWxsKGxzcEhpc3RvcnlEYXRhQ291bnRSZXNCZWFucyk7IH0KCSAqIG1vZGVsLmFkZEF0dHJpYnV0ZSgiY2FzRXJyb3JNZXNzYWdlIiwgY2FzRXJyb3JNZXNzYWdlKTsKCSAqIG1vZGVsLmFkZEF0dHJpYnV0ZSgiY2FzTWVzc2FnZURhdGEiLCBjYXNIaXN0b3J5RGF0YUNvdW50UmVzQmVhbnMpOyB9CgkgKi8KCglwcml2YXRlIENvbXBsZXRhYmxlRnV0dXJlPExpc3Q8Tm90aWNlRGF0YUNvdW50UmVzQmVhbj4+IGdldE5vdGljZURhdGFDb3VudFJlc0JlYW5zKFN0cmluZyBzdGFydERhdGVTdHIsCgkJCVN0cmluZyBlbmREYXRlU3RyKSB7CgkJU3RyaW5nIGFhZ0NvZGUgPSB0aGlzLmdldEFhZ2NvZGUoKTsKCQlTdHJpbmcgYWdlbnRJRCA9IHRoaXMuZ2V0QWdlbnRJZCgpOwoJCUNvbXBsZXRhYmxlRnV0dXJlPExpc3Q8Tm90aWNlRGF0YUNvdW50UmVzQmVhbj4+IG5vdGljZURhdGFDb3VudFJlc0JlYW5zRnV0dXJlID0gQ29tcGxldGFibGVGdXR1cmUKCQkJCS5zdXBwbHlBc3luYygoKSAtPiB7CgoJCQkJCUxpc3Q8Tm90aWNlRGF0YUNvdW50UmVzQmVhbj4gbm90aWNlRGF0YUNvdW50UmVzQmVhbnMgPSBuZXcgQXJyYXlMaXN0PE5vdGljZURhdGFDb3VudFJlc0JlYW4+KCk7CgkJCQkJdHJ5IHsKCQkJCQkJTm90aWNlRGF0YUNvdW50UmVxQmVhbiBub3RpY2VEYXRhQ291bnRSZXFCZWFuID0gbmV3IE5vdGljZURhdGFDb3VudFJlcUJlYW4oKTsKCQkJCQkJbm90aWNlRGF0YUNvdW50UmVxQmVhbi5zZXRBZ2VudENvZGUoYWFnQ29kZSk7CgkJCQkJCW5vdGljZURhdGFDb3VudFJlcUJlYW4uc2V0U3RhcnREYXRlKHN0YXJ0RGF0ZVN0cik7CgkJCQkJCW5vdGljZURhdGFDb3VudFJlcUJlYW4uc2V0RW5kRGF0ZShlbmREYXRlU3RyKTsKCQkJCQkJbm90aWNlRGF0YUNvdW50UmVzQmVhbnMgPSBpS2FzaFNlcnZpY2UuZ2V0Tm90aWNlRGF0YUNvdW50KG5vdGljZURhdGFDb3VudFJlcUJlYW4pOwoJCQkJCQlpZiAobm90aWNlRGF0YUNvdW50UmVzQmVhbnMgPT0gbnVsbCkgewoJCQkJCQkJbm90aWNlRGF0YUNvdW50UmVzQmVhbnMgPSBuZXcgQXJyYXlMaXN0PE5vdGljZURhdGFDb3VudFJlc0JlYW4+KCk7CgkJCQkJCX0KCQkJCQl9IGNhdGNoIChBcGlFeGNlcHRpb24gZSkgewoJCQkJCQlMT0dHRVIuZXJyb3IoInsnY29kZSc6JyIgKyBlLmdldENvZGUoKSArICInLCdtZXNzYWdlJzonIiArIGUuZ2V0TWVzc2FnZSgpICsgIicsICdkZXNjcmlwdGlvbic6JyIKCQkJCQkJCQkrIGUuZ2V0RGVzY3JpcHRpb24oKSArICInfSIsIGUpOwoJCQkJCX0KCQkJCQlyZXR1cm4gbm90aWNlRGF0YUNvdW50UmVzQmVhbnM7CgkJCQl9LCBleGVjdXRvcik7CgoJCUNvbXBsZXRhYmxlRnV0dXJlPExpc3Q8Tm90aWNlRGF0YUNvdW50UmVzQmVhbj4+IGxzcE5vdGljZURhdGFDb3VudFJlc0JlYW5zRnV0dXJlID0gQ29tcGxldGFibGVGdXR1cmUKCQkJCS5zdXBwbHlBc3luYygoKSAtPiB7CgkJCQkJTGlzdDxOb3RpY2VEYXRhQ291bnRSZXNCZWFuPiBsc3BOb3RpY2VEYXRhQ291bnRSZXNCZWFucyA9IG5ldyBBcnJheUxpc3Q8Tm90aWNlRGF0YUNvdW50UmVzQmVhbj4oKTsKCQkJCQl0cnkgewoJCQkJCQlMc3BOb3RpY2VEYXRhQ291bnRSZXFCZWFuIGxzcE5vdGljZURhdGFDb3VudFJlcUJlYW4gPSBuZXcgTHNwTm90aWNlRGF0YUNvdW50UmVxQmVhbigpOwoJCQkJCQlsc3BOb3RpY2VEYXRhQ291bnRSZXFCZWFuLnNldEFnZW50Q29kZShhYWdDb2RlKTsKCQkJCQkJbHNwTm90aWNlRGF0YUNvdW50UmVxQmVhbi5zZXRTdGFydERhdGUoc3RhcnREYXRlU3RyKTsKCQkJCQkJbHNwTm90aWNlRGF0YUNvdW50UmVxQmVhbi5zZXRFbmREYXRlKGVuZERhdGVTdHIpOwoJCQkJCQlsc3BOb3RpY2VEYXRhQ291bnRSZXNCZWFucyA9IGNoYW5uZWxBcGlTZXJ2aWNlLmdldExzcE5vdGljZURhdGFDb3VudChsc3BOb3RpY2VEYXRhQ291bnRSZXFCZWFuKTsKCQkJCQl9IGNhdGNoIChBcGlFeGNlcHRpb24gZSkgewoJCQkJCQlMT0dHRVIuZXJyb3IoInsnY29kZSc6JyIgKyBlLmdldENvZGUoKSArICInLCdtZXNzYWdlJzonIiArIGUuZ2V0TWVzc2FnZSgpICsgIicsICdkZXNjcmlwdGlvbic6JyIKCQkJCQkJCQkrIGUuZ2V0RGVzY3JpcHRpb24oKSArICInfSIsIGUpOwoJCQkJCX0KCQkJCQlyZXR1cm4gbHNwTm90aWNlRGF0YUNvdW50UmVzQmVhbnM7CgkJCQl9LCBleGVjdXRvcik7CgoJCUNvbXBsZXRhYmxlRnV0dXJlPExpc3Q8Tm90aWNlRGF0YUNvdW50UmVzQmVhbj4+IGxpc05vdGljZURhdGFDb3VudFJlc0JlYW5zRnV0dXJlID0gQ29tcGxldGFibGVGdXR1cmUKCQkJCS5zdXBwbHlBc3luYygoKSAtPiB7CgkJCQkJTGlzdDxOb3RpY2VEYXRhQ291bnRSZXNCZWFuPiBsaXNOb3RpY2VEYXRhQ291bnRSZXNCZWFucyA9IG5ldyBBcnJheUxpc3Q8Tm90aWNlRGF0YUNvdW50UmVzQmVhbj4oKTsKCQkJCQl0cnkgewoJCQkJCQlMaXNOb3RpY2VEYXRhQ291bnRSZXFCZWFuIGxpc05vdGljZURhdGFDb3VudFJlcUJlYW4gPSBuZXcgTGlzTm90aWNlRGF0YUNvdW50UmVxQmVhbigpOwoJCQkJCQlsaXNOb3RpY2VEYXRhQ291bnRSZXFCZWFuLnNldEFnZW50Q29kZShhYWdDb2RlKTsKCQkJCQkJbGlzTm90aWNlRGF0YUNvdW50UmVxQmVhbi5zZXRTdGFydERhdGUoc3RhcnREYXRlU3RyKTsKCQkJCQkJbGlzTm90aWNlRGF0YUNvdW50UmVxQmVhbi5zZXRFbmREYXRlKGVuZERhdGVTdHIpOwoJCQkJCQkvLyAxMTIwOTAxMTc5LTAwX1N0YXJ0CgkJCQkJCWxpc05vdGljZURhdGFDb3VudFJlcUJlYW4uc2V0VHJhblR5cGUoIlkiKTsKCQkJCQkJbGlzTm90aWNlRGF0YUNvdW50UmVxQmVhbi5zZXRTdGF0dXMoIignUCcsJ04nKSIpOwoJCQkJCQkvLyAxMTIwOTAxMTc5LTAwX0VuZAoJCQkJCQlMaXNOb3RpY2VEYXRhQ291bnRSZXNCZWFuIGxpc3QgPSBsaXNBcGlTZXJ2aWNlLmdldExpc05vdGljZURhdGFDb3VudChsaXNOb3RpY2VEYXRhQ291bnRSZXFCZWFuKTsKCQkJCQkJbGlzTm90aWNlRGF0YUNvdW50UmVzQmVhbnMgPSBsaXN0LmdldE5vdGljZURhdGFDb3VudFJlc0JlYW4oKTsKCQkJCQkJLy8g5Y675o6JY291bnTnrYbmlbjngrow55qE6aCF55uuX1N0YXJ0CgkJCQkJCWZvciAoaW50IGkgPSBsaXNOb3RpY2VEYXRhQ291bnRSZXNCZWFucy5zaXplKCkgLSAxOyBpID49IDA7IGktLSkgewoJCQkJCQkJTm90aWNlRGF0YUNvdW50UmVzQmVhbiBiZWFuID0gbGlzTm90aWNlRGF0YUNvdW50UmVzQmVhbnMuZ2V0KGkpOwoJCQkJCQkJaWYgKGJlYW4uZ2V0Q291bnQoKSA9PSAwKSB7CgkJCQkJCQkJbGlzTm90aWNlRGF0YUNvdW50UmVzQmVhbnMucmVtb3ZlKGkpOwoJCQkJCQkJfQoJCQkJCQl9CgkJCQkJCS8vIOWOu+aOiWNvdW50562G5pW454K6MOeahOmgheebrl9FbmQKCQkJCQl9IGNhdGNoIChBcGlFeGNlcHRpb24gZSkgewoJCQkJCQlMT0dHRVIuZXJyb3IoInsnY29kZSc6JyIgKyBlLmdldENvZGUoKSArICInLCdtZXNzYWdlJzonIiArIGUuZ2V0TWVzc2FnZSgpICsgIicsICdkZXNjcmlwdGlvbic6JyIKCQkJCQkJCQkrIGUuZ2V0RGVzY3JpcHRpb24oKSArICInfSIsIGUpOwoJCQkJCX0KCQkJCQlyZXR1cm4gbGlzTm90aWNlRGF0YUNvdW50UmVzQmVhbnM7CgkJCQl9LCBleGVjdXRvcik7CgoJCS8vMTE0LjA3LjIyXzExNDA3MDIyNjgtMDDnkIbos6DpgJrnn6Xmm7hfTElT57O757Wx5Liy5o6l5L6G5rqQ6Kq/5pW0KDExMDTmnIPorbBtZW1vKQoJCUNvbXBsZXRhYmxlRnV0dXJlPENsYW1Ob3RpY2VEYXRhQ291bnRSZXNCZWFuPiBjbGFtTm90ZU5vdGljZURhdGFDb3VudFJlc0JlYW5GdXR1cmUgPSBDb21wbGV0YWJsZUZ1dHVyZQoJCQkJLnN1cHBseUFzeW5jKCgpIC0+IHsKCQkJCQlDbGFtTm90aWNlRGF0YUNvdW50UmVzQmVhbiBjbGFtTm90aWNlRGF0YUNvdW50UmVzQmVhbiA9IG5ldyBDbGFtTm90aWNlRGF0YUNvdW50UmVzQmVhbigpOwoJCQkJCXRyeSB7CgkJCQkJCUNsYW1Ob3RlUmVxQmVhbiBjbGFtTm90ZVJlcUJlYW4gPSBuZXcgQ2xhbU5vdGVSZXFCZWFuKCk7CgkJCQkJCWNsYW1Ob3RlUmVxQmVhbi5zZXRBZ2VudElkKGFnZW50SUQpOwoJCQkJCQljbGFtTm90aWNlRGF0YUNvdW50UmVzQmVhbiA9IGNsYW1Ob3RlU2VydmljZS5nZXRDbGFtTm90aWNlRGF0YUNvdW50KGNsYW1Ob3RlUmVxQmVhbik7CgkJCQkJCS8vIOWOu+aOiWNvdW50562G5pW454K6MOeahOmgheebrl9FbmQKCQkJCQl9IGNhdGNoIChBcGlFeGNlcHRpb24gZSkgewoJCQkJCQlMT0dHRVIuZXJyb3IoInsnY29kZSc6JyIgKyBlLmdldENvZGUoKSArICInLCdtZXNzYWdlJzonIiArIGUuZ2V0TWVzc2FnZSgpICsgIicsICdkZXNjcmlwdGlvbic6JyIKCQkJCQkJCQkrIGUuZ2V0RGVzY3JpcHRpb24oKSArICInfSIsIGUpOwoJCQkJCX0KCQkJCQlyZXR1cm4gY2xhbU5vdGljZURhdGFDb3VudFJlc0JlYW47CgkJCQl9LCBleGVjdXRvcik7CgkJCgkJCgkJQ29tcGxldGFibGVGdXR1cmU8TGlzdDxOb3RpY2VEYXRhQ291bnRSZXNCZWFuPj4gZnV0dXJlID0gQ29tcGxldGFibGVGdXR1cmUuYWxsT2Yobm90aWNlRGF0YUNvdW50UmVzQmVhbnNGdXR1cmUsCgkJCQlsc3BOb3RpY2VEYXRhQ291bnRSZXNCZWFuc0Z1dHVyZSwgbGlzTm90aWNlRGF0YUNvdW50UmVzQmVhbnNGdXR1cmUsIGNsYW1Ob3RlTm90aWNlRGF0YUNvdW50UmVzQmVhbkZ1dHVyZSkudGhlbkFwcGx5KHggLT4gewoJCQkJCUxpc3Q8Tm90aWNlRGF0YUNvdW50UmVzQmVhbj4gbm90aWNlRGF0YUNvdW50UmVzQmVhbnMgPSBub3RpY2VEYXRhQ291bnRSZXNCZWFuc0Z1dHVyZS5qb2luKCk7CgkJCQkJTGlzdDxOb3RpY2VEYXRhQ291bnRSZXNCZWFuPiBsc3BOb3RpY2VEYXRhQ291bnRSZXNCZWFucyA9IGxzcE5vdGljZURhdGFDb3VudFJlc0JlYW5zRnV0dXJlLmpvaW4oKTsKCQkJCQlMaXN0PE5vdGljZURhdGFDb3VudFJlc0JlYW4+IGxpc05vdGljZURhdGFDb3VudFJlc0JlYW5zID0gbGlzTm90aWNlRGF0YUNvdW50UmVzQmVhbnNGdXR1cmUuam9pbigpOwoJCQkJCUNsYW1Ob3RpY2VEYXRhQ291bnRSZXNCZWFuIGNsYW1Ob3RpY2VEYXRhQ291bnRSZXNCZWFuID0gY2xhbU5vdGVOb3RpY2VEYXRhQ291bnRSZXNCZWFuRnV0dXJlLmpvaW4oKTsKCQkJCQltZXJnZU5vdGljZURhdGFDb3VudExpc3Qobm90aWNlRGF0YUNvdW50UmVzQmVhbnMsIGxzcE5vdGljZURhdGFDb3VudFJlc0JlYW5zKTsKCQkJCQltZXJnZU5vdGljZURhdGFDb3VudExpc3Qobm90aWNlRGF0YUNvdW50UmVzQmVhbnMsIGxpc05vdGljZURhdGFDb3VudFJlc0JlYW5zKTsKCQkJCQlib29sZWFuIGlzRW1wdHlDbGFtRGF0YSA9IHRydWU7CgoJCQkJCWlmIChub3RpY2VEYXRhQ291bnRSZXNCZWFucyAhPSBudWxsKSB7CgkJCQkJCUNvbGxlY3Rpb25zLnNvcnQobm90aWNlRGF0YUNvdW50UmVzQmVhbnMsIG5ldyBDb21wYXJhdG9yPE5vdGljZURhdGFDb3VudFJlc0JlYW4+KCkgewoJCQkJCQkJQE92ZXJyaWRlCgkJCQkJCQlwdWJsaWMgaW50IGNvbXBhcmUoTm90aWNlRGF0YUNvdW50UmVzQmVhbiBvMSwgTm90aWNlRGF0YUNvdW50UmVzQmVhbiBvMikgewoJCQkJCQkJCVN0cmluZyBvcmRlcmluZzEgPSBOb3RpY2VEYXRhT3JkZXJpbmdFbnVtLnJlc29sdmUobzEuZ2V0VXdubVNvdXJjZSgpKSAhPSBudWxsCgkJCQkJCQkJCQk/IE5vdGljZURhdGFPcmRlcmluZ0VudW0ucmVzb2x2ZShvMS5nZXRVd25tU291cmNlKCkpLmdldE9yZGVpbmcoKQoJCQkJCQkJCQkJOiAiOTkiOwoJCQkJCQkJCVN0cmluZyBvcmRlcmluZzIgPSBOb3RpY2VEYXRhT3JkZXJpbmdFbnVtLnJlc29sdmUobzIuZ2V0VXdubVNvdXJjZSgpKSAhPSBudWxsCgkJCQkJCQkJCQk/IE5vdGljZURhdGFPcmRlcmluZ0VudW0ucmVzb2x2ZShvMi5nZXRVd25tU291cmNlKCkpLmdldE9yZGVpbmcoKQoJCQkJCQkJCQkJOiAiOTkiOwoJCQkJCQkJCXJldHVybiBvcmRlcmluZzEuY29tcGFyZVRvKG9yZGVyaW5nMik7CgkJCQkJCQl9CgkJCQkJCX0pOwoJCQkJCQkKCQkJCQkJLy8xMTQuMDcuMjJfMTE0MDcwMjI2OC0wMOeQhuizoOmAmuefpeabuF9MSVPns7vntbHkuLLmjqXkvobmupDoqr/mlbQoMTEwNOacg+itsG1lbW8pCgkJCQkJCWlmIChjbGFtTm90aWNlRGF0YUNvdW50UmVzQmVhbiAhPSBudWxsICYmIGNsYW1Ob3RpY2VEYXRhQ291bnRSZXNCZWFuLmdldENvdW50KCkgIT0gMCkgewoJCQkJCQkJZm9yIChOb3RpY2VEYXRhQ291bnRSZXNCZWFuIG5vdGljZURhdGFDb3VudFJlc0JlYW4gOiBub3RpY2VEYXRhQ291bnRSZXNCZWFucykgewoJCQkJCQkJCU5vdGljZURhdGFNZXNzYWdlRGF0YVR5cGUgY3VycmVudERhdGFUeXBlID0gTm90aWNlRGF0YU1lc3NhZ2VEYXRhVHlwZQoJCQkJCQkJCQkJLnJlc29sdmUobm90aWNlRGF0YUNvdW50UmVzQmVhbi5nZXRVd25tU291cmNlKCkpOwoJCQkJCQkJCWlmIChOb3RpY2VEYXRhTWVzc2FnZURhdGFUeXBlLkNMID09IGN1cnJlbnREYXRhVHlwZSkgewoJCQkJCQkJCQlub3RpY2VEYXRhQ291bnRSZXNCZWFuLnNldENvdW50KG5vdGljZURhdGFDb3VudFJlc0JlYW4uZ2V0Q291bnQoKSArIGNsYW1Ob3RpY2VEYXRhQ291bnRSZXNCZWFuLmdldENvdW50KCkpOwoJCQkJCQkJCQlpc0VtcHR5Q2xhbURhdGEgPSBmYWxzZTsKCQkJCQkJCQkJYnJlYWs7CgkJCQkJCQkJfQoJCQkJCQkJfQoJCQkJCQl9CgkJCQkJCQoJCQkJCX0gCgoJCQkJCS8vMTE0LjA3LjIyXzExNDA3MDIyNjgtMDDnkIbos6DpgJrnn6Xmm7hfTElT57O757Wx5Liy5o6l5L6G5rqQ6Kq/5pW0KDExMDTmnIPorbBtZW1vKQoJCQkJCWlmIChub3RpY2VEYXRhQ291bnRSZXNCZWFucy5pc0VtcHR5KCkgfHwgaXNFbXB0eUNsYW1EYXRhKSB7CgkJCQkJCU5vdGljZURhdGFDb3VudFJlc0JlYW4gbm90aWNlRGF0YUNvdW50UmVzQmVhbiA9IG5ldyBOb3RpY2VEYXRhQ291bnRSZXNCZWFuKCk7CgkJCQkJCW5vdGljZURhdGFDb3VudFJlc0JlYW4uc2V0Q291bnQoY2xhbU5vdGljZURhdGFDb3VudFJlc0JlYW4uZ2V0Q291bnQoKSk7CgkJCQkJCW5vdGljZURhdGFDb3VudFJlc0JlYW4uc2V0VXdubVNvdXJjZShOb3RpY2VEYXRhTWVzc2FnZURhdGFUeXBlLkNMLm5hbWUoKSk7CgkJCQkJCW5vdGljZURhdGFDb3VudFJlc0JlYW4uc2V0VXdubVNvdXJjZU5hbWUoTm90aWNlRGF0YU1lc3NhZ2VEYXRhVHlwZS5DTC5nZXREaXNwbGF5TmFtZSgpKTsKCgkJCQkJCW5vdGljZURhdGFDb3VudFJlc0JlYW5zLmFkZChub3RpY2VEYXRhQ291bnRSZXNCZWFuKTsKCQkJCQl9CgoJCQkJCXJldHVybiBub3RpY2VEYXRhQ291bnRSZXNCZWFuczsKCQkJCX0pOwoJCQoJCXJldHVybiBmdXR1cmU7CgoJfQoKCXByaXZhdGUgQ29tcGxldGFibGVGdXR1cmU8TGlzdDxOZXdQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbj4+IGdldE5ld1BvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFucygpIHsKCQlTdHJpbmcgYWFnQ29kZSA9IHRoaXMuZ2V0QWFnY29kZSgpOwoJCUNvbXBsZXRhYmxlRnV0dXJlPExpc3Q8TmV3UG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW4+PiBuZXdQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbnNGdXR1cmUgPSBDb21wbGV0YWJsZUZ1dHVyZQoJCQkJLnN1cHBseUFzeW5jKCgpIC0+IHsKCQkJCQlMaXN0PE5ld1BvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFuPiBuZXdQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbnMgPSBuZXcgQXJyYXlMaXN0PE5ld1BvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFuPigpOwoJCQkJCXRyeSB7CgkJCQkJCU5ld1BvbGljeVNjaGVkdWxlQ291bnRSZXFCZWFuIG5ld1BvbGljeVNjaGVkdWxlQ291bnRSZXFCZWFuID0gbmV3IE5ld1BvbGljeVNjaGVkdWxlQ291bnRSZXFCZWFuKCk7CgkJCQkJCW5ld1BvbGljeVNjaGVkdWxlQ291bnRSZXFCZWFuLnNldEFnZW50Q29kZShhYWdDb2RlKTsKCQkJCQkJbmV3UG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW5zID0gaUthc2hTZXJ2aWNlCgkJCQkJCQkJLmdldE5ld1BvbGljeVNjaGVkdWxlQ291bnQobmV3UG9saWN5U2NoZWR1bGVDb3VudFJlcUJlYW4pOwoJCQkJCQlpZiAobmV3UG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW5zID09IG51bGwgfHwgbmV3UG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW5zLnNpemUoKSA9PSAwKSB7CgkJCQkJCQlpZiAobmV3UG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW5zID09IG51bGwpIHsKCQkJCQkJCQluZXdQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbnMgPSBuZXcgQXJyYXlMaXN0PE5ld1BvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFuPigpOwoJCQkJCQkJfQoJCQkJCQl9CgkJCQkJfSBjYXRjaCAoQXBpRXhjZXB0aW9uIGUpIHsKCQkJCQkJTE9HR0VSLmVycm9yKCJ7J2NvZGUnOiciICsgZS5nZXRDb2RlKCkgKyAiJywnbWVzc2FnZSc6JyIgKyBlLmdldE1lc3NhZ2UoKSArICInLCAnZGVzY3JpcHRpb24nOiciCgkJCQkJCQkJKyBlLmdldERlc2NyaXB0aW9uKCkgKyAiJ30iLCBlKTsKCQkJCQl9CgkJCQkJcmV0dXJuIG5ld1BvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFuczsKCQkJCX0sIGV4ZWN1dG9yKTsKCgkJQ29tcGxldGFibGVGdXR1cmU8TmV3UG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW4+IG5ld1BvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFuRnV0dXJlID0gQ29tcGxldGFibGVGdXR1cmUKCQkJCS5zdXBwbHlBc3luYygoKSAtPiB7CgkJCQkJTmV3UG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW4gbmV3UG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW4gPSBudWxsOwoJCQkJCXRyeSB7CgkJCQkJCS8vIExJUyDlpZHntITpgLLluqbnrYbmlbgKCQkJCQkJTGlzUG9saWN5U2NoZWR1bGVDb3VudFJlcUJlYW4gbmV3UG9saWN5U2NoZWR1bGVDb3VudFJlcUJlYW4gPSBuZXcgTGlzUG9saWN5U2NoZWR1bGVDb3VudFJlcUJlYW4oKTsKCQkJCQkJbmV3UG9saWN5U2NoZWR1bGVDb3VudFJlcUJlYW4uc2V0QWdlbnRDb2RlKGFhZ0NvZGUpOwoJCQkJCQluZXdQb2xpY3lTY2hlZHVsZUNvdW50UmVxQmVhbi5zZXRUeXBlKFBvbGljeVNjaGVkdWxlVHlwZUVudW0uTkIuZ2V0VmFsdWUoKSk7CgkJCQkJCS8vIG5ld1BvbGljeVNjaGVkdWxlQ291bnRSZXFCZWFuLnNldFN0YXJ0RGF0ZShjaGFuZ2VQb2xpY3lTdGFydERhdGVTdHIpOwoJCQkJCQkvLyBuZXdQb2xpY3lTY2hlZHVsZUNvdW50UmVxQmVhbi5zZXRFbmREYXRlKGVuZERhdGVTdHIpOwoJCQkJCQluZXdQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbiA9IGxpc0FwaVNlcnZpY2UuZ2V0TGlzUG9saWN5U2NoZWR1bGVDb3VudCgKCQkJCQkJCQluZXdQb2xpY3lTY2hlZHVsZUNvdW50UmVxQmVhbiwgTmV3UG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW4uY2xhc3MpOwoJCQkJCX0gY2F0Y2ggKEFwaUV4Y2VwdGlvbiBlKSB7CgkJCQkJCUxPR0dFUi5lcnJvcigieydjb2RlJzonIiArIGUuZ2V0Q29kZSgpICsgIicsJ21lc3NhZ2UnOiciICsgZS5nZXRNZXNzYWdlKCkgKyAiJywgJ2Rlc2NyaXB0aW9uJzonIgoJCQkJCQkJCSsgZS5nZXREZXNjcmlwdGlvbigpICsgIid9IiwgZSk7CgkJCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCQkJTE9HR0VSLmVycm9yKCIiLCBlKTsKCQkJCQl9CgkJCQkJcmV0dXJuIG5ld1BvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFuOwoJCQkJfSwgZXhlY3V0b3IpOwoKCQlDb21wbGV0YWJsZUZ1dHVyZTxMaXN0PE5ld1BvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFuPj4gZnV0dXJlID0gQ29tcGxldGFibGVGdXR1cmUKCQkJCS5hbGxPZihuZXdQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbnNGdXR1cmUsIG5ld1BvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFuRnV0dXJlKS50aGVuQXBwbHkoeCAtPiB7CgkJCQkJTGlzdDxOZXdQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbj4gbmV3UG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW5zID0gbmV3UG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW5zRnV0dXJlCgkJCQkJCQkuam9pbigpOwoJCQkJCU5ld1BvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFuIG5ld1BvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFuID0gbmV3UG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW5GdXR1cmUKCQkJCQkJCS5qb2luKCk7CgkJCQkJaWYgKG5ld1BvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFuICE9IG51bGwpIHsKCQkJCQkJaWYgKG5ld1BvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFucy5zaXplKCkgPiAwKSB7CgkJCQkJCQluZXdQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbnMuZ2V0KDApLnNldENvdW50KG5ld1BvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFucy5nZXQoMCkuZ2V0Q291bnQoKQoJCQkJCQkJCQkrIG5ld1BvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFuLmdldENvdW50KCkpOwoJCQkJCQl9CgkJCQkJfQoJCQkJCXJldHVybiBuZXdQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbnM7CgkJCQl9KTsKCQlyZXR1cm4gZnV0dXJlOwoJfQoKCXByaXZhdGUgQ29tcGxldGFibGVGdXR1cmU8TGlzdDxDaGFuZ2VQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbj4+IGdldENoYW5nZVBvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFucygKCQkJU3RyaW5nIGNoYW5nZVBvbGljeVN0YXJ0RGF0ZVN0ciwgU3RyaW5nIGVuZERhdGVTdHIpIHsKCQlTdHJpbmcgYWFnY29kZSA9IHRoaXMuZ2V0QWFnY29kZSgpOwoJCUNvbXBsZXRhYmxlRnV0dXJlPExpc3Q8Q2hhbmdlUG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW4+PiBjaGFuZ2VQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbnNGdXR1cmUgPSBDb21wbGV0YWJsZUZ1dHVyZQoJCQkJLnN1cHBseUFzeW5jKCgpIC0+IHsKCQkJCQlMaXN0PENoYW5nZVBvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFuPiBjaGFuZ2VQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbnMgPSBuZXcgQXJyYXlMaXN0PENoYW5nZVBvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFuPigpOwoJCQkJCXRyeSB7CgkJCQkJCUNoYW5nZVBvbGljeVNjaGVkdWxlQ291bnRSZXFCZWFuIGNoYW5nZVBvbGljeVNjaGVkdWxlQ291bnRSZXFCZWFuID0gbmV3IENoYW5nZVBvbGljeVNjaGVkdWxlQ291bnRSZXFCZWFuKCk7CgkJCQkJCWNoYW5nZVBvbGljeVNjaGVkdWxlQ291bnRSZXFCZWFuLnNldEFnZW50Q29kZShhYWdjb2RlKTsKCQkJCQkJY2hhbmdlUG9saWN5U2NoZWR1bGVDb3VudFJlcUJlYW4uc2V0U3RhcnREYXRlKGNoYW5nZVBvbGljeVN0YXJ0RGF0ZVN0cik7CgkJCQkJCWNoYW5nZVBvbGljeVNjaGVkdWxlQ291bnRSZXFCZWFuLnNldEVuZERhdGUoZW5kRGF0ZVN0cik7CgkJCQkJCWNoYW5nZVBvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFucyA9IGlLYXNoU2VydmljZQoJCQkJCQkJCS5nZXRDaGFuZ2VQb2xpY3lTY2hlZHVsZUNvdW50KGNoYW5nZVBvbGljeVNjaGVkdWxlQ291bnRSZXFCZWFuKTsKCQkJCQkJaWYgKGNoYW5nZVBvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFucyA9PSBudWxsKSB7CgkJCQkJCQljaGFuZ2VQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbnMgPSBuZXcgQXJyYXlMaXN0PD4oKTsKCQkJCQkJfQoJCQkJCX0gY2F0Y2ggKEFwaUV4Y2VwdGlvbiBlKSB7CgkJCQkJCUxPR0dFUi5lcnJvcigieydjb2RlJzonIiArIGUuZ2V0Q29kZSgpICsgIicsJ21lc3NhZ2UnOiciICsgZS5nZXRNZXNzYWdlKCkgKyAiJywgJ2Rlc2NyaXB0aW9uJzonIgoJCQkJCQkJCSsgZS5nZXREZXNjcmlwdGlvbigpICsgIid9IiwgZSk7CgkJCQkJfQoJCQkJCXJldHVybiBjaGFuZ2VQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbnM7CgkJCQl9LCBleGVjdXRvcik7CgoJCUNvbXBsZXRhYmxlRnV0dXJlPENoYW5nZVBvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFuPiBjaGFuZ2VQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbkZ1dHVyZSA9IENvbXBsZXRhYmxlRnV0dXJlCgkJCQkuc3VwcGx5QXN5bmMoKCkgLT4gewoJCQkJCUNoYW5nZVBvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFuIGNoYW5nZVBvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFuID0gbnVsbDsKCQkJCQl0cnkgewoJCQkJCQkvLyBMSVMg5L+d5YWo6YCy5bqm562G5pW4CgkJCQkJCUxpc1BvbGljeVNjaGVkdWxlQ291bnRSZXFCZWFuIGNoYW5nZVBvbGljeVNjaGVkdWxlQ291bnRSZXFCZWFuID0gbmV3IExpc1BvbGljeVNjaGVkdWxlQ291bnRSZXFCZWFuKCk7CgkJCQkJCWNoYW5nZVBvbGljeVNjaGVkdWxlQ291bnRSZXFCZWFuLnNldEFnZW50Q29kZShhYWdjb2RlKTsKCQkJCQkJY2hhbmdlUG9saWN5U2NoZWR1bGVDb3VudFJlcUJlYW4uc2V0VHlwZShQb2xpY3lTY2hlZHVsZVR5cGVFbnVtLlBDLmdldFZhbHVlKCkpOwoJCQkJCQljaGFuZ2VQb2xpY3lTY2hlZHVsZUNvdW50UmVxQmVhbi5zZXRTdGFydERhdGUoY2hhbmdlUG9saWN5U3RhcnREYXRlU3RyKTsKCQkJCQkJY2hhbmdlUG9saWN5U2NoZWR1bGVDb3VudFJlcUJlYW4uc2V0RW5kRGF0ZShlbmREYXRlU3RyKTsKCQkJCQkJY2hhbmdlUG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW4gPSBsaXNBcGlTZXJ2aWNlLmdldExpc1BvbGljeVNjaGVkdWxlQ291bnQoCgkJCQkJCQkJY2hhbmdlUG9saWN5U2NoZWR1bGVDb3VudFJlcUJlYW4sIENoYW5nZVBvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFuLmNsYXNzKTsKCQkJCQl9IGNhdGNoIChBcGlFeGNlcHRpb24gZSkgewoJCQkJCQlMT0dHRVIuZXJyb3IoInsnY29kZSc6JyIgKyBlLmdldENvZGUoKSArICInLCdtZXNzYWdlJzonIiArIGUuZ2V0TWVzc2FnZSgpICsgIicsICdkZXNjcmlwdGlvbic6JyIKCQkJCQkJCQkrIGUuZ2V0RGVzY3JpcHRpb24oKSArICInfSIsIGUpOwoJCQkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7IC8vIDEwOTA5MDA3MTQtMDAKCQkJCQkJTE9HR0VSLmVycm9yKCIiLCBlKTsKCQkJCQl9CgkJCQkJcmV0dXJuIGNoYW5nZVBvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFuOwoJCQkJfSwgZXhlY3V0b3IpOwoJCUNvbXBsZXRhYmxlRnV0dXJlPExpc3Q8Q2hhbmdlUG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW4+PiBmdXR1cmUgPSBDb21wbGV0YWJsZUZ1dHVyZQoJCQkJLmFsbE9mKGNoYW5nZVBvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFuc0Z1dHVyZSwgY2hhbmdlUG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW5GdXR1cmUpLnRoZW5BcHBseSh4IC0+IHsKCQkJCQlMaXN0PENoYW5nZVBvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFuPiBjaGFuZ2VQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbnMgPSBjaGFuZ2VQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbnNGdXR1cmUKCQkJCQkJCS5qb2luKCk7CgkJCQkJQ2hhbmdlUG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW4gY2hhbmdlUG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW4gPSBjaGFuZ2VQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbkZ1dHVyZQoJCQkJCQkJLmpvaW4oKTsKCQkJCQlpZiAoY2hhbmdlUG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW4gIT0gbnVsbCkgewoJCQkJCQlpZiAoY2hhbmdlUG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW5zLnNpemUoKSA+IDApIHsKCQkJCQkJCWNoYW5nZVBvbGljeVNjaGVkdWxlQ291bnRSZXNCZWFucy5nZXQoMCkKCQkJCQkJCS5zZXRDb3VudChjaGFuZ2VQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbnMuZ2V0KDApLmdldENvdW50KCkKCQkJCQkJCQkJKyBjaGFuZ2VQb2xpY3lTY2hlZHVsZUNvdW50UmVzQmVhbi5nZXRDb3VudCgpKTsKCQkJCQkJfQoJCQkJCX0KCQkJCQlyZXR1cm4gY2hhbmdlUG9saWN5U2NoZWR1bGVDb3VudFJlc0JlYW5zOwoJCQkJfSk7CgkJcmV0dXJuIGZ1dHVyZTsKCgl9CgoJcHJpdmF0ZSBDb21wbGV0YWJsZUZ1dHVyZTxMaXN0PENsYWltU2NoZWR1bGVDb3VudFJlc0JlYW4+PiBnZXRDbGFpbVNjaGVkdWxlQ291bnRSZXNCZWFuKCkgewoJCVN0cmluZyBhYWdjb2RlID0gdGhpcy5nZXRBYWdjb2RlKCk7CgkJQ29tcGxldGFibGVGdXR1cmU8TGlzdDxDbGFpbVNjaGVkdWxlQ291bnRSZXNCZWFuPj4gY2xhaW1TY2hlZHVsZUNvdW50UmVzQmVhbnNGdXR1cmUgPSBDb21wbGV0YWJsZUZ1dHVyZQoJCQkJLnN1cHBseUFzeW5jKCgpIC0+IHsKCQkJCQlMaXN0PENsYWltU2NoZWR1bGVDb3VudFJlc0JlYW4+IGNsYWltU2NoZWR1bGVDb3VudFJlc0JlYW5zID0gbmV3IEFycmF5TGlzdDxDbGFpbVNjaGVkdWxlQ291bnRSZXNCZWFuPigpOwoJCQkJCXRyeSB7CgkJCQkJCUNsYWltU2NoZWR1bGVDb3VudFJlcUJlYW4gY2xhaW1TY2hlZHVsZUNvdW50UmVxQmVhbiA9IG5ldyBDbGFpbVNjaGVkdWxlQ291bnRSZXFCZWFuKCk7CgkJCQkJCWNsYWltU2NoZWR1bGVDb3VudFJlcUJlYW4uc2V0QWdlbnRDb2RlKGFhZ2NvZGUpOwoJCQkJCQljbGFpbVNjaGVkdWxlQ291bnRSZXNCZWFucyA9IGlLYXNoU2VydmljZS5nZXRDbGFpbVNjaGVkdWxlQ291bnQoY2xhaW1TY2hlZHVsZUNvdW50UmVxQmVhbik7CgkJCQkJCWlmIChjbGFpbVNjaGVkdWxlQ291bnRSZXNCZWFucyA9PSBudWxsKSB7CgkJCQkJCQljbGFpbVNjaGVkdWxlQ291bnRSZXNCZWFucyA9IG5ldyBBcnJheUxpc3Q8PigpOwoJCQkJCQl9CgkJCQkJfSBjYXRjaCAoQXBpRXhjZXB0aW9uIGUpIHsKCQkJCQkJTE9HR0VSLmVycm9yKCJ7J2NvZGUnOiciICsgZS5nZXRDb2RlKCkgKyAiJywnbWVzc2FnZSc6JyIgKyBlLmdldE1lc3NhZ2UoKSArICInLCAnZGVzY3JpcHRpb24nOiciCgkJCQkJCQkJKyBlLmdldERlc2NyaXB0aW9uKCkgKyAiJ30iLCBlKTsKCQkJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgeyAvLyAxMDkwOTAwNzE0LTAwCgkJCQkJCUxPR0dFUi5lcnJvcigiIiwgZSk7CgkJCQkJfQoJCQkJCXJldHVybiBjbGFpbVNjaGVkdWxlQ291bnRSZXNCZWFuczsKCQkJCX0sIGV4ZWN1dG9yKTsKCQlDb21wbGV0YWJsZUZ1dHVyZTxDbGFpbVNjaGVkdWxlQ291bnRSZXNCZWFuPiBjbGFpbVNjaGVkdWxlQ291bnRSZXNCZWFuRnV0dXJlID0gQ29tcGxldGFibGVGdXR1cmUKCQkJCS5zdXBwbHlBc3luYygoKSAtPiB7CgkJCQkJQ2xhaW1TY2hlZHVsZUNvdW50UmVzQmVhbiBjbGFpbVNjaGVkdWxlQ291bnRSZXNCZWFuID0gbnVsbDsKCQkJCQl0cnkgewoJCQkJCQlDbGFpbVNjaGVkdWxlQ291bnRSZXFCZWFuIGNsYWltU2NoZWR1bGVDb3VudFJlcUJlYW4gPSBuZXcgQ2xhaW1TY2hlZHVsZUNvdW50UmVxQmVhbigpOwoJCQkJCQljbGFpbVNjaGVkdWxlQ291bnRSZXFCZWFuLnNldEFnZW50Q29kZShhYWdjb2RlKTsKCQkJCQkJY2xhaW1TY2hlZHVsZUNvdW50UmVzQmVhbiA9IGNoYW5uZWxBcGlTZXJ2aWNlLmdldENsYWltU2NoZWR1bGVDb3VudChjbGFpbVNjaGVkdWxlQ291bnRSZXFCZWFuKTsKCQkJCQl9IGNhdGNoIChBcGlFeGNlcHRpb24gZSkgewoJCQkJCQlMT0dHRVIuZXJyb3IoInsnY29kZSc6JyIgKyBlLmdldENvZGUoKSArICInLCdtZXNzYWdlJzonIiArIGUuZ2V0TWVzc2FnZSgpICsgIicsICdkZXNjcmlwdGlvbic6JyIKCQkJCQkJCQkrIGUuZ2V0RGVzY3JpcHRpb24oKSArICInfSIsIGUpOwoJCQkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7IC8vIDEwOTA5MDA3MTQtMDAKCQkJCQkJTE9HR0VSLmVycm9yKCIiLCBlKTsKCQkJCQl9CgkJCQkJcmV0dXJuIGNsYWltU2NoZWR1bGVDb3VudFJlc0JlYW47CgkJCQl9LCBleGVjdXRvcik7CgkJQ29tcGxldGFibGVGdXR1cmU8Q2xhaW1TY2hlZHVsZUNvdW50UmVzQmVhbj4gY2xhaW1TY2hlZHVsZUNvdW50UmVzQmVhbjJGdXR1cmUgPSBDb21wbGV0YWJsZUZ1dHVyZQoJCQkJLnN1cHBseUFzeW5jKCgpIC0+IHsKCQkJCQlDbGFpbVNjaGVkdWxlQ291bnRSZXNCZWFuIGNsYWltU2NoZWR1bGVDb3VudFJlc0JlYW4yID0gbnVsbDsKCQkJCQl0cnkgewoJCQkJCQkvLyBMSVMg55CG6LOg6YCy5bqm562G5pW4CgkJCQkJCUxpc1BvbGljeVNjaGVkdWxlQ291bnRSZXFCZWFuIGNsYWltU2NoZWR1bGVDb3VudFJlcUJlYW4gPSBuZXcgTGlzUG9saWN5U2NoZWR1bGVDb3VudFJlcUJlYW4oKTsKCQkJCQkJY2xhaW1TY2hlZHVsZUNvdW50UmVxQmVhbi5zZXRBZ2VudENvZGUoYWFnY29kZSk7CgkJCQkJCWNsYWltU2NoZWR1bGVDb3VudFJlcUJlYW4uc2V0VHlwZShQb2xpY3lTY2hlZHVsZVR5cGVFbnVtLkNMLmdldFZhbHVlKCkpOwoJCQkJCQkvLyBjbGFpbVNjaGVkdWxlQ291bnRSZXFCZWFuLnNldFN0YXJ0RGF0ZShjaGFuZ2VQb2xpY3lTdGFydERhdGVTdHIpOwoJCQkJCQkvLyBjbGFpbVNjaGVkdWxlQ291bnRSZXFCZWFuLnNldEVuZERhdGUoZW5kRGF0ZVN0cik7CgkJCQkJCWNsYWltU2NoZWR1bGVDb3VudFJlc0JlYW4yID0gbGlzQXBpU2VydmljZS5nZXRMaXNQb2xpY3lTY2hlZHVsZUNvdW50KGNsYWltU2NoZWR1bGVDb3VudFJlcUJlYW4sCgkJCQkJCQkJQ2xhaW1TY2hlZHVsZUNvdW50UmVzQmVhbi5jbGFzcyk7CgkJCQkJfSBjYXRjaCAoQXBpRXhjZXB0aW9uIGUpIHsKCQkJCQkJTE9HR0VSLmVycm9yKCJ7J2NvZGUnOiciICsgZS5nZXRDb2RlKCkgKyAiJywnbWVzc2FnZSc6JyIgKyBlLmdldE1lc3NhZ2UoKSArICInLCAnZGVzY3JpcHRpb24nOiciCgkJCQkJCQkJKyBlLmdldERlc2NyaXB0aW9uKCkgKyAiJ30iLCBlKTsKCQkJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJCQlMT0dHRVIuZXJyb3IoIiIsIGUpOwoJCQkJCX0KCQkJCQlyZXR1cm4gY2xhaW1TY2hlZHVsZUNvdW50UmVzQmVhbjI7CgkJCQl9LCBleGVjdXRvcik7CgoJCUNvbXBsZXRhYmxlRnV0dXJlPExpc3Q8Q2xhaW1TY2hlZHVsZUNvdW50UmVzQmVhbj4+IGZ1dHVyZSA9IENvbXBsZXRhYmxlRnV0dXJlCgkJCQkuYWxsT2YoY2xhaW1TY2hlZHVsZUNvdW50UmVzQmVhbnNGdXR1cmUsIGNsYWltU2NoZWR1bGVDb3VudFJlc0JlYW5GdXR1cmUsCgkJCQkJCWNsYWltU2NoZWR1bGVDb3VudFJlc0JlYW4yRnV0dXJlKQoJCQkJLnRoZW5BcHBseSh4IC0+IHsKCQkJCQlMaXN0PENsYWltU2NoZWR1bGVDb3VudFJlc0JlYW4+IGNsYWltU2NoZWR1bGVDb3VudFJlc0JlYW5zID0gY2xhaW1TY2hlZHVsZUNvdW50UmVzQmVhbnNGdXR1cmUKCQkJCQkJCS5qb2luKCk7CgkJCQkJQ2xhaW1TY2hlZHVsZUNvdW50UmVzQmVhbiBjbGFpbVNjaGVkdWxlQ291bnRSZXNCZWFuID0gY2xhaW1TY2hlZHVsZUNvdW50UmVzQmVhbkZ1dHVyZS5qb2luKCk7CgkJCQkJQ2xhaW1TY2hlZHVsZUNvdW50UmVzQmVhbiBjbGFpbVNjaGVkdWxlQ291bnRSZXNCZWFuMiA9IGNsYWltU2NoZWR1bGVDb3VudFJlc0JlYW4yRnV0dXJlLmpvaW4oKTsKCQkJCQlpZiAoY2xhaW1TY2hlZHVsZUNvdW50UmVzQmVhbiAhPSBudWxsKSB7CgkJCQkJCWNsYWltU2NoZWR1bGVDb3VudFJlc0JlYW5zLmdldCgwKS5zZXRDb3VudCgKCQkJCQkJCQljbGFpbVNjaGVkdWxlQ291bnRSZXNCZWFucy5nZXQoMCkuZ2V0Q291bnQoKSArIGNsYWltU2NoZWR1bGVDb3VudFJlc0JlYW4uZ2V0Q291bnQoKSk7CgkJCQkJfQoKCQkJCQlpZiAoY2xhaW1TY2hlZHVsZUNvdW50UmVzQmVhbjIgIT0gbnVsbCkgewoJCQkJCQlpZiAoY2xhaW1TY2hlZHVsZUNvdW50UmVzQmVhbnMuc2l6ZSgpID4gMCkgewoJCQkJCQkJY2xhaW1TY2hlZHVsZUNvdW50UmVzQmVhbnMuZ2V0KDApLnNldENvdW50KAoJCQkJCQkJCQljbGFpbVNjaGVkdWxlQ291bnRSZXNCZWFucy5nZXQoMCkuZ2V0Q291bnQoKSArIGNsYWltU2NoZWR1bGVDb3VudFJlc0JlYW4yLmdldENvdW50KCkpOwoJCQkJCQl9CgkJCQkJfQoJCQkJCXJldHVybiBjbGFpbVNjaGVkdWxlQ291bnRSZXNCZWFuczsKCQkJCX0pOwoJCXJldHVybiBmdXR1cmU7Cgl9CgoJcHJpdmF0ZSB2b2lkIG1lcmdlTWVzc2FnZURhdGFDb3VudExpc3QoTGlzdDxNZXNzYWdlRGF0YUNvdW50UmVzQmVhbj4gbWVzc2FnZURhdGFDb3VudFJlc0JlYW5zMSwKCQkJTGlzdDxNZXNzYWdlRGF0YUNvdW50UmVzQmVhbj4gbWVzc2FnZURhdGFDb3VudFJlc0JlYW5zMikgewoJCWlmIChtZXNzYWdlRGF0YUNvdW50UmVzQmVhbnMyID09IG51bGwgfHwgbWVzc2FnZURhdGFDb3VudFJlc0JlYW5zMSA9PSBudWxsKSB7CgkJCXJldHVybjsKCQl9CgkJTGlzdDxNZXNzYWdlRGF0YUNvdW50UmVzQmVhbj4gdGVtcHMgPSBuZXcgQXJyYXlMaXN0PE1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuPigpOwoJCWZvciAoTWVzc2FnZURhdGFDb3VudFJlc0JlYW4gbWVzc2FnZURhdGFDb3VudFJlc0JlYW4yIDogbWVzc2FnZURhdGFDb3VudFJlc0JlYW5zMikgewoJCQlib29sZWFuIGlzRHVwaWxpY2F0ZWQgPSBmYWxzZTsKCQkJZm9yIChNZXNzYWdlRGF0YUNvdW50UmVzQmVhbiBtZXNzYWdlRGF0YUNvdW50UmVzQmVhbjEgOiBtZXNzYWdlRGF0YUNvdW50UmVzQmVhbnMxKSB7CgkJCQlpZiAobWVzc2FnZURhdGFDb3VudFJlc0JlYW4xLmdldEFwMDlUeXBlMSgpLmVxdWFscyhtZXNzYWdlRGF0YUNvdW50UmVzQmVhbjIuZ2V0QXAwOVR5cGUxKCkpKSB7CgkJCQkJbWVzc2FnZURhdGFDb3VudFJlc0JlYW4xCgkJCQkJCQkuc2V0Q291bnQobWVzc2FnZURhdGFDb3VudFJlc0JlYW4xLmdldENvdW50KCkgKyBtZXNzYWdlRGF0YUNvdW50UmVzQmVhbjIuZ2V0Q291bnQoKSk7CgkJCQkJaXNEdXBpbGljYXRlZCA9IHRydWU7CgkJCQl9CgkJCX0KCQkJaWYgKCFpc0R1cGlsaWNhdGVkKSB7CgkJCQl0ZW1wcy5hZGQobWVzc2FnZURhdGFDb3VudFJlc0JlYW4yKTsKCQkJfQoJCX0KCQkvLyDntbHkuIDoqIrmga/pgJrnn6XlpKfliIbpoZ5nZXRBcDA5VHlwZTHkuYvkuK3mloflkb3lkI0oZm9sbG93IElLYXNoU2VydmljZUltcGwgZ2V0TWVzc2FnZURhdGFDb3VudOWvq+azlSkKCQljaGFuZ2VNZXNzYWdlVHlwZU5hbWUodGVtcHMpOwoJCW1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuczEuYWRkQWxsKHRlbXBzKTsKCX0KCglwcml2YXRlIHZvaWQgbWVyZ2VOb3RpY2VEYXRhQ291bnRMaXN0KExpc3Q8Tm90aWNlRGF0YUNvdW50UmVzQmVhbj4gbm90aWNlRGF0YUNvdW50UmVzQmVhbnMxLAoJCQlMaXN0PE5vdGljZURhdGFDb3VudFJlc0JlYW4+IG5vdGljZURhdGFDb3VudFJlc0JlYW5zMikgewoJCWlmIChub3RpY2VEYXRhQ291bnRSZXNCZWFuczIgPT0gbnVsbCB8fCBub3RpY2VEYXRhQ291bnRSZXNCZWFuczEgPT0gbnVsbCkgewoJCQlyZXR1cm47CgkJfQoJCUxpc3Q8Tm90aWNlRGF0YUNvdW50UmVzQmVhbj4gdGVtcHMgPSBuZXcgQXJyYXlMaXN0PE5vdGljZURhdGFDb3VudFJlc0JlYW4+KCk7CgkJZm9yIChOb3RpY2VEYXRhQ291bnRSZXNCZWFuIG5vdGljZURhdGFDb3VudFJlc0JlYW4yIDogbm90aWNlRGF0YUNvdW50UmVzQmVhbnMyKSB7CgkJCWJvb2xlYW4gaXNEdXBpbGljYXRlZCA9IGZhbHNlOwoJCQlmb3IgKE5vdGljZURhdGFDb3VudFJlc0JlYW4gbm90aWNlRGF0YUNvdW50UmVzQmVhbjEgOiBub3RpY2VEYXRhQ291bnRSZXNCZWFuczEpIHsKCQkJCWlmIChub3RpY2VEYXRhQ291bnRSZXNCZWFuMS5nZXRVd25tU291cmNlKCkuZXF1YWxzKG5vdGljZURhdGFDb3VudFJlc0JlYW4yLmdldFV3bm1Tb3VyY2UoKSkpIHsKCQkJCQlub3RpY2VEYXRhQ291bnRSZXNCZWFuMQoJCQkJCQkJLnNldENvdW50KG5vdGljZURhdGFDb3VudFJlc0JlYW4xLmdldENvdW50KCkgKyBub3RpY2VEYXRhQ291bnRSZXNCZWFuMi5nZXRDb3VudCgpKTsKCQkJCQlpc0R1cGlsaWNhdGVkID0gdHJ1ZTsKCQkJCX0KCQkJfQoJCQlpZiAoIWlzRHVwaWxpY2F0ZWQpIHsKCQkJCXRlbXBzLmFkZChub3RpY2VEYXRhQ291bnRSZXNCZWFuMik7CgkJCX0KCQl9CgkJLy8g57Wx5LiA54Wn5pyD6YCa55+l5aSn5YiG6aGeZ2V0QXAwOVR5cGUx5LmL5Lit5paH5ZG95ZCNKGZvbGxvdyBJS2FzaFNlcnZpY2VJbXBsIGdldE5vdGljZURhdGFDb3VudOWvq+azlSkKCQljaGFuZ2VOb3RpY2VUeXBlTmFtZSh0ZW1wcyk7CgkJbm90aWNlRGF0YUNvdW50UmVzQmVhbnMxLmFkZEFsbCh0ZW1wcyk7Cgl9CgoJcHJpdmF0ZSB2b2lkIHVwZGF0ZU5vdGljZURldGFpbFJlc0JlYW4oZmluYWwgTGlzdDw/IGV4dGVuZHMgTm90aWNlUmVzQmVhbj4gc291cmNlLCBmaW5hbCBBcmVhRW51bSBhcmVhLAoJCQlmaW5hbCBTdHJpbmcgY2F0ZWdvcnkpIHsKCQlzb3VyY2Uuc3RyZWFtKCkuZm9yRWFjaChyZXMgLT4gewoJCQlyZXMuc2V0QXJlYShhcmVhLmdldENvZGUoKSk7CgkJCXJlcy5zZXRDYXRlZ29yeShjYXRlZ29yeSk7CgkJfSk7CgkJdXBkYXRlUmVhZFN0YXR1cyhzb3VyY2UsIGFyZWEsIGNhdGVnb3J5KTsKCX0KCglwcml2YXRlIHZvaWQgdXBkYXRlUmVhZFN0YXR1cyhmaW5hbCBMaXN0PD8gZXh0ZW5kcyBOb3RpY2VSZXNCZWFuPiBzb3VyY2UsIGZpbmFsIEFyZWFFbnVtIGFyZWEsCgkJCWZpbmFsIFN0cmluZyBjYXRlZ29yeSkgewoJCWZpbmFsIExpc3Q8Tm90aWNlUmVhZD4gbm90aWNlUmVhZExpc3QgPSBub3RpY2VSZWFkU2VydmljZS5nZXROb3RpY2VSZWFkTGlzdCh0aGlzLmdldEFhZ2NvZGUoKSwgYXJlYS5nZXRDb2RlKCksCgkJCQljYXRlZ29yeSk7CgkJLy8g5L6dIGhhc2hDb2RlIOWIhue1hAoJCWZpbmFsIE1hcDxJbnRlZ2VyLCBMaXN0PE5vdGljZVJlYWQ+PiBub3RpY2VSZWFkTWFwID0gbm90aWNlUmVhZExpc3Quc3RyZWFtKCkuY29sbGVjdCgKCQkJCUNvbGxlY3RvcnMuZ3JvdXBpbmdCeShOb3RpY2VSZWFkOjpnZXRIYXNoQ29kZSwgSGFzaE1hcDo6bmV3LCBDb2xsZWN0b3JzLnRvQ29sbGVjdGlvbihBcnJheUxpc3Q6Om5ldykpKTsKCQlzb3VyY2Uuc3RyZWFtKCkuZm9yRWFjaChyZXMgLT4gewoJCQlpZiAobm90aWNlUmVhZE1hcC5jb250YWluc0tleShyZXMuZ2V0SGFzaENvZGUoKSkpIHsKCQkJCWlmIChub3RpY2VSZWFkTWFwLmdldChyZXMuZ2V0SGFzaENvZGUoKSkuc2l6ZSgpID09IDEpIHsKCQkJCQlyZXMuc2V0UmVhZCh0cnVlKTsKCQkJCX0gZWxzZSB7CgkJCQkJLy8g6Iul5pyJ5aSa562G6LOH5paZ5YmH6YCQ562G5q+U5bCN5Y6f5aeL6LOH5paZ5YWn5a65CgkJCQkJZm9yIChOb3RpY2VSZWFkIG5vdGljZVJlYWQgOiBub3RpY2VSZWFkTWFwLmdldChyZXMuZ2V0SGFzaENvZGUoKSkpIHsKCQkJCQkJdHJ5IHsKCQkJCQkJCU5vdGljZVJlc0JlYW4gYmVhbiA9IG51bGw7CgkJCQkJCQlzd2l0Y2ggKGFyZWEpIHsKCQkJCQkJCWNhc2UgTUVTU0FHRV9EQVRBX0FSRUE6CgkJCQkJCQkJYmVhbiA9IEpzb25VdGlsLmZyb20obm90aWNlUmVhZC5nZXRNZXNzYWdlKCksIE1lc3NhZ2VEYXRhRGV0YWlsUmVzQmVhbi5jbGFzcyk7CgkJCQkJCQkJYnJlYWs7CgkJCQkJCQljYXNlIE5PVElDRV9EQVRBX0FSRUE6CgkJCQkJCQkJYmVhbiA9IEpzb25VdGlsLmZyb20obm90aWNlUmVhZC5nZXRNZXNzYWdlKCksIE5vdGljZURhdGFEZXRhaWxSZXNCZWFuLmNsYXNzKTsKCQkJCQkJCQlicmVhazsKCQkJCQkJCWNhc2UgUFJPR1JFU1NfREFUQV9BUkVBOgoJCQkJCQkJCXN3aXRjaCAoUHJvZ3Jlc3NOb3RpY2VFbnVtLnZhbHVlT2YocmVzLmdldENhdGVnb3J5KCkpKSB7CgkJCQkJCQkJY2FzZSBOQjoKCQkJCQkJCQkJYmVhbiA9IEpzb25VdGlsLmZyb20obm90aWNlUmVhZC5nZXRNZXNzYWdlKCksIE5ld1BvbGljeVNjaGVkdWxlRGV0YWlsUmVzQmVhbi5jbGFzcyk7CgkJCQkJCQkJCWJyZWFrOwoJCQkJCQkJCWNhc2UgUEM6CgkJCQkJCQkJCWJlYW4gPSBKc29uVXRpbC5mcm9tKG5vdGljZVJlYWQuZ2V0TWVzc2FnZSgpLAoJCQkJCQkJCQkJCUNoYW5nZVBvbGljeVNjaGVkdWxlRGV0YWlsUmVzQmVhbi5jbGFzcyk7CgkJCQkJCQkJCWJyZWFrOwoJCQkJCQkJCWNhc2UgQ0w6CgkJCQkJCQkJCWJlYW4gPSBKc29uVXRpbC5mcm9tKG5vdGljZVJlYWQuZ2V0TWVzc2FnZSgpLAoJCQkJCQkJCQkJCUNoYW5nZVBvbGljeVNjaGVkdWxlRGV0YWlsUmVzQmVhbi5jbGFzcyk7CgkJCQkJCQkJCWJyZWFrOwoJCQkJCQkJCX0KCQkJCQkJCWRlZmF1bHQ6CgkJCQkJCQkJYnJlYWs7CgkJCQkJCQl9CgkJCQkJCQlpZiAocmVzLmVxdWFscyhiZWFuKSkgewoJCQkJCQkJCXJlcy5zZXRSZWFkKHRydWUpOwoJCQkJCQkJCWJyZWFrOwoJCQkJCQkJfQoJCQkJCQl9IGNhdGNoIChJT0V4Y2VwdGlvbiBlKSB7CgkJCQkJCQllLnByaW50U3RhY2tUcmFjZSgpOwoJCQkJCQl9CgkJCQkJfQoJCQkJfQoJCQl9CgkJfSk7Cgl9CgoJLy8g57Wx5LiA6KiK5oGv6YCa55+l5aSn5YiG6aGeZ2V0QXAwOVR5cGUx5LmL5Lit5paH5ZG95ZCNKGZvbGxvdyBJS2FzaFNlcnZpY2VJbXBsIGdldE1lc3NhZ2VEYXRhQ291bnTlr6vms5UpCglwcm90ZWN0ZWQgdm9pZCBjaGFuZ2VNZXNzYWdlVHlwZU5hbWUoTGlzdDxNZXNzYWdlRGF0YUNvdW50UmVzQmVhbj4gbWVzc2FnZURhdGFDb3VudFJlc0JlYW5zKSB7CgkJZm9yIChNZXNzYWdlRGF0YUNvdW50UmVzQmVhbiBtZXNzYWdlRGF0YUNvdW50UmVzQmVhbiA6IG1lc3NhZ2VEYXRhQ291bnRSZXNCZWFucykgewoJCQlOb3RpY2VEYXRhTWVzc2FnZURhdGFUeXBlIG5vdGljZURhdGFNZXNzYWdlRGF0YVR5cGUgPSBOb3RpY2VEYXRhTWVzc2FnZURhdGFUeXBlCgkJCQkJLnJlc29sdmUobWVzc2FnZURhdGFDb3VudFJlc0JlYW4uZ2V0QXAwOVR5cGUxKCkpOwoJCQlpZiAobm90aWNlRGF0YU1lc3NhZ2VEYXRhVHlwZSAhPSBudWxsICYmIG5vdGljZURhdGFNZXNzYWdlRGF0YVR5cGUuZ2V0RGlzcGxheU5hbWUoKSAhPSBudWxsKSB7CgkJCQkvLyBMT0dHRVIuaW5mbygib2xkIG5hbWUtPiB7fSwgbmV3IG5hbWUgLT4ge30iLAoJCQkJLy8gbWVzc2FnZURhdGFDb3VudFJlc0JlYW4uZ2V0QXAwOVR5cGUxTmFtZSgpLAoJCQkJLy8gbm90aWNlRGF0YU1lc3NhZ2VEYXRhVHlwZS5nZXREaXNwbGF5TmFtZSgpKTsKCQkJCW1lc3NhZ2VEYXRhQ291bnRSZXNCZWFuLnNldEFwMDlUeXBlMU5hbWUobm90aWNlRGF0YU1lc3NhZ2VEYXRhVHlwZS5nZXREaXNwbGF5TmFtZSgpKTsKCQkJfQoJCX0KCX0KCgkvLyDntbHkuIDnhafmnIPpgJrnn6XlpKfliIbpoZ5nZXRBcDA5VHlwZTHkuYvkuK3mloflkb3lkI0oZm9sbG93IElLYXNoU2VydmljZUltcGwKCS8vIGdldE5vdGljZU1lc3NhZ2VEYXRhQ291bnTlr6vms5UpCglwcm90ZWN0ZWQgdm9pZCBjaGFuZ2VOb3RpY2VUeXBlTmFtZShMaXN0PE5vdGljZURhdGFDb3VudFJlc0JlYW4+IG5vdGljZURhdGFDb3VudFJlc0JlYW5zKSB7CgkJZm9yIChOb3RpY2VEYXRhQ291bnRSZXNCZWFuIG5vdGljZURhdGFDb3VudFJlc0JlYW4gOiBub3RpY2VEYXRhQ291bnRSZXNCZWFucykgewoJCQlOb3RpY2VEYXRhTWVzc2FnZURhdGFUeXBlIG5vdGljZURhdGFNZXNzYWdlRGF0YVR5cGUgPSBOb3RpY2VEYXRhTWVzc2FnZURhdGFUeXBlCgkJCQkJLnJlc29sdmUobm90aWNlRGF0YUNvdW50UmVzQmVhbi5nZXRVd25tU291cmNlKCkpOwoJCQlpZiAobm90aWNlRGF0YU1lc3NhZ2VEYXRhVHlwZSAhPSBudWxsICYmIG5vdGljZURhdGFNZXNzYWdlRGF0YVR5cGUuZ2V0RGlzcGxheU5hbWUoKSAhPSBudWxsKSB7CgkJCQkvLyBMT0dHRVIuaW5mbygib2xkIG5hbWUtPiB7fSwgbmV3IG5hbWUgLT4ge30iLAoJCQkJLy8gbm90aWNlRGF0YUNvdW50UmVzQmVhbi5nZXRVd25tU291cmNlTmFtZSgpLAoJCQkJLy8gbm90aWNlRGF0YU1lc3NhZ2VEYXRhVHlwZS5nZXREaXNwbGF5TmFtZSgpKTsKCQkJCW5vdGljZURhdGFDb3VudFJlc0JlYW4uc2V0VXdubVNvdXJjZU5hbWUobm90aWNlRGF0YU1lc3NhZ2VEYXRhVHlwZS5nZXREaXNwbGF5TmFtZSgpKTsKCQkJfQoJCX0KCX0KCn0K