Added container accessor to Castle.Core
[castle.git] / InversionOfControl / Castle.MicroKernel / SubSystems / Naming / BinaryTreeComponentName.cs
blobb16036b32e6e7a1e85ef7cd0284990d3b445d1f6
1 // Copyright 2004-2007 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.MicroKernel.SubSystems.Naming
17 using System;
18 using System.Collections;
20 [Serializable]
21 public class BinaryTreeComponentName
23 private TreeNode root;
24 private int count;
26 public BinaryTreeComponentName()
30 public int Count
32 get { return count; }
35 public IHandler[] Handlers
37 get
39 ArrayList list = new ArrayList();
40 Visit(root, list);
41 return (IHandler[])list.ToArray(typeof(IHandler));
45 public bool Contains(ComponentName name)
47 return FindNode(name) != null;
50 public void Remove(ComponentName name)
52 Remove(FindNode(name));
55 public void Add(ComponentName name, IHandler handler)
57 if (root == null)
59 root = new TreeNode(name, handler);
60 count++;
61 return;
64 TreeNode current = root;
66 while (true)
68 int cmp = String.Compare(current.CompName.Service, name.Service);
70 if (cmp < 0)
72 if (current.Left != null)
74 current = current.Left;
76 else
78 current.Left = new TreeNode(name, handler);
79 count++;
80 break;
83 else if (cmp > 0)
85 if (current.Right != null)
87 current = current.Right;
89 else
91 current.Right = new TreeNode(name, handler);
92 count++;
93 break;
96 else
98 current.AddSibling(new TreeNode(name, handler));
99 count++;
100 break;
105 public IHandler GetHandler(ComponentName name)
107 TreeNode node = FindNode(name);
109 return node != null ? node.Handler : null;
112 public IHandler[] GetHandlers(ComponentName name)
114 TreeNode node = FindNode(name);
116 if (node != null)
118 ArrayList list = new ArrayList();
120 list.Add(node.Handler);
122 while (node.NextSibling != null)
124 node = node.NextSibling.FindBestMatch(name);
126 list.Add(node.Handler);
129 return (IHandler[])list.ToArray(typeof(IHandler));
132 return null;
135 internal void Visit(TreeNode node, ArrayList list)
137 if (node == null) return;
139 list.Add(node.Handler);
141 if (node.Left != null)
143 Visit(node.Left, list);
145 if (node.Right != null)
147 Visit(node.Right, list);
150 while (node.NextSibling != null)
152 list.Add(node.NextSibling.Handler);
153 node = node.NextSibling;
157 internal TreeNode FindNode(ComponentName name)
159 if (root == null) return null;
161 TreeNode current = root;
163 while (true)
165 int cmp = String.Compare(current.CompName.Service, name.Service);
167 if (cmp < 0)
169 if (current.Left != null)
171 current = current.Left;
173 else
175 return null;
178 else if (cmp > 0)
180 if (current.Right != null)
182 current = current.Right;
184 else
186 return null;
189 else
191 return current.FindBestMatch(name);
196 private void Remove(TreeNode node)
198 if (node == null) return;
200 //A real tree node (this should be better indicated, there is really two types of nodes here)
201 if (node.PreviousSibling == null)
203 if (node.NextSibling != null)
205 TreeNode replacement = node.NextSibling;
206 replacement.PreviousSibling = null;
207 PromoteNode(node, replacement);
209 else
211 RemoveBinaryTreeNode(node);
214 else
215 node.PreviousSibling.NextSibling = node.NextSibling;
217 count--;
220 /// <summary>
221 /// Method finds the next biggest node
222 /// It assumes Add puts lesser nodes on the right
223 /// </summary>
224 private TreeNode FindSuccessor(TreeNode node)
226 TreeNode current = node.Left;
227 if (current != null)
229 while (current.Right != null)
231 current = current.Right;
235 return current;
238 private void PromoteNode(TreeNode oldNode, TreeNode promoted)
240 if (promoted.Right != null || promoted.Left != null)
241 throw new InvalidOperationException("promoted node can not have child nodes, remove node from tree before promoting");
243 promoted.Right = oldNode.Right;
244 promoted.Left = oldNode.Left;
246 if (root == oldNode)
247 root = promoted;
248 else
249 ReplaceNode(oldNode, promoted);
252 private void ReplaceNode(TreeNode oldNode, TreeNode newNode)
254 TreeNode parent = oldNode.Parent;
255 if (parent == null)
257 root = newNode;
259 else if (parent.Right == oldNode)
261 parent.Right = newNode;
263 else if (parent.Left == oldNode)
265 parent.Left = newNode;
268 //throw if wanted
271 private void RemoveBinaryTreeNode(TreeNode node)
273 if (node.Left != null && node.Right != null)
275 TreeNode inorderSuccessor = FindSuccessor(node);
276 RemoveBinaryTreeNode(inorderSuccessor); //it has maximum one node to reorder
277 PromoteNode(node, inorderSuccessor);
279 else if (node.Left == null && node.Right == null)
281 ReplaceNode(node, null);
283 else if (node.Left != null)
285 ReplaceNode(node, node.Left);
286 node.Left = null;
288 else if (node.Right != null)
290 ReplaceNode(node, node.Right);
291 node.Right = null;
297 [Serializable]
298 internal class TreeNode
300 private ComponentName compName;
301 private IHandler handler;
303 /// <summary>Node's left</summary>
304 private TreeNode left;
306 /// <summary>Node's right</summary>
307 private TreeNode right;
309 /// <summary>Node's parent</summary>
310 private TreeNode parent;
312 /// <summary>DA Linked List</summary>
313 private TreeNode nextSibling;
314 private TreeNode previousSibling;
316 public TreeNode(ComponentName compName, IHandler handler)
318 if (compName == null) throw new ArgumentNullException("compName");
319 if (handler == null) throw new ArgumentNullException("handler");
321 this.compName = compName;
322 this.handler = handler;
325 public ComponentName CompName
327 get { return compName; }
330 public IHandler Handler
332 get { return handler; }
335 public TreeNode Parent
337 get { return parent; }
338 set { parent = value; }
341 public TreeNode Left
343 get { return left; }
346 left = value;
347 if (left != null)
349 left.Parent = this;
354 public TreeNode Right
356 get { return right; }
359 right = value;
360 if (right != null)
362 right.Parent = this;
367 public TreeNode NextSibling
369 get { return nextSibling; }
372 nextSibling = value;
373 if (nextSibling != null) nextSibling.PreviousSibling = this;
377 public TreeNode PreviousSibling
379 get { return previousSibling; }
380 set { previousSibling = value; }
384 public void AddSibling(TreeNode node)
386 if (NextSibling == null)
388 NextSibling = node; return;
391 TreeNode current = NextSibling;
393 while (current.NextSibling != null)
395 current = current.NextSibling;
398 current.NextSibling = node;
401 public TreeNode FindBestMatch(ComponentName name)
403 if ("*".Equals(name.LiteralProperties))
405 return this;
407 else if (name.LiteralProperties == null || name.LiteralProperties == string.Empty)
409 return FindWithEmptyProperties();
411 else
413 return FindBestMatchByProperties(name);
417 private TreeNode FindWithEmptyProperties()
419 TreeNode current = this;
421 while (current != null)
423 if (current.CompName.LiteralProperties == null || current.CompName.LiteralProperties == string.Empty)
425 return current;
428 current = current.NextSibling;
431 return this;
434 private TreeNode FindBestMatchByProperties(ComponentName name)
436 TreeNode current = this;
438 while (current != null)
440 bool selected = true;
442 foreach (DictionaryEntry entry in name.Properties)
444 String value = current.CompName.Properties[entry.Key] as String;
446 if (value == null || !value.Equals(entry.Value))
448 selected = false;
449 break;
453 if (selected) break;
455 current = current.NextSibling;
458 return current;