Ejemplo n.º 1
0
        /// <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 &lt; 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);
        }