2008-05-12 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.Xml.Linq / System.Xml.Linq / XContainer.cs
1 //
2 // Authors:
3 //   Atsushi Enomoto
4 //
5 // Copyright 2007 Novell (http://www.novell.com)
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining
8 // a copy of this software and associated documentation files (the
9 // "Software"), to deal in the Software without restriction, including
10 // without limitation the rights to use, copy, modify, merge, publish,
11 // distribute, sublicense, and/or sell copies of the Software, and to
12 // permit persons to whom the Software is furnished to do so, subject to
13 // the following conditions:
14 // 
15 // The above copyright notice and this permission notice shall be
16 // included in all copies or substantial portions of the Software.
17 // 
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 //
26
27 using System;
28 using System.Collections;
29 using System.Collections.Generic;
30 using System.IO;
31 using System.Text;
32 using System.Xml;
33
34 namespace System.Xml.Linq
35 {
36         public abstract class XContainer : XNode
37         {
38                 internal XContainer ()
39                 {
40                 }
41
42                 XNode first;
43                 XNode last;
44
45                 public XNode FirstNode {
46                         get { return first; }
47                         internal set { first = value; }
48                 }
49
50                 public XNode LastNode {
51                         get { return last; }
52                         internal set { last = value; }
53                 }
54
55                 void CheckChildType (object o, bool addFirst)
56                 {
57                         if (o == null || o is string || o is XNode)
58                                 return;
59                         if (o is IEnumerable) {
60                                 foreach (object oc in ((IEnumerable) o))
61                                         CheckChildType (oc, addFirst);
62                                 return;
63                         }
64                         else
65                                 throw new ArgumentException ("Invalid child type: " + o.GetType ());
66                 }
67
68 /*
69                 private void AddAttribute (XAttribute attr)
70                 {
71                         if (this is XElement)
72                                 ((XElement) this).SetAttributeNode (attr);
73                         else
74                                 throw new ArgumentException ("Attribute is not allowed here.");
75                 }
76 */
77
78                 public void Add (object content)
79                 {
80                         if (content == null)
81                                 return;
82
83                         foreach (object o in XUtil.ExpandArray (content))
84                                 if (!OnAddingObject (o))
85                                         foreach (XNode n in XUtil.ToNodes (o))
86                                                 AddNode (n);
87                 }
88
89                 void AddNode (XNode n)
90                 {
91                         CheckChildType (n, false);
92                         OnAdded (n, false);
93                         n.SetOwner (this);
94                         if (first == null)
95                                 last = first = n;
96                         else {
97                                 last.NextNode = n;
98                                 n.PreviousNode = last;
99                                 last = n;
100                         }
101                 }
102
103                 public void Add (params object [] content)
104                 {
105                         if (content == null)
106                                 return;
107                         foreach (object o in XUtil.ExpandArray (content))
108                                 Add (o);
109                 }
110
111                 public void AddFirst (object content)
112                 {
113                         if (first == null)
114                                 Add (content);
115                         else
116                                 AddFirst (XUtil.ExpandArray (content));
117                 }
118
119                 public void AddFirst (params object [] content)
120                 {
121                         if (content == null)
122                                 return;
123                         if (first == null)
124                                 Add (content);
125                         else
126                                 foreach (object o in XUtil.ExpandArray (content))
127                                         if (!OnAddingObject (o))
128                                                 first.AddBeforeSelf (o);
129                 }
130
131                 internal virtual bool OnAddingObject (object o)
132                 {
133                         return false;
134                 }
135
136                 public XmlWriter CreateWriter ()
137                 {
138                         return new XNodeWriter (this);
139                 }
140
141                 public IEnumerable <XNode> Nodes ()
142                 {
143                         XNode next;
144                         for (XNode n = FirstNode; n != null; n = next) {
145                                 next = n.NextNode;
146                                 yield return n;
147                         }
148                 }
149
150                 public IEnumerable<XNode> DescendantNodes ()
151                 {
152                         foreach (XNode n in Nodes ()) {
153                                 yield return n;
154                                 XContainer c = n as XContainer;
155                                 if (c != null)
156                                         foreach (XNode d in c.DescendantNodes ())
157                                                 yield return d;
158                         }
159                 }
160
161                 public IEnumerable <XElement> Descendants ()
162                 {
163                         foreach (XNode n in DescendantNodes ()) {
164                                 XElement el = n as XElement;
165                                 if (el != null)
166                                         yield return el;
167                         }
168                 }
169
170                 public IEnumerable <XElement> Descendants (XName name)
171                 {
172                         foreach (XElement el in Descendants ())
173                                 if (el.Name == name)
174                                         yield return el;
175                 }
176
177                 public IEnumerable <XElement> Elements ()
178                 {
179                         foreach (XNode n in Nodes ()) {
180                                 XElement el = n as XElement;
181                                 if (el != null)
182                                         yield return el;
183                         }
184                 }
185
186                 public IEnumerable <XElement> Elements (XName name)
187                 {
188                         foreach (XElement el in Elements ())
189                                 if (el.Name == name)
190                                         yield return el;
191                 }
192
193                 public XElement Element (XName name)
194                 {
195                         foreach (XElement el in Elements ())
196                                 if (el.Name == name)
197                                         return el;
198                         return null;
199                 }
200
201                 internal void ReadContentFrom (XmlReader reader, LoadOptions options)
202                 {
203                         while (!reader.EOF) {
204                                 if (reader.NodeType == XmlNodeType.EndElement)
205                                         // end of the element.
206                                         break;
207                                 Add (XNode.ReadFrom (reader, options));
208                         }
209                 }
210
211                 public void RemoveNodes ()
212                 {
213                         foreach (XNode n in Nodes ())
214                                 n.Remove ();
215                 }
216
217                 public void ReplaceNodes (object content)
218                 {
219                         RemoveNodes ();
220                         Add (content);
221                 }
222
223                 public void ReplaceNodes (params object [] content)
224                 {
225                         RemoveNodes ();
226                         Add (content);
227                 }
228
229                 /*
230                 public void WriteContentTo (XmlWriter writer)
231                 {
232                         foreach (object o in Content ()) {
233                                 if (o is string)
234                                         writer.WriteString ((string) o);
235                                 else if (o is XNode)
236                                         ((XNode) o).WriteTo (writer);
237                                 else
238                                         throw new SystemException ("INTERNAL ERROR: list content item was " + o.GetType ());
239                         }
240                 }
241                 */
242         }
243 }