| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682 | using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Windows.Forms.VisualStyles;using System.Xml.Schema;using System.Xml;using System.IO;using Aitex.Core.RT.Log;using System.Text.RegularExpressions;using Aitex.Common.Util;using Aitex.Core.RT.Event;using Aitex.Core.Util;using Aitex.Core.Utilities;using Aitex.Core.WCF;using MECF.Framework.Common.OperationCenter;using MECF.Framework.Common.Properties;using MECF.Framework.Common.RecipeCenter;using System.Collections.ObjectModel;using Aitex.Core.RT.SCCore;using MECF.Framework.Common.DataCenter;using MECF.Framework.Common.ParameterCenter;using System.Linq;using MECF.Framework.Common.CommonData;namespace Aitex.Core.RT.ParameterCenter{    public class ParameterFileManager : Singleton<ParameterFileManager>    {        //Recipe文件 统一放在 Recipes 文件夹下面        public const string SourceModule = "Parameter";        string _chamberId;        private bool _recipeIsValid;        private List<string> _validationErrors = new List<string>();        private List<string> _validationWarnings = new List<string>();        private Dictionary<int, Dictionary<string, string>> _parameterItems;        IParameterFileContext _rcpContext;        public ParameterFileManager()        {            _chamberId = SC.GetStringValue("System.EditParameter.EditChamberType");            if (_chamberId == null)                _chamberId = "Parameter";        }        public void Initialize(IParameterFileContext context)        {            Initialize(context, true);        }        public void Initialize(IParameterFileContext rcpContext, bool enableService)        {            _rcpContext = rcpContext == null ? new DefaultParameterFileContext() : rcpContext;            CultureSupported.UpdateCoreCultureResource(CultureSupported.English);            if (enableService)            {                Singleton<WcfServiceManager>.Instance.Initialize(new Type[]                {                    typeof(ParameterService)                });            }            var dir = string.Format("{0}{1}\\", PathManager.GetParameterDir(), "");            DirectoryInfo di = new DirectoryInfo(dir);            if (!di.Exists)            {                di.Create();            }        }        private void ValidationEventHandler(object sender, ValidationEventArgs e)        {            switch (e.Severity)            {                case XmlSeverityType.Error:                    _validationErrors.Add(e.Message);                    _recipeIsValid = false;                    break;                case XmlSeverityType.Warning:                    _validationWarnings.Add(e.Message);                    break;            }        }        /// <summary>        /// XML schema checking        /// </summary>        /// <param name="chamId"></param>        /// <param name="parameterName"></param>        /// <param name="parameterContent"></param>        /// <param name="reason"></param>        /// <returns></returns>        public bool ValidateParameter(string chamberId, string parameterName, string parameterContent, out List<string> reason)        {            try            {                XmlDocument document = new XmlDocument();                document.LoadXml(parameterContent);                MemoryStream schemaStream = new MemoryStream(ASCIIEncoding.ASCII.GetBytes(GetParameterSchema(chamberId)));                XmlReader xmlSchemaReader = XmlReader.Create(schemaStream);                XmlSchema schema1 = XmlSchema.Read(xmlSchemaReader, ValidationEventHandler);                document.Schemas.Add(schema1);                document.LoadXml(parameterContent);                ValidationEventHandler eventHandler = new ValidationEventHandler(ValidationEventHandler);                _recipeIsValid = true;                _validationErrors = new List<string>();                _validationWarnings = new List<string>();                // Validates recipe.                document.Validate(eventHandler);            }            catch (Exception ex)            {                LOG.Write(ex.Message);                _recipeIsValid = false;            }            if (!_recipeIsValid && _validationErrors.Count == 0)            {                _validationErrors.Add(Resources.RecipeFileManager_ValidateRecipe_XMLSchemaValidateFailed);            }            reason = _validationErrors;            return _recipeIsValid;        }        public bool GetParameterChecked(string chamberId, string parameterName)        {            string chamberType = chamberId.Split('\\')[0];            string processType = chamberId.Split('\\')[1];            string parameterContent = LoadParameter(chamberId, parameterName, false);            var xmlParameter = new XmlDocument();            try            {                if (string.IsNullOrEmpty(parameterContent))                    throw new Exception("invalid Parameter file.");                xmlParameter.LoadXml(parameterContent);                XmlNodeList nodeSteps = xmlParameter.SelectNodes($"Aitex/TableParameterData/Module[@Name='{processType}']/Step");                XmlNode nodeConfig = xmlParameter.SelectNodes($"Aitex/TableParameterData/Config")[0];                foreach (var item in nodeSteps)                {                    XmlElement step = item as XmlElement;                    string strModuleName = step.Attributes["ModuleName"]?.Value;                    if (string.IsNullOrEmpty(strModuleName)) continue;                    if (!string.IsNullOrEmpty(strModuleName))                    {                        string[] temp = strModuleName.Split(',')[0].Split(' ');                        if (temp.Length > 1)                            strModuleName = temp[1];                    }                    else                        continue;                    if (ovenModuleName.Contains(strModuleName))                        strModuleName = "Oven";                    string linkParameterName = step.Attributes["ParameterName"]?.Value;                    if (string.IsNullOrEmpty(linkParameterName)) continue;                    string[] subParameterNames = linkParameterName.Split(',');                    foreach (var subItem in subParameterNames)                    {                        string subParameterName = string.Empty;                        string[] subParameterNameStrings = subItem.Split(':');                        if (subParameterNameStrings.Length > 1)                        {                            subParameterName = subParameterNameStrings[1];                        }                        else                        {                            subParameterName = subParameterNameStrings[0];                        }                        if (!GetParameterChecked($"{_chamberId}\\{strModuleName}", subParameterName))                        {                            return false;                        }                    }                }                //check system Parameter                string strSystemParameterName = nodeConfig.Attributes["SystemParameter"]?.Value;                if (!string.IsNullOrEmpty(strSystemParameterName))                {                    if (!GetParameterChecked($"{_chamberId}\\System", strSystemParameterName))                    {                        return false;                    }                }                XmlElement nodeData = xmlParameter.SelectSingleNode($"Aitex/TableParameterData") as XmlElement;                string checkResult = nodeData.Attributes["CheckResult"].Value;                if (string.IsNullOrEmpty(checkResult))                    return false;                else                    return true;            }            catch (Exception ex)            {                LOG.Write(ex);                return false;            }        }        /// <summary>        /// Check recipe content        /// </summary>        /// <param name="chamId"></param>        /// <param name="parameterContent"></param>        /// <param name="reasons"></param>        /// <returns></returns>        public bool CheckParameter(string chamberId, string parameterName, out List<string> reasons)        {            reasons = new List<string>();            string chamberType = chamberId.Split('\\')[0];            string processType = chamberId.Split('\\')[1];            string parameterContent = LoadParameter(chamberId, parameterName, false);            var xmlParameter = new XmlDocument();            try            {                if (string.IsNullOrEmpty(parameterContent))                    throw new Exception("invalid Parameter file.");                xmlParameter.LoadXml(parameterContent);                XmlNodeList nodeSteps = xmlParameter.SelectNodes($"Aitex/TableParameterData/Module[@Name='{processType}']/Step");                XmlNode nodeConfig = xmlParameter.SelectNodes($"Aitex/TableParameterData/Config")[0];            }            catch (Exception ex)            {                reasons.Add(ex.Message);                LOG.Write(ex);                return false;            }            XmlElement nodeData = xmlParameter.SelectSingleNode($"Aitex/TableParameterData") as XmlElement;            bool bResult = reasons.Count == 0;            if (bResult)            {                nodeData.SetAttribute("CheckResult", "Correct");            }            else            {                nodeData.SetAttribute("CheckResult", "Error");            }            SaveParameter(chamberId, parameterName, xmlParameter.OuterXml, false, false);            return bResult;        }        /// <summary>        /// Check recipe content        /// </summary>        /// <param name="chamId"></param>        /// <param name="recipeContent"></param>        /// <param name="reasons"></param>        /// <returns></returns>        public bool CheckRestoreParameter(string chamberId, string parameterName, out List<string> reasons)        {            reasons = new List<string>();            string chamberType = chamberId.Split('\\')[0];            string processType = chamberId.Split('\\')[1];            string recipeContent = LoadRestoreParameter(chamberId, parameterName, false);            var xmlRecipe = new XmlDocument();            try            {                if (string.IsNullOrEmpty(recipeContent))                    throw new Exception("invalid recipe file.");                xmlRecipe.LoadXml(recipeContent);                XmlNodeList nodeSteps = xmlRecipe.SelectNodes($"Aitex/TableParameterData/Module[@Name='{processType}']/Step");                XmlNode nodeConfig = xmlRecipe.SelectNodes($"Aitex/TableParameterData/Config")[0];            }            catch (Exception ex)            {                reasons.Add(ex.Message);                LOG.Write(ex);                return false;            }            XmlElement nodeData = xmlRecipe.SelectSingleNode($"Aitex/TableParameterData") as XmlElement;            bool bResult = reasons.Count == 0;            if (bResult)            {                nodeData.SetAttribute("CheckResult", "Correct");            }            else            {                nodeData.SetAttribute("CheckResult", "Error");            }            SaveRestoreParameter(chamberId, parameterName, xmlRecipe.OuterXml, false, false);            return bResult;        }        /// <summary>        /// This method will be invoked by two places:        /// (1) Load a recipe from server to GUI for editing (do not need validation when loading, do validation when saving);        /// (2) Load a recipe from recipe engine to run process(always do a validation before run recipe);        /// </summary>        /// <param name="parameterName"></param>        /// <param name="needValidation">indicate whether a recipe format validation is needed or not</param>        /// <returns></returns>        public string LoadParameter(string chamberId, string parameterName, bool needValidation)        {            string rcp = string.Empty;            try            {                using (StreamReader fs = new StreamReader(GenerateParameterFilePath(chamberId, parameterName)))                {                    rcp = fs.ReadToEnd();                    fs.Close();                }                //if (needValidation)                //{                //    List<string> reason;                //    if (!ValidateRecipe(chamberId, recipeName, rcp, out reason))                //    {                //        rcp = string.Empty;                //        LOG.Write("校验recipe file 出错, " + string.Join(",", reason.ToArray()));                //    }                //}            }            catch (Exception ex)            {                LOG.Write(ex, $"load recipe file failed, {parameterName}");                rcp = string.Empty;            }            return rcp;        }        /// <summary>        /// Get recipe list        /// </summary>        /// <param name="chamId"></param>        /// <param name="includingUsedRecipe"></param>        /// <returns></returns>        public IEnumerable<string> GetParameters(string chamberId, bool includingUsedRecipe)        {            return _rcpContext.GetParameters(chamberId, includingUsedRecipe);        }        /// <summary>        /// Get recipe list in xml format        /// </summary>        /// <param name="chamId"></param>        /// <param name="includingUsedParameter"></param>        /// <returns></returns>        public string GetXmlParameterList(string chamberId, bool includingUsedParameter)        {            XmlDocument doc = new XmlDocument();            var baseFolderPath = getParameterDirPath(chamberId);            DirectoryInfo curFolderInfo = new DirectoryInfo(baseFolderPath);            doc.AppendChild(GenerateParameterList(chamberId, curFolderInfo, doc, includingUsedParameter));            return doc.OuterXml;        }        public void SaveParameterHistory(string chamberId, string parameterName, string parameterContent, bool needSaveAs = true)        {            try            {                if (!string.IsNullOrEmpty(parameterName) && needSaveAs)                {                    string newRecipeName = string.Format("HistoryParameter\\{0}\\{1}", DateTime.Now.ToString("yyyyMM"), parameterName);                    SaveParameter(chamberId, newRecipeName, parameterContent, true, false);                    LOG.Write(string.Format("{0}通知TM保存工艺程序{1}", chamberId, parameterName));                }            }            catch (Exception ex)            {                LOG.Write(ex, string.Format("保存{0}工艺程序{1}发生错误", chamberId, parameterName));            }        }        /// <summary>        /// generate recipe list information in current directory        /// </summary>        /// <param name="chamId"></param>        /// <param name="currentDir"></param>        /// <param name="doc"></param>        /// <returns></returns>        XmlElement GenerateParameterList(string chamberId, DirectoryInfo currentDir, XmlDocument doc, bool includingUsedParameter)        {            int trimLength = getParameterDirPath(chamberId).Length;            XmlElement folderEle = doc.CreateElement("Folder");            folderEle.SetAttribute("Name", currentDir.FullName.Substring(trimLength));            DirectoryInfo[] dirInfos = currentDir.GetDirectories();            foreach (DirectoryInfo dirInfo in dirInfos)            {                if (!includingUsedParameter && dirInfo.Name == "HistoryParameter")                    continue;                folderEle.AppendChild(GenerateParameterList(chamberId, dirInfo, doc, includingUsedParameter));            }            FileInfo[] fileInfos = currentDir.GetFiles("*.rcp");            foreach (FileInfo fileInfo in fileInfos)            {                XmlElement fileNd = doc.CreateElement("File");                string fileStr = fileInfo.FullName.Substring(trimLength).TrimStart(new char[] { '\\' }); ;                fileStr = fileStr.Substring(0, fileStr.LastIndexOf("."));                fileNd.SetAttribute("Name", fileStr);                folderEle.AppendChild(fileNd);            }            return folderEle;        }        XmlElement GeneratelRestoreParameterList(string chamberId, DirectoryInfo currentDir, XmlDocument doc, bool includingUsedRecipe)        {            int trimLength = getParameterBackupDirPath(chamberId).Length;            XmlElement folderEle = doc.CreateElement("Folder");            var name = currentDir.FullName.Substring(trimLength);            folderEle.SetAttribute("Name", name);            DirectoryInfo[] dirInfos = currentDir.GetDirectories();            foreach (DirectoryInfo dirInfo in dirInfos)            {                if (!includingUsedRecipe && dirInfo.Name == "HistoryParameter")                    continue;                folderEle.AppendChild(GeneratelRestoreParameterList(chamberId, dirInfo, doc, includingUsedRecipe));            }            FileInfo[] fileInfos = currentDir.GetFiles("*.rcp");            foreach (FileInfo fileInfo in fileInfos)            {                XmlElement fileNd = doc.CreateElement("File");                string fileStr = fileInfo.FullName.Substring(trimLength).TrimStart(new char[] { '\\' }); ;                fileStr = fileStr.Substring(0, fileStr.LastIndexOf("."));                fileNd.SetAttribute("Name", fileStr);                folderEle.AppendChild(fileNd);            }            return folderEle;        }        /// <summary>        /// Delete a recipe by recipe name        /// </summary>        /// <param name="chamId"></param>        /// <param name="parameterName"></param>        /// <returns></returns>        public bool DeleteParameter(string chamberId, string parameterName)        {            try            {                File.Delete(GenerateParameterFilePath(chamberId, parameterName));                EventInfo(string.Format(Resources.RecipeFileManager_DeleteRecipe_RecipeFile0DeleteSucceeded, parameterName));            }            catch (Exception ex)            {                LOG.Write(ex, "删除recipe file 出错");                EventWarning(string.Format(Resources.RecipeFileManager_DeleteRecipe_RecipeFile0DeleteFailed, parameterName));                return false;            }            return true;        }        /// <summary>        ///  Rename recipe        /// </summary>        /// <param name="chamId"></param>        /// <param name="oldName"></param>        /// <param name="newName"></param>        /// <returns></returns>        public bool RenameParameter(string chamId, string oldName, string newName)        {            try            {                if (File.Exists(GenerateParameterFilePath(chamId, newName)))                {                    EventWarning(string.Format(Resources.RecipeFileManager_RenameRecipe_RecipeFile0FileExisted, oldName));                    return false;                }                else                {                    File.Move(GenerateParameterFilePath(chamId, oldName), GenerateParameterFilePath(chamId, newName));                    EventInfo(string.Format(Resources.RecipeFileManager_RenameRecipe_RecipeFile0Renamed, oldName, newName));                }            }            catch (Exception ex)            {                LOG.Write(ex, "重命名recipe file 出错");                EventWarning(string.Format(Resources.RecipeFileManager_RenameRecipe_RecipeFile0RenameFailed, oldName, newName));                return false;            }            return true;        }        private static string ovenModuleName = "CPL,HHP,LHP,CHP,TCP";        private string[] ovenModuleNames = ovenModuleName.Split(',');        private void UpdateCheckResult(string parameterName)        {            var xmlRecipe = new XmlDocument();            using (StreamReader fs = new StreamReader(parameterName))            {                string parameterContent = fs.ReadToEnd();                fs.Close();                xmlRecipe.LoadXml(parameterContent);            }            XmlNode nodeConfig = xmlRecipe.SelectNodes($"Aitex/TableParameterData")[0];            nodeConfig.Attributes["CheckResult"].Value = string.Empty;            XmlTextWriter writer = new XmlTextWriter(parameterName, Encoding.UTF8);            writer.Formatting = Formatting.Indented;            xmlRecipe.Save(writer);            writer.Close();        }        public bool BackupParameter(string fileOriginalPath, string fileDestinationPath, bool isSaveLinkParameter, List<string> parameterNames)        {            try            {            }            catch (Exception ex)            {                LOG.Write(ex, "Backup Recipe file error");            }            return true;        }        public bool CheckBackParameterIsLinkParameter(string fileOriginalPath, List<string> parameterNames)        {            string chamberType = fileOriginalPath.Split('\\')[0];            string processType = fileOriginalPath.Split('\\')[1];            foreach (var item in parameterNames)            {                string parameterContent = LoadParameter(fileOriginalPath, item, false);                var xmlParameter = new XmlDocument();                try                {                    if (string.IsNullOrEmpty(parameterContent))                        continue;                    xmlParameter.LoadXml(parameterContent);                    XmlNodeList nodeSteps = xmlParameter.SelectNodes($"Aitex/TableParameterData/Module[@Name='{processType}']/Step");                    XmlNode nodeConfig = xmlParameter.SelectNodes($"Aitex/TableParameterData/Config")[0];                    switch (processType)                    {                        case "WaferFlow":                            foreach (var step in nodeSteps)                            {                                XmlElement nodestep = step as XmlElement;                                string strModuleName = nodestep.Attributes["ModuleName"]?.Value;                                if (string.IsNullOrEmpty(strModuleName))                                { continue; }                                var linkRecipeName = nodestep.Attributes["RecipeName"].Value;                                if (string.IsNullOrEmpty(linkRecipeName))                                { continue; }                                else                                {                                    return true;                                }                            }                            string strSystemReicpeName = nodeConfig.Attributes["SystemRecipe"]?.Value;                            if (!string.IsNullOrEmpty(strSystemReicpeName))                            {                                return true;                            }                            break;                        case "COT":                        case "DEV":                            string pumpRecipeName = nodeConfig.Attributes["COTPumpRecipe"]?.Value;                            if (!string.IsNullOrEmpty(pumpRecipeName))                            {                                return true;                            }                            break;                        case "Dummy":                            foreach (var step in nodeSteps)                            {                                XmlElement nodestep = step as XmlElement;                                string regularSequence = nodestep.Attributes["RegularSequence"]?.Value;                                string preSequence = nodestep.Attributes["PreSequence"]?.Value;                                if (!string.IsNullOrEmpty(regularSequence))                                {                                    string[] regularSequences = regularSequence.Split(';');                                    foreach (var subItem in regularSequences)                                    {                                        if (string.IsNullOrEmpty(subItem)) continue;                                        var pumpRecipe = GetKeyValue(subItem, "PumpRecipe");                                        if (!string.IsNullOrEmpty(pumpRecipe)) return true;                                    }                                }                                if (!string.IsNullOrEmpty(preSequence))                                {                                    string[] preSequences = preSequence.Split(';');                                    foreach (var subItem in preSequences)                                    {                                        if (string.IsNullOrEmpty(subItem)) continue;                                        var pumpRecipe = GetKeyValue(subItem, "PumpRecipe");                                        if (!string.IsNullOrEmpty(pumpRecipe)) return true;                                    }                                }                            }                            break;                        case "Wash":                            foreach (var step in nodeSteps)                            {                                XmlElement nodestep = step as XmlElement;                                string sequence = nodestep.Attributes["Sequence"]?.Value;                                if (string.IsNullOrEmpty(sequence))                                { continue; }                                var subSequences = sequence.Split(';');                                foreach (var subSeq in subSequences)                                {                                    if (string.IsNullOrEmpty(subSeq))                                    {                                        continue;                                    }                                    var pumpRecipe = GetKeyValue(subSeq, "PumpRecipe");                                    if (!string.IsNullOrEmpty(subSeq))                                    {                                        return true;                                    }                                }                            }                            break;                        case "ADH":                        case "Oven":                            break;                    }                }                catch (Exception ex)                {                    LOG.Write(ex);                    return false;                }            }            return false;        }        private static string GetKeyValue(string args, string name)        {            string indexString = $"{name}=";            string subString = args.Substring(args.IndexOf(indexString) + indexString.Length);            int endIndex = subString.IndexOf(',');            if (endIndex > 0)                return subString.Substring(0, endIndex);            else                return subString;        }        public string GetXmlRestoreParameterList(string chamberId, bool includingUsedParameter)        {            XmlDocument doc = new XmlDocument();            var baseFolderPath = getParameterBackupDirPath(chamberId);            DirectoryInfo curFolderInfo = new DirectoryInfo(baseFolderPath);            doc.AppendChild(GeneratelRestoreParameterList(chamberId, curFolderInfo, doc, includingUsedParameter));            return doc.OuterXml;        }        public List<string> RestoreParameterFolderList()        {            List<string> folderList = new List<string>();            var parameterBackupPath = PathManager.GetParameterBackupDir();            DirectoryInfo directoryInfo = new DirectoryInfo(parameterBackupPath);            DirectoryInfo[] directoryInfos = directoryInfo.GetDirectories();            foreach (var item in directoryInfos)            {                folderList.Add(item.Name);            }            return folderList;        }        public string LoadRestoreParameter(string chamberId, string parameterName, bool needValidation)        {            string rcp = string.Empty;            try            {                using (StreamReader fs = new StreamReader(GenerateBackupParameterFilePath(chamberId, parameterName)))                {                    rcp = fs.ReadToEnd();                    fs.Close();                }            }            catch (Exception ex)            {                LOG.Write(ex, $"load recipe file failed, {parameterName}");                rcp = string.Empty;            }            return rcp;        }        public bool SigRestoreParameter(string chamId, List<string> parameterNames)        {            try            {                string filePath = getParameterBackupDirPath(chamId);                foreach (var item in parameterNames)                {                    string strdest = chamId;                    string destFilePath = GenerateParameterFilePath(strdest, item);                    string sourceFilePath = GenerateBackupParameterFilePath(chamId, item);                    if (item.Contains("\\"))                    {                        DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(destFilePath));                        if (!di.Exists) di.Create();                    }                    File.Copy(sourceFilePath, destFilePath, true);                }            }            catch (Exception ex)            {                LOG.Write(ex, "Backup Recipe file error");            }            return true;        }        private static Dictionary<string, List<string>> CreateRestoreDirectory = new Dictionary<string, List<string>>();        private string RestoreDestFileCheck(string chamId, string parameterName)        {            string newParameterName = parameterName;            //有文件夹的处理方式            if (parameterName.Contains("\\"))            {                int index = 1;                while (true)                {                    int firstIndex = parameterName.IndexOf("\\");                    string firstStr = parameterName.Substring(0, firstIndex);                    string tempRecipeDirectory = "";                    string lastStr = parameterName.Substring(firstIndex + 1, parameterName.Length - firstStr.Length - 1);                    if (firstStr.Contains("(") && firstStr.Contains(")") && (firstStr.IndexOf("(") < firstStr.IndexOf(")")) && (firstStr.IndexOf(")") == firstStr.Length - 1))                    {                        var tempFirstStr = firstStr.Remove(firstStr.IndexOf("("), firstStr.IndexOf(")"));                        newParameterName = $"{tempFirstStr}({index}){lastStr}";                        tempRecipeDirectory = $"{tempFirstStr}({index})";                    }                    else                    {                        newParameterName = $"{firstStr}({index})\\{lastStr}";                        tempRecipeDirectory = $"{firstStr}({index})";                    }                    var fileName = getParameterDirPath(chamId) + newParameterName + ".rcp";                    DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(fileName));                    if (CreateRestoreDirectory.ContainsKey(chamId) && CreateRestoreDirectory[chamId].Contains(tempRecipeDirectory))                    {                        break;                    }                    else if (di.Exists)                    {                        index++;                    }                    else                    {                        if (!CreateRestoreDirectory.ContainsKey(chamId))                        {                            List<string> recipeDicectory = new List<string>();                            recipeDicectory.Add(tempRecipeDirectory);                            CreateRestoreDirectory.Add(chamId, recipeDicectory);                        }                        else                        {                            CreateRestoreDirectory[chamId].Add(tempRecipeDirectory);                        }                        di.Create();                        break;                    }                }            }            //直接文件的处理方式            else            {                int index = 1;                while (true)                {                    if (parameterName.Contains("(") && parameterName.Contains(")") && (parameterName.IndexOf("(") < parameterName.IndexOf(")")) && (parameterName.IndexOf(")") == parameterName.Length - 1))                    {                        var tempFirstStr = parameterName.Remove(parameterName.IndexOf("("), parameterName.IndexOf(")"));                        newParameterName = $"{tempFirstStr}({index})";                    }                    else                    {                        newParameterName = $"{parameterName}({index})";                        break;                    }                }            }            return getParameterDirPath(chamId) + newParameterName + ".rcp";        }        public bool RestoreParameter(string chamId, bool isSaveLink, List<string> parameterNames)        {            try            {                string filePath = getParameterBackupDirPath(chamId);                CreateRestoreDirectory.Clear();                foreach (var item in parameterNames)                {                    string strdest = chamId.Remove(5, 14);                    //string destFilePath = GenerateRecipeFilePath(strdest, item);                    string destFilePath = RestoreDestFileCheck(strdest, item);                    string sourceFilePath = GenerateBackupParameterFilePath(chamId, item);                    if (File.Exists(sourceFilePath))                    {                        DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(destFilePath));                        if (!di.Exists) di.Create();                        File.Copy(sourceFilePath, destFilePath, true);                    }                    if (isSaveLink)                    {                        string recipeContent = LoadRestoreParameter(chamId, item, false);                        var xmlRecipe = new XmlDocument();                        try                        {                            string chamberType = chamId.Split('\\')[0];                            string processType = chamId.Split('\\')[1];                            if (string.IsNullOrEmpty(recipeContent))                                continue;                            xmlRecipe.LoadXml(recipeContent);                            XmlNodeList nodeSteps = xmlRecipe.SelectNodes($"Aitex/TableRecipeData/Module[@Name='{processType}']/Step");                            XmlNode nodeConfig = xmlRecipe.SelectNodes($"Aitex/TableRecipeData/Config")[0];                            switch (processType)                            {                                case "WaferFlow":                                    string strSystemReicpeName = nodeConfig.Attributes["SystemRecipe"]?.Value;                                    if (!string.IsNullOrEmpty(strSystemReicpeName))                                    {                                        string subSourceFilePath = GenerateBackupParameterFilePath($"{chamId.Split('\\')[0]}\\System", strSystemReicpeName);                                        string subDestFilePath = RestoreDestFileCheck($"{_chamberId}\\System", strSystemReicpeName);                                        if (File.Exists(subSourceFilePath))                                        {                                            DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(subDestFilePath));                                            if (!di.Exists) di.Create();                                            File.Copy(subSourceFilePath, subDestFilePath, true);                                        }                                    }                                    foreach (var step in nodeSteps)                                    {                                        XmlElement nodestep = step as XmlElement;                                        string strModuleName = nodestep.Attributes["ModuleName"]?.Value;                                        if (string.IsNullOrEmpty(strModuleName))                                        { continue; }                                        else                                        {                                            string[] temp = strModuleName.Split(',')[0].Split(' ');                                            if (temp.Length > 1)                                                strModuleName = temp[1];                                        }                                        var linkRecipeName = nodestep.Attributes["RecipeName"].Value;                                        if (string.IsNullOrEmpty(linkRecipeName))                                        { continue; }                                        string[] subRecipeNames = linkRecipeName.Split(',');                                        foreach (var subitem in subRecipeNames)                                        {                                            string subRecipeName = string.Empty;                                            string[] subRecipeNameStrings = subitem.Split(':');                                            if (subRecipeNameStrings.Length > 1)                                            {                                                subRecipeName = subRecipeNameStrings[1];                                            }                                            else                                            {                                                subRecipeName = subRecipeNameStrings[0];                                            }                                            if (ovenModuleName.Contains(strModuleName))                                            {                                                strModuleName = "Oven";                                            }                                            string subSourceFilePath = GenerateBackupParameterFilePath($"{chamId.Split('\\')[0]}\\{strModuleName}", subRecipeName);                                            string subDestFilePath = RestoreDestFileCheck($"{_chamberId}\\{strModuleName}", subRecipeName);                                            if (File.Exists(subSourceFilePath))                                            {                                                DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(subDestFilePath));                                                if (!di.Exists) di.Create();                                                File.Copy(subSourceFilePath, subDestFilePath, true);                                            }                                            if (strModuleName == "COT")                                            {                                                string subCotPath = GenerateBackupParameterFilePath($"{ _chamberId}\\{strModuleName}", subRecipeName);                                                var subXmlRecipe = new XmlDocument();                                                string subRecipeContent = LoadParameter($"{ _chamberId}\\{strModuleName}", subRecipeName, false);                                                if (string.IsNullOrEmpty(subRecipeContent))                                                    continue;                                                subXmlRecipe.LoadXml(subRecipeContent);                                                XmlNode subNodeConfig = subXmlRecipe.SelectNodes($"Aitex/TableRecipeData/Config")[0];                                                string subPumpRecipeName = subNodeConfig.Attributes["COTPumpRecipe"]?.Value;                                                if (!string.IsNullOrEmpty(subPumpRecipeName))                                                {                                                    string subPumpSourceFilePath = GenerateBackupParameterFilePath($"{chamId.Split('\\')[0]}\\Pump", subPumpRecipeName);                                                    string subPumpDestFilePath = RestoreDestFileCheck($"{_chamberId}\\Pump", subPumpRecipeName);                                                    if (File.Exists(subPumpSourceFilePath))                                                    {                                                        DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(subPumpDestFilePath));                                                        if (!di.Exists) di.Create();                                                        File.Copy(subPumpSourceFilePath, subPumpDestFilePath, true);                                                    }                                                }                                            }                                        }                                    }                                    break;                                case "COT":                                case "DEV":                                    string pumpRecipeName = nodeConfig.Attributes["COTPumpRecipe"]?.Value;                                    if (!string.IsNullOrEmpty(pumpRecipeName))                                    {                                        string subSourceFilePath = GenerateBackupParameterFilePath($"{chamId.Split('\\')[0]}\\Pump", pumpRecipeName);                                        string subDestFilePath = RestoreDestFileCheck($"{_chamberId}\\Pump", pumpRecipeName);                                        if (File.Exists(subSourceFilePath))                                        {                                            DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(subDestFilePath));                                            if (!di.Exists) di.Create();                                            File.Copy(subSourceFilePath, subDestFilePath, true);                                        }                                    }                                    break;                                case "Dummy":                                    foreach (var step in nodeSteps)                                    {                                        XmlElement nodestep = step as XmlElement;                                        string regularSequence = nodestep.Attributes["RegularSequence"]?.Value;                                        string preSequence = nodestep.Attributes["PreSequence"]?.Value;                                        if (!string.IsNullOrEmpty(regularSequence))                                        {                                            string[] regularSequences = regularSequence.Split(';');                                            foreach (var subItem in regularSequences)                                            {                                                if (string.IsNullOrEmpty(subItem)) continue;                                                var pumpRecipe = GetKeyValue(subItem, "PumpRecipe");                                                if (!string.IsNullOrEmpty(pumpRecipe))                                                {                                                    string subSourceFilePath = GenerateBackupParameterFilePath($"{chamId.Split('\\')[0]}\\Pump", pumpRecipe);                                                    string subDestFilePath = RestoreDestFileCheck($"{_chamberId}\\Pump", pumpRecipe);                                                    if (File.Exists(subSourceFilePath))                                                    {                                                        DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(subDestFilePath));                                                        if (!di.Exists) di.Create();                                                        File.Copy(subSourceFilePath, subDestFilePath, true);                                                    }                                                }                                            }                                        }                                        if (!string.IsNullOrEmpty(preSequence))                                        {                                            string[] preSequences = preSequence.Split(';');                                            foreach (var subItem in preSequences)                                            {                                                if (string.IsNullOrEmpty(subItem)) continue;                                                var pumpRecipe = GetKeyValue(item, "PumpRecipe");                                                if (!string.IsNullOrEmpty(pumpRecipe))                                                {                                                    string subSourceFilePath = GenerateBackupParameterFilePath($"{chamId.Split('\\')[0]}\\Pump", pumpRecipe);                                                    string subDestFilePath = RestoreDestFileCheck($"{_chamberId}\\Pump", pumpRecipe);                                                    if (File.Exists(subSourceFilePath))                                                    {                                                        DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(subDestFilePath));                                                        if (!di.Exists) di.Create();                                                        File.Copy(subSourceFilePath, subDestFilePath, true);                                                    }                                                }                                            }                                        }                                    }                                    break;                                case "Wash":                                    foreach (var step in nodeSteps)                                    {                                        XmlElement nodestep = step as XmlElement;                                        string sequence = nodestep.Attributes["Sequence"]?.Value;                                        if (string.IsNullOrEmpty(sequence))                                        { continue; }                                        var subSequences = sequence.Split(';');                                        foreach (var subSeq in subSequences)                                        {                                            if (string.IsNullOrEmpty(subSeq))                                            {                                                continue;                                            }                                            var pumpRecipe = GetKeyValue(subSeq, "PumpRecipe");                                            if (!string.IsNullOrEmpty(pumpRecipe))                                            {                                                string subSourceFilePath = GenerateBackupParameterFilePath($"{chamId.Split('\\')[0]}\\Pump", pumpRecipe);                                                string subDestFilePath = RestoreDestFileCheck($"{_chamberId}\\Pump", pumpRecipe);                                                if (File.Exists(subSourceFilePath))                                                {                                                    DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(subDestFilePath));                                                    if (!di.Exists) di.Create();                                                    File.Copy(subSourceFilePath, subDestFilePath, true);                                                }                                            }                                        }                                    }                                    break;                                case "ADH":                                case "Oven":                                    break;                            }                        }                        catch (Exception ex)                        {                            LOG.Write(ex);                            continue;                        }                    }                }            }            catch (Exception ex)            {                LOG.Write(ex, "Backup Parameter file error");            }            return true;        }        private void EventInfo(string message)        {            _rcpContext.PostInfoEvent(message);        }        private void EventWarning(string message)        {            _rcpContext.PostWarningEvent(message);        }        private void EventAlarm(string message)        {            _rcpContext.PostAlarmEvent(message);        }        private void InfoDialog(string message)        {            _rcpContext.PostInfoDialogMessage(message);        }        private void WarningDialog(string message)        {            _rcpContext.PostWarningDialogMessage(message);        }        //private void AlarmDialog(string message)        //{        //    _rcpContext.PostAlarmDialogMessage(message);        //}        private void EventDialog(string message, List<string> reason)        {            string msg = message;            foreach (var r in reason)            {                msg += "\r\n" + r;            }            _rcpContext.PostDialogEvent(msg);        }        /// <summary>        /// get recipe's file path        /// </summary>        /// <param name="parameterName"></param>        /// <returns></returns>        public string GenerateParameterFilePath(string chamId, string parameterName)        {            return getParameterDirPath(chamId) + parameterName + ".rcp";        }        private string GenerateBackupParameterFilePath(string chamId, string parameterName)        {            return getParameterBackupDirPath(chamId) + parameterName + ".rcp";        }        /// <summary>        /// get recipe's dir path        /// </summary>        /// <param name="recipeName"></param>        /// <returns></returns>        private string getParameterDirPath(string chamId)        {            var dir = string.Format("{0}{1}\\", PathManager.GetParameterDir(), chamId);            DirectoryInfo di = new DirectoryInfo(dir);            if (!di.Exists) di.Create();            return dir;        }        /// <summary>        /// get parameter's dir path        /// </summary>        /// <param name="ParameterName"></param>        /// <returns></returns>        private string getParameterBackupDirPath(string chamId)        {            var dir = string.Format("{0}{1}\\", PathManager.GetParameterBackupDir(), chamId);            DirectoryInfo di = new DirectoryInfo(dir);            if (!di.Exists) di.Create();            return dir;        }        /// <summary>        /// delete a recipe folder        /// </summary>        /// <param name="chamId"></param>        /// <param name="folderName"></param>        /// <returns></returns>        public bool DeleteFolder(string chamId, string folderName)        {            try            {                Directory.Delete(getParameterDirPath(chamId) + folderName, true);                EventInfo(string.Format(Resources.RecipeFileManager_DeleteFolder_RecipeFolder0DeleteSucceeded, folderName));            }            catch (Exception ex)            {                LOG.Write(ex, "删除recipe folder 出错");                EventAlarm(string.Format("recipe folder  {0} delete failed", folderName));                return false;            }            return true;        }        /// <summary>        /// save as recipe content        /// </summary>        /// <param name="chamId"></param>        /// <param name="recipeName"></param>        /// <param name="recipeContent"></param>        /// <returns></returns>        public bool SaveAsParameter(string chamId, string recipeName, string recipeContent)        {            var path = GenerateParameterFilePath(chamId, recipeName);            if (File.Exists(path))            {                EventAlarm(string.Format(Resources.RecipeFileManager_SaveAsRecipe_RecipeFile0savefailed, recipeName));                return false;            }            return SaveParameter(chamId, recipeName, recipeContent, true, true);        }        /// <summary>        /// save recipe content        /// </summary>        /// <param name="chamId"></param>        /// <param name="parameterName"></param>        /// <param name="parameterContent"></param>        /// <returns></returns>        public bool SaveParameter(string chamId, string parameterName, string parameterContent, bool clearBarcode, bool notifyUI)        {            //validate recipe format when saving a recipe file            //var reasons1 = new List<string>();            //var reasons2 = new List<string>();            //ValidateRecipe(chamId, recipeName, recipeContent, out reasons1);            //CheckRecipe(chamId, recipeContent, out reasons2);            //reasons1.AddRange(reasons2);            //if (reasons1.Count > 0)            //{            //    EventDialog(string.Format( Resources.RecipeFileManager_SaveRecipe_SaveRecipeContentError, recipeName), reasons1);            //}            bool ret = true;            try            {                var path = GenerateParameterFilePath(chamId, parameterName);                FileInfo fi = new FileInfo(path);                if (!fi.Directory.Exists)                    fi.Directory.Create();                XmlDocument xml = new XmlDocument();                xml.LoadXml(parameterContent);                XmlTextWriter writer = new XmlTextWriter(path, Encoding.UTF8);                writer.Formatting = Formatting.Indented;                xml.Save(writer);                writer.Close();                if (notifyUI)                {                    InfoDialog(string.Format(Resources.RecipeFileManager_SaveRecipe_RecipeFile0SaveCompleted, parameterName));                }                else                {                    EV.PostMessage("System", EventEnum.GeneralInfo, string.Format(Resources.RecipeFileManager_SaveRecipe_RecipeFile0SaveCompleted, parameterName));                }            }            catch (Exception ex)            {                LOG.Write(ex, "保存recipe file 出错");                if (notifyUI)                {                    WarningDialog(string.Format(Resources.RecipeFileManager_SaveRecipe_RecipeFile0SaveFailed, parameterName));                }                ret = false;            }            return ret;        }        /// <summary>        /// save recipe content        /// </summary>        /// <param name="chamId"></param>        /// <param name="parameterName"></param>        /// <param name="parameterContent"></param>        /// <returns></returns>        public bool SaveRestoreParameter(string chamId, string parameterName, string parameterContent, bool clearBarcode, bool notifyUI)        {            //validate recipe format when saving a recipe file            //var reasons1 = new List<string>();            //var reasons2 = new List<string>();            //ValidateRecipe(chamId, recipeName, recipeContent, out reasons1);            //CheckRecipe(chamId, recipeContent, out reasons2);            //reasons1.AddRange(reasons2);            //if (reasons1.Count > 0)            //{            //    EventDialog(string.Format( Resources.RecipeFileManager_SaveRecipe_SaveRecipeContentError, recipeName), reasons1);            //}            bool ret = true;            try            {                var path = GenerateBackupParameterFilePath(chamId, parameterName);                FileInfo fi = new FileInfo(path);                if (!fi.Directory.Exists)                    fi.Directory.Create();                XmlDocument xml = new XmlDocument();                xml.LoadXml(parameterContent);                XmlTextWriter writer = new XmlTextWriter(path, Encoding.UTF8);                writer.Formatting = Formatting.Indented;                xml.Save(writer);                writer.Close();                if (notifyUI)                {                    InfoDialog(string.Format(Resources.RecipeFileManager_SaveRecipe_RecipeFile0SaveCompleted, parameterName));                }                else                {                    EV.PostMessage("System", EventEnum.GeneralInfo, string.Format(Resources.RecipeFileManager_SaveRecipe_RecipeFile0SaveCompleted, parameterName));                }            }            catch (Exception ex)            {                LOG.Write(ex, "保存recipe file 出错");                if (notifyUI)                {                    WarningDialog(string.Format(Resources.RecipeFileManager_SaveRecipe_RecipeFile0SaveFailed, parameterName));                }                ret = false;            }            return ret;        }        /// <summary>        /// create a new recipe folder        /// </summary>        /// <param name="chamId"></param>        /// <param name="folderName"></param>        /// <returns></returns>        public bool CreateFolder(string chamId, string folderName)        {            try            {                Directory.CreateDirectory(getParameterDirPath(chamId) + folderName);                EventInfo(string.Format(Resources.RecipeFileManager_CreateFolder_RecipeFolder0Created, folderName));            }            catch (Exception ex)            {                LOG.Write(ex, "create recipe folder failed");                EventAlarm(string.Format(Resources.RecipeFileManager_CreateFolder_RecipeFolder0CreateFailed, folderName));                return false;            }            return true;        }        /// <summary>        /// Rename recipe folder name        /// </summary>        /// <param name="chamId"></param>        /// <param name="oldName"></param>        /// <param name="newName"></param>        /// <returns></returns>        public bool RenameFolder(string chamId, string oldName, string newName)        {            try            {                string oldPath = getParameterDirPath(chamId) + oldName;                string newPath = getParameterDirPath(chamId) + newName;                Directory.Move(oldPath, newPath);                EventInfo(string.Format(Resources.RecipeFileManager_RenameFolder_RecipeFolder0renamed, oldName, newName));            }            catch (Exception ex)            {                LOG.Write(ex, "Rename recipe folder failed");                EventAlarm(string.Format(Resources.RecipeFileManager_RenameFolder_RecipeFolder0RenameFailed, oldName, newName));                return false;            }            return true;        }        public XmlDocument ParameterDom = new XmlDocument();        private string GetParameterBody(string chamberId, string nodePath)        {            if (_rcpContext == null)                return string.Empty;            string schema = _rcpContext.GetParameterDefiniton(chamberId);            ParameterDom = new XmlDocument();            ParameterDom.LoadXml(schema);            XmlNode node = ParameterDom.SelectSingleNode(nodePath);            return node.OuterXml;        }        public string ChamberType        {            get;            set;        }        public string Version        {            get;            set;        }        public int TableNumber        {            get;            set;        }        public Dictionary<string, ObservableCollection<ParameterTemplateColumnBase>> GetGroupParameterTemplate()        {            try            {                XmlNode nodeRoot = ParameterDom.SelectSingleNode("Aitex/TableParameterFormat");                ChamberType = nodeRoot.Attributes["ChamberType"].Value;                Version = nodeRoot.Attributes["Version"].Value;                TableNumber = nodeRoot.Attributes["TableNumber"] != null ? Convert.ToInt32(nodeRoot.Attributes["TableNumber"].Value) : 0;            }            catch (Exception ex)            {                LOG.Write(ex);                return null;            }            var columns = new Dictionary<string, ObservableCollection<ParameterTemplateColumnBase>>();            ParameterTemplateColumnBase col = null;            XmlNodeList nodes = ParameterDom.SelectNodes("Aitex/TableParameterFormat/Catalog/Group");            foreach (XmlNode node in nodes)            {                XmlNodeList childNodes = node.SelectNodes("Step");                int tableNum = 1;                string nameList = null;                if (node.Attributes["TableNumber"] != null)                {                    tableNum = Convert.ToInt32(node.Attributes["TableNumber"].Value);                }                if (node.Attributes["NameList"] != null)                {                    nameList = node.Attributes["NameList"].Value.Replace("\t\t\t\t   ", "").Replace("\n", "").Replace("\r", "");                }                if (nameList != null && nameList.Contains(","))                {                    tableNum = tableNum > nameList.Split(',').Length ? tableNum : nameList.Split(',').Length;                }                string[] namelist = new string[tableNum];                for (int i = 0; i < namelist.Length; i++)                {                    namelist[i] = "";                }                if (!string.IsNullOrEmpty(nameList))                {                    var list = nameList.Split(',');                    for (int i = 0; i < list.Length; i++)                    {                        namelist[i] = list[i];                    }                }                for (int i = 1; i <= tableNum; i++)                {                    var sigcolumns = new ObservableCollection<ParameterTemplateColumnBase>();                    foreach (XmlNode step in childNodes)                    {                        //step number                        if (step.Attributes["ControlName"].Value == "TableNo")                        {                            col = new ParameterTemplateColumnBase()                            {                                DisplayName = "Table",                                ControlName = "TableNo",                            };                            sigcolumns.Add(col);                            continue;                        }                        switch (step.Attributes["InputType"].Value)                        {                            case "TextInput":                                col = new ParameterTemplateColumnBase()                                {                                    ValueType = "TextInput",                                    ModuleName = step.Attributes["ModuleName"].Value,                                    ControlName = step.Attributes["ControlName"].Value,                                    DisplayName = step.Attributes["DisplayName"].Value,                                    IsEnable = !bool.Parse(step.Attributes["ReadOnly"] != null ? step.Attributes["ReadOnly"].Value : "false"),                                    EnableConfig = step.Attributes["EnableConfig"] != null && Convert.ToBoolean(step.Attributes["EnableConfig"].Value),                                    Default = step.Attributes["DefaultValue"] != null ? step.Attributes["DefaultValue"].Value : "",                                    EnableTolerance = step.Attributes["EnableTolerance"] != null && Convert.ToBoolean(step.Attributes["EnableTolerance"].Value),                                };                                sigcolumns.Add(col);                                break;                            case "NumInput":                                col = new ParameterTemplateColumnBase()                                {                                    ValueType = "NumInput",                                    ModuleName = step.Attributes["ModuleName"].Value,                                    ControlName = step.Attributes["ControlName"].Value,                                    DisplayName = step.Attributes["DisplayName"].Value,                                    InputMode = step.Attributes["InputMode"].Value,                                    Minimun = double.Parse(step.Attributes["Min"].Value),                                    Maximun = double.Parse(step.Attributes["Max"].Value),                                    Value = step.Attributes["DefaultValue"] != null ? Convert.ToInt32(step.Attributes["DefaultValue"].Value) : 0,                                    IsEnable = !bool.Parse(step.Attributes["ReadOnly"] != null ? step.Attributes["ReadOnly"].Value : "false"),                                    EnableConfig = step.Attributes["EnableConfig"] != null && Convert.ToBoolean(step.Attributes["EnableConfig"].Value),                                    EnableTolerance = step.Attributes["EnableTolerance"] != null && Convert.ToBoolean(step.Attributes["EnableTolerance"].Value),                                };                                sigcolumns.Add(col);                                break;                            case "DoubleInput":                                col = new ParameterTemplateColumnBase()                                {                                    ValueType = "DoubleInput",                                    ModuleName = step.Attributes["ModuleName"].Value,                                    ControlName = step.Attributes["ControlName"].Value,                                    DisplayName = step.Attributes["DisplayName"].Value,                                    InputMode = step.Attributes["InputMode"].Value,                                    Minimun = double.Parse(step.Attributes["Min"].Value),                                    Maximun = double.Parse(step.Attributes["Max"].Value),                                    Value = step.Attributes["DefaultValue"] != null ? Convert.ToDouble(step.Attributes["DefaultValue"].Value) : 0.0f,                                    IsEnable = !bool.Parse(step.Attributes["ReadOnly"] != null ? step.Attributes["ReadOnly"].Value : "false"),                                    EnableConfig = step.Attributes["EnableConfig"] != null && Convert.ToBoolean(step.Attributes["EnableConfig"].Value),                                    EnableTolerance = step.Attributes["EnableTolerance"] != null && Convert.ToBoolean(step.Attributes["EnableTolerance"].Value),                                };                                sigcolumns.Add(col);                                break;                            case "EditableSelection":                                col = new ParameterTemplateColumnBase()                                {                                    ValueType = "EditableSelection",                                    ModuleName = step.Attributes["ModuleName"].Value,                                    Default = step.Attributes["Default"] != null ? step.Attributes["Default"].Value : "",                                    ControlName = step.Attributes["ControlName"].Value,                                    DisplayName = step.Attributes["DisplayName"].Value,                                    IsEnable = !bool.Parse(step.Attributes["ReadOnly"] != null ? step.Attributes["ReadOnly"].Value : "false"),                                    EnableConfig = step.Attributes["EnableConfig"] != null && Convert.ToBoolean(step.Attributes["EnableConfig"].Value),                                    EnableTolerance = step.Attributes["EnableTolerance"] != null && Convert.ToBoolean(step.Attributes["EnableTolerance"].Value),                                };                                XmlNodeList items = step.SelectNodes("Item");                                foreach (XmlNode item in items)                                {                                    Option opt = new Option();                                    opt.ControlName = item.Attributes["ControlName"].Value;                                    opt.DisplayName = item.Attributes["DisplayName"].Value;                                    ((ParameterTemplateColumnBase)col).Options.Add(opt);                                }                                sigcolumns.Add(col);                                break;                            case "ReadOnlySelection":                            case "LoopSelection":                                col = new ParameterTemplateColumnBase()                                {                                    ValueType = "LoopSelection",                                    IsReadOnly = bool.Parse(step.Attributes["ReadOnly"] != null ? step.Attributes["ReadOnly"].Value : "false"),                                    ModuleName = step.Attributes["ModuleName"].Value,                                    ControlName = step.Attributes["ControlName"].Value,                                    DisplayName = step.Attributes["DisplayName"].Value,                                    EnableConfig = step.Attributes["EnableConfig"] != null && Convert.ToBoolean(step.Attributes["EnableConfig"].Value),                                    EnableTolerance = step.Attributes["EnableTolerance"] != null && Convert.ToBoolean(step.Attributes["EnableTolerance"].Value),                                };                                XmlNodeList options = step.SelectNodes("Item");                                foreach (XmlNode item in options)                                {                                    Option opt = new Option();                                    opt.ControlName = item.Attributes["ControlName"].Value;                                    opt.DisplayName = item.Attributes["DisplayName"].Value;                                    ((ParameterTemplateColumnBase)col).Options.Add(opt);                                }                                sigcolumns.Add(col);                                break;                            case "PopSetting":                                col = new ParameterTemplateColumnBase()                                {                                    ValueType = "LoopSelection",                                    ModuleName = step.Attributes["ModuleName"].Value,                                    ControlName = step.Attributes["ControlName"].Value,                                    DisplayName = step.Attributes["DisplayName"].Value,                                    EnableConfig = step.Attributes["EnableConfig"] != null && Convert.ToBoolean(step.Attributes["EnableConfig"].Value),                                    EnableTolerance = step.Attributes["EnableTolerance"] != null && Convert.ToBoolean(step.Attributes["EnableTolerance"].Value),                                };                                sigcolumns.Add(col);                                break;                        }                    }                    if (tableNum == 1 && string.IsNullOrEmpty(nameList))                    {                        columns.Add(node.Attributes["DisplayName"].Value, sigcolumns);                    }                    else if (tableNum == 1 && !string.IsNullOrEmpty(nameList))                    {                        columns.Add($"{node.Attributes["DisplayName"].Value}\t1\t{namelist[0]}", sigcolumns);                    }                    else                    {                        columns.Add($"{node.Attributes["DisplayName"].Value}\t{i}\t{namelist[i - 1]}", sigcolumns);                    }                }            }            return columns;        }        /// <summary>        /// get reactor's recipe format define file        /// </summary>        /// <param name="chamId"></param>        /// <returns></returns>        public string GetParameterFormatXml(string chamberId)        {            var rtn = GetParameterBody(chamberId, "/Aitex/TableParameterFormat");            return rtn;        }        /// <summary>        /// get reactor's template recipe file        /// </summary>        /// <param name="chamId"></param>        /// <returns></returns>        public string GetParameterTemplate(string chamberId)        {            if (_rcpContext != null)                return _rcpContext.GetParameterTemplate(chamberId);            return GetParameterBody(chamberId, "/Aitex/TableParameterData");        }        /// <summary>        /// get reactor's template recipe file        /// </summary>        /// <param name="chamId"></param>        /// <returns></returns>        public string GetParameterSchema(string chamberId)        {            if (_rcpContext == null)                return string.Empty;            string schema = _rcpContext.GetParameterDefiniton(chamberId);            XmlDocument dom = new XmlDocument();            dom.LoadXml(schema);            XmlNode node = dom.SelectSingleNode("/Aitex/TableParameterSchema");            return node.InnerXml;        }        public string GetParameterByBarcode(string chamberId, string barcode)        {            try            {                string parameterPath = PathManager.GetRecipeDir() + chamberId + "\\";                var di = new DirectoryInfo(parameterPath);                var fis = di.GetFiles("*.rcp", SearchOption.AllDirectories);                XmlDocument xml = new XmlDocument();                foreach (var fi in fis)                {                    string str = fi.FullName.Substring(parameterPath.Length);                    if (!str.Contains("HistoryParameter\\"))                    {                        xml.Load(fi.FullName);                        if (xml.SelectSingleNode(string.Format("/TableParameterData[@Barcode='{0}']", barcode)) != null)                        {                            return str.Substring(0, str.LastIndexOf('.'));                        }                    }                }                return string.Empty;            }            catch (Exception ex)            {                LOG.Write(ex);                return string.Empty;            }        }        public List<FileNodeItem> GetFileNodeParameterListByPath(string chamberId)        {            List<FileNodeItem> files = new List<FileNodeItem>();            var baseFolderPath = getParameterDirPath(chamberId);            DirectoryInfo curFolderInfo = new DirectoryInfo(baseFolderPath);            FileNodeItem nodeItem = new FileNodeItem();            nodeItem.IsFile = false;            GenerateFileNodeParameterList(chamberId, curFolderInfo, nodeItem);            files.Add(nodeItem);            return files;        }        FileNodeItem GenerateFileNodeParameterList(string chamberId, DirectoryInfo currentDir, FileNodeItem nodeItem)        {            int trimLength = getParameterDirPath(chamberId).Length;            DirectoryInfo[] dirInfos = currentDir.GetDirectories();            foreach (DirectoryInfo dirInfo in dirInfos)            {                GenerateFileNodeParameterList(chamberId, dirInfo, nodeItem);            }            FileInfo[] fileInfos = currentDir.GetFiles("*.rcp");            foreach (FileInfo fileInfo in fileInfos)            {                string fileStr = fileInfo.FullName.Substring(trimLength).TrimStart(new char[] { '\\' }); ;                FileNodeItem subNodeItem = new FileNodeItem();                subNodeItem.Name = fileInfo.Name.Replace(".rcp", "");                subNodeItem.FullPath = subNodeItem.Name;                subNodeItem.PrefixPath = chamberId;                subNodeItem.IsFile = true;                ReadFileSetFileNode(chamberId, subNodeItem.Name, subNodeItem);                nodeItem.Files.Add(subNodeItem);            }            return nodeItem;        }        private void ReadFileSetFileNode(string chamberId,string fileName, FileNodeItem fileNodeItem)        {            string content = LoadParameter(chamberId, fileName, false);            XmlDocument _doc = new XmlDocument();            _doc.LoadXml(content);            XmlElement nodeData = _doc.SelectSingleNode($"Aitex/TableParameterData") as XmlElement;            fileNodeItem.Creator = nodeData.GetAttribute("CreatedBy");            fileNodeItem.Description = nodeData.GetAttribute("Description");            fileNodeItem.CreatTime = nodeData.GetAttribute("CreationTime");            fileNodeItem.ReviseTime = nodeData.GetAttribute("LastRevisionTime");            fileNodeItem.Revisor = nodeData.GetAttribute("LastRevisedBy");            fileNodeItem.Permission = nodeData.GetAttribute("Permission");            fileNodeItem.Level = nodeData.GetAttribute("Level");            fileNodeItem.IsChecked = nodeData.GetAttribute("CheckResult") == "Correct";        }    }}
 |