diff --git a/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectsNamespaceParser.cs b/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectsNamespaceParser.cs index 9b00a66c..3d4c5174 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectsNamespaceParser.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectsNamespaceParser.cs @@ -1247,7 +1247,7 @@ namespace Spring.Objects.Factory.Xml /// . /// [Obsolete("not used anymore - ObjectsNamespaceParser will be dropped with 2.x, use ObjectDefinitionParserHelper instead", false)] - protected XmlNodeList SelectNodes(XmlElement element, string childElementName) + protected virtual XmlNodeList SelectNodes(XmlElement element, string childElementName) { XmlNamespaceManager nsManager = new XmlNamespaceManager(new NameTable()); nsManager.AddNamespace(GetNamespacePrefix(element), element.NamespaceURI); diff --git a/src/Spring/Spring.Template.Velocity/Template/Velocity/Config/TemplateNamespaceParser.cs b/src/Spring/Spring.Template.Velocity/Template/Velocity/Config/TemplateNamespaceParser.cs index 510fac7b..789aec00 100644 --- a/src/Spring/Spring.Template.Velocity/Template/Velocity/Config/TemplateNamespaceParser.cs +++ b/src/Spring/Spring.Template.Velocity/Template/Velocity/Config/TemplateNamespaceParser.cs @@ -27,6 +27,7 @@ using System.Xml; using NVelocity.Runtime; using NVelocity.Runtime.Resource.Loader; using Spring.Core.TypeResolution; +using Spring.Objects; using Spring.Objects.Factory; using Spring.Objects.Factory.Config; using Spring.Objects.Factory.Support; @@ -39,17 +40,19 @@ using Spring.Util; namespace Spring.Template.Velocity.Config { /// /// Implementation of the custom configuration parser for template configurations + /// based on + /// /// /// Erez Mazor + /// [ NamespaceParser( Namespace = "http://www.springframework.net/nvelocity", SchemaLocationAssemblyHint = typeof(TemplateNamespaceParser), SchemaLocation = "/Spring.Template.Velocity.Config/spring-nvelocity-1.3.xsd") ] - public sealed class TemplateNamespaceParser : AbstractSingleObjectDefinitionParser { + public class TemplateNamespaceParser : ObjectsNamespaceParser { private const string TemplateTypePrefix = "template: "; - private static readonly ObjectNamespaceParserHelper objectNamespaceParserHelper = new ObjectNamespaceParserHelper(); static TemplateNamespaceParser() { TypeRegistry.RegisterType(TemplateTypePrefix + TemplateDefinitionConstants.NVelocityElement, typeof(VelocityEngineFactoryObject)); @@ -61,18 +64,27 @@ namespace Spring.Template.Velocity.Config { public TemplateNamespaceParser() { } + /// + public override IObjectDefinition ParseElement(XmlElement element, ParserContext parserContext) { + string name = element.GetAttribute(ObjectDefinitionConstants.IdAttribute); + IConfigurableObjectDefinition templateDefinition = ParseTemplateDefinition(element, parserContext); + if (!StringUtils.HasText(name)) { + name = ObjectDefinitionReaderUtils.GenerateObjectName(templateDefinition, parserContext.Registry); + } + parserContext.Registry.RegisterObjectDefinition(name, templateDefinition); + return null; + } + /// - /// Parses single object definition for the templating namespace + /// Parse a template definition from the templating namespace /// - /// the current XmlElement to parse + /// the root element defining the templating object /// the parser context - /// the ObjectDefinitionBuilder used to configure this object - /// - protected override void DoParse(XmlElement element, ParserContext parserContext, ObjectDefinitionBuilder builder) { + /// + private IConfigurableObjectDefinition ParseTemplateDefinition(XmlElement element, ParserContext parserContext) { switch (element.LocalName) { case TemplateDefinitionConstants.NVelocityElement: - ParseNVelocityEngine(element, parserContext, builder); - return; + return ParseNVelocityEngine(element, parserContext); default: throw new ArgumentException(string.Format("undefined element for templating namespace: {0}", element.LocalName)); } @@ -84,28 +96,34 @@ namespace Spring.Template.Velocity.Config { /// /// the root element defining the velocity engine /// the parser context - /// the ObjectDefinitionBuilder used to configure this object - private void ParseNVelocityEngine(XmlElement element, ParserContext parserContext, ObjectDefinitionBuilder builder) { + private IConfigurableObjectDefinition ParseNVelocityEngine(XmlElement element, ParserContext parserContext) { + string typeName = GetTypeName(element); + IConfigurableObjectDefinition configurableObjectDefinition = parserContext.ReaderContext.ObjectDefinitionFactory.CreateObjectDefinition( + typeName, null, parserContext.ReaderContext.Reader.Domain); + string preferFileSystemAccess = GetAttributeValue(element, TemplateDefinitionConstants.AttributePreferFileSystemAccess); string overrideLogging = GetAttributeValue(element, TemplateDefinitionConstants.AttributeOverrideLogging); string configFile = GetAttributeValue(element, TemplateDefinitionConstants.AttributeConfigFile); + MutablePropertyValues objectDefinitionProperties = new MutablePropertyValues(); if (StringUtils.HasText(preferFileSystemAccess)) { - builder.AddPropertyValue(TemplateDefinitionConstants.PropertyPreferFileSystemAccess, preferFileSystemAccess); + objectDefinitionProperties.Add(TemplateDefinitionConstants.PropertyPreferFileSystemAccess, preferFileSystemAccess); } if (StringUtils.HasText(overrideLogging)) { - builder.AddPropertyValue(TemplateDefinitionConstants.PropertyOverrideLogging, overrideLogging); + objectDefinitionProperties.Add(TemplateDefinitionConstants.PropertyOverrideLogging, overrideLogging); } if (StringUtils.HasText(configFile)) { - builder.AddPropertyValue(TemplateDefinitionConstants.PropertyConfigFile, configFile); + objectDefinitionProperties.Add(TemplateDefinitionConstants.PropertyConfigFile, configFile); } XmlNodeList childElements = element.ChildNodes; if (childElements.Count > 0) { - ParseChildDefinitions(childElements, parserContext, builder); + ParseChildDefinitions(childElements, parserContext, objectDefinitionProperties); } + configurableObjectDefinition.PropertyValues = objectDefinitionProperties; + return configurableObjectDefinition; } /// @@ -113,14 +131,14 @@ namespace Spring.Template.Velocity.Config { /// /// the XmlNodeList representing the child configuration of the root NVelocity engine element /// the parser context - /// the ObjectDefinitionBuilder used to configure this object - private void ParseChildDefinitions(XmlNodeList childElements, ParserContext parserContext, ObjectDefinitionBuilder builder) { + /// the MutablePropertyValues used to configure this object + private void ParseChildDefinitions(XmlNodeList childElements, ParserContext parserContext, MutablePropertyValues objectDefinitionProperties) { IDictionary properties = new Dictionary(); foreach (XmlElement element in childElements) { switch (element.LocalName) { case TemplateDefinitionConstants.ElementResourceLoader: - ParseResourceLoader(element, builder, properties); + ParseResourceLoader(element, objectDefinitionProperties, properties); break; case TemplateDefinitionConstants.ElementNVelocityProperties: ParseNVelocityProperties(element, parserContext, properties); @@ -129,7 +147,7 @@ namespace Spring.Template.Velocity.Config { } if (properties.Count > 0) { - builder.AddPropertyValue(TemplateDefinitionConstants.PropertyVelocityProperties, properties); + objectDefinitionProperties.Add(TemplateDefinitionConstants.PropertyVelocityProperties, properties); } } @@ -137,9 +155,9 @@ namespace Spring.Template.Velocity.Config { /// Configures the NVelocity resource loader definitions from the xml definition /// /// the root resource loader element - /// the ObjectDefinitionBuilder used to configure this object + /// the MutablePropertyValues used to configure this object /// the properties used to initialize the velocity engine - private void ParseResourceLoader(XmlElement element, ObjectDefinitionBuilder builder, IDictionary properties) { + private void ParseResourceLoader(XmlElement element, MutablePropertyValues objectDefinitionProperties, IDictionary properties) { string caching = GetAttributeValue(element, TemplateDefinitionConstants.AttributeTemplateCaching); string defaultCacheSize = GetAttributeValue(element, TemplateDefinitionConstants.AttributeDefaultCacheSize); string modificationCheckInterval = GetAttributeValue(element, TemplateDefinitionConstants.AttributeModificationCheckInterval); @@ -160,7 +178,7 @@ namespace Spring.Template.Velocity.Config { AppendResourceLoaderGlobalProperties(properties, VelocityConstants.Assembly, caching, null); break; case TemplateDefinitionConstants.Spring: - AppendResourceLoaderPaths(loaderElements, builder); + AppendResourceLoaderPaths(loaderElements, objectDefinitionProperties); AppendResourceLoaderGlobalProperties(properties, TemplateDefinitionConstants.Spring, caching, null); break; case TemplateDefinitionConstants.Custom: @@ -239,14 +257,14 @@ namespace Spring.Template.Velocity.Config { /// attribute). /// /// list of resource loader path elements - /// the object definiton builder to set the property for the engine factory - private void AppendResourceLoaderPaths(XmlNodeList elements, ObjectDefinitionBuilder builder) { + /// the MutablePropertyValues to set the property for the engine factory + private void AppendResourceLoaderPaths(XmlNodeList elements, MutablePropertyValues objectDefinitionProperties) { IList paths = new List(); foreach (XmlElement element in elements) { string path = GetAttributeValue(element, TemplateDefinitionConstants.AttributeUri); paths.Add(path); } - builder.AddPropertyValue(TemplateDefinitionConstants.PropertyResourceLoaderPaths, paths); + objectDefinitionProperties.Add(TemplateDefinitionConstants.PropertyResourceLoaderPaths, paths); } /// @@ -274,7 +292,7 @@ namespace Spring.Template.Velocity.Config { /// the parser context /// the properties used to initialize the velocity engine private void ParseNVelocityProperties(XmlElement element, ParserContext parserContext, IDictionary properties) { - IDictionary parsedProperties = objectNamespaceParserHelper.ParseDictionaryElementInternal(element, + IDictionary parsedProperties = ParseDictionaryElement(element, TemplateDefinitionConstants.ElementNVelocityProperties, parserContext); foreach (DictionaryEntry entry in parsedProperties) { properties.Add(Convert.ToString(entry.Key), entry.Value); @@ -282,11 +300,16 @@ namespace Spring.Template.Velocity.Config { } /// - /// construct the element type name (e.g, nv:engine, nv:resource-loader) + /// Gets the name of the object type for the specified element. /// - /// the current xml element - protected override string GetObjectTypeName(XmlElement element) { - return TemplateTypePrefix + element.LocalName; + /// The element. + /// The name of the object type. + private string GetTypeName(XmlElement element) { + string typeName = element.GetAttribute(ObjectDefinitionConstants.TypeAttribute); + if (StringUtils.IsNullOrEmpty(typeName)) { + return TemplateTypePrefix + element.LocalName; + } + return typeName; } /// @@ -300,253 +323,151 @@ namespace Spring.Template.Velocity.Config { return type + VelocityConstants.Separator + RuntimeConstants.RESOURCE_LOADER + VelocityConstants.Separator + suffix; } - } - - - /// - /// Helper class to access the ParseDictionaryElement of the ObjectsNamespaceParser - /// todo: remove this and externalize the logic in ObjectsNamespaceParser.ParseDictionaryElement - /// - internal class ObjectNamespaceParserHelper : ObjectsNamespaceParser { /// - /// Gets a dictionary definition. + /// This method is overriden from ObjectsNamespaceParser since when invoked on + /// sub-elements from the objets namespace (e.g., objects:objectMap for nvelocity + /// property map) the element.SelectNodes fails because it is in + /// the nvelocity custom namespace and not the object's namespace (http://www.springframwork.net) + /// to amend this the object's namespace is added to the provided XmlNamespaceManager /// - /// The element describing the dictionary definition. - /// The name of the object (definition) associated with the dictionary definition. - /// The namespace-aware parser. - /// The dictionary definition. - public IDictionary ParseDictionaryElementInternal(XmlElement mapEle, string name, ParserContext parserContext) { - ManagedDictionary dictionary = new ManagedDictionary(); - string keyTypeName = GetAttributeValue(mapEle, "key-type"); - string valueTypeName = GetAttributeValue(mapEle, "value-type"); - if (StringUtils.HasText(keyTypeName)) { - dictionary.KeyTypeName = keyTypeName; - } - if (StringUtils.HasText(valueTypeName)) { - dictionary.ValueTypeName = valueTypeName; - } - dictionary.MergeEnabled = ParseMergeAttribute(mapEle, parserContext.ParserHelper); - - XmlNodeList entryElements = SelectNodes(mapEle, ObjectDefinitionConstants.EntryElement); - foreach (XmlElement entryEle in entryElements) { - #region Key - - object key = null; - - XmlAttribute keyAtt = entryEle.Attributes[ObjectDefinitionConstants.KeyAttribute]; - if (keyAtt != null) { - key = keyAtt.Value; - } else { - // ok, we're not using the 'key' attribute; lets check for the ref shortcut... - XmlAttribute keyRefAtt = entryEle.Attributes[ObjectDefinitionConstants.DictionaryKeyRefShortcutAttribute]; - if (keyRefAtt != null) { - key = new RuntimeObjectReference(keyRefAtt.Value); - } else { - // so check for the 'key' element... - XmlNode keyNode = SelectSingleNode(entryEle, ObjectDefinitionConstants.KeyElement); - if (keyNode == null) { - throw new ObjectDefinitionStoreException( - parserContext.ReaderContext.Resource, name, - string.Format("One of either the '{0}' element, or the the '{1}' or '{2}' attributes " + - "is required for the <{3}/> element.", - ObjectDefinitionConstants.KeyElement, - ObjectDefinitionConstants.KeyAttribute, - ObjectDefinitionConstants.DictionaryKeyRefShortcutAttribute, - ObjectDefinitionConstants.EntryElement)); - } - XmlElement keyElement = (XmlElement)keyNode; - XmlNodeList keyNodes = keyElement.GetElementsByTagName("*"); - if (keyNodes == null || keyNodes.Count == 0) { - throw new ObjectDefinitionStoreException( - parserContext.ReaderContext.Resource, name, - string.Format("Malformed <{0}/> element... the value of the key must be " + - "specified as a child value-style element.", - ObjectDefinitionConstants.KeyElement)); - } - key = ParsePropertySubElement((XmlElement)keyNodes.Item(0), name, parserContext); - } - } - - #endregion - - #region Value - - XmlAttribute inlineValueAtt = entryEle.Attributes[ObjectDefinitionConstants.ValueAttribute]; - if (inlineValueAtt != null) { - // ok, we're using the value attribute shortcut... - dictionary[key] = inlineValueAtt.Value; - } else if (entryEle.Attributes[ObjectDefinitionConstants.DictionaryValueRefShortcutAttribute] != null) { - // ok, we're using the value-ref attribute shortcut... - XmlAttribute inlineValueRefAtt = entryEle.Attributes[ObjectDefinitionConstants.DictionaryValueRefShortcutAttribute]; - RuntimeObjectReference ror = new RuntimeObjectReference(inlineValueRefAtt.Value); - dictionary[key] = ror; - } else if (entryEle.Attributes[ObjectDefinitionConstants.ExpressionAttribute] != null) { - // ok, we're using the expression attribute shortcut... - XmlAttribute inlineExpressionAtt = entryEle.Attributes[ObjectDefinitionConstants.ExpressionAttribute]; - ExpressionHolder expHolder = new ExpressionHolder(inlineExpressionAtt.Value); - dictionary[key] = expHolder; - } else { - XmlNode keyNode = SelectSingleNode(entryEle, ObjectDefinitionConstants.KeyElement); - if (keyNode != null) { - entryEle.RemoveChild(keyNode); - } - // ok, we're using the original full-on value element... - XmlNodeList valueElements = entryEle.GetElementsByTagName("*"); - if (valueElements == null || valueElements.Count == 0) { - throw new ObjectDefinitionStoreException( - parserContext.ReaderContext.Resource, name, - string.Format("One of either the '{0}' or '{1}' attributes, or a value-style element " + - "is required for the <{2}/> element.", - ObjectDefinitionConstants.ValueAttribute, ObjectDefinitionConstants.DictionaryValueRefShortcutAttribute, ObjectDefinitionConstants.EntryElement)); - } - dictionary[key] = ParsePropertySubElement((XmlElement)valueElements.Item(0), name, parserContext); - } - - #endregion - } - return dictionary; - } - private bool ParseMergeAttribute(XmlElement collectionElement, ObjectDefinitionParserHelper helper) { - string val = collectionElement.GetAttribute(ObjectDefinitionConstants.MergeAttribute); - if (ObjectDefinitionConstants.DefaultValue.Equals(val)) { - val = helper.Defaults.Merge; - } - return ObjectDefinitionConstants.TrueValue.Equals(val); - } - - /// - /// This method overrides SelectNodes from ObjectsNamespaceParser because the original method - /// picks up the NamespaceURI from the nvelocity which causes element.SelectNodes to return an empty - /// list. Consider removing. - /// - protected new XmlNodeList SelectNodes(XmlElement element, string childElementName) { + /// The element to be searched in. + /// The name of the child nodes to look for. + /// + /// The child s of the supplied + /// with the supplied . + /// + /// + [Obsolete("not used anymore - ObjectsNamespaceParser will be dropped with 2.x, use ObjectDefinitionParserHelper instead")] + protected override XmlNodeList SelectNodes(XmlElement element, string childElementName) { XmlNamespaceManager nsManager = new XmlNamespaceManager(new NameTable()); + nsManager.AddNamespace(GetNamespacePrefix(element), element.NamespaceURI); nsManager.AddNamespace(GetNamespacePrefix(element), Namespace); return element.SelectNodes(GetNamespacePrefix(element) + ":" + childElementName, nsManager); } - private string GetNamespacePrefix(XmlElement element) { return StringUtils.HasText(element.Prefix) ? element.Prefix : "spring"; } } - + + + #region Element & Attribute Name Constants + /// + /// Template definition constants + /// + public class TemplateDefinitionConstants { /// - /// Template definition constants + /// Engine element definition /// - public class TemplateDefinitionConstants { - /// - /// Engine element definition - /// - public const string NVelocityElement = "engine"; + public const string NVelocityElement = "engine"; - /// - /// Spring resource loader element definition - /// - public const string Spring = "spring"; + /// + /// Spring resource loader element definition + /// + public const string Spring = "spring"; - /// - /// Custom resource loader element definition - /// - public const string Custom = "custom"; + /// + /// Custom resource loader element definition + /// + public const string Custom = "custom"; - /// - /// uri attribute of the spring element - /// - public const string AttributeUri = "uri"; + /// + /// uri attribute of the spring element + /// + public const string AttributeUri = "uri"; - /// - /// prefer-file-system-access attribute of the engine factory - /// - public const string AttributePreferFileSystemAccess = "prefer-file-system-access"; + /// + /// prefer-file-system-access attribute of the engine factory + /// + public const string AttributePreferFileSystemAccess = "prefer-file-system-access"; - /// - /// config-file attribute of the engine factory - /// - public const string AttributeConfigFile = "config-file"; + /// + /// config-file attribute of the engine factory + /// + public const string AttributeConfigFile = "config-file"; - /// - /// override-logging attribute of the engine factory - /// - public const string AttributeOverrideLogging = "override-logging"; + /// + /// override-logging attribute of the engine factory + /// + public const string AttributeOverrideLogging = "override-logging"; - /// - /// template-caching attribute of the nvelocity engine - /// - public const string AttributeTemplateCaching = "template-caching"; + /// + /// template-caching attribute of the nvelocity engine + /// + public const string AttributeTemplateCaching = "template-caching"; - /// - /// default-cache-size attribute of the nvelocity engine resource manager - /// - public const string AttributeDefaultCacheSize = "default-cache-size"; + /// + /// default-cache-size attribute of the nvelocity engine resource manager + /// + public const string AttributeDefaultCacheSize = "default-cache-size"; - /// - /// modification-check-interval attribute of the nvelocity engine resource loader - /// - public const string AttributeModificationCheckInterval = "modification-check-interval"; + /// + /// modification-check-interval attribute of the nvelocity engine resource loader + /// + public const string AttributeModificationCheckInterval = "modification-check-interval"; - /// - /// resource loader element - /// - public const string ElementResourceLoader = "resource-loader"; + /// + /// resource loader element + /// + public const string ElementResourceLoader = "resource-loader"; - /// - /// nvelocity propeties element (map) - /// - public const string ElementNVelocityProperties = "nvelocity-properties"; + /// + /// nvelocity propeties element (map) + /// + public const string ElementNVelocityProperties = "nvelocity-properties"; - /// - /// PreferFileSystemAccess property of the engine factory - /// - public const string PropertyPreferFileSystemAccess = "PreferFileSystemAccess"; + /// + /// PreferFileSystemAccess property of the engine factory + /// + public const string PropertyPreferFileSystemAccess = "PreferFileSystemAccess"; - /// - /// OverrideLogging property of the engine factory - /// - public const string PropertyOverrideLogging = "OverrideLogging"; + /// + /// OverrideLogging property of the engine factory + /// + public const string PropertyOverrideLogging = "OverrideLogging"; - /// - /// ConfigLocation property of the engine factory - /// - public const string PropertyConfigFile = "ConfigLocation"; + /// + /// ConfigLocation property of the engine factory + /// + public const string PropertyConfigFile = "ConfigLocation"; - /// - /// ResourceLoaderPaths property of the engine factory - /// - public const string PropertyResourceLoaderPaths = "ResourceLoaderPaths"; + /// + /// ResourceLoaderPaths property of the engine factory + /// + public const string PropertyResourceLoaderPaths = "ResourceLoaderPaths"; - /// - /// VelocityProperties property of the engine factory - /// - public const string PropertyVelocityProperties = "VelocityProperties"; + /// + /// VelocityProperties property of the engine factory + /// + public const string PropertyVelocityProperties = "VelocityProperties"; - /// - /// resource.loader.cache property of the resource loader configuration - /// - public const string PropertyResourceLoaderCaching = "resource.loader.cache"; + /// + /// resource.loader.cache property of the resource loader configuration + /// + public const string PropertyResourceLoaderCaching = "resource.loader.cache"; - /// - /// resource.loader.modificationCheckInterval property of the resource loader configuration - /// - public const string PropertyResourceLoaderModificationCheckInterval = "resource.loader.modificationCheckInterval"; + /// + /// resource.loader.modificationCheckInterval property of the resource loader configuration + /// + public const string PropertyResourceLoaderModificationCheckInterval = "resource.loader.modificationCheckInterval"; - /// - /// the type used for file resource loader - /// - public const string FileResourceLoaderClass = "NVelocity.Runtime.Resource.Loader.FileResourceLoader; NVelocity"; + /// + /// the type used for file resource loader + /// + public const string FileResourceLoaderClass = "NVelocity.Runtime.Resource.Loader.FileResourceLoader; NVelocity"; - /// - /// the type used for assembly resource loader - /// - public const string AssemblyResourceLoaderClass = "NVelocity.Runtime.Resource.Loader.AssemblyResourceLoader; NVelocity"; + /// + /// the type used for assembly resource loader + /// + public const string AssemblyResourceLoaderClass = "NVelocity.Runtime.Resource.Loader.AssemblyResourceLoader; NVelocity"; - /// - /// the type used for spring resource loader - /// - public const string SpringResourceLoaderClass = "Spring.Template.Velocity.SpringResourceLoader; Spring.Template.Velocity"; - } - #endregion + /// + /// the type used for spring resource loader + /// + public const string SpringResourceLoaderClass = "Spring.Template.Velocity.SpringResourceLoader; Spring.Template.Velocity"; + } + #endregion } \ No newline at end of file