using Adaptation.Shared; using Adaptation.Shared.Metrology; using Adaptation.Shared.Properties; using System; using System.Collections.Generic; using System.IO; using System.Text; namespace Adaptation.FileHandlers.OpenInsightMetrologyViewer; public class WSRequest { public int Id { get; set; } public string AreaCountAvg { get; set; } public string AreaCountMax { get; set; } public string AreaCountMin { get; set; } public string AreaCountStdDev { get; set; } public string AreaTotalAvg { get; set; } public string AreaTotalMax { get; set; } public string AreaTotalMin { get; set; } public string AreaTotalStdDev { get; set; } public string Date { get; set; } public string HazeAverageAvg { get; set; } public string HazeAverageMax { get; set; } public string HazeAverageMin { get; set; } public string HazeAverageStdDev { get; set; } public string HazeRegionAvg { get; set; } public string HazeRegionMax { get; set; } public string HazeRegionMin { get; set; } public string HazeRegionStdDev { get; set; } public string Layer { get; set; } public string LotID { get; set; } public string LPDCM2Avg { get; set; } public string LPDCM2Max { get; set; } public string LPDCM2Min { get; set; } public string LPDCM2StdDev { get; set; } public string LPDCountAvg { get; set; } public string LPDCountMax { get; set; } public string LPDCountMin { get; set; } public string LPDCountStdDev { get; set; } public string Operator { get; set; } public string ParseErrorText { get; set; } public string PSN { get; set; } public string RDS { get; set; } public string Reactor { get; set; } public string Recipe { get; set; } public string ScratchCountAvg { get; set; } public string ScratchCountMax { get; set; } public string ScratchCountMin { get; set; } public string ScratchCountStdDev { get; set; } public string ScratchTotalAvg { get; set; } public string ScratchTotalMax { get; set; } public string ScratchTotalMin { get; set; } public string ScratchTotalStdDev { get; set; } public string SumOfDefectsAvg { get; set; } public string SumOfDefectsMax { get; set; } public string SumOfDefectsMin { get; set; } public string SumOfDefectsStdDev { get; set; } public string Title { get; set; } public string UniqueId { get; set; } public string Zone { get; set; } public string CellName { get; set; } public string Data { get; set; } #pragma warning disable IDE1006 public int i { get; set; } public List Details { get; protected set; } [Obsolete("For json")] public WSRequest() { } #pragma warning disable IDE0060 internal WSRequest(IFileRead fileRead, Logistics logistics, List descriptions, string processDataStandardFormat = null) #pragma warning restore IDE0060 { i = -1; Id = -1; Zone = null; Layer = null; Title = null; Data = "*Data*"; Details = new List(); CellName = logistics.MesEntity; pcl.Description x = descriptions[0]; //Header { AreaCountAvg = x.AreaCountAvg; AreaCountMax = x.AreaCountMax; AreaCountMin = x.AreaCountMin; AreaCountStdDev = x.AreaCountStdDev; AreaTotalAvg = x.AreaTotalAvg; AreaTotalMax = x.AreaTotalMax; AreaTotalMin = x.AreaTotalMin; AreaTotalStdDev = x.AreaTotalStdDev; Date = x.Date; HazeAverageAvg = x.HazeAverageAvg; HazeAverageMax = x.HazeAverageMax; HazeAverageMin = x.HazeAverageMin; HazeAverageStdDev = x.HazeAverageStdDev; HazeRegionAvg = x.HazeRegionAvg; HazeRegionMax = x.HazeRegionMax; HazeRegionMin = x.HazeRegionMin; HazeRegionStdDev = x.HazeRegionStdDev; LotID = x.Lot; LPDCM2Avg = x.LPDCM2Avg; LPDCM2Max = x.LPDCM2Max; LPDCM2Min = x.LPDCM2Min; LPDCM2StdDev = x.LPDCM2StdDev; LPDCountAvg = x.LPDCountAvg; LPDCountMax = x.LPDCountMax; LPDCountMin = x.LPDCountMin; LPDCountStdDev = x.LPDCountStdDev; ParseErrorText = x.ParseErrorText; PSN = x.PSN; RDS = x.RDS; Reactor = x.Reactor; Recipe = x.Recipe; Operator = x.Employee; ScratchCountAvg = x.ScratchCountAvg; ScratchCountMax = x.ScratchCountMax; ScratchCountMin = x.ScratchCountMin; ScratchCountStdDev = x.ScratchCountStdDev; ScratchTotalAvg = x.ScratchTotalAvg; ScratchTotalMax = x.ScratchTotalMax; ScratchTotalMin = x.ScratchTotalMin; ScratchTotalStdDev = x.ScratchTotalStdDev; SumOfDefectsAvg = x.SumOfDefectsAvg; SumOfDefectsMax = x.SumOfDefectsMax; SumOfDefectsMin = x.SumOfDefectsMin; SumOfDefectsStdDev = x.SumOfDefectsStdDev; UniqueId = x.UniqueId; } pcl.Detail detail; foreach (pcl.Description description in descriptions) { detail = new pcl.Detail { Data = "*Data*", i = -1, Id = 0, //item.Id, AreaCount = description.AreaCount, AreaTotal = description.AreaTotal, Bin1 = description.Bin1, Bin2 = description.Bin2, Bin3 = description.Bin3, Bin4 = description.Bin4, Bin5 = description.Bin5, Bin6 = description.Bin6, Bin7 = description.Bin7, Bin8 = description.Bin8, Comments = description.Comments, Date = description.Date, Diameter = description.Diameter, Exclusion = description.Exclusion, Gain = description.Gain, HazeAverage = description.HazeAverage, HazePeak = description.HazePeak, HazeRegion = description.HazeRegion, HazeRng = description.HazeRng, HeaderUniqueId = description.HeaderUniqueId, LPDCM2 = description.LPDCM2, LPDCount = description.LPDCount, Laser = description.Laser, Mean = description.Mean, Recipe = description.Recipe, ScratchCount = description.ScratchCount, ScratchTotal = description.ScratchTotal, Slot = description.Slot, Sort = description.Sort, StdDev = description.StdDev, SumOfDefects = description.SumOfDefects, Thresh = description.Thresh, Thruput = description.Thruput, Title = null, UniqueId = description.UniqueId }; Details.Add(detail); } Date = logistics.DateTimeFromSequence.ToString(); if (UniqueId is null && Details.Count != 0) UniqueId = Details[0].HeaderUniqueId; for (int i = 0; i < Details.Count; i++) { if (string.IsNullOrEmpty(Details[i].Bin1)) Details[i].Bin1 = null; if (string.IsNullOrEmpty(Details[i].Bin2)) Details[i].Bin2 = null; if (string.IsNullOrEmpty(Details[i].Bin3)) Details[i].Bin3 = null; if (string.IsNullOrEmpty(Details[i].Bin4)) Details[i].Bin4 = null; if (string.IsNullOrEmpty(Details[i].Bin5)) Details[i].Bin5 = null; if (string.IsNullOrEmpty(Details[i].Bin6)) Details[i].Bin6 = null; if (string.IsNullOrEmpty(Details[i].Bin7)) Details[i].Bin7 = null; if (string.IsNullOrEmpty(Details[i].Bin8)) Details[i].Bin8 = null; } UniqueId = $"{logistics.JobID}_{logistics.MID}_{logistics.DateTimeFromSequence:yyyyMMddHHmmssffff}"; for (int i = 0; i < Details.Count; i++) { Details[i].HeaderUniqueId = UniqueId; Details[i].UniqueId = $"{logistics.JobID}_{logistics.MID}_{logistics.DateTimeFromSequence:yyyyMMddHHmmssffff}_Item-{i + 1}"; } } private static void UpdateDataPDF(List descriptions, string checkFileName) { string value; string fullName; object possiblePage; object possibleString; object possibleCOSArray; java.util.List tokenList; java.util.List arrayList; java.io.OutputStream outputStream; List updateValues = new(); StringBuilder stringBuilder = new(); java.util.ListIterator tokenIterator; java.util.ListIterator arrayIterator; java.io.File file = new(checkFileName); string reactorLoadLock = descriptions[0].Comments; org.apache.pdfbox.pdmodel.common.PDStream pdStream; org.apache.pdfbox.pdmodel.common.PDStream updatedStream; org.apache.pdfbox.pdfparser.PDFStreamParser pdfStreamParser; org.apache.pdfbox.pdfwriter.ContentStreamWriter contentStreamWriter; org.apache.pdfbox.pdmodel.PDDocument pdDocument = org.apache.pdfbox.pdmodel.PDDocument.load(file); org.apache.pdfbox.pdmodel.PDDocumentCatalog pdDocumentCatalog = pdDocument.getDocumentCatalog(); java.util.List pagesList = pdDocumentCatalog.getAllPages(); java.util.ListIterator pageIterator = pagesList.listIterator(); if (string.IsNullOrEmpty(descriptions[0].Lot) || string.IsNullOrEmpty(descriptions[0].Reactor) || descriptions[0].Lot.StartsWith(descriptions[0].Reactor)) fullName = string.Empty; else fullName = $"{descriptions[0].Reactor}-{descriptions[0].RDS}-{descriptions[0].PSN} "; for (short i = 1; i < short.MaxValue; i++) { if (!pageIterator.hasNext()) break; possiblePage = pageIterator.next(); if (possiblePage is not org.apache.pdfbox.pdmodel.PDPage page) continue; pdStream = page.getContents(); pdfStreamParser = new org.apache.pdfbox.pdfparser.PDFStreamParser(pdStream); pdfStreamParser.parse(); tokenList = pdfStreamParser.getTokens(); tokenIterator = tokenList.listIterator(); for (short t = 1; i < short.MaxValue; t++) { if (!tokenIterator.hasNext()) break; possibleCOSArray = tokenIterator.next(); if (possibleCOSArray is not org.apache.pdfbox.cos.COSArray cossArray) continue; _ = stringBuilder.Clear(); arrayList = cossArray.toList(); arrayIterator = arrayList.listIterator(); for (short a = 1; i < short.MaxValue; a++) { if (!arrayIterator.hasNext()) break; possibleString = arrayIterator.next(); if (possibleString is not org.apache.pdfbox.cos.COSString cossString) continue; value = cossString.getString(); _ = stringBuilder.Append(value); if (value != "]") continue; updateValues.Add(value); value = stringBuilder.ToString(); if (value.Contains("[]")) cossArray.setString(a - 1, string.Concat("*", fullName, reactorLoadLock, "]")); else cossArray.setString(a - 1, string.Concat(" {*", fullName, reactorLoadLock, "}]")); } } if (updateValues.Count != 0) { updatedStream = new org.apache.pdfbox.pdmodel.common.PDStream(pdDocument); outputStream = updatedStream.createOutputStream(); contentStreamWriter = new org.apache.pdfbox.pdfwriter.ContentStreamWriter(outputStream); contentStreamWriter.writeTokens(tokenList); outputStream.close(); page.setContents(updatedStream); } } if (updateValues.Count != 0) pdDocument.save(checkFileName); pdDocument.close(); } internal static long GetHeaderId(IFileRead fileRead, Logistics logistics, string openInsightMetrologyViewerAPI, string openInsightMetrologyViewerFileShare, int weekOfYear, WS.Results results, List descriptions) { long result; if (results is not null && results.HeaderId is not null) result = results.HeaderId.Value; else { WSRequest wsRequest = new(fileRead, logistics, descriptions); string directory = Path.Combine(openInsightMetrologyViewerFileShare, logistics.DateTimeFromSequence.Year.ToString(), $"WW{weekOfYear:00}"); (_, WS.Results wsResults) = WS.SendData(openInsightMetrologyViewerAPI, logistics.Sequence, directory, wsRequest); if (wsResults.Success is null || !wsResults.Success.Value) throw new Exception(wsResults.ToString()); result = wsResults.HeaderId.Value; } return result; } #pragma warning disable IDE0060 internal static void PostOpenInsightMetrologyViewerAttachments(IFileRead fileRead, Logistics logistics, string openInsightMetrologyViewerAPI, List descriptions, string matchDirectory, WS.Results results, string headerIdDirectory) #pragma warning restore IDE0060 { string checkFileName; pcl.Description description; string[] pclFiles = Directory.GetFiles(matchDirectory, "*.pcl", SearchOption.TopDirectoryOnly); if (pclFiles.Length != 1) throw new Exception($"Invalid source file count for <{results.HeaderId}>!"); string sourceFileNameNoExt = Path.GetFileNameWithoutExtension(pclFiles[0]); List dataAttachments = new(); List headerAttachments = new(); checkFileName = Path.Combine(matchDirectory, $"{sourceFileNameNoExt}_data.pdf"); if (!File.Exists(checkFileName)) throw new Exception("Header file doesn't exist!"); else { UpdateDataPDF(descriptions, checkFileName); headerAttachments.Add(new WS.Attachment(results, headerIdDirectory, $"{logistics.JobID}_{logistics.MID}_{logistics.DateTimeFromSequence:yyyyMMddHHmmssffff}", "Data.pdf", checkFileName)); } for (int i = 0; i < descriptions.Count; i++) { description = descriptions[i]; checkFileName = Path.Combine(matchDirectory, $"{sourceFileNameNoExt}_s{description.Slot}_image.pdf"); if (File.Exists(checkFileName)) dataAttachments.Add(new WS.Attachment(results, headerIdDirectory, $"{logistics.JobID}_{logistics.MID}_{logistics.DateTimeFromSequence:yyyyMMddHHmmssffff}_Item-{i + 1}", "Image.pdf", checkFileName)); else { checkFileName = Path.Combine(matchDirectory, $"{sourceFileNameNoExt}_s{description.Slot}_data.pdf"); if (File.Exists(checkFileName)) dataAttachments.Add(new WS.Attachment(results, headerIdDirectory, $"{logistics.JobID}_{logistics.MID}_{logistics.DateTimeFromSequence:yyyyMMddHHmmssffff}_Item-{i + 1}", "Image.pdf", checkFileName)); } } if (dataAttachments.Count == 0 || dataAttachments.Count != descriptions.Count) throw new Exception($"Invalid attachment count! {dataAttachments.Count} != {descriptions.Count}"); WS.AttachFiles(openInsightMetrologyViewerAPI, headerAttachments, dataAttachments); } }