using Adaptation.Shared; using Adaptation.Shared.Metrology; using Adaptation.Shared.Properties; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Text.Json; namespace Adaptation.FileHandlers.OpenInsightMetrologyViewer; public class WSRequest { public long 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() { } internal WSRequest(IFileRead fileRead, Logistics logistics, List descriptions) { if (fileRead is null) { } i = -1; Id = 0; 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.Any()) 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; } } 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.Any()) { 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.Any()) pdDocument.save(checkFileName); pdDocument.close(); } internal static void PostOpenInsightMetrologyViewerAttachments(IFileRead fileRead, Logistics logistics, string openInsightMetrologyViewerAPI, DateTime dateTime, string json, List descriptions, string matchDirectory) { if (dateTime == DateTime.MinValue) { } string checkFileName; if (string.IsNullOrEmpty(json)) { WSRequest wsRequest = new(fileRead, logistics, descriptions); (json, WS.Results wsResults) = WS.SendData(openInsightMetrologyViewerAPI, wsRequest); if (!wsResults.Success) throw new Exception(wsResults.ToString()); } WS.Results metrologyWSRequest = JsonSerializer.Deserialize(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); long wsResultsHeaderID = metrologyWSRequest.HeaderID; string[] pclFiles = Directory.GetFiles(matchDirectory, "*.pcl", SearchOption.TopDirectoryOnly); if (pclFiles.Length != 1) throw new Exception($"Invalid source file count for <{wsResultsHeaderID}>!{Environment.NewLine}{json}"); 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(descriptions[0].HeaderUniqueId, "Data.pdf", checkFileName)); } foreach (pcl.Description description in descriptions) { checkFileName = Path.Combine(matchDirectory, $"{sourceFileNameNoExt}_{description.Slot.Replace('*', 's')}_image.pdf"); if (File.Exists(checkFileName)) dataAttachments.Add(new WS.Attachment(description.UniqueId, "Image.pdf", checkFileName)); else { checkFileName = Path.Combine(matchDirectory, $"{sourceFileNameNoExt}_{description.Slot.Replace('*', 's')}_data.pdf"); if (File.Exists(checkFileName)) dataAttachments.Add(new WS.Attachment(description.UniqueId, "Image.pdf", checkFileName)); } } if (dataAttachments.Count == 0 || dataAttachments.Count != descriptions.Count) throw new Exception($"Invalid attachment count! {dataAttachments.Count} != {descriptions.Count}"); WS.AttachFiles(openInsightMetrologyViewerAPI, wsResultsHeaderID, headerAttachments, dataAttachments); } }