1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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
18 using System
.Collections
;
19 using System
.Collections
.Specialized
;
20 using System
.Text
.RegularExpressions
;
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
;
39 /// Initializes a new instance of the <see cref="DefaultXmlProcessorEngine"/> class.
41 /// <param name="environmentName">Name of the environment.</param>
42 public DefaultXmlProcessorEngine(string environmentName
) : this(environmentName
, new DefaultResourceSubSystem())
47 /// Initializes a new instance of the <see cref="DefaultXmlProcessorEngine"/> class.
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
);
71 throw new XmlProcessorException("{0} does not implement IElementProcessor interface", type
.FullName
);
76 /// Processes the element.
78 /// <param name="nodeList">The element.</param>
79 /// <returns></returns>
80 public void DispatchProcessAll(IXmlProcessorNodeList nodeList
)
82 while(nodeList
.MoveNext())
84 DispatchProcessCurrent(nodeList
);
89 /// Processes the element.
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
;
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
);
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()
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
);
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
);