/// <summary>
        /// Render 
        /// </summary>
        public void DrawTable(TableData data, IPDFDraw drawer)
        {
            tableData = data;
            pdfDrawer = drawer;

            if (tableData.LoopData != null)
            {
                PdfPTable table = DrawTableHead();
                DrawTableLoop(ref table);
                DrawTableFoot(ref table);

                if (table.Rows.Count > 0)
                {
                    var pdfDraw = (PDFDrawItextSharp.PDFDrawItextSharp)pdfDrawer;
                    pdfDrawer.NextRow(1, DocumentGroup.Table);
                    pdfDraw.DrawTable(table, pdfDraw.Current_x, pdfDraw.Current_y);
                    pdfDraw.NextRow(table.TotalHeight, DocumentGroup.Table);
                }
            }
        }
        /// <summary>
        /// Render
        /// </summary>
        public void DrawTable(TableData data, IPDFDraw drawer)
        {
            tableData = data;
            pdfDrawer = drawer;

            if (tableData.LoopData != null)
            {
                PdfPTable table = DrawTableHead();
                DrawTableLoop(ref table);
                DrawTableFoot(ref table);

                if (table.Rows.Count > 0)
                {
                    var pdfDraw = (PDFDrawItextSharp.PDFDrawItextSharp)pdfDrawer;
                    pdfDrawer.NextRow(1, DocumentGroup.Table);
                    pdfDraw.DrawTable(table, pdfDraw.Current_x, pdfDraw.Current_y);
                    pdfDraw.NextRow(table.TotalHeight, DocumentGroup.Table);
                }
            }
        }
        /// <summary>
        /// draw row and table items inside body. 
        /// table items are treated as tables 
        /// </summary>
        public void DrawBody(Hashtable data, IPDFDraw drawer)
        {
            if (bodyItems == null)
                return;

            XmlAttributeCollection font = pdfTemplate.DefaultFontAttrs;
            if (bodyNode.FirstChild.Name == "font")
            {
                font = bodyNode.FirstChild.Attributes;
            }

            foreach (XmlNode itemNode in bodyItems)
            {
                if (!IsNodeVisible(itemNode, data))
                    continue;

                if (itemNode.Name == "row")
                {
                    RowGroup rowGroup = new RowGroup
                    {
                        Y = Helper.GetFloatAttributeValue("y", bodyNode.Attributes, -1)
                    };
                    rowGroup.AddRow(pdfTemplate._buildRow(itemNode, font));
                    pdfTemplate.DrawRowGroup(rowGroup, data, DocumentGroup.Body);
                }
                else if (itemNode.Name == "table")
                {
                    var tableGenerator = new TableGenerator(pdfTemplate, itemNode);
                    if (itemNode.Attributes == null)
                        continue;
                    var keyAttribute = itemNode.Attributes["var"];
                    if (keyAttribute == null || !data.ContainsKey(keyAttribute.Value))
                        continue;
                    var tableParameters = data[keyAttribute.Value];
                    if (!(tableParameters is TableData))
                        throw new Exception("table parameter must be of type TableData");

                    tableGenerator.DrawTable((TableData) (tableParameters), drawer);
                }
            }
        }
        /// <summary>
        /// Render
        /// </summary>
        public void DrawTable(TableData data, IPDFDraw drawer)
        {
            tableData = data;
            pdfDrawer = drawer;

            // Dynamic columns init: add dynamic columns model
            if (tableData.DynamicColumns != null && tableData.DynamicColumns.Any())
            {
                // define dynamic table object attributes
                var     tableAttributes = tableElement.Attributes;
                XmlNode cellPerRowAttr  = tableAttributes.GetNamedItem("cellperrow");
                XmlNode cellwidthAttr   = tableAttributes.GetNamedItem("cellwidth");
                if (cellPerRowAttr != null && cellwidthAttr != null)
                {
                    var cellPerRow = IntHelper.TryParseDefault(cellPerRowAttr.Value, -1);
                    cellPerRowAttr.Value = (cellPerRow + tableData.DynamicColumns.Count).ToString();
                    cellwidthAttr.Value  = cellwidthAttr.Value + (string.IsNullOrEmpty(cellwidthAttr.Value) ? "" : ",") +
                                           string.Join(",", tableData.DynamicColumns.Select(x => x.CellWidth));
                }

                foreach (var dynamicColumn in tableData.DynamicColumns)
                {
                    // nconvert templates to xmlnode element
                    var nodeHead = string.IsNullOrEmpty(dynamicColumn.HeaderTemplate) ? null : GenerateNode(dynamicColumn.HeaderTemplate);
                    var nodeData = GenerateNode(dynamicColumn.DataTemplate);
                    var nodeFoot = string.IsNullOrEmpty(dynamicColumn.FooterTemplate) ? null : GenerateNode(dynamicColumn.FooterTemplate);

                    // define dynamic table head items
                    if (nodeHead != null)
                    {
                        tableRowGroupHead.TableRows.ForEach(x =>
                        {
                            x.AddTableCell(BuildTableCell(nodeHead, fontHead));
                        });
                    }
                    // define dynamic tableloop items
                    tableRowGroupLoop.TableRows.ForEach(x =>
                    {
                        x.AddTableCell(BuildTableCell(nodeData, fontLoop));
                    });
                    // define dynamic table foot items
                    if (nodeFoot != null)
                    {
                        tableRowGroupFoot.TableRows.ForEach(x =>
                        {
                            x.AddTableCell(BuildTableCell(nodeFoot, fontFoot));
                        });
                    }
                }
            }

            if (tableData.LoopData != null)
            {
                PdfPTable table = DrawTableHead();
                DrawTableLoop(ref table);
                DrawTableFoot(ref table);

                if (table.Rows.Count > 0)
                {
                    var pdfDraw = (PDFDrawItextSharp.PDFDrawItextSharp)pdfDrawer;
                    pdfDrawer.NextRow(1, DocumentGroup.Table);
                    pdfDraw.DrawTable(table, pdfDraw.Current_x, pdfDraw.Current_y);
                    pdfDraw.NextRow(table.TotalHeight, DocumentGroup.Table);
                }
            }
        }
        /// <summary>
        /// draw row and table items inside body.
        /// table items are treated as tables
        /// </summary>
        public void DrawBody(Hashtable data, IPDFDraw drawer)
        {
            if (bodyItems == null)
            {
                return;
            }

            XmlAttributeCollection font = pdfTemplate.DefaultFontAttrs;

            if (bodyNode.FirstChild.Name == "font")
            {
                font = bodyNode.FirstChild.Attributes;
            }

            foreach (XmlNode itemNode in bodyItems)
            {
                if (!IsNodeVisible(itemNode, data))
                {
                    continue;
                }

                if (itemNode.Name == "row")
                {
                    RowGroup rowGroup = new RowGroup
                    {
                        Y = XmlHelper.GetFloatAttributeValue("y", bodyNode.Attributes, -1)
                    };
                    // add new page if the attribute "newPage" == "true"
                    var newPageAttribute = itemNode.Attributes?["newPage"];
                    if (newPageAttribute != null && newPageAttribute.Value == "true")
                    {
                        var orientationAttribute = itemNode.Attributes?["orientation"];
                        if (orientationAttribute == null)
                        {
                            pdfTemplate.NextPage();
                        }
                        else if (orientationAttribute.Value.ToUpper() == "LANDSCAPE")
                        {
                            pdfTemplate.NextPage(Orientation.Landscape);
                        }
                        else
                        {
                            pdfTemplate.NextPage(Orientation.Portrait);
                        }

                        pdfTemplate.DrawHeader();
                    }
                    rowGroup.AddRow(pdfTemplate._buildRow(itemNode, font));
                    pdfTemplate.DrawRowGroup(rowGroup, data, DocumentGroup.Body);
                }
                else if (itemNode.Name == "table")
                {
                    var tableGenerator = new TableGenerator(pdfTemplate, itemNode);
                    if (itemNode.Attributes == null)
                    {
                        continue;
                    }
                    var keyAttribute = itemNode.Attributes["var"];
                    if (keyAttribute == null || !data.ContainsKey(keyAttribute.Value))
                    {
                        continue;
                    }
                    // add new page if the attribute "newPage" == "true"
                    var newPageAttribute = itemNode.Attributes?["newPage"];
                    if (newPageAttribute != null && newPageAttribute.Value == "true")
                    {
                        pdfTemplate.NextPage();
                        pdfTemplate.DrawHeader();
                    }
                    var tableParameters = data[keyAttribute.Value];
                    if (!(tableParameters is TableData))
                    {
                        throw new Exception("table parameter must be of type TableData");
                    }

                    tableGenerator.DrawTable((TableData)tableParameters, drawer);
                }
            }
        }