Saturday, November 16, 2013

My experiments with TPL Dataflow

Another WOW technique from the house of Microsoft is the TPL Dataflow for dealing with collections in parallel utilizing the multiple CPU's available. I was doing some experiments with it recently and the code is below;

I implemented the below process using TPL;


class Program
    {
        static Employer employer = new Employer();
        static EmployeeCollection employees = new EmployeeCollection();
        static int i = 0;

        static void Main(string[] args)
        {
            LoadEmployees();
            PayEmployees();
        }

        static void LoadEmployees()
        {
            string fileName = @"C:\Users\m1003014\Desktop\employees.txt";
            var inputBlock = new BufferBlock();
            var processBlock = new TransformBlock(
                x =>
                {
                    Employee emp = null;
                    string[] values = x.Split(@";".ToCharArray());
                    BankAccount bankAccount = new BankAccount(Convert.ToDecimal(values[6]));
                    emp = new Employee(i++, values[0], values[1], Convert.ToDecimal(values[2]), bankAccount);
                    if (Convert.ToDecimal(values[3]) > 0)
                    {
                        emp.TakeAdvance(Convert.ToDecimal(values[3]), Convert.ToDecimal(values[4]), Convert.ToDecimal(values[5]));
                    }
                    return emp;
                });
            var outputBlock = new ActionBlock(
                x =>
                {
                    employees.Add(x);
                });

            using (inputBlock.LinkTo(processBlock))
            using (processBlock.LinkTo(outputBlock))
            {
                inputBlock.Completion.ContinueWith(t => processBlock.Complete());
                processBlock.Completion.ContinueWith(t => outputBlock.Complete());

                if (File.Exists(fileName))
                {
                    StreamReader sr = new StreamReader(fileName);
                    sr.ReadLine();
                    String line = sr.ReadLine();

                    do
                    {
                        inputBlock.Post(line);
                        line = sr.ReadLine();
                    } while (line != null);
                }
                inputBlock.Complete();
                outputBlock.Completion.Wait();
            }
        }

        static void PayEmployees()
        {
            var inputBlock = new BufferBlock();
            var processBlock = new TransformBlock(
                x =>
                {
                    employer.PaySalary(x);
                    return x;
                });
            var outputBlock = new ActionBlock(
                x =>
                {
                    Console.WriteLine(string.Format("The salary of '{1}' INR has been paid to '{0}'", x.FirstName, x.SalaryTobePaid));
                });
            using (inputBlock.LinkTo(processBlock))
            using (processBlock.LinkTo(outputBlock))
            {
                inputBlock.Completion.ContinueWith(t => processBlock.Complete());
                processBlock.Completion.ContinueWith(t => outputBlock.Complete());

                foreach (Employee emp in employees)
                {
                    inputBlock.Post(emp);
                }

                inputBlock.Complete();
                outputBlock.Completion.Wait();
            }
        }
    }

 public class Employee
    {
        int _id;
        string _firstName;
        string _lastName;
        decimal _salary;
        decimal _advanceTaken;
        decimal _monthlyDeduction;
        decimal _tenure;
        decimal _pendingTenure;
        decimal _advanceLeft;
        BankAccount _employeeBankAccount;

        public Employee(int id, string firstName, string lastName, decimal salary, BankAccount employeeBankAccount)
        {
            _id = id;
            _firstName = firstName;
            _lastName = lastName;
            _salary = salary;
            _employeeBankAccount = employeeBankAccount;
        }

        public int EmployeeID
        {
            get { return _id; }
        }

        public string FirstName
        {
            get { return _firstName; }
        }

        public string LastName
        {
            get { return _firstName; }
        }

        public decimal Salary
        {
            get { return _salary; }
        }

        public decimal AdvanceTaken
        {
            get { return _advanceTaken; }
        }

        public decimal AdvanceLeft
        {
            get { return _advanceLeft; }
        }
        public decimal SalaryTobePaid
        {
            get { return _salary - _monthlyDeduction; }
        }

        public BankAccount EmployeeBankAccount
        {
            get { return _employeeBankAccount; }
        }

        public void TakeAdvance(decimal amount, decimal monthlyDeduction, decimal tenure)
        {
            _advanceTaken = amount;
            _advanceLeft = amount;
            _monthlyDeduction = monthlyDeduction;
            _tenure = tenure;
            _pendingTenure = tenure;
        }

        public void UpdateAdvance()
        {
            _advanceLeft -= _monthlyDeduction;
            _pendingTenure -= 1;
        }

        public void CreditSalary()
        {
            _employeeBankAccount.Credit(SalaryTobePaid);
        }

        public bool HasTakenAdvance()
        {
            if (_pendingTenure > 0)
                return true;
            else
                return false;
        }
    }

    public class BankAccount
    {
        decimal _balance;

        public BankAccount(decimal balance)
        {
            _balance = balance;
        }

        public decimal Balance
        {
            get { return _balance; }
        }

        public void Credit(decimal amount)
        {
            _balance += amount;
        }

        public void Debit(decimal amount)
        {
            if (_balance - amount < 0)
                throw new Exception("Insufficient fund available");
            _balance -= amount;
        }
    }

    public class EmployeeCollection : KeyedCollection
    {
        public EmployeeCollection()
            : base()
        {
        }

        protected override int GetKeyForItem(Employee emp)
        {
            return emp.EmployeeID;
        }
    }

    public class MonthlySummary
    {
        int _totalEmployeesReceivingSalary;
        decimal _totalMonthlySalary;
        decimal _totalMonthlyRecovery;

        public int TotalEmployeesReceivingSalary
        {
            get { return _totalEmployeesReceivingSalary; }
        }

        public decimal TotalMonthlySalary
        {
            get { return _totalMonthlySalary; }
        }

        public decimal TotalMonthlyRecovery
        {
            get { return _totalMonthlyRecovery; }
        }

        public void UpdateThisEmployeeDetails(Employee emp)
        {
            _totalEmployeesReceivingSalary += 1;
            _totalMonthlySalary += emp.SalaryTobePaid;
            _totalMonthlyRecovery += emp.SalaryTobePaid - emp.Salary;
        }
    }

    public class Employer
    {
        BankAccount _employerBankAccount;
        MonthlySummary _monthlySummary;

        public Employer()
        {
            _employerBankAccount = new BankAccount(100000000);
            _monthlySummary = new MonthlySummary();
        }

        public void PaySalary(Employee emp)
        {
            _employerBankAccount.Debit(emp.SalaryTobePaid);
            emp.CreditSalary();
            _monthlySummary.UpdateThisEmployeeDetails(emp);
        }
    }

Sample input file;
FirstName;LastName;Salary;AdvanceTaken;MonthlyDeduction;Tenure;AccountBalance
Raja;vel;10000;0;0;0;200000
Bal;ji;10000;0;0;0;100000
test;test;10000;100000;5000;20;10000

TDD using Moq

Recently I was experimenting TDD in C# using Moq mocking framework. An awesome mocking framework. Some samples are below;

For more details on Moq refer this link;
https://code.google.com/p/moq/

[TestMethod]
        public void TestEnrollCustomer()
        {
            var enrollment = new Mock(MockBehavior.Strict, MockCustomerDetails.One);
            bool actual = false;
              actual=  enrollment.Object.EnrollCustomer();
            Assert.AreEqual(true, actual, "Failed to execute");
        }

public class MockCustomerDetails
    {
        static CustomerDetails customer1 = null;
        static CustomerDetails customer2 = null;
        static CustomerDetails customer3 = null;
        static MockCustomerDetails()
        {
            customer1 = new CustomerDetails(MockCustomer.One, MockBIB.One, MockLockBox.One);
            customer2 = new CustomerDetails(MockCustomer.Two, MockBIB.Two, MockLockBox.Two);
            customer3 = new CustomerDetails(MockCustomer.Three, MockBIB.Three, MockLockBox.Three);
        }

        public static CustomerDetails One
        {
            get
            {
                return customer1;
            }
        }
        public static CustomerDetails Two
        {
            get
            {
                return customer2;
            }
        }
        public static CustomerDetails Three
        {
            get
            {
                return customer3;
            }
        }
    }

public class MockBIB
    {
        static DummyBIB bib1 = null;
        static DummyBIB bib2 = null;
        static DummyBIB bib3 = null;

        static MockBIB()
        {
            bib1 = new DummyBIB("1213121");
            bib2 = new DummyBIB("12131zcxc21");
            bib3 = new DummyBIB("12wewe13121");
        }
        public static DummyBIB One
        {
            get
            {
                return bib1;
            }
        }
        public static DummyBIB Two
        {
            get
            {
                return bib2;
            }
        }
        public static DummyBIB Three
        {
            get
            {
                return bib3;
            }
        }
    }

public class MockLockBox
    {
        static DummyLockBox lock1 = null;
        static DummyLockBox lock2 = null;
        static DummyLockBox lock3 = null;

        static MockLockBox()
        {
            lock1 = new DummyLockBox("1213121");
            lock2 = new DummyLockBox("121sdsad3121"); 
            lock3 = new DummyLockBox("1213wrtwrtrw121");
        }
        public static DummyLockBox One
        {
            get
            {
                return lock1;
            }
        }
        public static DummyLockBox Two
        {
            get
            {
                return lock2;
            }
        }
        public static DummyLockBox Three
        {
            get
            {
                return lock3;
            }
        }
    }

Monday, February 20, 2012

Dynamic XPATH in XSLT using C#

Recently I had a task of converting a flat XML to hierarchical XML deserializable to .NET entities. Everything was smooth until I got into a situation where-in I had some elements like shown below


...
<CCY1>GBP</CCY1>
<Value1>1.34</Value1>
<CCY2>EUR</CCY2>


<Value2>1.34</Value2>
...


which needed to be like after conversion as shown below


....
<CCYDetails>
<CCYDetail>
<CCY>GBP</CCY>
<Value>1.34</Value>
....
</CCYDetails>
</CCYDetail>
...
 
After some research in internet, I figured out that it is not straight forward in XSLT. It needs some help of scripting language. Since I am from .NET background, I wasn't able to find much help in this regard. Then I found one code in one of the forum threads and tweaked a bit to get it working.


XSLT
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
xmlns:user="http://tempuri.org/user">
<msxsl:script language="CSharp" implements-prefix="user">
<![CDATA[
public XPathNodeIterator FilterNodes(XPathNodeIterator context,string xpath)
{
context.MoveNext();
return context.Current.Select(xpath);
}
]]>
</msxsl:script>
<xsl:template match="/">
<root>
<CCYDetailss>
<xsl:for-each select="MinPayInAmendment">
<xsl:call-template name="ccy_loop">
</xsl:call-template>
</xsl:for-each>
</CCYDetails>
</root>
</xsl:template>
<xsl:template name="ccy_loop">
<xsl:param name="num">1</xsl:param>
<xsl:if test="not ($num=17)">
<xsl:variable name="ccy" select="concat('CCY',$num)">
</xsl:variable>
<xsl:variable name="new" select="concat('New',$num)">
</xsl:variable>
<CCYDetail>
<CCY>
<xsl:value-of select="user:FilterNodes(.,$ccy)"/>
</CCY>
<New>
<xsl:value-of select="user:FilterNodes(.,$new)"/>
</New>
</CCYDetail>
<xsl:call-template name="ccy_loop">
<xsl:with-param name="num">
<xsl:value-of select="$num+1"></xsl:value-of>
</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>


C#
XPathDocument xpath = new XPathDocument(@"C:\input_xml.xml");

XPathNavigator navi = xpath.CreateNavigator();
XsltSettings settings = new XsltSettings();
settings.EnableScript = true;
settings.EnableDocumentFunction = true;
XslCompiledTransform transform = new XslCompiledTransform();
transform.Load(@"C:\XSLTFile1.xslt",settings,new XmlUrlResolver());
MemoryStream resultStream = new MemoryStream();
XmlWriterSettings writer_settings = new XmlWriterSettings();
writer_settings.Indent = true;
XmlWriter writer = XmlWriter.Create(resultStream,writer_settings);
transform.Transform(xpath, null, writer);
resultStream.Position = 0;
StreamReader stream = new StreamReader(resultStream);
Console.WriteLine(stream.ReadToEnd());
writer.Close();



PDF to XML using iTextsharp

Here is the very simple way of creating the XML from PDF document. I used Form fields in the PDF document. Then using the iTextsharp, I looped through the Acrofields or Form fields and created the flat XML document out of it. You can customize to create more complex structures if need be.

XmlDocument doc = new XmlDocument();
PdfReader reader = new PdfReader(@"C:\Input.pdf");
AcroFields fields = reader.AcroFields;
doc.LoadXml(string.Format("<{0}/>", root));
foreach (string keyName in fields.Fields.Keys)
{
AcroFields.Item item = fields.GetFieldItem(keyName);
XmlElement elt = doc.CreateElement(keyName);
elt.InnerXml = "<![CDATA[" + fields.GetField(keyName) + "]]>"";
doc.DocumentElement.AppendChild(elt);
}

doc.Save(@"C:\output.xml");

Wednesday, February 8, 2012

Generic Error Handling in WCF REST

It is very obvious that we will not have the luxury of throwing the service exceptions when we create web service wrappers to the business processing logic. But it is not end of the world. WCF provides IErrorHandler interface which allows us to handle all the exceptions that are generated from the layers below in generic fashion. For WCF this is OK, but what to do for WCF REST? Don't worry, the same interface can be enhanced to support the error handling functionality for WCF REST services as well. Below is the sample implementation of generic error handling in WCF REST services;

1) Implement the IErrorHandler interface

public class BSErrorHandler : IErrorHandler
{
public bool HandleError(Exception error)
{
return true;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
//This condition is needed to skip handling the WebFaultException
//since it is already handled in the layers below  (I have used WebFaultException<string>
//In case you use different type, add the condition for that)
if (!(error is System.ServiceModel.Web.WebFaultException))
{
//I have used XML type; so why I am using DataContractSerializer
//If you want to use JSON type, use DataContractJSONSerializer
fault = Message.CreateMessage(version,string.Empty, string.Format("Error: {0}", error.Message), new DataContractSerializer(typeof(string)));
fault.Properties.Add(WebBodyFormatMessageProperty.Name, new WebBodyFormatMessageProperty(WebContentFormat.Xml));
//Below code sets the response status to OK (200) so that client
//knows this is a valid response and handle it accordingly
HttpResponseMessageProperty hrp = new HttpResponseMessageProperty();
hrp.StatusCode = System.Net.HttpStatusCode.OK;
fault.Properties[HttpResponseMessageProperty.Name] = hrp;
}
}
}

2) Inject this error handler in the Channel Dispatcher as shown below;

public class CustomMessageBehavior : IEndpointBehavior

{
#region IEndpointBehavior Members
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
BSErrorHandler err = new BSErrorHandler();
endpointDispatcher.ChannelDispatcher.ErrorHandlers.Add(err);
}
public void Validate(ServiceEndpoint endpoint)
{
}
#endregion
}

3) Configure the dispatcher in the Web.Config

Job done!!