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
.Components
.Binder
18 using System
.Collections
.Specialized
;
24 public class TreeBuilder
26 public CompositeNode
BuildSourceNode(NameValueCollection nameValueCollection
)
28 CompositeNode root
= new CompositeNode("root");
30 PopulateTree(root
, nameValueCollection
);
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]);
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]);
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
)
94 if (name
[0] == '.' || name
[0] == '[' || name
[0] == ']')
96 AddLeafNode(node
, type
, name
, value);
100 int dotIndex
= name
.IndexOf('.');
101 int startBracketIndex
= name
.IndexOf('[');
103 if (dotIndex
!= -1 && (startBracketIndex
== -1 || dotIndex
< startBracketIndex
))
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)
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);
141 name
= name
.Substring(endBracket
+ 2); // entries like customer[0].name = value
143 newNode
= GetOrCreateCompositeNode(newNode
, enclosed
);
145 ProcessNode(newNode
, type
, name
, value);
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
);
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
);
195 node
= new IndexedNode(nodeName
);
196 parent
.AddChildNode(node
);
199 return (IndexedNode
) node
;