#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;
_deSerializerFactory = new DeSerializerFactory(_configScope);
_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.TypeHandlerFactory.AddTypeAlias(cacheAlias.Name, cacheAlias);
cacheAlias = new TypeAlias(typeof(LruCacheController));
cacheAlias.Name = "LRU";
_configScope.SqlMapper.TypeHandlerFactory.AddTypeAlias(cacheAlias.Name, cacheAlias);
cacheAlias = new TypeAlias(typeof(FifoCacheController));
cacheAlias.Name = "FIFO";
_configScope.SqlMapper.TypeHandlerFactory.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.Id + "] 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.Id, 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.Id, 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.Id, 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