Fixing an issue with output parameters that are of type IntPtr
[castle.git] / Components / Binder / Castle.Components.Binder / TreeBuilder.cs
blob8ea70787684e4517fff774d9e19982c613eb00c1
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.Components.Binder
17 using System;
18 using System.Collections.Specialized;
19 using System.Web;
21 /// <summary>
22 ///
23 /// </summary>
24 public class TreeBuilder
26 public CompositeNode BuildSourceNode(NameValueCollection nameValueCollection)
28 CompositeNode root = new CompositeNode("root");
30 PopulateTree(root, nameValueCollection);
32 return root;
35 public void PopulateTree(CompositeNode root, NameValueCollection nameValueCollection)
37 foreach(String key in nameValueCollection.Keys)
39 if (key == null) continue;
40 string singleKeyName = NormalizeKey(key);
41 String[] values = nameValueCollection.GetValues(key);
43 if (values == null) continue;
45 if (values.Length == 1 && key.EndsWith("[]"))
47 if (values[0] == string.Empty)
49 ProcessNode(root, typeof(String[]), singleKeyName, new string[0]);
51 else
53 values = values[0].Split(',');
54 ProcessNode(root, typeof(String[]), singleKeyName, values);
57 else if (values.Length == 1)
59 ProcessNode(root, typeof(String), key, values[0]);
61 else
63 ProcessNode(root, typeof(String[]), singleKeyName, values);
68 public void PopulateTree(CompositeNode root, HttpFileCollection fileCollection)
70 foreach(String key in fileCollection.Keys)
72 if (key == null) continue;
74 HttpPostedFile value = fileCollection.Get(key);
76 if (value == null) continue;
78 ProcessNode(root, typeof(HttpPostedFile), key, value);
82 private string NormalizeKey(string key)
84 return key.EndsWith("[]") ? key.Substring(0, key.Length - 2) : key;
87 private void ProcessNode(CompositeNode node, Type type, String name, object value)
89 if (name == null || name == String.Empty)
91 // Ignore
92 return;
94 if (name[0] == '.' || name[0] == '[' || name[0] == ']')
96 AddLeafNode(node, type, name, value);
97 return;
100 int dotIndex = name.IndexOf('.');
101 int startBracketIndex = name.IndexOf('[');
103 if (dotIndex != -1 && (startBracketIndex == -1 || dotIndex < startBracketIndex))
105 // Child node
107 String childNodeName = name.Substring(0, dotIndex);
109 CompositeNode newNode = GetOrCreateCompositeNode(node, childNodeName);
111 ProcessNode(newNode, type, name.Substring(dotIndex + 1), value);
113 else if (startBracketIndex != -1)
115 // Indexed node
117 int endBracket = name.IndexOf(']');
119 if (endBracket == -1)
121 // TODO: Something is wrong
124 String enclosed = name.Substring(startBracketIndex + 1, endBracket - startBracketIndex - 1);
126 if (enclosed == null || enclosed == String.Empty)
128 // TODO: Something is wrong
131 String indexedNodeName = name.Substring(0, startBracketIndex);
133 CompositeNode newNode = GetOrCreateIndexedNode(node, indexedNodeName);
135 if (endBracket + 1 == name.Length) // entries like emails[0] = value
137 AddLeafNode(newNode, type, value);
139 else
141 name = name.Substring(endBracket + 2); // entries like customer[0].name = value
143 newNode = GetOrCreateCompositeNode(newNode, enclosed);
145 ProcessNode(newNode, type, name, value);
148 else
150 AddLeafNode(node, type, name, value);
154 private void AddLeafNode(CompositeNode parent, Type type, object value)
156 AddLeafNode(parent, type, String.Empty, value);
159 private void AddLeafNode(CompositeNode parent, Type type, String nodeName, object value)
161 parent.AddChildNode(new LeafNode(type, nodeName, value));
164 private CompositeNode GetOrCreateCompositeNode(CompositeNode parent, string nodeName)
166 Node node = parent.GetChildNode(nodeName);
168 if (node != null && node.NodeType != NodeType.Composite)
170 throw new BindingException("Attempt to create or obtain a composite node " +
171 "named {0}, but a node with the same exists with the type {1}", nodeName, node.NodeType);
174 if (node == null)
176 node = new CompositeNode(nodeName);
177 parent.AddChildNode(node);
180 return (CompositeNode) node;
183 private IndexedNode GetOrCreateIndexedNode(CompositeNode parent, string nodeName)
185 Node node = parent.GetChildNode(nodeName);
187 if (node != null && node.NodeType != NodeType.Indexed)
189 throw new BindingException("Attempt to create or obtain an indexed node " +
190 "named {0}, but a node with the same exists with the type {1}", nodeName, node.NodeType);
193 if (node == null)
195 node = new IndexedNode(nodeName);
196 parent.AddChildNode(node);
199 return (IndexedNode) node;