Click here to Skip to main content
15,881,828 members
Articles / Web Development / HTML

Transformalizing NorthWind

Rate me:
Please Sign up or sign in to vote.
4.95/5 (29 votes)
24 Jul 2014GPL37 min read 57.5K   341   53  
Combining de-normalization, transformation, replication, and awesome-ness.
//===============================================================================
// Microsoft patterns & practices Enterprise Library
// Core
//===============================================================================
// Copyright © Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================

using System;
using System.Collections.Generic;
using System.Text;

namespace Transformalize.Libs.EnterpriseLibrary.Common
{
    /// <summary>
    /// This class provides an engine to process a string that contains
    /// replacement tokens of the form "{token}" and replace them with
    /// calculated value later.
    /// </summary>
    public class ReplacementFormatter
    {
        private List<ReplacementToken> tokens = new List<ReplacementToken>();

        /// <summary>
        /// Create a new <see cref="ReplacementFormatter"/>.
        /// </summary>
        public ReplacementFormatter()
        {
        }

        /// <summary>
        /// Create a new <see cref="ReplacementFormatter"/>.
        /// </summary>
        /// <param name="tokens">List of tokens to replace.</param>
        public ReplacementFormatter(params ReplacementToken[] tokens)
        {
            AddRange(tokens);
        }
        
        /// <summary>
        /// Create a new <see cref="ReplacementFormatter"/>.
        /// </summary>
        /// <param name="tokens">List of tokens to replace.</param>
        public ReplacementFormatter(IEnumerable<ReplacementToken> tokens)
        {
            AddRange(tokens);
        }

        /// <summary>
        /// Add a new set of replacement tokens.
        /// </summary>
        /// <param name="tokens">Tokens to add to the list.</param>
        public void Add(params ReplacementToken[] tokens)
        {
            AddRange(tokens);    
        }

        /// <summary>
        /// Add new tokens to the set of replacements.
        /// </summary>
        /// <param name="tokens">Tokens to add to the list.</param>
        public void AddRange(IEnumerable<ReplacementToken> tokens)
        {
            this.tokens.AddRange(tokens);
        }

        /// <summary>
        /// Format the given template, replacing any tokens present.
        /// </summary>
        /// <param name="template">The string to format, containing the replacement tokens.</param>
        /// <returns>The formatted string, with tokens replaced.</returns>
        public string Format(string template)
        {
            StringBuilder templateBuilder = new StringBuilder(template);
            // Escape literal backslash
            templateBuilder.Replace(@"\\", @"\\.");
            // Escape the \{ sequence
            templateBuilder.Replace(@"\{", @"\{.");
            foreach(ReplacementToken token in tokens)
            {
                token.ReplaceToken(templateBuilder);
            }
            templateBuilder.Replace(@"\{.", "{");
            templateBuilder.Replace(@"\\.", @"\");
            return templateBuilder.ToString();
        }
    }

    /// <summary>
    /// A single replacement token used by the <see cref="ReplacementFormatter"/>. A
    /// token consists of two things:
    /// <list type="bullet">
    /// <item><description>The actual text of the token (including the {})</description></item>
    /// <item><description>A delegate to retrieve the value to replace the token.</description></item>
    /// </list>
    /// </summary>
    public class ReplacementToken
    {
        private string token;
        private ReplacementTextDelegate getReplacementText;

        /// <summary>
        /// Create a new <see cref="ReplacementToken"/>.
        /// </summary>
        /// <param name="token">The string marking where the token should be replaced.</param>
        /// <param name="getReplacementText">Delegate to return the value that replaces the token.</param>
        public ReplacementToken(string token, ReplacementTextDelegate getReplacementText)
        {
            this.token = token;
            this.getReplacementText = getReplacementText;
        }

        /// <summary>
        /// The token string.
        /// </summary>
        /// <value>The token string.</value>
        public string Token
        {
            get { return token; }
        }

        /// <summary>
        /// The text to replace this token with.
        /// </summary>
        /// <value>Replacement text.</value>
        public string ReplacementText
        {
            get { return getReplacementText(); }
        }

        /// <summary>
        /// Replace this token in the given stringbuilder.
        /// </summary>
        /// <param name="sb"><see cref="StringBuilder"/> holding the template to perform the token replacement on.</param>
        public void ReplaceToken(StringBuilder sb)
        {
            if (sb == null) throw new ArgumentNullException("sb");

            sb.Replace(token, ReplacementText);
        }
    }

    /// <summary>
    /// Delegate type giving a function that returns the replacement text for a token.
    /// </summary>
    /// <returns>The replacement text.</returns>
    public delegate string ReplacementTextDelegate();
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Software Developer (Senior)
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions