/// <summary>
        /// Deserialize a Dao object
        /// </summary>
        /// <param name="node"></param>
        /// <param name="configScope"></param>
        /// <returns></returns>
        public static Dao Deserialize(XmlNode node, ConfigurationScope configScope)
        {
            Dao dao = new Dao();

            NameValueCollection prop = NodeUtils.ParseAttributes(node, configScope.Properties);
            dao.Implementation = NodeUtils.GetStringAttribute(prop, "implementation");
            dao.Interface = NodeUtils.GetStringAttribute(prop, "interface");

            return dao;
        }
        /// <summary>
        /// Deserialize a Dao object
        /// </summary>
        /// <param name="node"></param>
        /// <param name="configScope"></param>
        /// <returns></returns>
        public static DaoSessionHandler Deserialize(XmlNode node, ConfigurationScope configScope)
        {
            DaoSessionHandler daoSessionHandler = new DaoSessionHandler();

            NameValueCollection prop = NodeUtils.ParseAttributes(node, configScope.Properties);
            daoSessionHandler.Implementation = NodeUtils.GetStringAttribute(prop, "implementation");
            daoSessionHandler.Name = NodeUtils.GetStringAttribute(prop, "id");
            daoSessionHandler.IsDefault = NodeUtils.GetBooleanAttribute(prop, "default", false);

            return daoSessionHandler;
        }
        /// <summary>
        /// Initialize the provider
        /// </summary>
        /// <param name="configurationScope">The scope of the configuration</param>
        /// <returns>A provider</returns>
        private IDbProvider ParseProvider(ConfigurationScope configurationScope)
        {
            XmlNode node = configurationScope.NodeContext.SelectSingleNode( ApplyNamespacePrefix(XML_DATABASE_PROVIDER), configurationScope.XmlNamespaceManager);

            configurationScope.ErrorContext.Activity = "configure provider";

            if (node != null)
            {
                configurationScope.ErrorContext.Resource = node.OuterXml.ToString();
                string providerName = NodeUtils.ParsePropertyTokens(node.Attributes["name"].Value, configurationScope.Properties);

                configurationScope.ErrorContext.ObjectId = providerName;

                if (configurationScope.Providers.Contains(providerName) == true)
                {
                    return (IDbProvider)configurationScope.Providers[providerName];
                }
                else
                {
                    throw new ConfigurationException(
                        string.Format("Error while configuring the Provider named \"{0}\" in the Context named \"{1}\".",
                        providerName, configurationScope.NodeContext.Attributes["name"].Value));
                }
            }
            else
            {
                if(configurationScope.Providers.Contains(DEFAULT_PROVIDER_NAME) == true)
                {
                    return (IDbProvider) configurationScope.Providers[DEFAULT_PROVIDER_NAME];
                }
                else
                {
                    throw new ConfigurationException(
                        string.Format("Error while configuring the Context named \"{0}\". There is no default provider.",
                        configurationScope.NodeContext.Attributes["name"].Value));
                }
            }
        }
        /// <summary>
        /// Initialize the list of variables defined in the
        /// properties file.
        /// </summary>
        /// <param name="configurationScope">The scope of the configuration</param>
        private void ParseGlobalProperties(ConfigurationScope configurationScope)
        {
            XmlNode nodeProperties = configurationScope.NodeContext.SelectSingleNode(ApplyNamespacePrefix(XML_PROPERTIES), configurationScope.XmlNamespaceManager);

            configurationScope.ErrorContext.Activity = "add global properties";

            if (nodeProperties != null)
            {
                if (nodeProperties.HasChildNodes)
                {
                    foreach (XmlNode propertyNode in nodeProperties.SelectNodes(ApplyNamespacePrefix(XML_PROPERTY), configurationScope.XmlNamespaceManager))
                    {
                        XmlAttribute keyAttrib = propertyNode.Attributes[KEY_ATTRIBUTE];
                        XmlAttribute valueAttrib = propertyNode.Attributes[VALUE_ATTRIBUTE];

                        if ( keyAttrib != null && valueAttrib!=null)
                        {
                            configurationScope.Properties.Add( keyAttrib.Value,  valueAttrib.Value);
                            _logger.Info( string.Format("Add property \"{0}\" value \"{1}\"",keyAttrib.Value,valueAttrib.Value) );
                        }
                        else
                        {
                            // Load the file defined by the attribute
                            XmlDocument propertiesConfig = Resources.GetAsXmlDocument(propertyNode, configurationScope.Properties);

                            foreach (XmlNode node in propertiesConfig.SelectNodes(XML_SETTINGS_ADD))
                            {
                                configurationScope.Properties[node.Attributes[KEY_ATTRIBUTE].Value] = node.Attributes[VALUE_ATTRIBUTE].Value;
                                _logger.Info( string.Format("Add property \"{0}\" value \"{1}\"",node.Attributes[KEY_ATTRIBUTE].Value,node.Attributes[VALUE_ATTRIBUTE].Value) );
                            }
                        }
                    }
                }
                else
                {
                    // JIRA-38 Fix
                    // <properties> element's InnerXml is currently an empty string anyway
                    // since <settings> are in properties file

                    configurationScope.ErrorContext.Resource = nodeProperties.OuterXml.ToString();

                    // Load the file defined by the attribute
                    XmlDocument propertiesConfig = Resources.GetAsXmlDocument(nodeProperties, configurationScope.Properties);

                    foreach (XmlNode node in propertiesConfig.SelectNodes(XML_SETTINGS_ADD))
                    {
                        configurationScope.Properties[node.Attributes[KEY_ATTRIBUTE].Value] = node.Attributes[VALUE_ATTRIBUTE].Value;
                        _logger.Info( string.Format("Add property \"{0}\" value \"{1}\"",node.Attributes[KEY_ATTRIBUTE].Value,node.Attributes[VALUE_ATTRIBUTE].Value) );
                    }
                }
            //				// Load the file defined by the resource attribut
            //				XmlDocument propertiesConfig = Resources.GetAsXmlDocument(nodeProperties, configurationScope.Properties);
            //
            //				foreach (XmlNode node in propertiesConfig.SelectNodes("/settings/add"))
            //				{
            //					configurationScope.Properties[node.Attributes["key"].Value] = node.Attributes["value"].Value;
            //				}
            }

            configurationScope.ErrorContext.Resource = string.Empty;
            configurationScope.ErrorContext.MoreInfo = string.Empty;
        }
        //        /// <summary>
        //        /// Build a provider
        //        /// </summary>
        //        /// <param name="node"></param>
        //        /// <returns></returns>
        //        /// <remarks>
        //        /// Not use, I use it to test if it faster than serializer.
        //        /// But the tests are not concluant...
        //        /// </remarks>
        //        private static Provider BuildProvider(XmlNode node)
        //        {
        //            XmlAttribute attribute = null;
        //            Provider provider = new Provider();
        //
        //            attribute = node.Attributes["assemblyName"];
        //            provider.AssemblyName = attribute.Value;
        //            attribute = node.Attributes["default"];
        //            if (attribute != null)
        //            {
        //                provider.IsDefault = Convert.ToBoolean( attribute.Value );
        //            }
        //            attribute = node.Attributes["enabled"];
        //            if (attribute != null)
        //            {
        //                provider.IsEnabled = Convert.ToBoolean( attribute.Value );
        //            }
        //            attribute = node.Attributes["connectionClass"];
        //            provider.ConnectionClass = attribute.Value;
        //            attribute = node.Attributes["UseParameterPrefixInSql"];
        //            if (attribute != null)
        //            {
        //                provider.UseParameterPrefixInSql = Convert.ToBoolean( attribute.Value );
        //            }
        //            attribute = node.Attributes["useParameterPrefixInParameter"];
        //            if (attribute != null)
        //            {
        //                provider.UseParameterPrefixInParameter = Convert.ToBoolean( attribute.Value );
        //            }
        //            attribute = node.Attributes["usePositionalParameters"];
        //            if (attribute != null)
        //            {
        //                provider.UsePositionalParameters = Convert.ToBoolean( attribute.Value );
        //            }
        //            attribute = node.Attributes["commandClass"];
        //            provider.CommandClass = attribute.Value;
        //            attribute = node.Attributes["parameterClass"];
        //            provider.ParameterClass = attribute.Value;
        //            attribute = node.Attributes["parameterDbTypeClass"];
        //            provider.ParameterDbTypeClass = attribute.Value;
        //            attribute = node.Attributes["parameterDbTypeProperty"];
        //            provider.ParameterDbTypeProperty = attribute.Value;
        //            attribute = node.Attributes["dataAdapterClass"];
        //            provider.DataAdapterClass = attribute.Value;
        //            attribute = node.Attributes["commandBuilderClass"];
        //            provider.CommandBuilderClass = attribute.Value;
        //            attribute = node.Attributes["commandBuilderClass"];
        //            provider.CommandBuilderClass = attribute.Value;
        //            attribute = node.Attributes["name"];
        //            provider.Name = attribute.Value;
        //            attribute = node.Attributes["parameterPrefix"];
        //            provider.ParameterPrefix = attribute.Value;
        //
        //            return provider;
        //        }
        /// <summary>
        /// Build the data source object
        /// </summary>
        /// <param name="configurationScope">The scope of the configuration</param>
        /// <returns>A DataSource</returns>
        private DataSource ParseDataSource(ConfigurationScope configurationScope)
        {
            DataSource dataSource = null;
            XmlNode node = configurationScope.NodeContext.SelectSingleNode( ApplyNamespacePrefix(XML_DATABASE_DATASOURCE), configurationScope.XmlNamespaceManager);

            configurationScope.ErrorContext.Resource = node.InnerXml.ToString();
            configurationScope.ErrorContext.MoreInfo = "configure data source";

            dataSource = DataSourceDeSerializer.Deserialize( node );
            //				(DataSource)serializer.Deserialize(new XmlNodeReader(node));

            dataSource.ConnectionString = NodeUtils.ParsePropertyTokens(dataSource.ConnectionString, configurationScope.Properties);

            configurationScope.ErrorContext.Resource = string.Empty;
            configurationScope.ErrorContext.MoreInfo = string.Empty;

            return dataSource;
        }
        /// <summary>
        /// Parse dao factory tag
        /// </summary>
        /// <param name="configurationScope">The scope of the configuration</param>
        /// <param name="daoManager"></param>
        private void ParseDaoFactory(ConfigurationScope configurationScope, DaoManager daoManager)
        {
            Dao dao = null;

            configurationScope.ErrorContext.MoreInfo = "configure dao";

            foreach (XmlNode node in configurationScope.NodeContext.SelectNodes(ApplyNamespacePrefix(XML_DAO), configurationScope.XmlNamespaceManager ))
            {
                dao = DaoDeSerializer.Deserialize(node, configurationScope);
                    //(Dao) serializer.Deserialize(new XmlNodeReader(node));

                configurationScope.ErrorContext.ObjectId = dao.Implementation;

                dao.Initialize(daoManager);
                daoManager.RegisterDao(dao);
            }

            configurationScope.ErrorContext.Resource = string.Empty;
            configurationScope.ErrorContext.MoreInfo = string.Empty;
            configurationScope.ErrorContext.ObjectId = string.Empty;
        }
        /// <summary>
        /// Load and initialize providers from specified file.
        /// </summary>
        /// <param name="configurationScope">The scope of the configuration</param>
        private void GetProviders(ConfigurationScope configurationScope)
        {
            IDbProvider provider = null;
            XmlDocument xmlProviders = null;

            configurationScope.ErrorContext.Activity = "Loading Providers config file";

            XmlNode providersNode = null;
            providersNode = configurationScope.DaoConfigDocument.SelectSingleNode( ApplyNamespacePrefix(XML_CONFIG_PROVIDERS), configurationScope.XmlNamespaceManager);

            if (providersNode != null )
            {
                xmlProviders = Resources.GetAsXmlDocument( providersNode, configurationScope.Properties );
            }
            else
            {
                xmlProviders = Resources.GetConfigAsXmlDocument(PROVIDERS_FILE_NAME);
            }

            foreach (XmlNode node in xmlProviders.SelectNodes(ApplyProviderNamespacePrefix(XML_PROVIDER), configurationScope.XmlNamespaceManager ) )
            {
                configurationScope.ErrorContext.Resource = node.InnerXml.ToString();

                provider = ProviderDeSerializer.Deserialize(node);

                if (provider.IsEnabled == true)
                {
                    configurationScope.ErrorContext.ObjectId = provider.Name;
                    configurationScope.ErrorContext.MoreInfo = "initialize provider";

                    provider.Initialize() ;
                    configurationScope.Providers.Add(provider.Name, provider);
                    if (provider.IsDefault == true)
                    {
                        if (configurationScope.Providers[DEFAULT_PROVIDER_NAME] == null)
                        {
                            configurationScope.Providers.Add(DEFAULT_PROVIDER_NAME, provider);
                        }
                        else
                        {
                            throw new ConfigurationException(
                                string.Format("Error while configuring the Provider named \"{0}\" There can be only one default Provider.",provider.Name));
                        }
                    }
                }
            }

            configurationScope.ErrorContext.Reset();
        }
        /// <summary>
        /// Load and initialize custom DaoSession Handlers.
        /// </summary>
        /// <param name="configurationScope">The scope of the configuration</param>
        private void GetDaoSessionHandlers(ConfigurationScope configurationScope)
        {
            XmlNode daoSessionHandlersNode = null;

            configurationScope.ErrorContext.Activity = "loading custom DaoSession Handlers";

            daoSessionHandlersNode = configurationScope.DaoConfigDocument.SelectSingleNode( ApplyNamespacePrefix(XML_DAO_SESSION_HANDLERS), configurationScope.XmlNamespaceManager);

            if (daoSessionHandlersNode != null)
            {
                foreach (XmlNode node in daoSessionHandlersNode.SelectNodes( ApplyNamespacePrefix(XML_HANDLER), configurationScope.XmlNamespaceManager))
                {
                    configurationScope.ErrorContext.Resource = node.InnerXml.ToString();

                    DaoSessionHandler daoSessionHandler = DaoSessionHandlerDeSerializer.Deserialize(node, configurationScope);

                    configurationScope.ErrorContext.ObjectId = daoSessionHandler.Name;
                    configurationScope.ErrorContext.MoreInfo = "build daoSession handler";

                    configurationScope.DaoSectionHandlers[daoSessionHandler.Name] = daoSessionHandler.TypeInstance;

                    if (daoSessionHandler.IsDefault == true)
                    {
                        configurationScope.DaoSectionHandlers[DEFAULT_DAOSESSIONHANDLER_NAME] = daoSessionHandler.TypeInstance;
                    }
                }
            }

            configurationScope.ErrorContext.Reset();
        }
        /// <summary>
        /// Build dao contexts
        /// </summary>
        /// <param name="configurationScope">The scope of the configuration</param>
        private void GetContexts(ConfigurationScope configurationScope)
        {
            DaoManager daoManager = null;
            XmlAttribute attribute = null;

            // Init
            DaoManager.Reset();

            // Build one daoManager for each context
            foreach (XmlNode contextNode in configurationScope.DaoConfigDocument.SelectNodes(ApplyNamespacePrefix(XML_DAO_CONTEXT), configurationScope.XmlNamespaceManager))
            {
                configurationScope.ErrorContext.Activity = "build daoManager";
                configurationScope.NodeContext = contextNode;

                #region Configure a new DaoManager

                attribute = contextNode.Attributes["id"];
                daoManager = DaoManager.NewInstance(attribute.Value);

                configurationScope.ErrorContext.Activity += daoManager.Id;

                // default
                attribute = contextNode.Attributes["default"];
                if (attribute != null)
                {
                    if (attribute.Value=="true")
                    {
                        daoManager.IsDefault = true;
                    }
                    else
                    {
                        daoManager.IsDefault= false;
                    }
                }
                else
                {
                    daoManager.IsDefault= false;
                }
                #endregion

                #region Properties
                ParseGlobalProperties( configurationScope );
                #endregion

                #region provider
                daoManager.DbProvider = ParseProvider( configurationScope );

                configurationScope.ErrorContext.Resource = string.Empty;
                configurationScope.ErrorContext.MoreInfo = string.Empty;
                configurationScope.ErrorContext.ObjectId = string.Empty;
                #endregion

                #region DataSource
                daoManager.DataSource = ParseDataSource( configurationScope );
                daoManager.DataSource.DbProvider = daoManager.DbProvider;
                #endregion

                #region DaoSessionHandler

                XmlNode nodeSessionHandler = contextNode.SelectSingleNode( ApplyNamespacePrefix(XML_DAO_SESSION_HANDLER), configurationScope.XmlNamespaceManager);

                configurationScope.ErrorContext.Activity = "configure DaoSessionHandler";

                // The resources use to initialize the SessionHandler
                IDictionary resources = new Hashtable();
                // By default, add the DataSource
                resources.Add( "DataSource", daoManager.DataSource);
                // By default, add the useConfigFileWatcher
                resources.Add( "UseConfigFileWatcher", configurationScope.UseConfigFileWatcher);

                IDaoSessionHandler sessionHandler = null;
                Type typeSessionHandler = null;

                if (nodeSessionHandler!= null)
                {
                    configurationScope.ErrorContext.Resource = nodeSessionHandler.InnerXml.ToString();

                    typeSessionHandler = configurationScope.DaoSectionHandlers[nodeSessionHandler.Attributes[ID_ATTRIBUTE].Value] as Type;

                    // Parse property node
                    foreach(XmlNode nodeProperty in nodeSessionHandler.SelectNodes( ApplyNamespacePrefix(XML_PROPERTY), configurationScope.XmlNamespaceManager ))
                    {
                        resources.Add(nodeProperty.Attributes["name"].Value,
                                      NodeUtils.ParsePropertyTokens(nodeProperty.Attributes["value"].Value, configurationScope.Properties));
                    }
                }
                else
                {
                    typeSessionHandler = configurationScope.DaoSectionHandlers[DEFAULT_DAOSESSIONHANDLER_NAME] as Type;
                }

                // Configure the sessionHandler
                configurationScope.ErrorContext.ObjectId = typeSessionHandler.FullName;

                try
                {
                    sessionHandler =(IDaoSessionHandler)Activator.CreateInstance(typeSessionHandler, EmptyObjects);
                }
                catch(Exception e)
                {
                    throw new ConfigurationException(
                        string.Format("DaoManager could not configure DaoSessionHandler. DaoSessionHandler of type \"{0}\", failed. Cause: {1}", typeSessionHandler.Name, e.Message),e
                        );
                }

                sessionHandler.Configure(configurationScope.Properties,  resources );

                daoManager.DaoSessionHandler = sessionHandler;

                configurationScope.ErrorContext.Resource = string.Empty;
                configurationScope.ErrorContext.MoreInfo = string.Empty;
                configurationScope.ErrorContext.ObjectId = string.Empty;
                #endregion

                #region Build Daos
                ParseDaoFactory(configurationScope, daoManager);
                #endregion

                #region Register DaoManager

                configurationScope.ErrorContext.MoreInfo = "register DaoManager";
                configurationScope.ErrorContext.ObjectId = daoManager.Id;

                DaoManager.RegisterDaoManager(daoManager.Id, daoManager);

                configurationScope.ErrorContext.Resource = string.Empty;
                configurationScope.ErrorContext.MoreInfo = string.Empty;
                configurationScope.ErrorContext.ObjectId = string.Empty;
                #endregion
            }
        }
 /// <summary>
 /// Load and build the dao managers.
 /// </summary>
 /// <param name="configurationScope">The scope of the configuration</param>
 private void GetConfig(ConfigurationScope configurationScope)
 {
     GetProviders( configurationScope );
     GetDaoSessionHandlers( configurationScope );
     GetContexts( configurationScope );
 }
        /// <summary>
        /// Build DaoManagers from config document.
        /// </summary>
        //        [MethodImpl(MethodImplOptions.Synchronized)]
        public void BuildDaoManagers(XmlDocument document, bool useConfigFileWatcher)
        {
            ConfigurationScope configurationScope = new ConfigurationScope();

            configurationScope.UseConfigFileWatcher = useConfigFileWatcher;
            configurationScope.DaoConfigDocument = document;

            configurationScope.XmlNamespaceManager = new XmlNamespaceManager(configurationScope.DaoConfigDocument.NameTable);
            configurationScope.XmlNamespaceManager.AddNamespace(DAO_NAMESPACE_PREFIX, DAO_XML_NAMESPACE);
            configurationScope.XmlNamespaceManager.AddNamespace(PROVIDERS_NAMESPACE_PREFIX, PROVIDER_XML_NAMESPACE);

            try
            {
                GetConfig( configurationScope );
            }
            catch(Exception ex)
            {
                throw new ConfigurationException( configurationScope.ErrorContext.ToString(), ex);
            }
        }