2004-02-06 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.XML / System.Xml / XmlAttributeCollection.cs
index a434ed72536c709b9e5c180a3fac437f25222ce0..d1d63a20f9db73a030537532a3193aecf0a35e61 100644 (file)
@@ -29,15 +29,11 @@ namespace System.Xml
                }
 
                bool ICollection.IsSynchronized {
-                       get {
-                               throw new NotImplementedException ();
-                       }
+                       get { return false; }
                }
 
                bool IsReadOnly {
-                       get {
-                               return ownerElement.IsReadOnly;
-                       }
+                       get { return ownerElement.IsReadOnly; }
                }
 
                [System.Runtime.CompilerServices.IndexerName ("ItemOf")]
@@ -62,9 +58,7 @@ namespace System.Xml
                }
 
                object ICollection.SyncRoot {
-                       get {
-                               throw new NotImplementedException ();
-                       }
+                       get { return this; }
                }
 
                
@@ -89,58 +83,39 @@ namespace System.Xml
 
                public virtual XmlAttribute InsertAfter (XmlAttribute newNode, XmlAttribute refNode)
                {
-                       if(newNode.OwnerDocument != this.ownerDocument)
-                               throw new ArgumentException ("different document created this newNode.");
-
-                       ownerDocument.onNodeInserting (newNode, null);
-
-                       int pos = Nodes.Count + 1;
-                       if(refNode != null)
-                       {
-                               for(int i=0; i<Nodes.Count; i++)
-                               {
-                                       XmlNode n = Nodes [i] as XmlNode;
-                                       if(n == refNode)
-                                       {
-                                               pos = i + 1;
-                                               break;
-                                       }
-                               }
-                               if(pos > Nodes.Count)
-                                       throw new XmlException ("refNode not found in this collection.");
+                       if (refNode == null) {
+                               if (Nodes.Count == 0)
+                                       return InsertBefore (newNode, null);
+                               else
+                                       return InsertBefore (newNode, this [0]);
                        }
-                       else
-                               pos = 0;
-                       SetNamedItem (newNode, pos);
-
-                       ownerDocument.onNodeInserted (newNode, null);
+                       for (int i = 0; i < Nodes.Count; i++)
+                               if (refNode == Nodes [i])
+                                       return InsertBefore (newNode, Nodes.Count == i + 1 ? null : this [i + 1]);
 
-                       return newNode;
+                       throw new ArgumentException ("refNode not found in this collection.");
                }
 
                public virtual XmlAttribute InsertBefore (XmlAttribute newNode, XmlAttribute refNode)
                {
-                       if(newNode.OwnerDocument != ownerDocument)
+                       if (newNode.OwnerDocument != ownerDocument)
                                throw new ArgumentException ("different document created this newNode.");
 
                        ownerDocument.onNodeInserting (newNode, null);
 
                        int pos = Nodes.Count;
-                       if(refNode != null)
-                       {
-                               for(int i=0; i<Nodes.Count; i++)
-                               {
+                       if (refNode != null) {
+                               for (int i = 0; i < Nodes.Count; i++) {
                                        XmlNode n = Nodes [i] as XmlNode;
-                                       if(n == refNode)
-                                       {
+                                       if (n == refNode) {
                                                pos = i;
                                                break;
                                        }
                                }
-                               if(pos == Nodes.Count)
-                                       throw new XmlException ("refNode not found in this collection.");
+                               if (pos == Nodes.Count)
+                                       throw new ArgumentException ("refNode not found in this collection.");
                        }
-                       SetNamedItem (newNode, pos);
+                       SetNamedItem (newNode, pos, false);
 
                        ownerDocument.onNodeInserted (newNode, null);
 
@@ -173,13 +148,30 @@ namespace System.Xml
                                RemoveIdenticalAttribute (retAttr);
                                ownerDocument.onNodeRemoved (node, null);
                        }
+                       // If it is default, then directly create new attribute.
+                       DTDAttListDeclaration attList = ownerDocument.DocumentType != null ? ownerDocument.DocumentType.DTD.AttListDecls [ownerElement.Name] : null;
+                       DTDAttributeDefinition def = attList != null ? attList [retAttr.Name] : null;
+                       if (def != null && def.DefaultValue != null) {
+                               XmlAttribute attr = ownerDocument.CreateAttribute (
+                                       retAttr.Prefix, retAttr.LocalName, retAttr.NamespaceURI);
+                               attr.Value = def.DefaultValue;
+                               attr.SetDefault ();
+                               this.SetNamedItem (attr);
+                       }
+                       retAttr.SetOwnerElement (null);
                        return retAttr;
                }
 
                public virtual void RemoveAll () 
                {
-                       while(Count > 0)
-                               Remove ((XmlAttribute)Nodes [0]);
+                       int current = 0;
+                       while (current < Count) {
+                               XmlAttribute attr = this [current];
+                               if (!attr.Specified)
+                                       current++;
+                               // It is called for the purpose of event support.
+                               Remove (attr);
+                       }
                }
 
                public virtual XmlAttribute RemoveAt (int i) 
@@ -194,7 +186,18 @@ namespace System.Xml
                        if(IsReadOnly)
                                throw new XmlException ("this AttributeCollection is read only.");
 
-                       return AdjustIdenticalAttributes (node as XmlAttribute, base.SetNamedItem (node, -1) as XmlAttribute);
+                       XmlAttribute attr = node as XmlAttribute;
+                       if (attr.OwnerElement != null)
+                               throw new InvalidOperationException ("This attribute is already set to another element.");
+
+                       ownerElement.OwnerDocument.onNodeInserting (node, ownerElement);
+
+                       attr.SetOwnerElement (ownerElement);
+                       XmlNode n = AdjustIdenticalAttributes (node as XmlAttribute, base.SetNamedItem (node, -1, false));
+
+                       ownerElement.OwnerDocument.onNodeInserted (node, ownerElement);
+
+                       return n as XmlAttribute;
                }
 
                internal void AddIdenticalAttribute ()
@@ -240,7 +243,7 @@ namespace System.Xml
 
                }
 
-               private XmlNode AdjustIdenticalAttributes (XmlNode node, XmlNode existing)
+               private XmlNode AdjustIdenticalAttributes (XmlAttribute node, XmlNode existing)
                {
                        // If owner element is not appended to the document,
                        // ID table should not be filled.
@@ -253,8 +256,8 @@ namespace System.Xml
                        XmlDocumentType doctype = node.OwnerDocument.DocumentType;
                        if (doctype == null || doctype.DTD == null)
                                return existing;
-                       DTDElementDeclaration elem = doctype.DTD.ElementDecls [ownerElement.Name];
-                       DTDAttributeDefinition attdef = elem == null ? null : elem.Attributes [node.Name];
+                       DTDAttListDeclaration attList = doctype.DTD.AttListDecls [ownerElement.Name];
+                       DTDAttributeDefinition attdef = attList == null ? null : attList.Get (node.Name);
                        if (attdef == null || attdef.Datatype.TokenizedType != XmlTokenizedType.ID)
                                return existing;
 
@@ -263,7 +266,7 @@ namespace System.Xml
                        if (ownerDocument.GetIdenticalAttribute (node.Value) != null)
                                throw new XmlException (String.Format (
                                        "ID value {0} already exists in this document.", node.Value));
-                       ownerDocument.AddIdenticalAttribute (node as XmlAttribute);
+                       ownerDocument.AddIdenticalAttribute (node);
 
                        return existing;
                }