Archive

Archive for March 30, 2011

Basic Internal Dsl for Creating a Table Fluently :)

March 30, 2011 1 comment
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace Html.Table.Dsl
{

    public static class ObjectHtmlExtensions
    {
        public static string GetValuesAsSeperatedTdTags(this object @object)
        {
            var type = @object.GetType();
            string output = String.Empty;
            foreach (var property in type.GetProperties())
            {
                output += "<td>" + property.GetGetMethod().Invoke(@object, null) + "</td>";
            }
            return output;
        }
    }

    public class TableModel
    {
        public string Caption { get; set; }
        public string Id { get; set; }
        public string Class { get; set; }
        public IList<TableHeader> Headers { get; set; }
        public IList<object> Objects { get; set; }

        public IEnumerable Rows
        {
            get { return Objects; }
        }

        public TableModel()
        {
            Caption = String.Empty;
            Headers = new List<TableHeader>();
            Objects = new List<object>();
        }

        public void AddHeader(string name)
        {
            Headers.Add(new TableHeader(name));
        }

        public void SetClassFor(int index, string name)
        {
            Headers[index].Class = name;
        }

        public void SetAbsoluteWidthFor(int index, int width)
        {
            Headers[index].AbsoluteWidth = width;
        }

        public void SetPercentageWidthFor(int index, int width)
        {
            Headers[index].PercentageWidth = width;
        }

        public void AddObject(object entity)
        {
            Objects.Add(entity);
        }

        public void SetCaption(string caption)
        {
            Caption = caption;
        }

        public void SetClass(string @class)
        {
            Class = @class;
        }

        public void SetId(string id)
        {
            Id = id;
        }

        public void SetIdFor(int index, string id)
        {
            Headers[index].Id = id;
        }
    }

    public class TableHeader
    {
        public TableHeader(string name)
        {
            Name = name;
        }

        public string Id { get; set; }
        public string Name { get; set; }
        public string Class { get; set; }
        public int? AbsoluteWidth { get; set; }
        public int? PercentageWidth { get; set; }
    }

    public interface ITableCreater
    {
        ITableOptions CreateTable { get; }
    }

    public interface ITableOptions
    {
        ITableOptions WithCaption(string caption);
        ITableHeaders WithHeaders();
        ITableOptions WithClass(string @class);
        ITableOptions WithId(string id);
    }

    public interface ITableHeaders
    {
        ITableHeaders Add(string name);
        ITableHeaders Class(string name);
        ITableHeaders Id(string id);
        ITableHeaders WithAbsoluteWidth(int width);
        ITableHeaders WithPercentageWidth(int width);
        ITableData WithData();
    }

    public interface ITableData
    {
        ITableData Add(object entity);
        string Render();
    }

    class TableDataImpl : ITableData
    {
        public TableModel Model { get; set; }

        public TableDataImpl(TableModel model)
        {
            Model = model;
        }

        public ITableData Add(object entity)
        {
            Model.AddObject(entity);
            return this;
        }

        public string Render()
        {

            string output = String.Empty;
            output += "<table";

            output += AddIdFor();
            output += AddClassFor();
            output += AddCaptionFor();

            output += ">";

            output += AddHeaders();

            foreach (var entity in Model.Rows)
            {
                output += "<tr>";
                output += entity.GetValuesAsSeperatedTdTags();
                output += "</tr>";
            }

            return output + "</table>";
        }

        private string AddHeaders()
        {
            string output = String.Empty;
            if (Model.Headers.Any())
            {
                output += "<tr>";
                foreach (var header in Model.Headers)
                {
                    output += "<th";
                    output += AddIdForHeader(header);
                    output += AddClassForHeader(header);
                    output += AddWidthForHeader(header);
                    output += ">";
                    output += header.Name;
                    output += "</th>";
                }
                output += "</tr>";
            }
            return output;
        }

        private string AddWidthForHeader(TableHeader header)
        {
            string output = String.Empty;
            if (header == null || !(header.PercentageWidth.HasValue || header.AbsoluteWidth.HasValue))
                return output;

            if (header.AbsoluteWidth.HasValue)
            {
                output += " width='" + header.AbsoluteWidth + "' ";
                return output;
            }

            if (header.PercentageWidth.HasValue)
            {
                output += " width='" + header.AbsoluteWidth + "%' ";
                return output;
            }
            return output;
        }

        private string AddClassForHeader(TableHeader header)
        {
            string output = String.Empty;
            if (header == null || String.IsNullOrWhiteSpace(header.Class))
                return output;

            if (!String.IsNullOrWhiteSpace(Model.Class))
                output += " class='" + header.Class + "' ";
            return output;
        }

        private string AddIdForHeader(TableHeader header)
        {
            string output = String.Empty;
            if (header == null || String.IsNullOrWhiteSpace(header.Id))
                return output;

            if (!String.IsNullOrWhiteSpace(Model.Caption))
                output += " id='" + header.Id  + "' ";
            return output;
        }

        private string AddCaptionFor()
        {
            string output = String.Empty;
            if (!String.IsNullOrWhiteSpace(Model.Caption))
                output += " Caption='" + Model.Caption + "' ";
            return output;
        }

        private string AddClassFor()
        {
            string output = String.Empty;
            if (!String.IsNullOrWhiteSpace(Model.Class))
                output += " class='" + Model.Class + "' ";
            return output;
        }

        private string AddIdFor()
        {
            string output = String.Empty;
            if (!String.IsNullOrWhiteSpace(Model.Id))
                output += " id='" + Model.Id + "' ";
            return output;
        }
    }

    public class TableHeadersImpl : ITableHeaders
    {

        private readonly TableModel _model;
        private int _index = -1;

        public TableHeadersImpl(TableModel model)
        {
            _model = model;
            _index = -1;
        }

        public int Index
        {
            get { return _index; }
            set { _index = value; }
        }

        public TableModel Model
        {
            get { return _model; }
        }

        public ITableHeaders Add(string name)
        {
            ++Index;
            Model.AddHeader(name);
            return this;
        }

        public ITableHeaders Class(string name)
        {
            Model.SetClassFor(Index, name);
            return this;
        }

        public ITableHeaders Id(string id)
        {
            Model.SetIdFor(Index, id);
            return this;
        }

        public ITableHeaders WithAbsoluteWidth(int width)
        {
            Model.SetAbsoluteWidthFor(Index, width);
            return this;
        }

        public ITableHeaders WithPercentageWidth(int width)
        {
            Model.SetPercentageWidthFor(Index, width);
            return this;
        }

        public ITableData WithData()
        {
            return new TableDataImpl(Model);
        }
    }

    public class TableOptionsImpl : ITableOptions
    {
        private readonly TableModel _model;

        public TableOptionsImpl(TableModel model)
        {
            _model = model;
        }

        public TableModel Model
        {
            get { return _model; }
        }

        public ITableOptions WithCaption(string caption)
        {
            Model.SetCaption(caption);
            return this;
        }

        public ITableHeaders WithHeaders()
        {
            return new TableHeadersImpl(Model);
        }

        public ITableOptions WithClass(string @class)
        {
            Model.SetCaption(@class);
            return this;
        }

        public ITableOptions WithId(string id)
        {
            Model.SetId(id);
            return this;
        }
    }

    public class Fluently : ITableCreater
    {
        public ITableOptions CreateTable
        {
            get { return new TableOptionsImpl(new TableModel()); }
        }
    }

    class Program
    {
        static void Main()
        {

            string output = new Fluently()
                .CreateTable
                .WithCaption("Cool table")
                .WithClass("Class")
                .WithId("#Id")
                .WithHeaders()
                    .Add("Name")
                        .Class("cool")
                        .WithAbsoluteWidth(100)
                    .Add("Age")
                        .Class("cool")
                        .WithAbsoluteWidth(100)
                .WithData()
                    .Add(new { Name = "Blair", Age = 100 })
                .Render();

            Console.WriteLine(output);
            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();
        }
    }
}