diff --git a/PROMS/VEPROMS.CSLA.Library/Extension/ContentExt.cs b/PROMS/VEPROMS.CSLA.Library/Extension/ContentExt.cs index 184c59e5..f69fb30b 100644 --- a/PROMS/VEPROMS.CSLA.Library/Extension/ContentExt.cs +++ b/PROMS/VEPROMS.CSLA.Library/Extension/ContentExt.cs @@ -733,6 +733,244 @@ namespace VEPROMS.CSLA.Library { return str.Replace(@"\u8209?", "-").Replace(@"\u160?", " "); //dash and hard space } + + //C2022-028 (only used from Amin Tools) check the RO link text - compare with RO Usage information, annotate RO links that are bad + public bool CheckROLinkTextandUsage(ref int BadROLinksCount, ref int CheckROLinksCount, ref int FixedROLinksCount) + { + /*** needed if we fix RO link text + bool bFixedROLinks = false; + bool bFixedTableDataText = false; + ***/ + if (this.Text.Contains("#Link:ReferencedObject:")) + { + if (this.ContentRoUsageCount == 0) // Procedure text has one or more links but no RO Usage records + { + CheckROLinksCount++; + _MyLog.ErrorFormat(string.Format("No RO usage records for RO link(s) - ContentID = {0}", this.ContentID)); + using (Item myItem = this.ContentItems[0].MyItem) // so that myitem does not stay in cache + { + myItem.DisposeOfContent = false; // don't dispose of the contents may be needed if more than one RO needs processed + Annotation.MakeAnnotation(myItem, AnnotationType.GetByNameOrCreate("Bad RO link"), "", "Incomplete RO Link Information for all RO References in this text - Relink RO References", null); + } + } + else + { + // We have RO link text and RO Usages - so verify link information matches RO Usage record information + string findLink = @""; + MatchCollection ms = Regex.Matches(Text, findLink); // finds all the links (both RO and Transitions) + string lookFor = "#Link:ReferencedObject:"; + string fixedContentText = Text; + if (ms.Count > 0) + { + int roCnt = 0; + string sAnnotationText = ""; + foreach (Match mm in ms) + { + int offset = mm.Index; + Match m = Regex.Match(mm.Value, lookFor, RegexOptions.Singleline); // Is this a RO link? + if (m != null && m.Length > 0) + { + string linkText = mm.Value; // the link text for the Referenced Object + CheckROLinksCount++; + roCnt++; // the RO instance in the text that we are checking + // parse out usageid from link + int rousgidx = m.Index + m.Length; + int rousagid_len = mm.Value.IndexOf(" ", rousgidx) - rousgidx; + string sROusageID = mm.Value.Substring(rousgidx, rousagid_len); // ROUsageID from link text (as a string) + int roidIdx = rousgidx + rousagid_len + 1; + int roid_Len = mm.Value.IndexOf(" ", roidIdx) - roidIdx; + string sROid = mm.Value.Substring(roidIdx, roid_Len); // the ROID from the link text (as a string) + // initialize to zero for cases where the ROUsage text is to force a no match below + // when a link has either of these, then the process of inserting that RO link did not complete for some reason + int iRousage = 0; + if (!sROusageID.StartsWith("<")) // don't try to convert if link has for the ROUsageID value + iRousage = Convert.ToInt32(sROusageID); //ROUsageID as interger + // Both GoodROUsageID and GoodROUID must match in ROUsage record for link to be good + bool GoodROUsageID = false; + bool GoodROID = false; + // Check each ContentRoUsages and look for a matching ROUsageID and ROID + if (iRousage > 0 && this.ContentRoUsageCount > 0) + { + int lastROUsageID = -1; + string lastROID = ""; + RoUsageInfo badRoUsageInfo = null; + foreach (RoUsageInfo rui in this.ContentItems[0].MyItem.MyItemInfo.MyContent.ContentRoUsages) + { + GoodROID = rui.ROID.Equals(sROid); //does this usage record have a matching ROID with the link text? + GoodROUsageID = rui.ROUsageID.Equals(iRousage); //does the usage record have a matching ROUsageID with the link text? + if (GoodROID && GoodROUsageID) + { + //myROUsages.RemoveAt(myROUsageCnt - 1); + break; // jump out loop - valid RO Usage record found + } + if (GoodROID && !GoodROUsageID) + { + lastROUsageID = rui.ROUsageID; + lastROID = rui.ROID; + } + else if (!GoodROID && GoodROUsageID) + badRoUsageInfo = rui; + } + if (!GoodROID) // the ROID in the ROUsage record does not match the RO Link text - add annotation + { + BadROLinksCount++; + // Add detail information to the error log + _MyLog.ErrorFormat(string.Format("Invalid ROID - ContentID = {0} Link - {1}", this.ContentID, mm.Value)); + sAnnotationText += string.Format("Bad RO Instance {0} - RO Needs Relinked - RO Text different than RO Data\n", roCnt); + } + else if (!GoodROUsageID) // Link does not have a valid ROUsage record for that RO link - add annotation + { + BadROLinksCount++; + /********* + //** below is logic to replace the ROUsageID in the linked text with one (for this contentID) that has the same ROID + //** Commented out for now as this was test code for now - don't want to give to customers until we are comfortable + //if (lastROUsageID != -1) + //{ + // // set the ROUsageID in the link text to last good ROUsageID found in ROUsage table + // linkText = linkText.Replace(string.Format("#Link:ReferencedObject:{0} ", sROusageID), string.Format("#Link:ReferencedObject:{0} ", lastROUsageID)); + // fixedContentText = fixedContentText.Replace(string.Format("#Link:ReferencedObject:{0} ", sROusageID), string.Format("#Link:ReferencedObject:{0} ", lastROUsageID)); + // bFixedROLinks = true; // set to true so we know to update content text + // _MyLog.InfoFormat(string.Format("Fixed Invalid RO Link - ContentID = {0} badLink - {1} goodLink - {2}",this.ContentID, mm.Value, linkText)); + // FixedROLinksCount++; + // using (Item myItem = this.ContentItems[0].MyItem) // so that myitem does not stay in cache B2016-153 + // { + // myItem.DisposeOfContent = false; // don't dispose of the contents may be needed if more than one RO needs processed - part of B2017-060 + // //Annotation.MakeAnnotation(myItem, AnnotationType.GetByNameOrCreate("Bad RO link"), "", string.Format("Invalid RO Usage ID for RO Instance {0}",roCnt), null); + // Annotation.MakeAnnotation(myItem, AnnotationType.GetByNameOrCreate("Fixed Bad RO link"), "", string.Format("Fixed RO Instance {0} - Verify RO Value", roCnt), null); + // } + //} + *********/ + //else + //{ + // Add detail information to the error log + _MyLog.ErrorFormat(string.Format("Invalid ROUsageID - ContentID = {0} Link - {1}", this.ContentID, mm.Value)); + sAnnotationText += string.Format("RO Instance {0} Needs Relinked - Value Not Able To Update\n", roCnt); + //} + } + } + } + } + if (roCnt < this.ContentRoUsageCount) + { + BadROLinksCount++; + // there are more RO Usage records then there links in the step + _MyLog.WarnFormat(string.Format("Possible missing RO links, more RO Usage records than Links - ContentID = {0}", this.ContentID)); + sAnnotationText += "Possible missing RO links.\n"; + } + // if any bad RO links were found, put the information in an Annotation + if (sAnnotationText.Length > 0) + { + char[] newLine = { '\n' }; + sAnnotationText = sAnnotationText.TrimEnd(newLine); + using (Item myItem = this.ContentItems[0].MyItem) // so that myitem does not stay in cache B2016-153 + { + myItem.DisposeOfContent = false; // don't dispose of the contents may be needed if more than one RO needs processed - part of B2017-060 + //Annotation.MakeAnnotation(myItem, AnnotationType.GetByNameOrCreate("Bad RO link"), "", string.Format("Invalid RO Usage ID for RO Instance {0}",roCnt), null); + Annotation.MakeAnnotation(myItem, AnnotationType.GetByNameOrCreate("Bad RO link"), "", sAnnotationText, null); + } + } + /*** COMMENTED OUT BECAUSE WE NOT MAKING CHANGES TO THE DATA - FOR NOW + //if (bFixedROLinks) + //{ + // // save content text + // Text = fixedContentText; + //} + *****/ + + /******* + // if we fix RO links in the RTF then see if there is a grid to update too. + // WE DON'T NEED TO ADD ANNOTATIONS AS THAT IS DONE ABOVE (FOR THE RTF OF THE TABLE - BELOW IS THE XML OF THE TABLE + // *** bFixedROLinks WILL REMAIN FALSE FOR NOW AS WE ARE NOT CHANGING LINK TEXT - THIS WILL PREVENT THE CHECKING OF THE XML TABLE + if (bFixedROLinks && MyGrid != null && MyGrid.Data.Length > 0) + { + string fixedTableDataText = MyGrid.Data; + // **** NEED LOGIC TO CHECK RO TABLES **** + + //if (rotype == (int)E_ROValueType.Table) // if change in rotable data... + //{ + // if (origROFstInfo != null) + // { + // List retlist = origROFstInfo.OnROTableUpdate(this, new ROFstInfoROTableUpdateEventArgs(newvalue, MyGrid.Data)); + // if (MyGrid.Data != retlist[1]) + // { + // MyGrid.Data = retlist[1]; + // retval = Text; + // if (Text != retlist[0]) + // Text = retlist[0]; + // } + // } + //} + //else + { + // if it's an ro within a table, need to process into an flex grid to save the grid data: + string findLinkXml = @"<START\].*?\[END>"; + //string lookForXml = string.Format(@"^<START\](\\[^v \\]+)*\\v0(\\[^v '?{{}}\\]+)*( |\\u[0-9]{{1,4}}?|\\'[0-9a-fA-F]{{2}}|\\[{{}}~])(.*?)(\\[^v'?{{}} \\]+)*\\v(\\[^v \\]+)* #Link:ReferencedObject:{0} .*?\[END>$", rousg.ROUsageID); + string lookForXml = "#Link:ReferencedObject:"; + MatchCollection msg = Regex.Matches(MyGrid.Data, findLinkXml); + foreach (Match mmg in msg) + { + Match mg = Regex.Match(mmg.Value, lookForXml);// look for Referenced Object link in linked text + if (mg != null && mg.Groups.Count > 1) + { + string tblLinkText = mmg.Value; // the link text in the table XML + int rousgidx = mg.Index + mg.Length; + int rousagid_len = mmg.Value.IndexOf(" ", rousgidx) - rousgidx; + string sROusageID = mmg.Value.Substring(rousgidx, rousagid_len); // ROUsageID from link text + int roidIdx = rousgidx + rousagid_len + 1; + int roid_Len = mmg.Value.IndexOf(" ", roidIdx) - roidIdx; + string sROid = mmg.Value.Substring(roidIdx, roid_Len); + // initialize to zero for cases where the ROUsage is to force a no match below + // -when a link has either of these, then the process of inserting that RO link did not complete for some reason + int iRousage = 0; + if (!sROusageID.StartsWith("<")) // don't try to convert if link has for the ROUsageID value + iRousage = Convert.ToInt32(sROusageID); //ROUsageID as interger + // see if there is a ContentID and ROUsage record match + // Both GoodROUsageID and GoodROUID must match in ROUsage record for link to be good + bool GoodROUsageID = false; + bool GoodROID = false; + // Check each ContentRoUsages and look for a matching ROUsageID and ROID + if (iRousage > 0 && this.ContentRoUsageCount > 0) + { + int lastROUsageID = -1; + string lastROID = ""; + RoUsageInfo badRoUsageInfo = null; + foreach (RoUsageInfo rui in this.ContentItems[0].MyItem.MyItemInfo.MyContent.ContentRoUsages) + { + GoodROID = rui.ROID.Equals(sROid); //does this usage record have a matching ROID with the link text? + GoodROUsageID = rui.ROUsageID.Equals(iRousage); //does the usage record have a matching ROUsageID with the link text? + if (GoodROID && GoodROUsageID) break; // jump out loop - valid RO Usage record found + if (GoodROID && !GoodROUsageID) + { + lastROUsageID = rui.ROUsageID; + lastROID = rui.ROID; + } + else if (!GoodROID && GoodROUsageID) + badRoUsageInfo = rui; + } + if (!GoodROUsageID && GoodROID && lastROUsageID != -1) // Link does not have a valid ROUsage record for that RO link - add annotation + { + // set the ROUsageID in the link text to last good ROUsageID found in ROUsage table + tblLinkText = tblLinkText.Replace(string.Format("#Link:ReferencedObject:{0} ", sROusageID), string.Format("#Link:ReferencedObject:{0} ", lastROUsageID)); + fixedTableDataText = fixedTableDataText.Replace(string.Format("#Link:ReferencedObject:{0} ", sROusageID), string.Format("#Link:ReferencedObject:{0} ", lastROUsageID)); + bFixedTableDataText = true; // set to true so we know to update content text + } + if (bFixedTableDataText) // if we changed the table XML, then save it + { + this.MyGrid.Data = fixedTableDataText; + } + } + } + } + } + ******* End modify table ****/ + } + } + } + /*** needed if we fix RO links + return (bFixedROLinks || bFixedTableDataText); + ***/ + return false; + } } public delegate void StaticContentInfoEvent(object sender, StaticContentInfoEventArgs args);