/// <summary> /// Processes the source and destination documents from the supplied rules file /// </summary> /// <exception cref="SpencerGifts.Translate.RuleMappingException"></exception> /// <exception cref="SpencerGifts.Translate.RuleConditionException"></exception> /// <exception cref="SpencerGifts.Translate.RuleActionException"></exception> /// <exception cref="SpencerGifts.Translate.RuleConditionException"></exception> virtual protected void Process() { //Thread.CurrentThread.Priority = ThreadPriority.Lowest; //The xml document that will hold the final transalted document XmlDocument NewDestination = new XmlDocument(); //Start the document XmlDeclaration xmlDeclaration = NewDestination.CreateXmlDeclaration("1.0", "utf-8", null); //The Root node of the document XmlElement rootNode = NewDestination.CreateElement("ConvertedTLog"); NewDestination.InsertBefore(xmlDeclaration, NewDestination.DocumentElement); NewDestination.AppendChild(rootNode); XmlElement Parent = NewDestination.CreateElement(NewDocumentRoot); rootNode.AppendChild(Parent); using (XmlReader reader = SourceDocument) { //Get the root level node of the source document reader.MoveToContent(); reader.ReadStartElement(); //Execute the before rule process event //BeforeProcess(list, null); //BeforeProcess(reader, null); //Collection to hold the rules from supplied rules file List <IRule> tRules = null; //Collection used to hold any actions that will need to be performed after rule processing List <string> ActionsToExecute = new List <string>(); //Collection used to keep track of our actions that we have executed. This is used for the rules that have ProcessAsGroup = True (Defaults to False); //If we do not keep track of these they will execute everytime the condition is met instead of only one time. ActionsExecuted = new List <string>(); //Start looping through the source document and apply the rules as needed. int RecordCount = 0; //Start Reading through the xml doc while (!reader.EOF) { XmlDocument CurrentTransDoc = new XmlDocument(); try { string xml = reader.ReadOuterXml(); if (string.IsNullOrEmpty(xml)) { continue; } CurrentTransDoc.LoadXml(xml); //CurrentTransDoc.Load(reader); #if (DEBUG) //Console.WriteLine("Processing Transaction " + CurrentTransDoc.SelectSingleNode("//Transaction/@TransNumber").Value + " " + DateTime.Now.ToString("hh:mm:ss")); #endif } catch (Exception exc) { LogMessage(exc.Message); break; } BeforeProcess(CurrentTransDoc, null); XmlNode node = CurrentTransDoc.DocumentElement; XmlDocument NewDocTemplate = DestinationDocumentTemplate; //Load our rules if we haven't done so yet if (tRules == null) { tRules = TranslateRules; } //Process rules for each Line Item. //We need to go line by line because there could be multiple lines with the same element definition ImportNode = false; foreach (XmlNode ChildNode in node) { #if (DEBUG) //Console.WriteLine("Processing " + ChildNode.Name + " " + DateTime.Now.ToString("hh:mm:ss")); #endif TranslateRule tr = GetRule(ChildNode.Name); //if we dont have a rule for the current line skip it and continue to the next if (tr == null) { continue; } //Call the afterruleload even if (OnAfterRuleLoad != null) { TranslateEventArgs args = new TranslateEventArgs(); args.CurrentTranslateItem = ChildNode; args.OutputDocument = NewDestination; OnAfterRuleLoad(tr, args); } if (!tr.ProcessAsGroup) { NewDocTemplate = DestinationDocumentTemplate; } //if ExactMapping is set on the rule we will do a 1to1 mapping of attributes prior to any translating; if (tr.ExactMapping) { for (int i = 0, count = ChildNode.Attributes.Count; i < count; i++) { NewDocTemplate.SelectSingleNode(tr.DestinationSavePath).Attributes[i].Value = ChildNode.Attributes[i].Value; } ImportNode = true; } XPathNavigator nav = ChildNode.CreateNavigator(); //bool ImportNode = false; #region Process 1 to 1 Rule Mappings if (tr.RuleMappings.Count > 0) { //loop through the 1 to 1 mappings first foreach (RuleMapping mapping in tr.RuleMappings) { try { //if a type is defined convert it and format it to the type specified\ NewDocTemplate.SelectSingleNode(mapping.DestinationPath).Value = FormatValue(mapping.Format, mapping.FormatType, nav.Evaluate(GetXpathExpression(mapping.SourcePath)).ToString()); ImportNode = true; } catch (Exception ex) { RuleMappingException excep = new RuleMappingException("Rule Mapping Exception Error", ex); excep.RuleID = tr.ID; excep.SourceFile = SourceFile; excep.MappdingDestinationPath = mapping.DestinationPath; excep.MappingSourcePath = mapping.SourcePath; throw (excep); } } } #endregion #region Process Rule Conditions //now evaluate our specific condition rules bool ContinueProcessing = true; //XPathNavigator nav = ChildNode.CreateNavigator(); bool ContinueTransaction = true; foreach (RuleCondition condition in tr.RuleConditions) { try { ExecuteConditions(condition, NewDocTemplate, nav, ActionsToExecute, ref ContinueProcessing, ref ContinueTransaction); if (ContinueProcessing && ContinueTransaction) { continue; } break; } catch (Exception ex) { RuleConditionException except = new RuleConditionException("Condition Exception", ex); except.RuleID = tr.ID; except.ConditionID = condition.ID; except.SourceFile = SourceFile; except.ConditionDestination = condition.Destination; except.ConditionExpression = condition.Expression; throw (except); } } #endregion //If the current rule has ProcessAsGroup set to True and the next line is the same as the current then continue on to the next if ((tr.ProcessAsGroup && ChildNode.NextSibling.Name == ChildNode.Name) && (ContinueProcessing && ContinueTransaction)) { continue; } //if the new node has been flagged for importing into the destination document. if (ImportNode) { XmlNode NodeToAppend = NewDestination.ImportNode(NewDocTemplate.SelectSingleNode(tr.DestinationSavePath), true); //Fire the BeforeAppend event BeforeAppend(NodeToAppend, null); AppendNode(Parent, NodeToAppend); //Fire the afterappend event AfterAppend(NodeToAppend, null); } #region Process Actions Assiciated to our Rule Conditions //if we have actions to execute do it here //Clear our executed actions list incase we filled it on a previous line ActionsExecuted.Clear(); foreach (string actionName in ActionsToExecute) { //First check to see if the current translate rule even has actions to perform if (tr.RuleActions == null) { break; } //it does so find the action to execute foreach (RuleAction act in tr.RuleActions) { if (act.ID != actionName || ActionsExecuted.Contains(actionName)) { continue; } NewDocTemplate = DestinationDocumentTemplate; XmlNode NewNode = NewDocTemplate.SelectSingleNode(act.ItemToCreate); //Store our executed action for lookup later to make sure we do not execute this action again if (tr.ProcessAsGroup) //We only care about storing this value if we have the rule ProcessAsGroup = True { ActionsExecuted.Add(actionName); } //First take care of any attributes that get directly set. foreach (RuleAttribute NodeAttribute in act.Attributes) { //check to see if the attribute should use the builtin identity counter. Incrementing the counter is user defined. if (!NodeAttribute.UseBuiltInIdentity) { //Handle the case where the value of an attribute is an expression instead of a standard value string FilteredValue = ""; try { if (!NodeAttribute.IsExpression) { NewNode.Attributes[NodeAttribute.ID].Value = FormatValue(NodeAttribute.format, NodeAttribute.formatType, NodeAttribute.Value); } else { //check if the node expression should be run against the source file if (NodeAttribute.ExpressionSrouce == "SourceFile") { //if (NodeAttribute.Value.Contains("number(@rettax) - sum(./../L38[@tax_amount < 0]/@tax_amount)")) // Console.WriteLine(); string expressionvalue = ""; if (NodeAttribute.formatType == typeof(Decimal)) { expressionvalue = Decimal.Parse(nav.Evaluate(GetXpathExpression(NodeAttribute.Value)).ToString(), System.Globalization.NumberStyles.Float).ToString("F2"); } else { expressionvalue = nav.Evaluate(GetXpathExpression(NodeAttribute.Value)).ToString(); } NewNode.Attributes[NodeAttribute.ID].Value = FormatValue(NodeAttribute.format, NodeAttribute.formatType, expressionvalue); } //check if the node expression should be run against the destination file if (NodeAttribute.ExpressionSrouce == "DestinationFile") { XPathNavigator destNav = NewNode.CreateNavigator(); NewNode.Attributes[NodeAttribute.ID].Value = FormatValue(NodeAttribute.format, NodeAttribute.formatType, destNav.Evaluate(GetXpathExpression(NodeAttribute.Value)).ToString()); } } } catch (Exception ex) { RuleActionException except = new RuleActionException("Action Exception Occurred", ex); except.Source = SourceFile; except.RuleID = tr.ID; except.AcctionID = NodeAttribute.ID; except.ExpressionSource = NodeAttribute.ExpressionSrouce; throw (except); } } else { NewNode.Attributes[NodeAttribute.ID].Value = _Counter.ToString(); } } //check to see if our current action has conditions it needs to execute as well if (act.Conditions.Count > 0) { foreach (RuleCondition condition in act.Conditions) { try { ExecuteConditions(condition, NewDocTemplate, nav, ActionsToExecute, ref ContinueProcessing); if (ContinueProcessing) { continue; } break; } catch (Exception ex) { RuleConditionException except = new RuleConditionException("Condition Exception While Processing Action", ex); except.RuleID = tr.ID; except.ConditionID = condition.ID; except.SourceFile = SourceFile; except.ConditionDestination = condition.Destination; except.ConditionExpression = condition.Expression; throw (except); } } } //Fire BeforeAppend event BeforeAppend(NewNode, null); AppendNode(Parent, NewDestination.ImportNode(NewNode, true)); //Fire the afterappend event AfterAppend(NewNode, null); } } #endregion //remove our actions ActionsToExecute.Clear(); ImportNode = false; RecordCount++; //Pause the thread after 5 records to keep cpu usage down. //int Remainder; //Math.DivRem(RecordCount, 4, out Remainder); //if (Remainder == 0) //Thread.Sleep(1); //If we shouldnt continue the current transaction break out of loop if (!ContinueTransaction) { break; } } TranslateEventArgs RuleProcessArgs = new TranslateEventArgs(); RuleProcessArgs.CurrentTranslateItem = node; RuleProcessArgs.OutputDocument = NewDestination; AfterRuleProcess(node, RuleProcessArgs); //} } } //Translate complate so save the file #if (DEBUG) //Console.ReadLine(); #endif SaveTranslatedFile(NewDestination); Thread.Sleep(1); }