返回列表 上一筆 下一筆

📄 資料內容

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());
			}
		}
	}

}

🔐 Base64 編碼內容

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
返回列表 上一筆 下一筆