348 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			348 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Collections.Generic;
 | |
| using System.IO;
 | |
| using System.Linq;
 | |
| using System.Text;
 | |
| using System.Text.RegularExpressions;
 | |
| using System.Xml;
 | |
| using VEPROMS.CSLA.Library;
 | |
| 
 | |
| namespace VEPROMS
 | |
| {
 | |
|     //C2025-024 Electronic Procedures - Phase 2 (PROMS XML output)
 | |
|     //class inherits from normal import/export form
 | |
|     //then adds additional functionality
 | |
| #pragma warning disable S101 // Types should be named in PascalCase
 | |
|     public partial class dlgExportImportEP : dlgExportImport
 | |
| #pragma warning restore S101 // Types should be named in PascalCase
 | |
| 	{
 | |
| 		private readonly AnnotationTypeInfo _AnnotationType;
 | |
|         private readonly string multiseparator = ",";
 | |
| 
 | |
| 		private static Regex _ROAccPageTokenPattern = new Regex("[<][^<>-]+-[^<>]+[>]");
 | |
| 
 | |
|         public dlgExportImportEP(string mode, FolderInfo folderInfo, frmVEPROMS myFrmVEPROMS, int annotationTypeId, int unitIndex = 0) : base(mode, folderInfo, myFrmVEPROMS, ( unitIndex))
 | |
|         {
 | |
|             _AnnotationType = AnnotationTypeInfo.Get(annotationTypeId);
 | |
|             _ExportBothConvertedandNot = true;
 | |
|             DocReplace = new Dictionary<int, byte[]>();
 | |
|             FormClosed += OnClose;
 | |
|             Text = $"{mode} Electronic Procedure ({_AnnotationType.Name}) Dialog for {folderInfo.Name}";
 | |
| 		}
 | |
|         public dlgExportImportEP(string mode, DocVersionInfo docVersionInfo, frmVEPROMS myFrmVEPROMS, int annotationTypeId, int unitIndex = 0) : base(mode, docVersionInfo, myFrmVEPROMS, (unitIndex))
 | |
|         {
 | |
|             _AnnotationType = AnnotationTypeInfo.Get(annotationTypeId);
 | |
|             _ExportBothConvertedandNot = true;
 | |
|             DocReplace = new Dictionary<int, byte[]>();
 | |
|             FormClosed += OnClose;
 | |
|             Text = $"{mode} Electronic Procedure ({_AnnotationType.Name}) Dialog for {docVersionInfo.Name} of {docVersionInfo.MyFolder.Name}";
 | |
| 		}
 | |
|         public dlgExportImportEP(string mode, ProcedureInfo procedureInfo, frmVEPROMS myFrmVEPROMS, int annotationTypeId, int unitIndex = 0) : base(mode, procedureInfo, myFrmVEPROMS, (unitIndex))
 | |
| 		{
 | |
| 			_AnnotationType = AnnotationTypeInfo.Get(annotationTypeId);
 | |
| 			_ExportBothConvertedandNot = true;
 | |
| 			DocReplace = new Dictionary<int, byte[]>();
 | |
| 			FormClosed += OnClose;
 | |
| 			Text = $"{mode} Electronic Procedure ({_AnnotationType.Name}) Dialog for {procedureInfo.DisplayNumber}";
 | |
| 		}
 | |
| 
 | |
| 		//Overridden function to handle export of EP data
 | |
| 		protected override void ExportEPAnnotationInfo(XmlElement xe, ItemInfo ii)
 | |
| 		{
 | |
| 			if (_UnitIndex > 0)
 | |
|             {
 | |
| 				ii.MyDocVersion.DocVersionConfig.SelectedSlave = _UnitIndex;
 | |
| 				ii.MyProcedure.MyDocVersion.DocVersionConfig.SelectedSlave = _UnitIndex;
 | |
|             }
 | |
| 
 | |
|             //switch to handle customizations for different formats
 | |
|             switch (ii.ActiveFormat.PlantFormat.EPFormatFiles.Find(x => x.AnnotationTypeID == _AnnotationType.TypeID)?.Name)
 | |
| 			{
 | |
| 				default:
 | |
| 					ExportEPAnnotationInfo_Default(xe, ii);
 | |
| 					break;
 | |
| 			}
 | |
| 
 | |
| 			ii.MyDocVersion.DocVersionConfig.SelectedSlave = 0;
 | |
| 			ii.MyProcedure.MyDocVersion.DocVersionConfig.SelectedSlave = 0;
 | |
| 
 | |
| 		}
 | |
| 
 | |
| 		//default export of EP Data
 | |
| 		private void ExportEPAnnotationInfo_Default(XmlElement xe, ItemInfo ii)
 | |
| 		{
 | |
| 			//Add tab text to item
 | |
| 			string steptab = Volian.Print.Library.PDFReport.BuildStepTab(ii);
 | |
| 			xe.Attributes.SetNamedItem(AddAttribute(xe.OwnerDocument, "StepTab", steptab));
 | |
| 
 | |
| 			//Add db sequence to item
 | |
| 			string dbsequence = dbSeq(ii);
 | |
| 			xe.Attributes.SetNamedItem(AddAttribute(xe.OwnerDocument, "dbsequence", dbsequence));
 | |
| 
 | |
| 			//get first transition in item and add it as an xml element
 | |
| 			if (ii.MyContent.ContentTransitionCount > 0)
 | |
| 			{
 | |
| 				TransitionInfo ct = ii.MyContent.ContentTransitions[0];
 | |
| 				xe.Attributes.SetNamedItem(AddAttribute(xe.OwnerDocument, "TransitionToItemID", ct.ToID.ToString()));
 | |
| 				xe.Attributes.SetNamedItem(AddAttribute(xe.OwnerDocument, "TransitionTodbsequence", dbSeq(ct.ToID)));
 | |
| 			}
 | |
| 
 | |
| 			//export EP annotation details under an EPInfo node
 | |
| 			if (ii.ItemAnnotations != null)
 | |
| 			{
 | |
| 				XmlElement xepinfo = xe.OwnerDocument.CreateElement("EPInfo");
 | |
| 
 | |
| 				EPFields myEPFields = ii.GetValidEPFields(_AnnotationType.TypeID);
 | |
| 				ROFSTLookup lookup = ii.MyDocVersion.DocVersionAssociations[0].MyROFst.GetROFSTLookup(ii.MyDocVersion);
 | |
| 				bool epexportblank = ii.EPexportblank(_AnnotationType.TypeID); //should blank xml elements export?
 | |
| 
 | |
| 				//grab the current RO db so will know location of RO files and default graphics ext.
 | |
|                 using (RODbInfo myRODB = (RODbInfoList.Get()).FirstOrDefault(x => x.RODbID == ii.MyDocVersion.DocVersionAssociations[0].MyROFst.RODbID))
 | |
|                 {
 | |
| 					//For each annotation in the item that is of the current EP Annotation type
 | |
| 					foreach (var EPAnnotation in ii.ItemAnnotations.Where(x => x.TypeID == _AnnotationType.TypeID))
 | |
| 					{
 | |
| 						var EPAnnotationConfig = new AnnotationConfig(EPAnnotation.Config);
 | |
| 
 | |
| 						XmlElement xepdetails = xe.OwnerDocument.CreateElement("Details");
 | |
| 						//include the annotation ID for reference
 | |
| 						xepdetails.Attributes.SetNamedItem(AddAttribute(xepdetails.OwnerDocument, "AnnotationID", EPAnnotation.AnnotationID.ToString()));
 | |
| 
 | |
| 						//loop through each EP Field - name the xml elements the EP.name
 | |
| 						foreach (EPField EP in myEPFields)
 | |
| 						{
 | |
| 							string val = EPAnnotationConfig.GetValue("EP", EP.name);
 | |
| 
 | |
| 							if (epexportblank || !string.IsNullOrEmpty(val))
 | |
| 							{
 | |
| 
 | |
| 								if (_UnitIndex != 0)
 | |
| 								{
 | |
| 									val = DisplayText.ResolveUnitSpecific(ii.MyDocVersion, val);
 | |
| 								}
 | |
| 
 | |
| 								XmlElement xindivid = xe.OwnerDocument.CreateElement(EP.name);
 | |
| 
 | |
| 								//need to resolve ROs ROSingle, ROMulti, in text
 | |
| 								//get values
 | |
| 								switch (EP.type.ToLower())
 | |
| 								{
 | |
| 									case "text":
 | |
| 
 | |
| 										//for text, check if any embedded ROs
 | |
| 										//if none, set the xml element to the text
 | |
| 										//otherwise resolve the ROs
 | |
| 										MatchCollection matches = _ROAccPageTokenPattern.Matches(val);
 | |
| 										if (matches.Count == 0)
 | |
| 										{
 | |
| 											xindivid.InnerText = val;
 | |
| 										}
 | |
| 										else
 | |
| 										{
 | |
| 											//resolve ROs
 | |
| 											//text ROs will replace the AccID key in the text
 | |
| 											//for binary objects like images,
 | |
| 											//we will keep the AccID in the text and output the binary as a separate child
 | |
| 											//XML element with the same xml name as the AccID
 | |
| 											foreach (Match m in matches)
 | |
| 											{
 | |
| 												ROFSTLookup.rochild roc = lookup.GetROChildByAccPageID(m.Groups[0].Value);
 | |
| 
 | |
| 												// Exclude replacing Images since are binary - for those, add a sub item
 | |
| 												if (Enumerable.Range(8, 15).Contains(roc.type))
 | |
| 												{
 | |
| 													xindivid.InnerText = val;
 | |
| 
 | |
| 													XmlElement xroid = AddGraphic(xindivid, m.Groups[0].Value, roc, myRODB, roc.type != 8);
 | |
| 
 | |
| 													xindivid.AppendChild(xroid);
 | |
| 												}
 | |
| 												else if (!string.IsNullOrEmpty(roc.value))
 | |
| 												{
 | |
| 													bool convertCaretToDeltaSymbol = (ii.ActiveSection != null) && ii.ActiveSection.ActiveFormat.PlantFormat.FormatData.SectData.ConvertCaretToDelta;
 | |
| 
 | |
| 													string rocvalue = roc.value.Replace("`", "\xB0");
 | |
| 													rocvalue = rocvalue.Replace("\xF8", "\xB0");
 | |
| 													rocvalue = rocvalue.Replace("\x7F", "\x394"); //delta
 | |
| 													if (convertCaretToDeltaSymbol) rocvalue = rocvalue.Replace("^", "\x394"); // delta
 | |
| 													val = val.Replace($"{m.Groups[0].Value}", rocvalue);
 | |
| 													xindivid.InnerText = val;
 | |
| 												}
 | |
| 											}
 | |
| 										}
 | |
| 										break;
 | |
| 									case "rosingle":
 | |
| 										//Get the output columns from the EPFormatFile
 | |
| 										//set the "Item" nodes value = to those resolved items
 | |
| 										//separated by multiseparator
 | |
| 										XmlElement xindivid_rosingle = xindivid.OwnerDocument.CreateElement("Item");
 | |
| 										xindivid_rosingle.Attributes.SetNamedItem(AddAttribute(xindivid_rosingle.OwnerDocument, "ROID", val));
 | |
| 
 | |
| 										//add values specified in EP input list
 | |
| 										List<string> ro_single_tmp = EP.getROValuesList(EPAnnotation, val);
 | |
| 										xindivid_rosingle.InnerText = String.Join(multiseparator, ro_single_tmp.ToArray());
 | |
| 
 | |
| 										//if image, add location and binary of image
 | |
| 										// - images are type 8
 | |
| 										//   but if multiple return values could combine
 | |
| 										//   for example an text (1) + image (8) would be 9
 | |
| 										ROFSTLookup.rochild roc_single = lookup.GetRoChild(val);
 | |
| 										if (Enumerable.Range(8, 15).Contains(roc_single.type))
 | |
| 										{
 | |
| 											XmlElement xroid = AddGraphic(xindivid, val, roc_single, myRODB, roc_single.type != 8);
 | |
| 											xindivid_rosingle.AppendChild(xroid);
 | |
| 										}
 | |
| 
 | |
| 										xindivid.AppendChild(xindivid_rosingle);
 | |
| 										break;
 | |
| 									case "romulti":
 | |
| 										//Get the output columns from the EPFormatFile
 | |
| 										//create an "Item" subnode for each selected RO
 | |
| 										//set the nodes value = to those resolved items
 | |
| 										//separated by multiseparator
 | |
| 										foreach (string ival in val.Split(multiseparator.ToCharArray()))
 | |
| 										{
 | |
| 											XmlElement xindivid_romulti = xindivid.OwnerDocument.CreateElement("Item");
 | |
| 											xindivid_romulti.Attributes.SetNamedItem(AddAttribute(xindivid_romulti.OwnerDocument, "ROID", ival));
 | |
| 
 | |
| 											//add values specified in EP input list
 | |
| 											List<string> ro_multi_tmp = EP.getROValuesList(EPAnnotation, ival);
 | |
| 											xindivid_romulti.InnerText = String.Join(multiseparator, ro_multi_tmp.ToArray());
 | |
| 
 | |
| 											//if image, add location and binary of image
 | |
| 											// - images are type 8
 | |
| 											//   but if multiple return values could combine
 | |
| 											//   for example an text (1) + image (8) would be 9
 | |
| 											ROFSTLookup.rochild roc_multi = lookup.GetRoChild(ival);
 | |
| 											if (Enumerable.Range(8, 15).Contains(roc_multi.type))
 | |
| 											{
 | |
| 												XmlElement xroid = AddGraphic(xindivid, ival, roc_multi, myRODB, roc_multi.type != 8);
 | |
| 												xindivid_romulti.AppendChild(xroid);
 | |
| 											}
 | |
| 
 | |
| 											xindivid.AppendChild(xindivid_romulti);
 | |
| 										}
 | |
| 										break;
 | |
| 									case "tableinput":
 | |
| 										xindivid.InnerText = val;
 | |
| 										break;
 | |
| 									default:
 | |
| 										xindivid.InnerText = val;
 | |
| 										break;
 | |
| 								}
 | |
| 								xepdetails.AppendChild(xindivid);
 | |
| 							}
 | |
| 						}
 | |
| 						xepinfo.AppendChild(xepdetails);
 | |
| 					}
 | |
| 
 | |
| 				}
 | |
| 
 | |
| 				xe.AppendChild(xepinfo);
 | |
| 			}
 | |
| 
 | |
| 		}
 | |
| 
 | |
| 		//return a db sequence string from an Item ID
 | |
| 		private string dbSeq(int itemID)
 | |
| 		{
 | |
| 			using (ItemInfo ii = ItemInfo.Get(itemID))
 | |
|             {
 | |
| 				return dbSeq(ii);
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
|         //return a db sequence string from an ItemInfo
 | |
|         private string dbSeq(ItemInfo ii) => $"{((FolderInfo)ii.MyDocVersion.ActiveParent).Name}:{ii.MyProcedure.DisplayNumber} {ii.MyProcedure.DisplayText}:{ii.DBSequence}";
 | |
| 
 | |
|         //For Exporting an RO that is an image
 | |
|         //returns the Location and FileName of the RO Image
 | |
|         private string GetROImageFileLocation(ROFSTLookup.rochild roc, RODbInfo rodb, bool isMulti)
 | |
| 		{
 | |
| 			string rodbpath = rodb.FolderPath;
 | |
| 
 | |
| 			string rocval = roc.value;
 | |
| 			if (rocval == null) rocval = Array.Find(roc.children, x => x.value.Contains('.')).value;
 | |
| 
 | |
| 			if (rocval == null) return "";
 | |
| 			string imgname;
 | |
| 			if (isMulti)
 | |
| 			{
 | |
| 				imgname = rocval.Substring(rocval.IndexOf(' ') + 1, rocval.IndexOf("\r\n") - rocval.IndexOf(' ') - 1);
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				imgname = rocval.Substring(0, rocval.IndexOf('\n'));
 | |
| 			}
 | |
| 			int thedot = imgname.LastIndexOf('.');
 | |
| 			string fname = imgname;
 | |
| 			if (thedot == -1 || (thedot != (imgname.Length - 4)))
 | |
| 			{
 | |
| 				RODbConfig roDbCfg = new RODbConfig(rodb.Config);
 | |
| 				fname += string.Format(".{0}", roDbCfg.GetDefaultGraphicExtension());
 | |
| 			}
 | |
| 
 | |
| 			string imgfile = Path.Combine(rodbpath, fname);
 | |
| 			return imgfile;
 | |
| 		}
 | |
| 
 | |
| 		//For Exporting an RO that is an image
 | |
| 		//returns an xmlElement
 | |
| 		// - that is a child to xindivid
 | |
| 		// - that has a name of Name
 | |
| 		// - that has a value of the binary representation of the image
 | |
| 		// - that has an attribute designating the location of the image file
 | |
| 		private XmlElement AddGraphic(XmlElement xindivid, string Name, ROFSTLookup.rochild roc, RODbInfo rodb, bool isMulti)
 | |
| 		{
 | |
|             Name = Name.Replace("<", "").Replace(">", "");
 | |
| 
 | |
| 			XmlElement xroid = xindivid.OwnerDocument.CreateElement(Name);
 | |
| 
 | |
| 			string imgfile = GetROImageFileLocation(roc, rodb, isMulti);
 | |
| 			if (string.IsNullOrEmpty(imgfile)) return xroid;
 | |
| 			xroid.Attributes.SetNamedItem(AddAttribute(xroid.OwnerDocument, "Location", imgfile));
 | |
| 
 | |
| 			if (File.Exists(imgfile))
 | |
| 			{
 | |
| 				using (FileStream fsIn = new FileStream(imgfile, FileMode.Open, FileAccess.Read, FileShare.Read))
 | |
| 				{
 | |
| 					// Create an instance of StreamReader that can read characters from the FileStream.
 | |
| 					using (BinaryReader r = new BinaryReader(fsIn))
 | |
| 						xroid.InnerText = Encoding.Default.GetString(r.ReadBytes((int)fsIn.Length));
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			return xroid;
 | |
| 		}
 | |
| 
 | |
| 		//overridden - used to set the RO location for RO Images that are not in annotations
 | |
| 		protected override void SetROLocation(ref XmlElement xindivid, ROFSTLookup.rochild roc, RODbInfo rodb, bool isMulti)
 | |
| 		{
 | |
| 			string imgfile = GetROImageFileLocation(roc, rodb, isMulti);
 | |
| 			if (!string.IsNullOrEmpty(imgfile)) xindivid.Attributes.SetNamedItem(AddAttribute(xindivid.OwnerDocument, "Location", imgfile));
 | |
| 		}
 | |
| 
 | |
| 		//overridden - used to set specific enhanced doc info
 | |
| 		protected override void SetEPEnhancedDocLinks(ref XmlElement xe, ItemInfo ii)
 | |
| 		{
 | |
| 			EnhancedDocuments eds = ii.GetMyEnhancedDocuments();
 | |
| 
 | |
| 			if (eds != null && eds.Count == 1)
 | |
| 			{
 | |
| 				xe.Attributes.SetNamedItem(AddAttribute(xe.OwnerDocument, "EnhancedDocType", eds[0].Type.ToString()));
 | |
| 				xe.Attributes.SetNamedItem(AddAttribute(xe.OwnerDocument, "EnhancedDocToItemID", eds[0].ItemID.ToString()));
 | |
| 				xe.Attributes.SetNamedItem(AddAttribute(xe.OwnerDocument, "EnhancedDocToDbSeq", dbSeq(eds[0].ItemID)));
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		//clear objects to release memory
 | |
| 		private void OnClose(object sender, EventArgs e)
 | |
| 		{
 | |
| 			DocReplace.Clear();
 | |
| 			DocReplace = null;
 | |
| 		}
 | |
| 
 | |
| 
 | |
| 	}
 | |
| }
 |