#region Apache Notice /***************************************************************************** * $Header: $ * $Revision: $ * $Date: $ * * iBATIS.NET Data Mapper * Copyright (C) 2004 - Gilles Bayon * * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ********************************************************************************/ #endregion #region Using using System; using System.Collections; using System.Collections.Specialized; using System.IO; using System.Reflection; using System.Text; using System.Threading; using System.Xml; using System.Xml.Schema; using IBatisNet.Common; using IBatisNet.Common.Exceptions; using IBatisNet.Common.Logging; using IBatisNet.Common.Utilities; using IBatisNet.Common.Xml; using IBatisNet.DataMapper.Configuration.Alias; using IBatisNet.DataMapper.Configuration.Cache; using IBatisNet.DataMapper.Configuration.Cache.Fifo; using IBatisNet.DataMapper.Configuration.Cache.Lru; using IBatisNet.DataMapper.Configuration.Cache.Memory; using IBatisNet.DataMapper.Configuration.ParameterMapping; using IBatisNet.DataMapper.Configuration.ResultMapping; using IBatisNet.DataMapper.Configuration.Serializers; using IBatisNet.DataMapper.Configuration.Sql; using IBatisNet.DataMapper.Configuration.Sql.Dynamic; using IBatisNet.DataMapper.Configuration.Sql.Dynamic.Elements; using IBatisNet.DataMapper.Configuration.Sql.SimpleDynamic; using IBatisNet.DataMapper.Configuration.Sql.Static; using IBatisNet.DataMapper.Configuration.Statements; using IBatisNet.DataMapper.MappedStatements; using IBatisNet.DataMapper.Scope; using IBatisNet.DataMapper.TypeHandlers; #endregion namespace IBatisNet.DataMapper.Configuration { /// /// Builds SqlMapper instances from a supplied resource (e.g. XML configuration file) /// public class DomSqlMapBuilder { #region Embedded resource // Which files must we allow to be used as Embedded Resources ? // - slqMap.config [No] // - providers.config [No] // - sqlMap files [yes] // - properties file (like Database.config) [Yes] // see contribution, NHibernate usage, // see http://www.codeproject.com/csharp/EmbeddedResourceStrings.asp // see http://www.devhood.com/tutorials/tutorial_details.aspx?tutorial_id=75 #endregion #region Constant private const string PROPERTY_ELEMENT_KEY_ATTRIB = "key"; private const string PROPERTY_ELEMENT_VALUE_ATTRIB = "value"; /// /// /// private const string DATAMAPPER_NAMESPACE_PREFIX = "mapper"; private const string PROVIDERS_NAMESPACE_PREFIX = "provider"; private const string MAPPING_NAMESPACE_PREFIX = "mapping"; private const string DATAMAPPER_XML_NAMESPACE = "http://ibatis.apache.org/dataMapper"; private const string PROVIDER_XML_NAMESPACE = "http://ibatis.apache.org/providers"; private const string MAPPING_XML_NAMESPACE = "http://ibatis.apache.org/mapping"; /// /// Default congig name /// public const string DEFAULT_FILE_CONFIG_NAME = "sqlmap.config"; /// /// Default provider name /// private const string DEFAULT_PROVIDER_NAME = "_DEFAULT_PROVIDER_NAME"; /// /// Dot representation /// public const string DOT = "."; /// /// Token for SqlMapConfig xml root. /// private const string XML_DATAMAPPER_CONFIG_ROOT = "sqlMapConfig"; /// /// Token for xml path to SqlMapConfig settings element. /// private const string XML_CONFIG_SETTINGS = "sqlMapConfig/settings/setting"; /// /// Token for providers config file name. /// private const string PROVIDERS_FILE_NAME = "providers.config"; /// /// Token for xml path to SqlMapConfig providers element. /// private const string XML_CONFIG_PROVIDERS = "sqlMapConfig/providers"; /// /// Token for xml path to properties elements. /// private const string XML_PROPERTIES = "properties"; /// /// Token for xml path to property elements. /// private const string XML_PROPERTY = "property"; /// /// Token for xml path to settings add elements. /// private const string XML_SETTINGS_ADD = "/settings/add"; /// /// Token for xml path to global properties elements. /// private const string XML_GLOBAL_PROPERTIES = "*/add"; /// /// Token for xml path to provider elements. /// private const string XML_PROVIDER = "providers/provider"; /// /// Token for xml path to database provider elements. /// private const string XML_DATABASE_PROVIDER = "sqlMapConfig/database/provider"; /// /// Token for xml path to database source elements. /// private const string XML_DATABASE_DATASOURCE = "sqlMapConfig/database/dataSource"; /// /// Token for xml path to global type alias elements. /// private const string XML_GLOBAL_TYPEALIAS = "sqlMapConfig/alias/typeAlias"; /// /// Token for xml path to global type alias elements. /// private const string XML_GLOBAL_TYPEHANDLER = "sqlMapConfig/typeHandlers/typeHandler"; /// /// Token for xml path to sqlMap elements. /// private const string XML_SQLMAP = "sqlMapConfig/sqlMaps/sqlMap"; /// /// Token for mapping xml root. /// private const string XML_MAPPING_ROOT = "sqlMap"; /// /// Token for xml path to type alias elements. /// private const string XML_TYPEALIAS = "sqlMap/alias/typeAlias"; /// /// Token for xml path to resultMap elements. /// private const string XML_RESULTMAP = "sqlMap/resultMaps/resultMap"; /// /// Token for xml path to parameterMap elements. /// private const string XML_PARAMETERMAP = "sqlMap/parameterMaps/parameterMap"; /// /// Token for xml path to statement elements. /// private const string XML_STATEMENT = "sqlMap/statements/statement"; /// /// Token for xml path to select elements. /// private const string XML_SELECT = "sqlMap/statements/select"; /// /// Token for xml path to insert elements. /// private const string XML_INSERT = "sqlMap/statements/insert"; /// /// Token for xml path to selectKey elements. /// private const string XML_SELECTKEY= "selectKey"; /// /// Token for xml path to update elements. /// private const string XML_UPDATE ="sqlMap/statements/update"; /// /// Token for xml path to delete elements. /// private const string XML_DELETE ="sqlMap/statements/delete"; /// /// Token for xml path to procedure elements. /// private const string XML_PROCEDURE ="sqlMap/statements/procedure"; /// /// Token for xml path to cacheModel elements. /// private const string XML_CACHE_MODEL = "sqlMap/cacheModels/cacheModel"; /// /// Token for xml path to flushOnExecute elements. /// private const string XML_FLUSH_ON_EXECUTE = "flushOnExecute"; /// /// Token for xml path to search statement elements. /// private const string XML_SEARCH_STATEMENT ="sqlMap/statements"; /// /// Token for xml path to search parameterMap elements. /// private const string XML_SEARCH_PARAMETER ="sqlMap/parameterMaps/parameterMap[@id='"; /// /// Token for xml path to search resultMap elements. /// private const string XML_SEARCH_RESULTMAP ="sqlMap/resultMaps/resultMap[@id='"; /// /// Token for useStatementNamespaces attribute. /// private const string ATR_USE_STATEMENT_NAMESPACES = "useStatementNamespaces"; /// /// Token for cacheModelsEnabled attribute. /// private const string ATR_CACHE_MODELS_ENABLED = "cacheModelsEnabled"; /// /// Token for validateSqlMap attribute. /// private const string ATR_VALIDATE_SQLMAP = "validateSqlMap"; /// /// Token for embedStatementParams attribute. /// private const string ATR_EMBED_STATEMENT_PARAMS = "useEmbedStatementParams"; #endregion #region Fields private static readonly ILog _logger = LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType ); private ConfigurationScope _configScope = null; private DeSerializerFactory _deSerializerFactory = null; private InlineParameterMapParser _paramParser = null; #endregion #region Constructor /// /// Default constructor /// public DomSqlMapBuilder() { _configScope = new ConfigurationScope(); _paramParser = new InlineParameterMapParser(_configScope.ErrorContext); _deSerializerFactory = new DeSerializerFactory(_configScope); } /// /// Constructs a DomSqlMapBuilder /// with or without configuration document validation using the /// SqlMapConfig schema. /// /// /// Specify whether the configuration Xml document should be /// validated with the SqlMapConfig schema. /// public DomSqlMapBuilder(bool validateSqlMapConfig) { _configScope = new ConfigurationScope(); _configScope.ValidateSqlMapConfig = validateSqlMapConfig; _paramParser = new InlineParameterMapParser(_configScope.ErrorContext); } #endregion #region Configure /// /// Configure a SqlMapper from default resource file named SqlMap.config. /// /// An SqlMap /// The file path is relative to the application root. public SqlMapper Configure() { return Configure( Resources.GetConfigAsXmlDocument(DomSqlMapBuilder.DEFAULT_FILE_CONFIG_NAME) ); } /// /// Configure an SqlMap. /// /// An xml sql map configuration document. /// the SqlMap public SqlMapper Configure( XmlDocument document ) { return Build( document, false ); } /// /// Configure a SqlMapper from a file path. /// /// /// A relative ressource path from your Application root /// or a absolue file path file:\\c:\dir\a.config /// /// An SqlMap public SqlMapper Configure(string resource) { XmlDocument document = null; if (resource.StartsWith("file://")) { document = Resources.GetUrlAsXmlDocument( resource.Remove(0, 7) ); } else { document = Resources.GetResourceAsXmlDocument( resource ); } return Build( document, false); } /// /// Configure a SqlMapper from a stream. /// /// A stream resource /// An SqlMap public SqlMapper Configure(Stream resource) { XmlDocument document = Resources.GetStreamAsXmlDocument( resource ); return Build( document, false); } /// /// Configure a SqlMapper from a FileInfo. /// /// A FileInfo resource /// An SqlMap public SqlMapper Configure(FileInfo resource) { XmlDocument document = Resources.GetFileInfoAsXmlDocument( resource ); return Build( document, false); } /// /// Configure a SqlMapper from an Uri. /// /// A Uri resource /// public SqlMapper Configure(Uri resource) { XmlDocument document = Resources.GetUriAsXmlDocument( resource ); return Build( document, false); } /// /// Configure and monitor the default configuration file for modifications /// and automatically reconfigure SqlMap. /// /// An SqlMap public SqlMapper ConfigureAndWatch(ConfigureHandler configureDelegate) { return ConfigureAndWatch( DEFAULT_FILE_CONFIG_NAME, configureDelegate ) ; } /// /// Configure and monitor the configuration file for modifications /// and automatically reconfigure SqlMap. /// /// /// A relative ressource path from your Application root /// or an absolue file path file:\\c:\dir\a.config /// /// /// Delegate called when the file has changed, to rebuild the dal. /// /// An SqlMap public SqlMapper ConfigureAndWatch( string resource, ConfigureHandler configureDelegate ) { XmlDocument document = null; if (resource.StartsWith("file://")) { document = Resources.GetUrlAsXmlDocument( resource.Remove(0, 7) ); } else { document = Resources.GetResourceAsXmlDocument( resource ); } ConfigWatcherHandler.ClearFilesMonitored(); ConfigWatcherHandler.AddFileToWatch( Resources.GetFileInfo( resource ) ); TimerCallback callBakDelegate = new TimerCallback( DomSqlMapBuilder.OnConfigFileChange ); StateConfig state = new StateConfig(); state.FileName = resource; state.ConfigureHandler = configureDelegate; new ConfigWatcherHandler( callBakDelegate, state ); return Build( document, true ); } /// /// Configure and monitor the configuration file for modifications /// and automatically reconfigure SqlMap. /// /// /// A FileInfo to your config file. /// /// /// Delegate called when the file has changed, to rebuild the dal. /// /// An SqlMap public SqlMapper ConfigureAndWatch( FileInfo resource, ConfigureHandler configureDelegate ) { XmlDocument document = Resources.GetFileInfoAsXmlDocument(resource); ConfigWatcherHandler.ClearFilesMonitored(); ConfigWatcherHandler.AddFileToWatch( resource ); TimerCallback callBakDelegate = new TimerCallback( DomSqlMapBuilder.OnConfigFileChange ); StateConfig state = new StateConfig(); state.FileName = resource.FullName; state.ConfigureHandler = configureDelegate; new ConfigWatcherHandler( callBakDelegate, state ); return Build( document, true ); } /// /// Callback called when the SqlMap.config changed. /// /// The state config. public static void OnConfigFileChange(object obj) { StateConfig state = (StateConfig)obj; state.ConfigureHandler( null ); } #endregion #region Methods /// /// Build a SqlMapper instance /// /// An xml configuration document /// A data source /// /// /// return an a SqlMapper instance private SqlMapper Build(XmlDocument document,DataSource dataSource, bool useConfigFileWatcher, bool isCallFromDao) { _configScope.SqlMapConfigDocument = document; _configScope.DataSource = dataSource; _configScope.IsCallFromDao = isCallFromDao; _configScope.UseConfigFileWatcher = useConfigFileWatcher; _configScope.XmlNamespaceManager = new XmlNamespaceManager(_configScope.SqlMapConfigDocument.NameTable); _configScope.XmlNamespaceManager.AddNamespace(DATAMAPPER_NAMESPACE_PREFIX, DATAMAPPER_XML_NAMESPACE); _configScope.XmlNamespaceManager.AddNamespace(PROVIDERS_NAMESPACE_PREFIX, PROVIDER_XML_NAMESPACE); _configScope.XmlNamespaceManager.AddNamespace(MAPPING_NAMESPACE_PREFIX, MAPPING_XML_NAMESPACE); try { if (_configScope.ValidateSqlMapConfig) { ValidateSchema( document.ChildNodes[1], "SqlMapConfig.xsd" ); } Initialize(); return _configScope.SqlMapper; } catch(Exception e) { throw new ConfigurationException(_configScope.ErrorContext.ToString(), e); } } /// /// validate againts schema /// /// The doc to validate /// schema File Name private void ValidateSchema( XmlNode section, string schemaFileName ) { XmlValidatingReader validatingReader = null; Stream xsdFile = null; _configScope.ErrorContext.Activity = "Validate SqlMap config"; try { //Validate the document using a schema validatingReader = new XmlValidatingReader( new XmlTextReader( new StringReader( section.OuterXml ) ) ); validatingReader.ValidationType = ValidationType.Schema; xsdFile = GetStream( schemaFileName ); if (xsdFile == null) { // TODO: avoid using hard-coded value "IBatisNet.DataMapper" throw new ConfigurationException( "Unable to locate embedded resource [IBatisNet.DataMapper."+schemaFileName+"]. If you are building from source, verfiy the file is marked as an embedded resource."); } XmlSchema xmlSchema = XmlSchema.Read( xsdFile, new ValidationEventHandler(ValidationCallBack) ); validatingReader.Schemas.Add(xmlSchema); // Wire up the call back. The ValidationEvent is fired when the // XmlValidatingReader hits an issue validating a section of the xml validatingReader.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack); // Validate the document while (validatingReader.Read()){} if(! _configScope.IsXmlValid ) { throw new ConfigurationException( "Invalid SqlMap.config document. cause :"+_configScope.ErrorContext.Resource); //( Resource.ResourceManager.FormatMessage( Resource.MessageKeys.DocumentNotValidated, _schemaErrors )) ); } } finally { if( validatingReader != null ) validatingReader.Close(); if( xsdFile != null ) xsdFile.Close(); } } private void ValidationCallBack( object sender, ValidationEventArgs args ) { _configScope.IsXmlValid = false; _configScope.ErrorContext.Resource += args.Message + Environment.NewLine; } /// /// Load statement, parameters, resultmap. /// /// /// /// /// /// /// Used by Dao public SqlMapper Build(XmlDocument document, DataSource dataSource, bool useConfigFileWatcher, NameValueCollection properties) { _configScope.Properties.Add(properties); return Build(document, dataSource, useConfigFileWatcher, true); } /// /// Load SqlMap configuration from /// from the XmlDocument passed in parameter. /// /// The xml sql map configuration. /// public SqlMapper Build(XmlDocument document, bool useConfigFileWatcher) { return Build(document, null, useConfigFileWatcher, false); } /// /// Reset PreparedStatements cache /// private void Reset() { } /// /// Intialize an SqlMap. /// private void Initialize() { Reset(); _configScope.SqlMapper = new SqlMapper( new TypeHandlerFactory() ); #region Cache Alias TypeAlias cacheAlias = new TypeAlias(typeof(MemoryCacheControler)); cacheAlias.Name = "MEMORY"; _configScope.SqlMapper.AddTypeAlias(cacheAlias.Name, cacheAlias); cacheAlias = new TypeAlias(typeof(LruCacheController)); cacheAlias.Name = "LRU"; _configScope.SqlMapper.AddTypeAlias(cacheAlias.Name, cacheAlias); cacheAlias = new TypeAlias(typeof(FifoCacheController)); cacheAlias.Name = "FIFO"; _configScope.SqlMapper.AddTypeAlias(cacheAlias.Name, cacheAlias); #endregion #region Load Global Properties if (_configScope.IsCallFromDao == false) { _configScope.NodeContext = _configScope.SqlMapConfigDocument.SelectSingleNode( ApplyDataMapperNamespacePrefix(XML_DATAMAPPER_CONFIG_ROOT), _configScope.XmlNamespaceManager); ParseGlobalProperties(); } #endregion #region Load settings _configScope.ErrorContext.Activity = "loading global settings"; XmlNodeList settings = _configScope.SqlMapConfigDocument.SelectNodes( ApplyDataMapperNamespacePrefix(XML_CONFIG_SETTINGS), _configScope.XmlNamespaceManager); //XML_CONFIG_SETTINGS); if (settings!=null) { foreach (XmlNode setting in settings) { if (setting.Attributes[ATR_USE_STATEMENT_NAMESPACES] != null ) { string value = NodeUtils.ParsePropertyTokens(setting.Attributes[ATR_USE_STATEMENT_NAMESPACES].Value, _configScope.Properties); _configScope.UseStatementNamespaces = Convert.ToBoolean( value ); } if (setting.Attributes[ATR_CACHE_MODELS_ENABLED] != null ) { string value = NodeUtils.ParsePropertyTokens(setting.Attributes[ATR_CACHE_MODELS_ENABLED].Value, _configScope.Properties); _configScope.IsCacheModelsEnabled = Convert.ToBoolean( value ); } if (setting.Attributes[ATR_EMBED_STATEMENT_PARAMS] != null ) { string value = NodeUtils.ParsePropertyTokens(setting.Attributes[ATR_EMBED_STATEMENT_PARAMS].Value, _configScope.Properties); _configScope.UseEmbedStatementParams = Convert.ToBoolean( value ); } if (setting.Attributes[ATR_VALIDATE_SQLMAP] != null ) { string value = NodeUtils.ParsePropertyTokens(setting.Attributes[ATR_VALIDATE_SQLMAP].Value, _configScope.Properties); _configScope.ValidateSqlMap = Convert.ToBoolean( value ); } } } _configScope.SqlMapper.SetCacheModelsEnabled(_configScope.IsCacheModelsEnabled); _configScope.SqlMapper.SetUseEmbedStatementParams(_configScope.UseEmbedStatementParams); #endregion #region Load providers if (_configScope.IsCallFromDao == false) { GetProviders(); } #endregion #region Load DataBase #region Choose the provider Provider provider = null; if ( _configScope.IsCallFromDao==false ) { provider = ParseProvider(); _configScope.ErrorContext.Reset(); } #endregion #region Load the DataSources _configScope.ErrorContext.Activity = "loading Database DataSource"; XmlNode nodeDataSource = _configScope.SqlMapConfigDocument.SelectSingleNode( ApplyDataMapperNamespacePrefix(XML_DATABASE_DATASOURCE), _configScope.XmlNamespaceManager ); if (nodeDataSource == null) { if (_configScope.IsCallFromDao == false) { throw new ConfigurationException("There's no dataSource tag in SqlMap.config."); } else // patch from Luke Yang { _configScope.SqlMapper.DataSource = _configScope.DataSource; } } else { if (_configScope.IsCallFromDao == false) { _configScope.ErrorContext.Resource = nodeDataSource.OuterXml.ToString(); _configScope.ErrorContext.MoreInfo = "parse DataSource"; DataSource dataSource = DataSourceDeSerializer.Deserialize( nodeDataSource ); dataSource.Provider = provider; dataSource.ConnectionString = NodeUtils.ParsePropertyTokens(dataSource.ConnectionString, _configScope.Properties); _configScope.DataSource = dataSource; _configScope.SqlMapper.DataSource = _configScope.DataSource; } else { _configScope.SqlMapper.DataSource = _configScope.DataSource; } _configScope.ErrorContext.Reset(); } #endregion #endregion #region Load Global TypeAlias foreach (XmlNode xmlNode in _configScope.SqlMapConfigDocument.SelectNodes( ApplyDataMapperNamespacePrefix(XML_GLOBAL_TYPEALIAS), _configScope.XmlNamespaceManager)) { _configScope.ErrorContext.Activity = "loading global Type alias"; TypeAliasDeSerializer.Deserialize(xmlNode, _configScope); } _configScope.ErrorContext.Reset(); #endregion #region Load TypeHandlers foreach (XmlNode xmlNode in _configScope.SqlMapConfigDocument.SelectNodes( ApplyDataMapperNamespacePrefix(XML_GLOBAL_TYPEHANDLER), _configScope.XmlNamespaceManager)) { try { _configScope.ErrorContext.Activity = "loading typeHandler"; TypeHandlerDeSerializer.Deserialize( xmlNode, _configScope ); } catch (Exception e) { NameValueCollection prop = NodeUtils.ParseAttributes(xmlNode, _configScope.Properties); throw new ConfigurationException( String.Format("Error registering TypeHandler class \"{0}\" for handling .Net type \"{1}\" and dbType \"{2}\". Cause: {3}", NodeUtils.GetStringAttribute(prop, "callback"), NodeUtils.GetStringAttribute(prop, "type"), NodeUtils.GetStringAttribute(prop, "dbType"), e.Message), e); } } _configScope.ErrorContext.Reset(); #endregion #region Load sqlMap mapping files foreach (XmlNode xmlNode in _configScope.SqlMapConfigDocument.SelectNodes( ApplyDataMapperNamespacePrefix(XML_SQLMAP), _configScope.XmlNamespaceManager)) { _configScope.NodeContext = xmlNode; ConfigureSqlMap(); } #endregion #region Attach CacheModel to statement if (_configScope.IsCacheModelsEnabled) { foreach(DictionaryEntry entry in _configScope.SqlMapper.MappedStatements) { _configScope.ErrorContext.Activity = "Set CacheModel to statement"; IMappedStatement mappedStatement = (IMappedStatement)entry.Value; if (mappedStatement.Statement.CacheModelName.Length >0) { _configScope.ErrorContext.MoreInfo = "statement : "+mappedStatement.Statement.Id; _configScope.ErrorContext.Resource = "cacheModel : " +mappedStatement.Statement.CacheModelName; mappedStatement.Statement.CacheModel = _configScope.SqlMapper.GetCache(mappedStatement.Statement.CacheModelName); } } } _configScope.ErrorContext.Reset(); #endregion #region Register Trigger Statements for Cache Models foreach (DictionaryEntry entry in _configScope.CacheModelFlushOnExecuteStatements) { string cacheModelId = (string)entry.Key; IList statementsToRegister = (IList)entry.Value; if (statementsToRegister != null && statementsToRegister.Count > 0) { foreach (string statementName in statementsToRegister) { CacheModel cacheModel = _configScope.SqlMapper.GetCache(cacheModelId); IMappedStatement mappedStatement = (IMappedStatement)_configScope.SqlMapper.MappedStatements[statementName]; if (_logger.IsDebugEnabled) { _logger.Debug("Registering trigger statement [" + mappedStatement.Name + "] to cache model [" + cacheModel.Id + "]"); } cacheModel.RegisterTriggerStatement(mappedStatement); } } } #endregion #region Resolve "resultMap" attribute on Result Property + initialize Discriminator property foreach(DictionaryEntry entry in _configScope.SqlMapper.ResultMaps) { _configScope.ErrorContext.Activity = "Resolve 'resultMap' attribute on Result Property"; ResultMap resultMap = (ResultMap)entry.Value; foreach(DictionaryEntry item in resultMap.ColumnsToPropertiesMap) { ResultProperty result = (ResultProperty)item.Value; if(result.NestedResultMapName.Length >0) { result.NestedResultMap = _configScope.SqlMapper.GetResultMap(result.NestedResultMapName); } } if (resultMap.Discriminator != null) { resultMap.Discriminator.Initialize(_configScope); } } _configScope.ErrorContext.Reset(); #endregion } /// /// Load and initialize providers from specified file. /// private void GetProviders() { Provider provider = null; XmlDocument xmlProviders = null; _configScope.ErrorContext.Activity = "loading Providers"; XmlNode providersNode = null; providersNode = _configScope.SqlMapConfigDocument.SelectSingleNode( ApplyDataMapperNamespacePrefix(XML_CONFIG_PROVIDERS), _configScope.XmlNamespaceManager); if (providersNode != null ) { xmlProviders = Resources.GetAsXmlDocument( providersNode, _configScope.Properties ); } else { xmlProviders = Resources.GetConfigAsXmlDocument(PROVIDERS_FILE_NAME); } foreach (XmlNode node in xmlProviders.SelectNodes( ApplyProviderNamespacePrefix(XML_PROVIDER), _configScope.XmlNamespaceManager ) ) { _configScope.ErrorContext.Resource = node.InnerXml.ToString(); provider = ProviderDeSerializer.Deserialize(node); if (provider.IsEnabled == true) { _configScope.ErrorContext.ObjectId = provider.Name; _configScope.ErrorContext.MoreInfo = "initialize provider"; provider.Initialize(); _configScope.Providers.Add(provider.Name, provider); if (provider.IsDefault == true) { if (_configScope.Providers[DEFAULT_PROVIDER_NAME] == null) { _configScope.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)); } } } } _configScope.ErrorContext.Reset(); } /// /// Parse the provider tag. /// /// A provider object. private Provider ParseProvider() { _configScope.ErrorContext.Activity = "load DataBase Provider"; XmlNode node = _configScope.SqlMapConfigDocument.SelectSingleNode( ApplyDataMapperNamespacePrefix(XML_DATABASE_PROVIDER), _configScope.XmlNamespaceManager ); if (node != null) { _configScope.ErrorContext.Resource = node.OuterXml.ToString(); string providerName = NodeUtils.ParsePropertyTokens(node.Attributes["name"].Value, _configScope.Properties); _configScope.ErrorContext.ObjectId = providerName; if (_configScope.Providers.Contains(providerName) == true) { return (Provider) _configScope.Providers[providerName]; } else { throw new ConfigurationException( string.Format("Error while configuring the Provider named \"{0}\". Cause : The provider is not in 'providers.config'.", providerName)); } } else { if (_configScope.Providers.Contains(DEFAULT_PROVIDER_NAME) == true) { return (Provider) _configScope.Providers[DEFAULT_PROVIDER_NAME]; } else { throw new ConfigurationException( string.Format("Error while configuring the SqlMap. There is no provider marked default in 'providers.config' file.")); } } } /// /// Load sqlMap statement. /// private void ConfigureSqlMap( ) { XmlNode sqlMapNode = _configScope.NodeContext; _configScope.ErrorContext.Activity = "loading SqlMap"; _configScope.ErrorContext.Resource = sqlMapNode.OuterXml.ToString(); if (_configScope.UseConfigFileWatcher == true) { if (sqlMapNode.Attributes["resource"] != null || sqlMapNode.Attributes["url"] != null) { ConfigWatcherHandler.AddFileToWatch( Resources.GetFileInfo( Resources.GetValueOfNodeResourceUrl(sqlMapNode, _configScope.Properties) ) ); } } // Load the file _configScope.SqlMapDocument = Resources.GetAsXmlDocument(sqlMapNode, _configScope.Properties); if (_configScope.ValidateSqlMap) { ValidateSchema( _configScope.SqlMapDocument.ChildNodes[1], "SqlMap.xsd" ); } _configScope.SqlMapNamespace = _configScope.SqlMapDocument.SelectSingleNode( ApplyMappingNamespacePrefix(XML_MAPPING_ROOT), _configScope.XmlNamespaceManager ).Attributes["namespace"].Value; #region Load TypeAlias foreach (XmlNode xmlNode in _configScope.SqlMapDocument.SelectNodes( ApplyMappingNamespacePrefix(XML_TYPEALIAS), _configScope.XmlNamespaceManager)) { TypeAliasDeSerializer.Deserialize(xmlNode, _configScope); } _configScope.ErrorContext.MoreInfo = string.Empty; _configScope.ErrorContext.ObjectId = string.Empty; #endregion #region Load resultMap foreach (XmlNode xmlNode in _configScope.SqlMapDocument.SelectNodes( ApplyMappingNamespacePrefix(XML_RESULTMAP), _configScope.XmlNamespaceManager)) { _configScope.ErrorContext.MoreInfo = "loading ResultMap tag"; _configScope.NodeContext = xmlNode; // A ResultMap node BuildResultMap(); } #endregion #region Load parameterMaps foreach (XmlNode xmlNode in _configScope.SqlMapDocument.SelectNodes( ApplyMappingNamespacePrefix(XML_PARAMETERMAP), _configScope.XmlNamespaceManager)) { _configScope.ErrorContext.MoreInfo = "loading ParameterMap tag"; _configScope.NodeContext = xmlNode; // A ParameterMap node BuildParameterMap(); } #endregion #region Load statements #region Statement tag Statement statement = null; foreach (XmlNode xmlNode in _configScope.SqlMapDocument.SelectNodes( ApplyMappingNamespacePrefix(XML_STATEMENT), _configScope.XmlNamespaceManager)) { _configScope.ErrorContext.MoreInfo = "loading statement tag"; _configScope.NodeContext = xmlNode; // A statement tag MappedStatement mappedStatement = null; statement = StatementDeSerializer.Deserialize(xmlNode, _configScope); statement.CacheModelName = ApplyNamespace( statement.CacheModelName ); statement.ParameterMapName = ApplyNamespace( statement.ParameterMapName ); statement.ResultMapName = ApplyNamespace( statement.ResultMapName ); if (_configScope.UseStatementNamespaces == true) { statement.Id = ApplyNamespace(statement.Id); } _configScope.ErrorContext.ObjectId = statement.Id; statement.Initialize( _configScope ); // Build ISql (analyse sql statement) ProcessSqlStatement( statement ); // Build MappedStatement mappedStatement = new MappedStatement( _configScope.SqlMapper, statement); _configScope.SqlMapper.AddMappedStatement(mappedStatement.Name, mappedStatement); } #endregion #region Select tag Select select = null; foreach (XmlNode xmlNode in _configScope.SqlMapDocument.SelectNodes( ApplyMappingNamespacePrefix(XML_SELECT), _configScope.XmlNamespaceManager)) { _configScope.ErrorContext.MoreInfo = "loading select tag"; _configScope.NodeContext = xmlNode; // A select node select = SelectDeSerializer.Deserialize(xmlNode, _configScope); select.CacheModelName = ApplyNamespace( select.CacheModelName ); select.ParameterMapName = ApplyNamespace( select.ParameterMapName ); select.ResultMapName = ApplyNamespace( select.ResultMapName ); if (_configScope.UseStatementNamespaces == true) { select.Id = ApplyNamespace(select.Id); } _configScope.ErrorContext.ObjectId = select.Id; select.Initialize( _configScope ); if (select.Generate != null) { GenerateCommandText(_configScope.SqlMapper, select); } else { // Build ISql (analyse sql statement) ProcessSqlStatement( select); } // Build MappedStatement MappedStatement mappedStatement = new SelectMappedStatement( _configScope.SqlMapper, select); IMappedStatement mapStatement = mappedStatement; if (select.CacheModelName != null && select.CacheModelName.Length> 0 && _configScope.IsCacheModelsEnabled) { mapStatement = new CachingStatement( mappedStatement); } _configScope.SqlMapper.AddMappedStatement(mappedStatement.Name, mapStatement); } #endregion #region Insert tag Insert insert = null; foreach (XmlNode xmlNode in _configScope.SqlMapDocument.SelectNodes( ApplyMappingNamespacePrefix(XML_INSERT), _configScope.XmlNamespaceManager)) { _configScope.ErrorContext.MoreInfo = "loading insert tag"; _configScope.NodeContext = xmlNode; // A insert tag MappedStatement mappedStatement = null; insert = InsertDeSerializer.Deserialize(xmlNode, _configScope); insert.CacheModelName = ApplyNamespace( insert.CacheModelName ); insert.ParameterMapName = ApplyNamespace( insert.ParameterMapName ); insert.ResultMapName = ApplyNamespace( insert.ResultMapName ); if (_configScope.UseStatementNamespaces == true) { insert.Id = ApplyNamespace(insert.Id); } _configScope.ErrorContext.ObjectId = insert.Id; insert.Initialize( _configScope ); // Build ISql (analyse sql command text) if (insert.Generate != null) { GenerateCommandText(_configScope.SqlMapper, insert); } else { ProcessSqlStatement( insert); } // Build MappedStatement mappedStatement = new InsertMappedStatement( _configScope.SqlMapper, insert); _configScope.SqlMapper.AddMappedStatement(mappedStatement.Name, mappedStatement); #region statement SelectKey // Set sql statement SelectKey if (insert.SelectKey != null) { insert.SelectKey.Id = insert.Id; insert.SelectKey.Initialize( _configScope ); insert.SelectKey.Id += DOT + "SelectKey"; // Initialize can also use _configScope.ErrorContext.ObjectId to get the id // of the parent