1 // Copyright 2004-2007 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
.MicroKernel
.SubSystems
.Naming
18 using System
.Collections
;
21 public class BinaryTreeComponentName
23 private TreeNode root
;
26 public BinaryTreeComponentName()
35 public IHandler
[] Handlers
39 ArrayList list
= new ArrayList();
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
)
59 root
= new TreeNode(name
, handler
);
64 TreeNode current
= root
;
68 int cmp
= String
.Compare(current
.CompName
.Service
, name
.Service
);
72 if (current
.Left
!= null)
74 current
= current
.Left
;
78 current
.Left
= new TreeNode(name
, handler
);
85 if (current
.Right
!= null)
87 current
= current
.Right
;
91 current
.Right
= new TreeNode(name
, handler
);
98 current
.AddSibling(new TreeNode(name
, handler
));
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
);
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
));
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
;
165 int cmp
= String
.Compare(current
.CompName
.Service
, name
.Service
);
169 if (current
.Left
!= null)
171 current
= current
.Left
;
180 if (current
.Right
!= null)
182 current
= current
.Right
;
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
);
211 RemoveBinaryTreeNode(node
);
215 node
.PreviousSibling
.NextSibling
= node
.NextSibling
;
221 /// Method finds the next biggest node
222 /// It assumes Add puts lesser nodes on the right
224 private TreeNode
FindSuccessor(TreeNode node
)
226 TreeNode current
= node
.Left
;
229 while (current
.Right
!= null)
231 current
= current
.Right
;
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
;
249 ReplaceNode(oldNode
, promoted
);
252 private void ReplaceNode(TreeNode oldNode
, TreeNode newNode
)
254 TreeNode parent
= oldNode
.Parent
;
259 else if (parent
.Right
== oldNode
)
261 parent
.Right
= newNode
;
263 else if (parent
.Left
== oldNode
)
265 parent
.Left
= newNode
;
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
);
288 else if (node
.Right
!= null)
290 ReplaceNode(node
, node
.Right
);
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; }
354 public TreeNode Right
356 get { return right; }
367 public TreeNode NextSibling
369 get { return nextSibling; }
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
))
407 else if (name
.LiteralProperties
== null || name
.LiteralProperties
== string.Empty
)
409 return FindWithEmptyProperties();
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
)
428 current
= current
.NextSibling
;
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
))
455 current
= current
.NextSibling
;