2005-06-14 Lluis Sanchez Gual <lluis@novell.com>
[mono.git] / mcs / class / System.Configuration / System.Configuration / SectionGroupInfo.cs
1 //
2 // System.Configuration.SectionGroupInfo.cs
3 //
4 // Authors:
5 //      Lluis Sanchez (lluis@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 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
27 //
28 #if NET_2_0
29 using System;
30 using System.Collections;
31 using System.Collections.Specialized;
32 using System.Xml;
33 using System.IO;
34
35 namespace System.Configuration
36 {
37         internal class SectionGroupInfo: ConfigInfo
38         {
39                 ConfigInfoCollection sections;
40                 ConfigInfoCollection groups;
41                 static ConfigInfoCollection emptyList = new ConfigInfoCollection ();
42
43                 public SectionGroupInfo ()
44                 {
45                         TypeName = "System.Configuration.ConfigurationSectionGroup";
46                 }
47                 
48                 public SectionGroupInfo (string groupName, string typeName)
49                 {
50                         Name = groupName;
51                         TypeName = typeName;
52                 }
53                 
54                 public void AddChild (ConfigInfo data)
55                 {
56                         data.Parent = this;
57                         if (data is SectionInfo) {
58                                 if (sections == null) sections = new ConfigInfoCollection ();
59                                 sections [data.Name] = data;
60                         }
61                         else {
62                                 if (groups == null) groups = new ConfigInfoCollection ();
63                                 groups [data.Name] = data;
64                         }
65                 }
66                 
67                 public void Clear ()
68                 {
69                         if (sections != null) sections.Clear ();
70                         if (groups != null) groups.Clear ();
71                 }
72                 
73                 public bool HasChild (string name)
74                 {
75                         if (sections != null && sections [name] != null) return true;
76                         return (groups != null && groups [name] != null);
77                 }
78                 
79                 public void RemoveChild (string name)
80                 {
81                         if (sections != null)
82                                 sections.Remove (name);
83                         if (groups != null)
84                                 groups.Remove (name);
85                 }
86                 
87                 public SectionInfo GetChildSection (string name)
88                 {
89                         if (sections != null)
90                                 return sections [name] as SectionInfo;
91                         else
92                                 return null;
93                 }
94                 
95                 public SectionGroupInfo GetChildGroup (string name)
96                 {
97                         if (groups != null)
98                                 return groups [name] as SectionGroupInfo;
99                         else
100                                 return null;
101                 }
102                 
103                 public ConfigInfoCollection Sections
104                 {
105                         get { if (sections == null) return emptyList; else return sections; }
106                 }
107                 
108                 public ConfigInfoCollection Groups
109                 {
110                         get { if (groups == null) return emptyList; else return groups; }
111                 }
112                 
113                 public override bool HasDataContent (Configuration config)
114                 {
115                         foreach (ConfigInfoCollection col in new object[] {Sections, Groups}) {
116                                 foreach (string key in col) {
117                                         ConfigInfo cinfo = col [key];
118                                         if (cinfo.HasDataContent (config))
119                                                 return true;
120                                 }
121                         }
122                         return false;
123                 }
124                 
125                 public override bool HasConfigContent (Configuration cfg)
126                 {
127                         if (FileName == cfg.FileName) return true;
128                         foreach (ConfigInfoCollection col in new object[] {Sections, Groups}) {
129                                 foreach (string key in col) {
130                                         ConfigInfo cinfo = col [key];
131                                         if (cinfo.HasConfigContent (cfg))
132                                                 return true;
133                                 }
134                         }
135                         return false;
136                 }
137                 
138                 public override void ReadConfig (Configuration cfg, XmlTextReader reader)
139                 {
140                         FileName = cfg.FileName;
141                         
142                         if (reader.LocalName != "configSections")
143                         {
144                                 while (reader.MoveToNextAttribute ()) {
145                                         if (reader.Name == "name")
146                                                 Name = reader.Value;
147                                         else if (reader.Name == "type")
148                                                 TypeName = reader.Value;
149                                         else
150                                                 ThrowException ("Unrecognized attribute", reader);
151                                 }
152                                 
153                                 if (Name == null)
154                                         ThrowException ("sectionGroup must have a 'name' attribute", reader);
155         
156                                 if (Name == "location")
157                                         ThrowException ("location is a reserved section name", reader);
158                         }
159                         
160                         if (TypeName == null)
161                                 TypeName = "System.Configuration.ConfigurationSectionGroup";
162                         
163                         if (reader.IsEmptyElement) {
164                                 reader.Skip ();
165                                 return;
166                         }
167                         
168                         reader.ReadStartElement ();
169                         reader.MoveToContent ();
170                         
171                         while (reader.NodeType != XmlNodeType.EndElement)
172                         {
173                                 if (reader.NodeType != XmlNodeType.Element) {
174                                         reader.Skip ();
175                                         continue;
176                                 }
177                                 
178                                 string name = reader.LocalName;
179                                 ConfigInfo cinfo = null;
180                                 
181                                 if (name == "remove") {
182                                         ReadRemoveSection (reader);
183                                         continue;
184                                 }
185
186                                 if (name == "clear") {
187                                         if (reader.HasAttributes)
188                                                 ThrowException ("Unrecognized attribute.", reader);
189
190                                         Clear ();
191                                         reader.Skip ();
192                                         continue;
193                                 }
194
195                                 if (name == "section")
196                                         cinfo = new SectionInfo ();
197                                 else if (name == "sectionGroup")
198                                         cinfo = new SectionGroupInfo ();
199                                 else
200                                         ThrowException ("Unrecognized element: " + reader.Name, reader);
201                                         
202                                 cinfo.ReadConfig (cfg, reader);
203                                 ConfigInfo actInfo = Groups [cinfo.Name];
204                                 if (actInfo == null) actInfo = Sections [cinfo.Name];
205                                 
206                                 if (actInfo != null) {
207                                         if (actInfo.GetType () != cinfo.GetType ())
208                                                 ThrowException ("A section or section group named '" + cinfo.Name + "' already exists", reader);
209                                         // Make sure that this section is saved in this configuration file:
210                                         actInfo.FileName = cfg.FileName;
211                                 }
212                                 else
213                                         AddChild (cinfo);
214                         }
215                         
216                         reader.ReadEndElement ();
217                 }
218                 
219                 public override void WriteConfig (Configuration cfg, XmlWriter writer, ConfigurationUpdateMode mode)
220                 {
221                         if (Name != null) {
222                                 writer.WriteStartElement ("sectionGroup");
223                                 writer.WriteAttributeString ("name", Name);
224                                 if (TypeName != null && TypeName != "" && TypeName != "System.Configuration.ConfigurationSectionGroup")
225                                         writer.WriteAttributeString ("type", TypeName);
226                         }
227                         else
228                                 writer.WriteStartElement ("configSections");
229                         
230                         foreach (ConfigInfoCollection col in new object[] {Sections, Groups}) {
231                                 foreach (string key in col) {
232                                         ConfigInfo cinfo = col [key];
233                                         if (cinfo.HasConfigContent (cfg))
234                                                 cinfo.WriteConfig (cfg, writer, mode);
235                                 }
236                         }
237                         
238                         writer.WriteEndElement ();
239                 }
240
241                 private void ReadRemoveSection (XmlTextReader reader)
242                 {
243                         if (!reader.MoveToNextAttribute () || reader.Name != "name")
244                                 ThrowException ("Unrecognized attribute.", reader);
245
246                         string removeValue = reader.Value;
247                         if (removeValue == null || removeValue.Length == 0)
248                                 ThrowException ("Empty name to remove", reader);
249
250                         reader.MoveToElement ();
251
252                         if (!HasChild (removeValue))
253                                 ThrowException ("No factory for " + removeValue, reader);
254
255                         RemoveChild (removeValue);
256                         reader.Skip ();
257                 }
258
259                 public void ReadRootData (XmlTextReader reader, Configuration config)
260                 {
261                         reader.MoveToContent ();
262                         ReadContent (reader, config);
263                 }
264                 
265                 public override void ReadData (Configuration config, XmlTextReader reader)
266                 {
267                         reader.MoveToContent ();
268                         reader.ReadStartElement ();
269                         ReadContent (reader, config);
270                         reader.MoveToContent ();
271                         reader.ReadEndElement ();
272                 }
273                 
274                 void ReadContent (XmlTextReader reader, Configuration config)
275                 {
276                         while (reader.NodeType != XmlNodeType.EndElement) {
277                                 if (reader.NodeType != XmlNodeType.Element) {
278                                         reader.Skip ();
279                                         continue;
280                                 }
281                                 if (reader.LocalName == "location") {
282                                         Configuration locConfig = new Configuration (config);
283                                         string path = reader.GetAttribute ("path");
284                                         ConfigurationLocation loc = new ConfigurationLocation (path, locConfig);
285                                         config.Locations.Add (loc);
286                                         ReadData (locConfig, reader);
287                                 }
288                                 
289                                 ConfigInfo data = (sections != null) ? (ConfigInfo) sections [reader.LocalName] : (ConfigInfo) null;
290                                 if (data == null) data = (groups != null) ? (ConfigInfo) groups [reader.LocalName] : (ConfigInfo) null;
291                                 
292                                 if (data != null)
293                                         data.ReadData (config, reader);
294                                 else
295                                         ThrowException ("Unrecognized configuration section <" + reader.LocalName + ">", reader);
296                         }
297                 }
298                 
299                 public void WriteRootData (XmlWriter writer, Configuration config, ConfigurationUpdateMode mode)
300                 {
301                         WriteContent (writer, config, mode, false);
302                 }
303                 
304                 public override void WriteData (Configuration config, XmlWriter writer, ConfigurationUpdateMode mode)
305                 {
306                         writer.WriteStartElement (Name);
307                         WriteContent (writer, config, mode, true);
308                         writer.WriteEndElement ();
309                 }
310                 
311                 public void WriteContent (XmlWriter writer, Configuration config, ConfigurationUpdateMode mode, bool writeElem)
312                 {
313                         foreach (ConfigInfoCollection col in new object[] {Sections, Groups}) {
314                                 foreach (string key in col) {
315                                         ConfigInfo cinfo = col [key];
316                                         if (cinfo.HasDataContent (config))
317                                                 cinfo.WriteData (config, writer, mode);
318                                 }
319                         }
320                 }
321         }
322         
323         internal class ConfigInfoCollection : NameObjectCollectionBase
324         {
325                 public ICollection AllKeys
326                 {
327                         get { return Keys; }
328                 }
329                 
330                 public ConfigInfo this [string name]
331                 {
332                         get { return (ConfigInfo) BaseGet (name); }
333                         set { BaseSet (name, value); }
334                 }
335         
336                 public ConfigInfo this [int index]
337                 {
338                         get { return (ConfigInfo) BaseGet (index); }
339                         set { BaseSet (index, value); }
340                 }
341                 
342                 public void Add (string name, ConfigInfo config)
343                 {
344                         BaseAdd (name, config);
345                 }
346                 
347                 public void Clear ()
348                 {
349                         BaseClear ();
350                 }
351                 
352                 public string GetKey (int index)
353                 {
354                         return BaseGetKey (index);
355                 }
356                 
357                 public void Remove (string name)
358                 {
359                         BaseRemove (name);
360                 }
361                 
362                 public void RemoveAt (int index)
363                 {
364                         BaseRemoveAt (index);
365                 }
366         }
367 }
368
369 #endif