Exemple #1
0
        /// <summary>
        /// Traverse tree from DocumentFragment based on given xPath. If node is not present
        /// then add it.
        /// </summary>
        /// <param name="currentDocument"></param>
        /// <param name="xPath"></param>
        public static DocumentFragment AddIntermediateDocumentFragment(this DocumentFragment document, string xPath)
        {
            if (document == null)
            {
                throw new ArgumentNullException("document", "AddIntermediateDocumentFragment: Cannot add intermediate document fragments to null DocumentFragment");
            }

            if (string.IsNullOrEmpty(xPath))
            {
                throw new ArgumentNullException("xPath", "AddIntermediateDocumentFragment: xPath cannot be null");
            }

            ILogger logger = LoggerFactory.Logger;

            string[] pathElements = xPath.Split(new string[] { document.Pluglet.PathSeperator }, StringSplitOptions.None);

            // Check if root element and 1st element in path match
            if (string.Equals(pathElements[0], document.Name, StringComparison.OrdinalIgnoreCase) == false)
            {
                throw new PlugDataModelException(
                          string.Format("Error while adding intermediate in {0} path. First element in path {1} does not match with root element {2} of document",
                                        xPath, pathElements[0], document.Name));
            }

            DocumentFragment nextFragment    = null;
            DocumentFragment currentFragment = (DocumentFragment)document;

            StringBuilder pathTillCurrentNode = new StringBuilder();

            pathTillCurrentNode.AppendFormat("{0}", pathElements[0]);

            for (int i = 1; i < pathElements.Length - 1; i++)
            {
                //TODO: Optimize here - following call is not required once following if condition becomes true
                if (currentFragment.Children != null)
                {
                    // Check if it's last child is pathElements[i], otherwise create new instance
                    nextFragment = (DocumentFragment)currentFragment.Children.Last();

                    if (string.Equals(nextFragment.Name, pathElements[i], StringComparison.OrdinalIgnoreCase) == false)
                    {
                        nextFragment = null;
                    }

                    // Special case for last but one pathElement - Check if we need to recreate node (loop?)
                    // This is required to generate different loop nodes (e.g. BVT_X12_850.txt)
                    if (nextFragment != null && nextFragment.Children != null && i == pathElements.Length - 2 && nextFragment.Pluglet.IsRepeatable == true)
                    {
                        // Check last child and pathElements[i+1] child order
                        DocumentFragment lastChildFragment = (DocumentFragment)nextFragment.Children.Last();

                        bool restartLoop = false;
                        foreach (IPluglet child in nextFragment.Pluglet.Children)
                        {
                            if (string.Equals(child.Name, pathElements[i + 1], StringComparison.OrdinalIgnoreCase) == true)
                            {
                                restartLoop = true;
                                break;
                            }

                            if (string.Equals(child.Name, lastChildFragment.Name, StringComparison.OrdinalIgnoreCase) == true)
                            {
                                break;
                            }
                        }

                        if (restartLoop == true)
                        {
                            nextFragment = null;
                        }
                    }
                }

                pathTillCurrentNode.AppendFormat("{0}{1}", document.Pluglet.PathSeperator, pathElements[i]);
                if (nextFragment == null)
                {
                    logger.Debug("DocumentFragmentExtensions.AddDocumentFragment", "Node {0} does not exist, creating one now", currentFragment.Name);

                    IPluglet pluglet = document.Pluglet.MoveTo(pathTillCurrentNode.ToString());
                    nextFragment = pluglet.ConstructDocumentFragment(currentFragment, null);

                    if (currentFragment.Children == null)
                    {
                        currentFragment.Children = new List <IDocumentFragment>();
                    }
                    currentFragment.Children.Add(nextFragment);
                }

                currentFragment = nextFragment;
                nextFragment    = null;
            }

            return(currentFragment);
        }
        /// <summary>
        /// Read xml file and construct IFatpipeDocument.
        /// Xml file reader will traverse Xml files and for each element
        /// match it with current pluglet. If match fails then it tries to
        /// find matching pluglet (similar to X12).
        /// </summary>
        /// <returns></returns>
        public IFatpipeDocument ReadFile(Stream xmlFileStream, IDocumentPlug documentPlug)
        {
            if (xmlFileStream == null)
            {
                throw new ArgumentNullException("xmlFileStream", "Xml file stream cannot be null");
            }

            if (documentPlug == null)
            {
                throw new ArgumentNullException("documentPlug", "Document plug cannot be null");
            }

            string location = "XmlFileReader.ReadFile";

            Logger.Debug(location, "Start");

            BeautifiedOriginalPayload = string.Empty;
            CurrentElementNumber      = 0;
            TotalPayloadLength        = 0;
            CurrentLinePayloadStart   = 0;
            CurrentLinePayloadEnd     = 0;
            CurrentLevel = 0;
            Stopwatch sw = new Stopwatch();

            sw.Start();

            errors = new InterchangeErrors();

            // Since xml file doesn't have concept of ST/SE, ans we want to use InterchangeErrors for reporting purpose
            // create dummy transaction set details
            Errors.AddTransactionSetDetails(1, "", "", true);

            IPluglet currentPluglet = documentPlug.RootPluglet;

            currentPluglet.ResetCurrentOccurances();
            currentPluglet.InitializeStartSegmentList();

            FatpipeDocumentInst = new FatpipeDocument();
            FatpipeDocumentInst.DocumentPlug = documentPlug;
            FatpipeDocumentInst.RootFragment = currentPluglet.ConstructDocumentFragment(null, null);

            IDocumentFragment currentDocumentFragment = FatpipeDocumentInst.RootFragment;
            IDocumentFragment newDocumentFragment     = null;

            bool isLeafNode = false;

            try
            {
                XmlTextReader xmlReader = new XmlTextReader(xmlFileStream);

                // If some element doesn't match document plutlet then stop
                // TODO: Should we try to match other elements? If yes, which pluglet to start with?
                // Also we need to ignore this entire element
                bool stopProcessing = false;

                while (xmlReader.Read())
                {
                    switch (xmlReader.NodeType)
                    {
                    case XmlNodeType.Element:
                        isLeafNode = false;
                        AddStartElementToPayload(xmlReader.Name, xmlReader.IsEmptyElement);

                        if (xmlReader.IsEmptyElement)
                        {
                            break;
                        }

                        if (stopProcessing == false)
                        {
                            currentDocumentFragment = ConstructNewDocumentFragment(xmlReader.Name, currentPluglet, currentDocumentFragment);
                        }

                        // If some element doesn't match document plutlet then stop
                        // TODO: Should we try to match other elements? If yes, which pluglet to start with?
                        // Also we need to ignore this entire element
                        if (currentDocumentFragment == null)
                        {
                            stopProcessing = true;
                        }
                        else
                        {
                            currentPluglet = currentDocumentFragment.Pluglet;
                        }

                        CurrentLevel++;
                        CurrentElementNumber++;
                        break;

                    case XmlNodeType.Text:
                        isLeafNode = true;
                        AddValueToPayload(xmlReader.Value);
                        if (stopProcessing == false)
                        {
                            currentDocumentFragment.Value = xmlReader.Value;
                        }
                        // Assumption: Leaf nodes are on same line and non-leaf nodes are 1-per line (separate line for start and end element)
                        // If this assumption is wrong then we can construct the xml in string format to match fulfill above assumption
                        // and then Ux can use this string version of xml to highlight the errors.
                        CurrentElementNumber--;     // Decrement since leaf level elements are one line, so we need to increment element on endElement only.
                        break;

                    case XmlNodeType.EndElement:
                        CurrentLevel--;
                        AddEndElementToPayload(xmlReader.Name, isLeafNode);
                        if (stopProcessing == false)
                        {
                            // Check if all mandatory segments were present
                            CheckMissingMandatoryElements(currentPluglet, currentDocumentFragment);
                            currentDocumentFragment = currentDocumentFragment.Parent;
                            currentPluglet          = currentPluglet.Parent;
                        }

                        CurrentElementNumber++;
                        isLeafNode = false;
                        break;

                    default:
                        break;
                    }
                }
            }
            catch (XmlException xmlException)
            {
                // TODO: Pass start and end postition
                Errors.AddGenericError(currentPluglet == null ? "N/A" : currentPluglet.Name, X12ErrorCode.UnexpectedSegmentCode,
                                       string.Format("Error parsing XML document: {0}", xmlException.Message),
                                       CurrentElementNumber / 2, CurrentLinePayloadStart + TotalPayloadLength, CurrentLinePayloadEnd + TotalPayloadLength);
            }
            catch (Exception exception)
            {
                // TODO: Pass start and end postition (for all Errors.Add* calls) in this file.
                Errors.AddGenericError(currentPluglet == null ? "N/A" : currentPluglet.Name, X12ErrorCode.UnexpectedSegmentCode,
                                       "Internal error occurred, please contact Maarg",
                                       CurrentElementNumber / 2, CurrentLinePayloadStart + TotalPayloadLength, CurrentLinePayloadEnd + TotalPayloadLength);
                Logger.Error(location, EventId.XmlReaderUnhandledException, "Error occured during xml file processing: {0}", exception.ToString());
            }

            FatpipeDocumentInst.BeautifiedOriginalPayloadBody = BeautifiedOriginalPayload;

            sw.Stop();
            Logger.Debug(location, "Stop - Elapsed time {0} ms", sw.ElapsedMilliseconds);

            return(FatpipeDocumentInst);
        }
Exemple #3
0
        public static IFatpipeDocument Transform(IFatpipeDocument sourceDocument, ITransformPlug transformPlug)
        {
            if (sourceDocument == null)
            {
                throw new ArgumentNullException("sourceDocument");
            }

            Stopwatch sw = new Stopwatch();

            sw.Start();

            FatpipeDocument targetDocument = new FatpipeDocument();

            targetDocument.RootFragment = transformPlug.TargetDocument.RootPluglet.ConstructDocumentFragment(null, null);;

            //TODO: Handle loops
            foreach (ITransformGroup transformGroup in transformPlug.Facets)
            {
                Logger.Debug("DocumentTransformer.Transform", "Processing {0} tranformGroup", transformGroup.Name);

                foreach (ITransformLink transformLink in transformGroup.Links)
                {
                    Logger.Debug("DocumentTransformer.Transform", "Processing Link#-{0}: {1} [{2}] => {3} [{4}]"
                                 , transformLink.Name
                                 , transformLink.Source.ReferenceType, transformLink.Source.Name
                                 , transformLink.Target.ReferenceType, transformLink.Target.Name);

                    //TODO: Handle all kind of transformation
                    if (transformLink.Source.ReferenceType == ReferenceType.Document &&
                        transformLink.Target.ReferenceType == ReferenceType.Document)
                    {
                        // Traverse source path
                        IDocumentFragment sourceFragment = sourceDocument.RootFragment.MoveTo(transformLink.Source.Name);
                        if (sourceFragment != null)
                        {
                            IPluglet targetPluglet = targetDocument.RootFragment.Pluglet.MoveTo(transformLink.Target.Name);

                            if (targetPluglet != null)
                            {
                                Logger.Debug("DocumentTransformer.Transform", "Source = {0}, Target = {1}", sourceFragment.Name, targetPluglet.Tag);

                                Dictionary <string, string> attributes = new Dictionary <string, string>();
                                foreach (IPluglet attr in targetPluglet.Attributes)
                                {
                                    string attributeName = attr.Name;
                                    attributeName.Remove(0, 1);
                                    attributeName.Remove(attributeName.Length, 1);
                                    attributes.Add(attributeName, attributeName);
                                }

                                bool   isAttribute = false;
                                string name        = transformLink.Target.Name.Substring(
                                    transformLink.Target.Name.LastIndexOf(targetPluglet.PathSeperator) + targetPluglet.PathSeperator.Length);
                                // Check if this transformation point to attribute or leaf node
                                if (targetPluglet.Attributes != null && attributes.ContainsKey(name))
                                {
                                    isAttribute = true;
                                }

                                if (isAttribute == false)
                                {
                                    IDocumentFragment newFragment = targetPluglet.ConstructDocumentFragment(null, sourceFragment.Value);
                                    ((DocumentFragment)targetDocument.RootFragment).AddDocumentFragment(newFragment);
                                }
                                else
                                {
                                    ((DocumentFragment)targetDocument.RootFragment).AddDocumentFragment(transformLink.Target.Name, sourceFragment.Value);
                                }
                            }
                            else
                            {
                                string error = string.Format("Link#-{0}: {1} path not found in target tree", transformLink.Name, transformLink.Target.Name);
                                if (targetDocument.Errors == null)
                                {
                                    targetDocument.Errors = new List <string>();
                                }
                                targetDocument.Errors.Add(error);

                                Logger.Error("DocumentTransformer.Transform", EventId.DocTransformerNoMapping, error);
                            }
                        }
                    }
                    else
                    {
                        Logger.Debug("DocumentTransformer.Transform", "Ignoring Link#-{0}", transformLink.Name);
                    }
                }

                //TODO: Handle transformGroup.Formulas
            }

            sw.Stop();
            Logger.Debug("DocumentTransformer.Transform", "Stop. Elapsed time {0} ms", sw.ElapsedMilliseconds);

            return(targetDocument);
        }