예제 #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="strs"></param>
        /// <param name="catalogue"></param>
        /// <param name="section"></param>
        /// <param name="iteration">Indicates if looping through Catalogues and we are not at the last element in the collection yet.</param>
        /// <returns></returns>
        private string DoReplacements(string[] strs, Catalogue catalogue, CatalogueSection section, ElementIteration iteration)
        {
            StringBuilder sb = new StringBuilder();

            for (var index = 0; index < strs.Length; index++)
            {
                var    str  = strs[index];
                string copy = str;

                if (str.Trim().Equals(LoopCatalogueItems, StringComparison.CurrentCultureIgnoreCase))
                {
                    index = DoReplacements(strs, index, out copy, catalogue.CatalogueItems, section);
                }
                else
                {
                    foreach (var r in Replacements)
                    {
                        if (copy.Contains(r.Key))
                        {
                            copy = copy.Replace(r.Key, ValueToString(r.Value(catalogue)));
                        }
                    }

                    // when iterating we need to respect iteration symbols (e.g. $Comma).
                    if (iteration == ElementIteration.NotIterating)
                    {
                        ThrowIfContainsIterationElements(copy);
                    }
                    else
                    {
                        copy = copy.Replace(Comma, iteration == ElementIteration.RegularElement ? CommaSubstitution : "");
                    }
                }

                sb.AppendLine(copy.TrimEnd());
            }

            return(sb.ToString().TrimEnd());
        }
예제 #2
0
        /// <summary>
        /// Consumes from $foreach to $end looping <paramref name="catalogueItems"/> to produce output rows of string data
        /// </summary>
        /// <param name="strs">The original input in its entirety</param>
        /// <param name="index">The line in <paramref name="strs"/> in which the foreach was detected</param>
        /// <param name="result">The results of consuming the foreach block</param>
        /// <param name="catalogueItems"></param>
        /// <param name="section"></param>
        /// <returns>The index in <paramref name="strs"/> where the $end was detected</returns>
        private int DoReplacements(string[] strs, int index, out string result, CatalogueItem[] catalogueItems, CatalogueSection section)
        {
            // The foreach template block as extracted from strs
            StringBuilder block = new StringBuilder();

            //the result of printing out the block once for each CatalogueItem item (with replacements)
            StringBuilder sbResult = new StringBuilder();

            int  i = index + 1;
            bool blockTerminated = false;

            int sectionOffset = section?.LineNumber ?? 0;

            //starting on the next line after $foreach until the end of the file
            for (; i < strs.Length; i++)
            {
                var current         = strs[i];
                int lineNumberHuman = i + 1 + sectionOffset;

                if (current.Trim().Equals(EndLoop, StringComparison.CurrentCultureIgnoreCase))
                {
                    blockTerminated = true;
                    break;
                }

                if (current == LoopCatalogueItems)
                {
                    throw new CustomMetadataReportException($"Error, encountered '{current}' on line {lineNumberHuman} before the end of current block which started on line {lineNumberHuman}.  Make sure to add {EndLoop} at the end of each loop", lineNumberHuman);
                }

                block.AppendLine(current);
            }

            if (!blockTerminated)
            {
                throw new CustomMetadataReportException($"Expected {EndLoop} to match $foreach which started on line {index+1+sectionOffset}", index + 1 + sectionOffset);
            }

            for (int j = 0; j < catalogueItems.Length; j++)
            {
                sbResult.AppendLine(DoReplacements(block.ToString(), catalogueItems[j],
                                                   j < catalogueItems.Length - 1 ?
                                                   ElementIteration.RegularElement : ElementIteration.LastElement));
            }


            result = sbResult.ToString();

            return(i);
        }
예제 #3
0
        private IEnumerable <CatalogueSection> SplitCatalogueLoops(string[] templateBody)
        {
            if (templateBody.Length == 0)
            {
                yield break;
            }

            CatalogueSection currentSection = null;
            int depth = 0;

            for (int i = 0; i < templateBody.Length; i++)
            {
                var str = templateBody[i];

                // is it trying to loop catalogue items
                if (str.Trim().Equals(LoopCatalogueItems))
                {
                    if (currentSection == null || currentSection.IsPlainText)
                    {
                        throw new CustomMetadataReportException($"Error, Unexpected '{str}' on line {i+1}.  Current section is plain text, '{LoopCatalogueItems}' can only appear within a '{LoopCatalogues}' block (you cannot mix and match top level loop elements)", i + 1);
                    }

                    // ignore dives into CatalogueItems
                    depth++;

                    // but preserve it in the body because it will be needed later
                    currentSection.Body.Add(str);
                }
                else
                // is it a loop Catalogues
                if (str.Trim().Equals(LoopCatalogues))
                {
                    if (currentSection != null)
                    {
                        if (currentSection.IsPlainText)
                        {
                            yield return(currentSection);
                        }
                        else
                        {
                            throw new CustomMetadataReportException($"Unexpected '{str}' before the end of the last one on line {i+1}", i + 1);
                        }
                    }

                    // start new section looping Catalogues
                    currentSection = new CatalogueSection(false, i);
                    depth          = 1;
                }
                else
                // is it an end loop
                if (str.Trim().Equals(EndLoop))
                {
                    if (currentSection == null || currentSection.IsPlainText)
                    {
                        throw new CustomMetadataReportException($"Error, encountered '{str}' on line {i+1} while not in a {LoopCatalogues} block", i + 1);
                    }

                    depth--;

                    // does end loop correspond to ending a $foreach Catalogue
                    if (depth == 0)
                    {
                        yield return(currentSection);

                        currentSection = null;
                    }
                    else
                    if (depth < 0)
                    {
                        throw new CustomMetadataReportException($"Error, unexpected '{str}' on line {i+1}", i + 1);
                    }
                    else
                    {
                        // $end is for a CatalogueItem block so preserve it in the body
                        currentSection.Body.Add(str);
                    }
                }
                else
                {
                    // it's just a regular line of text

                    //if it's the first line of a new block we get a plaintext block
                    if (currentSection == null)
                    {
                        currentSection = new CatalogueSection(true, i);
                    }

                    currentSection.Body.Add(str);
                }
            }

            if (currentSection != null)
            {
                if (currentSection.IsPlainText)
                {
                    yield return(currentSection);
                }
                else
                {
                    throw new CustomMetadataReportException($"Reached end of template without finding an expected {EndLoop}", templateBody.Length);
                }
            }
        }