More working tests.
[castle.git] / InversionOfControl / Castle.Windsor / Configuration / Interpreters / XmlProcessor / DefaultXmlProcessorEngine.cs
blob08f0d338d382497bb0c8d83d0e937435ac134921
1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle.Windsor.Configuration.Interpreters.XmlProcessor
17 using System;
18 using System.Collections;
19 using System.Collections.Specialized;
20 using System.Text.RegularExpressions;
21 using System.Xml;
23 using Castle.MicroKernel.SubSystems.Resource;
24 using Castle.Core.Resource;
26 using ElementProcessors;
28 public class DefaultXmlProcessorEngine : IXmlProcessorEngine
30 private readonly Regex flagPattern = new Regex(@"^(\w|_)+$");
31 private readonly IDictionary properties = new HybridDictionary();
32 private readonly IDictionary flags = new HybridDictionary();
33 private readonly Stack resourceStack = new Stack();
34 private readonly Hashtable nodeProcessors = new Hashtable();
35 private readonly IXmlNodeProcessor defaultElementProcessor;
36 private IResourceSubSystem resourceSubSystem;
38 /// <summary>
39 /// Initializes a new instance of the <see cref="DefaultXmlProcessorEngine"/> class.
40 /// </summary>
41 /// <param name="environmentName">Name of the environment.</param>
42 public DefaultXmlProcessorEngine(string environmentName) : this(environmentName, new DefaultResourceSubSystem())
46 /// <summary>
47 /// Initializes a new instance of the <see cref="DefaultXmlProcessorEngine"/> class.
48 /// </summary>
49 /// <param name="environmentName">Name of the environment.</param>
50 /// <param name="resourceSubSystem">The resource sub system.</param>
51 public DefaultXmlProcessorEngine(string environmentName, IResourceSubSystem resourceSubSystem)
53 AddEnvNameAsFlag(environmentName);
54 this.resourceSubSystem = resourceSubSystem;
55 defaultElementProcessor = new DefaultElementProcessor();
58 public void AddNodeProcessor(Type type)
60 if (typeof(IXmlNodeProcessor).IsAssignableFrom(type))
62 IXmlNodeProcessor processor = Activator.CreateInstance(type) as IXmlNodeProcessor;
64 foreach(XmlNodeType nodeType in processor.AcceptNodeTypes)
66 RegisterProcessor(nodeType, processor);
69 else
71 throw new XmlProcessorException("{0} does not implement IElementProcessor interface", type.FullName);
75 /// <summary>
76 /// Processes the element.
77 /// </summary>
78 /// <param name="nodeList">The element.</param>
79 /// <returns></returns>
80 public void DispatchProcessAll(IXmlProcessorNodeList nodeList)
82 while(nodeList.MoveNext())
84 DispatchProcessCurrent(nodeList);
88 /// <summary>
89 /// Processes the element.
90 /// </summary>
91 /// <param name="nodeList">The element.</param>
92 /// <returns></returns>
93 public void DispatchProcessCurrent(IXmlProcessorNodeList nodeList)
95 IXmlNodeProcessor processor = GetProcessor(nodeList.Current);
97 if (processor != null)
99 processor.Process(nodeList, this);
103 private IXmlNodeProcessor GetProcessor(XmlNode node)
105 IXmlNodeProcessor processor = null;
106 IDictionary processors = nodeProcessors[node.NodeType] as IDictionary;
108 if (processors != null)
110 processor = processors[node.Name] as IXmlNodeProcessor;
112 // sometimes nodes with the same name will not accept a processor
113 if (processor == null || !processor.Accept(node))
115 if (node.NodeType == XmlNodeType.Element)
117 processor = defaultElementProcessor;
122 return processor;
125 private void RegisterProcessor(XmlNodeType type, IXmlNodeProcessor processor)
127 if (!nodeProcessors.Contains(type))
129 nodeProcessors[type] = new Hashtable();
132 IDictionary typeProcessors = nodeProcessors[type] as IDictionary;
134 if (typeProcessors.Contains(processor.Name))
136 throw new XmlProcessorException("There is already a processor register for {0} with name {1} ", type, processor.Name);
138 else
140 typeProcessors.Add(processor.Name, processor);
144 public bool HasFlag(string flag)
146 return flags.Contains(GetCanonicalFlagName(flag));
149 public void AddFlag(string flag)
151 flags[GetCanonicalFlagName(flag)] = true;
154 public void RemoveFlag(string flag)
156 flags.Remove(GetCanonicalFlagName(flag));
159 public void PushResource(IResource resource)
161 resourceStack.Push(resource);
164 public void PopResource()
166 resourceStack.Pop();
169 public bool HasSpecialProcessor( XmlNode node )
171 return GetProcessor(node) != defaultElementProcessor;
174 public IResource GetResource(String uri)
176 IResource resource = resourceStack.Count > 0 ? resourceStack.Peek() as IResource : null;
178 if (uri.IndexOf(Uri.SchemeDelimiter) != -1)
180 return resource == null ? resourceSubSystem.CreateResource(uri) :
181 resourceSubSystem.CreateResource(uri, resource.FileBasePath);
183 else if (resourceStack.Count > 0)
185 return resource.CreateRelative(uri);
187 else
189 throw new XmlProcessorException("Cannot get relative resource '" + uri + "', resource stack is empty");
193 public void AddProperty(XmlElement content)
195 properties[content.Name] = content;
198 public bool HasProperty(String name)
200 return properties.Contains(name);
203 public XmlElement GetProperty(string key)
205 XmlElement prop = properties[key] as XmlElement;
207 return prop == null ? null : prop.CloneNode(true) as XmlElement;
210 private void AddEnvNameAsFlag(string environmentName)
212 if (environmentName != null)
214 AddFlag(environmentName);
218 private string GetCanonicalFlagName(string flag)
220 flag = flag.Trim().ToLower();
222 if (!flagPattern.IsMatch(flag))
224 throw new XmlProcessorException("Invalid flag name '{0}'", flag);
227 return flag;