///////////////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Loads sub reports.
        /// </summary>
        /// <param name="nodeReport">Report node.</param>
        /// <returns>Readed subreports collection.</returns>
        private ICollection <SubReportInfo> _LoadSubReports(XmlNode nodeReport)
        {
            List <SubReportInfo> subReports = new List <SubReportInfo> ();

            foreach (XmlNode node in nodeReport.ChildNodes)
            {
                if (node.NodeType != XmlNodeType.Element)
                {
                    continue; // skip comments and other non element nodes
                }
                if (!node.Name.Equals(NODE_NAME_SUBREPORTS, StringComparison.OrdinalIgnoreCase))
                {
                    continue; // NOTE: skip not supported
                }
                foreach (XmlNode subReportNode in node.ChildNodes)
                {
                    if (node.NodeType != XmlNodeType.Element)
                    {
                        continue; // skip comments and other non element nodes
                    }
                    if (subReportNode.Name.Equals(NODE_NAME_SUBREPORT, StringComparison.OrdinalIgnoreCase))
                    {
                        string template = subReportNode.Attributes[ATTRIBUTE_NAME_FILEPATH].Value;

                        if (File.Exists(ReportsGenerator.GetTemplateAbsolutelyPath(template)))
                        {
                            string name      = subReportNode.Attributes[ATTRIBUTE_NAME_NAME].Value;
                            bool   isDefault = false;
                            if (null != subReportNode.Attributes[ATTRIBUTE_NAME_DEFAULT])
                            {
                                isDefault = bool.Parse(subReportNode.Attributes[ATTRIBUTE_NAME_DEFAULT].Value);
                            }
                            string groupId = null;
                            if (null != subReportNode.Attributes[ATTRIBUTE_NAME_GROUPID])
                            {
                                groupId = subReportNode.Attributes[ATTRIBUTE_NAME_GROUPID].Value;
                            }
                            bool isVisible = true; // default is visible state
                            if (null != subReportNode.Attributes[ATTRIBUTE_NAME_VISIBLE])
                            {
                                isVisible = bool.Parse(subReportNode.Attributes[ATTRIBUTE_NAME_VISIBLE].Value);
                            }

                            string        description = _LoadDescription(subReportNode);
                            SubReportInfo subInfo     = new SubReportInfo(name, template, description,
                                                                          isDefault, groupId, isVisible);
                            subReports.Add(subInfo);
                        }
                    }
                    else
                    {
                        Debug.Assert(false); // NOTE: not supported
                    }
                }
            }

            return(subReports.AsReadOnly());
        }
        ///////////////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Loads sub reports.
        /// </summary>
        /// <param name="nodeReport">Report node.</param>
        /// <returns>Readed subreports collection.</returns>
        private ICollection<SubReportInfo> _LoadSubReports(XmlNode nodeReport)
        {
            List<SubReportInfo> subReports = new List<SubReportInfo> ();
            foreach (XmlNode node in nodeReport.ChildNodes)
            {
                if (node.NodeType != XmlNodeType.Element)
                    continue; // skip comments and other non element nodes

                if (!node.Name.Equals(NODE_NAME_SUBREPORTS, StringComparison.OrdinalIgnoreCase))
                    continue; // NOTE: skip not supported

                foreach (XmlNode subReportNode in node.ChildNodes)
                {
                    if (node.NodeType != XmlNodeType.Element)
                        continue; // skip comments and other non element nodes

                    if (subReportNode.Name.Equals(NODE_NAME_SUBREPORT, StringComparison.OrdinalIgnoreCase))
                    {
                        string template = subReportNode.Attributes[ATTRIBUTE_NAME_FILEPATH].Value;

                        if (File.Exists(ReportsGenerator.GetTemplateAbsolutelyPath(template)))
                        {
                            string name = subReportNode.Attributes[ATTRIBUTE_NAME_NAME].Value;
                            bool isDefault = false;
                            if (null != subReportNode.Attributes[ATTRIBUTE_NAME_DEFAULT])
                                isDefault = bool.Parse(subReportNode.Attributes[ATTRIBUTE_NAME_DEFAULT].Value);
                            string groupId = null;
                            if (null != subReportNode.Attributes[ATTRIBUTE_NAME_GROUPID])
                                groupId = subReportNode.Attributes[ATTRIBUTE_NAME_GROUPID].Value;
                            bool isVisible = true; // default is visible state
                            if (null != subReportNode.Attributes[ATTRIBUTE_NAME_VISIBLE])
                                isVisible = bool.Parse(subReportNode.Attributes[ATTRIBUTE_NAME_VISIBLE].Value);

                            string description = _LoadDescription(subReportNode);
                            SubReportInfo subInfo = new SubReportInfo(name, template, description,
                                                                      isDefault, groupId, isVisible);
                            subReports.Add(subInfo);
                        }
                    }
                    else
                    {
                        Debug.Assert(false); // NOTE: not supported
                    }
                }
            }

            return subReports.AsReadOnly();
        }
        /// <summary>
        /// Duplicate button click handler.
        /// </summary>
        private void _DuplicateTemplate_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                ReportInfo selectedInfo = _GetSelectedInfo();
                if (null != selectedInfo)
                {
                    ReportsGenerator generator = App.Current.ReportGenerator;

                    // generate new name
                    string dir = Path.GetDirectoryName(selectedInfo.TemplatePath);

                    // create sub reports
                    List<SubReportInfo> subReports = new List<SubReportInfo>();
                    foreach (SubReportInfo subReport in selectedInfo.SubReports)
                    {
                        string subNameNew = _GetNameForDublicate(subReport.Name);
                        string subTemplatePath = ReportsGenerator.GetNewTemplatePath(subNameNew, subReport.TemplatePath);
                        SubReportInfo newSubReport = new SubReportInfo(subNameNew, subTemplatePath, subReport.Description,
                                                                       subReport.IsDefault, subReport.GroupId,
                                                                       subReport.IsVisible);
                        // copy template file for subreport template
                        _DuplicateReportFile(subReport.TemplatePath, newSubReport.TemplatePath);

                        subReports.Add(newSubReport);
                    }

                    // create new info
                    string nameNew = _GetNameForDublicate(selectedInfo.Name);
                    string templatePath = ReportsGenerator.GetNewTemplatePath(nameNew, selectedInfo.TemplatePath);
                    ReportInfo newInfo = new ReportInfo(nameNew, selectedInfo.Context, templatePath, selectedInfo.Description,
                                                        false, subReports);

                    // copy template file for template
                    _DuplicateReportFile(selectedInfo.TemplatePath, newInfo.TemplatePath);

                    generator.AddReportInfo(newInfo);
                    _itemToSelection = newInfo.Name;
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
                App.Current.Messenger.AddError(ex.Message);
            }

            _InitReportTable();
        }