/Source/Mbs.Castle/Configuration/DefaultXmlProcessorEngine.cs

# · C# · 197 lines · 155 code · 31 blank · 11 comment · 21 complexity · 274bf92224717a9a6c63e28be7f73ce9 MD5 · raw file

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Specialized;
  4. using System.Text.RegularExpressions;
  5. using System.Xml;
  6. using Castle.Core.Resource;
  7. using Castle.MicroKernel.SubSystems.Resource;
  8. namespace Mbs.CastleContainer
  9. {
  10. class DefaultXmlProcessorEngine : IXmlProcessorEngine
  11. {
  12. private readonly Regex flagPattern = new Regex(@"^(\w|_)+$");
  13. private readonly IDictionary properties = new HybridDictionary();
  14. private readonly IDictionary flags = new HybridDictionary();
  15. private readonly Stack resourceStack = new Stack();
  16. private readonly Hashtable nodeProcessors = new Hashtable();
  17. private readonly IXmlNodeProcessor defaultElementProcessor;
  18. private IResourceSubSystem resourseSubSystem;
  19. public DefaultXmlProcessorEngine()
  20. : this(new DefaultResourceSubSystem())
  21. {
  22. }
  23. public DefaultXmlProcessorEngine(IResourceSubSystem resourceSubSystem)
  24. {
  25. this.resourseSubSystem = resourceSubSystem;
  26. defaultElementProcessor = new DefaultElementProcessor();
  27. }
  28. public void AddNodeProcessor(Type type)
  29. {
  30. if (typeof(IXmlNodeProcessor).IsAssignableFrom(type))
  31. {
  32. IXmlNodeProcessor processor = Activator.CreateInstance(type) as IXmlNodeProcessor;
  33. foreach (XmlNodeType nodeType in processor.AcceptNodeTypes)
  34. {
  35. RegisterProcessor(nodeType, processor);
  36. }
  37. }
  38. else
  39. {
  40. throw new XmlProcessorException("{0} does not implement IElementProcessor interface", type.FullName);
  41. }
  42. }
  43. /// <summary>
  44. /// Processes the element.
  45. /// </summary>
  46. /// <param name="nodeList">The element.</param>
  47. /// <returns></returns>
  48. public void DispatchProcessAll(IXmlProcessorNodeList nodeList)
  49. {
  50. while (nodeList.MoveNext())
  51. {
  52. DispatchProcessCurrent(nodeList);
  53. }
  54. }
  55. /// <summary>
  56. /// Processes the element.
  57. /// </summary>
  58. /// <param name="nodeList">The element.</param>
  59. /// <returns></returns>
  60. public void DispatchProcessCurrent(IXmlProcessorNodeList nodeList)
  61. {
  62. IXmlNodeProcessor processor = GetProcessor(nodeList.Current);
  63. if (processor != null)
  64. {
  65. processor.Process(nodeList, this);
  66. }
  67. }
  68. private IXmlNodeProcessor GetProcessor(XmlNode node)
  69. {
  70. IXmlNodeProcessor processor = null;
  71. IDictionary processors = nodeProcessors[node.NodeType] as IDictionary;
  72. if (processors != null)
  73. {
  74. processor = processors[node.Name] as IXmlNodeProcessor;
  75. // sometime nodes with the same name will not accept a processor
  76. if (processor == null || !processor.Accept(node))
  77. {
  78. if (node.NodeType == XmlNodeType.Element)
  79. {
  80. processor = defaultElementProcessor;
  81. }
  82. }
  83. }
  84. return processor;
  85. }
  86. private void RegisterProcessor(XmlNodeType type, IXmlNodeProcessor processor)
  87. {
  88. if (!nodeProcessors.Contains(type))
  89. {
  90. nodeProcessors[type] = new Hashtable();
  91. }
  92. IDictionary typeProcessors = nodeProcessors[type] as IDictionary;
  93. if (typeProcessors.Contains(processor.Name))
  94. {
  95. throw new XmlProcessorException("There is already a processor register for {0} with name {1} ", type, processor.Name);
  96. }
  97. else
  98. {
  99. typeProcessors.Add(processor.Name, processor);
  100. }
  101. }
  102. public bool HasFlag(string flag)
  103. {
  104. return flags.Contains(GetCanonicalFlagName(flag));
  105. }
  106. public void AddFlag(string flag)
  107. {
  108. flags[GetCanonicalFlagName(flag)] = true;
  109. }
  110. public void RemoveFlag(string flag)
  111. {
  112. flags.Remove(GetCanonicalFlagName(flag));
  113. }
  114. public void PushResource(IResource resource)
  115. {
  116. resourceStack.Push(resource);
  117. }
  118. public void PopResource()
  119. {
  120. resourceStack.Pop();
  121. }
  122. public bool HasSpecialProcessor(XmlNode node)
  123. {
  124. return GetProcessor(node) != defaultElementProcessor;
  125. }
  126. public IResource GetResource(String uri)
  127. {
  128. IResource resource = resourceStack.Count > 0 ? resourceStack.Peek() as IResource : null;
  129. if (uri.IndexOf(Uri.SchemeDelimiter) != -1)
  130. {
  131. return resource == null ? resourseSubSystem.CreateResource(uri) :
  132. resourseSubSystem.CreateResource(uri, resource.FileBasePath);
  133. }
  134. else if (resourceStack.Count > 0)
  135. {
  136. return resource.CreateRelative(uri);
  137. }
  138. else
  139. {
  140. throw new XmlProcessorException("Cannot get relative resource '" + uri + "', resource stack is empty");
  141. }
  142. }
  143. public void AddProperty(XmlElement content)
  144. {
  145. properties[content.Name] = content;
  146. }
  147. public bool HasProperty(String name)
  148. {
  149. return properties.Contains(name);
  150. }
  151. public XmlElement GetProperty(string key)
  152. {
  153. XmlElement prop = properties[key] as XmlElement;
  154. return prop == null ? null : prop.CloneNode(true) as XmlElement;
  155. }
  156. private string GetCanonicalFlagName(string flag)
  157. {
  158. flag = flag.Trim().ToLower();
  159. if (!flagPattern.IsMatch(flag))
  160. {
  161. throw new XmlProcessorException("Invalid flag name '{0}'", flag);
  162. }
  163. return flag;
  164. }
  165. }
  166. }