Back to index

lightning-sunbird  0.9+nobinonly
nsDOMAttribute.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Communicator client code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "nsDOMAttribute.h"
00039 #include "nsGenericElement.h"
00040 #include "nsIContent.h"
00041 #include "nsITextContent.h"
00042 #include "nsINameSpaceManager.h"
00043 #include "nsDOMError.h"
00044 #include "nsContentUtils.h"
00045 #include "nsUnicharUtils.h"
00046 #include "nsDOMString.h"
00047 #include "nsIDocument.h"
00048 #include "nsIDOMDocument.h"
00049 #include "nsCOMArray.h"
00050 
00051 //----------------------------------------------------------------------
00052 PRBool nsDOMAttribute::sInitialized;
00053 
00054 nsDOMAttribute::nsDOMAttribute(nsDOMAttributeMap *aAttrMap,
00055                                nsINodeInfo       *aNodeInfo,
00056                                const nsAString   &aValue)
00057   : nsIAttribute(aAttrMap, aNodeInfo), mValue(aValue), mChild(nsnull),
00058     mChildList(nsnull)
00059 {
00060   NS_ABORT_IF_FALSE(mNodeInfo, "We must get a nodeinfo here!");
00061 
00062 
00063   // We don't add a reference to our content. It will tell us
00064   // to drop our reference when it goes away.
00065 }
00066 
00067 nsDOMAttribute::~nsDOMAttribute()
00068 {
00069   nsIDocument *doc = GetOwnerDoc();
00070   if (doc)
00071     doc->PropertyTable()->DeleteAllPropertiesFor(this);
00072 
00073   NS_IF_RELEASE(mChild);
00074   if (mChildList) {
00075     mChildList->DropReference();
00076     NS_RELEASE(mChildList);
00077   }
00078 }
00079 
00080 
00081 // QueryInterface implementation for nsDOMAttribute
00082 NS_INTERFACE_MAP_BEGIN(nsDOMAttribute)
00083   NS_INTERFACE_MAP_ENTRY(nsIDOMAttr)
00084   NS_INTERFACE_MAP_ENTRY(nsIAttribute)
00085   NS_INTERFACE_MAP_ENTRY(nsIDOMGCParticipant)
00086   NS_INTERFACE_MAP_ENTRY(nsIDOMNode)
00087   NS_INTERFACE_MAP_ENTRY(nsIDOM3Node)
00088   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMAttr)
00089   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(Attr)
00090 NS_INTERFACE_MAP_END
00091 
00092 
00093 NS_IMPL_ADDREF(nsDOMAttribute)
00094 NS_IMPL_RELEASE(nsDOMAttribute)
00095 
00096 // nsIDOMGCParticipant methods
00097 nsIDOMGCParticipant*
00098 nsDOMAttribute::GetSCCIndex()
00099 {
00100   nsIContent *owner = GetContentInternal();
00101 
00102   return owner ? owner->GetSCCIndex() : this;
00103 }
00104 
00105 void
00106 nsDOMAttribute::AppendReachableList(nsCOMArray<nsIDOMGCParticipant>& aArray)
00107 {
00108   NS_ASSERTION(GetContentInternal() == nsnull,
00109                "shouldn't be an SCC index if we're in an element");
00110 
00111   // This node is the root of a subtree that's been removed from the
00112   // document (since AppendReachableList is only called on SCC index
00113   // nodes).  The document is reachable from it (through
00114   // .ownerDocument), but it's not reachable from the document.
00115   nsCOMPtr<nsIDOMGCParticipant> participant = do_QueryInterface(GetOwnerDoc());
00116   aArray.AppendObject(participant);
00117 }
00118 
00119 void
00120 nsDOMAttribute::SetMap(nsDOMAttributeMap *aMap)
00121 {
00122   if (mAttrMap && !aMap && sInitialized) {
00123     // We're breaking a relationship with content and not getting a new one,
00124     // need to locally cache value. GetValue() does that.
00125     nsAutoString tmp;
00126     GetValue(tmp);
00127   }
00128   
00129   mAttrMap = aMap;
00130 }
00131 
00132 nsIContent*
00133 nsDOMAttribute::GetContent() const
00134 {
00135   return GetContentInternal();
00136 }
00137 
00138 nsresult
00139 nsDOMAttribute::GetName(nsAString& aName)
00140 {
00141   mNodeInfo->GetQualifiedName(aName);
00142   return NS_OK;
00143 }
00144 
00145 nsresult
00146 nsDOMAttribute::GetValue(nsAString& aValue)
00147 {
00148   nsIContent* content = GetContentInternal();
00149   if (content) {
00150     nsAutoString tmpValue;
00151     nsresult attrResult = content->GetAttr(mNodeInfo->NamespaceID(),
00152                                            mNodeInfo->NameAtom(),
00153                                            tmpValue);
00154     if (NS_CONTENT_ATTR_NOT_THERE != attrResult) {
00155       mValue = tmpValue;
00156     }
00157   }
00158 
00159   aValue = mValue;
00160 
00161   return NS_OK;
00162 }
00163 
00164 nsresult
00165 nsDOMAttribute::SetValue(const nsAString& aValue)
00166 {
00167   nsresult rv = NS_OK;
00168   nsIContent* content = GetContentInternal();
00169   if (content) {
00170     rv = content->SetAttr(mNodeInfo->NamespaceID(),
00171                           mNodeInfo->NameAtom(),
00172                           mNodeInfo->GetPrefixAtom(),
00173                           aValue,
00174                           PR_TRUE);
00175   }
00176   mValue = aValue;
00177 
00178   return rv;
00179 }
00180 
00181 nsresult
00182 nsDOMAttribute::GetSpecified(PRBool* aSpecified)
00183 {
00184   NS_ENSURE_ARG_POINTER(aSpecified);
00185 
00186   nsIContent* content = GetContentInternal();
00187   *aSpecified = content && content->HasAttr(mNodeInfo->NamespaceID(),
00188                                             mNodeInfo->NameAtom());
00189 
00190   return NS_OK;
00191 }
00192 
00193 NS_IMETHODIMP
00194 nsDOMAttribute::GetOwnerElement(nsIDOMElement** aOwnerElement)
00195 {
00196   NS_ENSURE_ARG_POINTER(aOwnerElement);
00197 
00198   nsIContent* content = GetContentInternal();
00199   PRBool hasAttr = content && content->HasAttr(mNodeInfo->NamespaceID(),
00200                                                mNodeInfo->NameAtom());
00201   if (hasAttr) {
00202     return CallQueryInterface(content, aOwnerElement);
00203   }
00204 
00205   *aOwnerElement = nsnull;
00206 
00207   return NS_OK;
00208 }
00209 
00210 NS_IMETHODIMP
00211 nsDOMAttribute::GetNodeName(nsAString& aNodeName)
00212 {
00213   return GetName(aNodeName);
00214 }
00215 
00216 NS_IMETHODIMP
00217 nsDOMAttribute::GetNodeValue(nsAString& aNodeValue)
00218 {
00219   return GetValue(aNodeValue);
00220 }
00221 
00222 NS_IMETHODIMP
00223 nsDOMAttribute::SetNodeValue(const nsAString& aNodeValue)
00224 {
00225   return SetValue(aNodeValue);
00226 }
00227 
00228 NS_IMETHODIMP
00229 nsDOMAttribute::GetNodeType(PRUint16* aNodeType)
00230 {
00231   NS_ENSURE_ARG_POINTER(aNodeType);
00232 
00233   *aNodeType = (PRUint16)nsIDOMNode::ATTRIBUTE_NODE;
00234   return NS_OK;
00235 }
00236 
00237 NS_IMETHODIMP
00238 nsDOMAttribute::GetParentNode(nsIDOMNode** aParentNode)
00239 {
00240   NS_ENSURE_ARG_POINTER(aParentNode);
00241 
00242   *aParentNode = nsnull;
00243   return NS_OK;
00244 }
00245 
00246 NS_IMETHODIMP
00247 nsDOMAttribute::GetChildNodes(nsIDOMNodeList** aChildNodes)
00248 {
00249   if (!mChildList) {
00250     mChildList = new nsAttributeChildList(this);
00251     NS_ENSURE_TRUE(mChildList, NS_ERROR_OUT_OF_MEMORY);
00252 
00253     NS_ADDREF(mChildList);
00254   }
00255 
00256   return CallQueryInterface(mChildList, aChildNodes);
00257 }
00258 
00259 NS_IMETHODIMP
00260 nsDOMAttribute::HasChildNodes(PRBool* aHasChildNodes)
00261 {
00262   *aHasChildNodes = PR_FALSE;
00263   if (mChild) {
00264     *aHasChildNodes = PR_TRUE;
00265   }
00266   else {
00267     nsAutoString value;
00268 
00269     GetValue(value);
00270     if (!value.IsEmpty()) {
00271       *aHasChildNodes = PR_TRUE;
00272     }
00273   }
00274 
00275   return NS_OK;
00276 }
00277 
00278 NS_IMETHODIMP
00279 nsDOMAttribute::HasAttributes(PRBool* aHasAttributes)
00280 {
00281   NS_ENSURE_ARG_POINTER(aHasAttributes);
00282 
00283   *aHasAttributes = PR_FALSE;
00284 
00285   return NS_OK;
00286 }
00287 
00288 NS_IMETHODIMP
00289 nsDOMAttribute::GetFirstChild(nsIDOMNode** aFirstChild)
00290 {
00291   nsAutoString value;
00292   nsresult result;
00293 
00294   result = GetValue(value);
00295   if (NS_OK != result) {
00296     return result;
00297   }
00298   if (!value.IsEmpty()) {
00299     if (!mChild) {
00300       nsCOMPtr<nsITextContent> content;
00301       result = NS_NewTextNode(getter_AddRefs(content),
00302                               mNodeInfo->NodeInfoManager());
00303       if (NS_FAILED(result)) {
00304         return result;
00305       }
00306       // XXX We should be setting |this| as the parent of the textnode!
00307       result = CallQueryInterface(content, &mChild);
00308     }
00309     mChild->SetData(value);
00310     result = CallQueryInterface(mChild, aFirstChild);
00311   }
00312   else {
00313     *aFirstChild = nsnull;
00314   }
00315   return result;
00316 }
00317 
00318 NS_IMETHODIMP
00319 nsDOMAttribute::GetLastChild(nsIDOMNode** aLastChild)
00320 {
00321   return GetFirstChild(aLastChild);
00322 }
00323 
00324 NS_IMETHODIMP
00325 nsDOMAttribute::GetPreviousSibling(nsIDOMNode** aPreviousSibling)
00326 {
00327   NS_ENSURE_ARG_POINTER(aPreviousSibling);
00328 
00329   *aPreviousSibling = nsnull;
00330   return NS_OK;
00331 }
00332 
00333 NS_IMETHODIMP
00334 nsDOMAttribute::GetNextSibling(nsIDOMNode** aNextSibling)
00335 {
00336   NS_ENSURE_ARG_POINTER(aNextSibling);
00337 
00338   *aNextSibling = nsnull;
00339   return NS_OK;
00340 }
00341 
00342 NS_IMETHODIMP
00343 nsDOMAttribute::GetAttributes(nsIDOMNamedNodeMap** aAttributes)
00344 {
00345   NS_ENSURE_ARG_POINTER(aAttributes);
00346 
00347   *aAttributes = nsnull;
00348   return NS_OK;
00349 }
00350 
00351 NS_IMETHODIMP
00352 nsDOMAttribute::InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild, nsIDOMNode** aReturn)
00353 {
00354   return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
00355 }
00356 
00357 NS_IMETHODIMP
00358 nsDOMAttribute::ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild, nsIDOMNode** aReturn)
00359 {
00360   return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
00361 }
00362 
00363 NS_IMETHODIMP
00364 nsDOMAttribute::RemoveChild(nsIDOMNode* aOldChild, nsIDOMNode** aReturn)
00365 {
00366   return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
00367 }
00368 
00369 NS_IMETHODIMP
00370 nsDOMAttribute::AppendChild(nsIDOMNode* aNewChild, nsIDOMNode** aReturn)
00371 {
00372   return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
00373 }
00374 
00375 NS_IMETHODIMP
00376 nsDOMAttribute::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
00377 {
00378   nsDOMAttribute* newAttr;
00379 
00380   nsAutoString value;
00381   GetValue(value);
00382   newAttr = new nsDOMAttribute(nsnull, mNodeInfo, value);
00383 
00384   if (!newAttr) {
00385     return NS_ERROR_OUT_OF_MEMORY;
00386   }
00387 
00388   return CallQueryInterface(newAttr, aReturn);
00389 }
00390 
00391 NS_IMETHODIMP
00392 nsDOMAttribute::GetOwnerDocument(nsIDOMDocument** aOwnerDocument)
00393 {
00394   *aOwnerDocument = nsnull;
00395 
00396   nsresult rv = NS_OK;
00397   nsIContent* content = GetContentInternal();
00398   if (content) {
00399     nsCOMPtr<nsIDOMNode> node = do_QueryInterface(content, &rv);
00400     if (NS_SUCCEEDED(rv)) {
00401       rv = node->GetOwnerDocument(aOwnerDocument);
00402     }
00403   }
00404   else {
00405     nsIDocument *document = mNodeInfo->GetDocument();
00406     if (document) {
00407       rv = CallQueryInterface(document, aOwnerDocument);
00408     }
00409   }
00410 
00411   return rv;
00412 }
00413 
00414 NS_IMETHODIMP
00415 nsDOMAttribute::GetNamespaceURI(nsAString& aNamespaceURI)
00416 {
00417   return mNodeInfo->GetNamespaceURI(aNamespaceURI);
00418 }
00419 
00420 NS_IMETHODIMP
00421 nsDOMAttribute::GetPrefix(nsAString& aPrefix)
00422 {
00423   mNodeInfo->GetPrefix(aPrefix);
00424   return NS_OK;
00425 }
00426 
00427 NS_IMETHODIMP
00428 nsDOMAttribute::SetPrefix(const nsAString& aPrefix)
00429 {
00430   nsCOMPtr<nsINodeInfo> newNodeInfo;
00431   nsCOMPtr<nsIAtom> prefix;
00432 
00433   if (!aPrefix.IsEmpty()) {
00434     prefix = do_GetAtom(aPrefix);
00435   }
00436 
00437   nsresult rv = nsContentUtils::PrefixChanged(mNodeInfo, prefix,
00438                                               getter_AddRefs(newNodeInfo));
00439   NS_ENSURE_SUCCESS(rv, rv);
00440 
00441   nsIContent* content = GetContentInternal();
00442   if (content) {
00443     nsIAtom *name = mNodeInfo->NameAtom();
00444     PRInt32 nameSpaceID = mNodeInfo->NamespaceID();
00445 
00446     nsAutoString tmpValue;
00447     rv = content->GetAttr(nameSpaceID, name, tmpValue);
00448     if (rv == NS_CONTENT_ATTR_HAS_VALUE) {
00449       content->UnsetAttr(nameSpaceID, name, PR_TRUE);
00450 
00451       content->SetAttr(newNodeInfo->NamespaceID(), newNodeInfo->NameAtom(),
00452                        newNodeInfo->GetPrefixAtom(), tmpValue, PR_TRUE);
00453     }
00454   }
00455 
00456   mNodeInfo.swap(newNodeInfo);
00457 
00458   return NS_OK;
00459 }
00460 
00461 NS_IMETHODIMP
00462 nsDOMAttribute::GetLocalName(nsAString& aLocalName)
00463 {
00464   mNodeInfo->GetLocalName(aLocalName);
00465   return NS_OK;
00466 }
00467 
00468 NS_IMETHODIMP
00469 nsDOMAttribute::Normalize()
00470 {
00471   // Nothing to do here
00472   return NS_OK;
00473 }
00474 
00475 NS_IMETHODIMP
00476 nsDOMAttribute::IsSupported(const nsAString& aFeature,
00477                             const nsAString& aVersion,
00478                             PRBool* aReturn)
00479 {
00480   return nsGenericElement::InternalIsSupported(NS_STATIC_CAST(nsIDOMAttr*, this), 
00481                                                aFeature, aVersion, aReturn);
00482 }
00483 
00484 NS_IMETHODIMP
00485 nsDOMAttribute::GetBaseURI(nsAString &aURI)
00486 {
00487   aURI.Truncate();
00488   nsresult rv = NS_OK;
00489   nsCOMPtr<nsIDOM3Node> node(do_QueryInterface(GetContentInternal()));
00490   if (node)
00491     rv = node->GetBaseURI(aURI);
00492   return rv;
00493 }
00494 
00495 NS_IMETHODIMP
00496 nsDOMAttribute::CompareDocumentPosition(nsIDOMNode* aOther,
00497                                         PRUint16* aReturn)
00498 {
00499   NS_ENSURE_ARG_POINTER(aOther);
00500   NS_PRECONDITION(aReturn, "Must have an out parameter");
00501 
00502   PRUint16 mask = 0;
00503 
00504   nsCOMPtr<nsIDOMElement> el;
00505   GetOwnerElement(getter_AddRefs(el));
00506   if (!el) {
00507     // If we have no owner element then there is no common container node,
00508     // (of course there isn't if we have no container!) and the order is
00509     // then based upon order between the root container of each node that
00510     // is in no container. In this case, the result is disconnected
00511     // and implementation-dependent.
00512     mask |= (nsIDOM3Node::DOCUMENT_POSITION_DISCONNECTED |
00513              nsIDOM3Node::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
00514 
00515     *aReturn = mask;
00516 
00517     return NS_OK;
00518   }
00519 
00520   // Check to see if the other node is also an attribute
00521   PRUint16 nodeType = 0;
00522   aOther->GetNodeType(&nodeType);
00523   if (nodeType == nsIDOMNode::ATTRIBUTE_NODE) {
00524     nsCOMPtr<nsIDOMAttr> otherAttr(do_QueryInterface(aOther));
00525     nsCOMPtr<nsIDOMElement> otherEl;
00526     otherAttr->GetOwnerElement(getter_AddRefs(otherEl));
00527     if (el == otherEl) {
00528       PRBool sameNode = PR_FALSE;
00529       IsSameNode(aOther, &sameNode);
00530       if (!sameNode) {
00531         // If neither of the two determining nodes is a child node and
00532         // nodeType is the same for both determining nodes, then an
00533         // implementation-dependent order between the determining nodes
00534         // is returned.
00535         mask |= nsIDOM3Node::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
00536       }
00537 
00538       // If the two nodes being compared are the same node,
00539       // then no flags are set on the return.
00540     }
00541 
00542     *aReturn = mask;
00543 
00544     return NS_OK;
00545   }
00546 
00547   PRBool sameNode = PR_FALSE;
00548 
00549   if (nodeType == nsIDOMNode::TEXT_NODE ||
00550       nodeType == nsIDOMNode::CDATA_SECTION_NODE ||
00551       nodeType == nsIDOMNode::ENTITY_REFERENCE_NODE) {
00552     // XXXcaa we really should check the other node's parentNode
00553     // against ourselves.  But since we can't, we should walk our
00554     // child node list to see if it's a descendant.  But wait!
00555     // We suck so bad that we cannot even do that, since we store
00556     // only one text node per attribute, even if there are multiple.
00557     // So technically, we could walk the child nodes list, but it
00558     // would not make sense really to walk it for only one thing.
00559     // How lame.  So.... it seems the only option that we DO have
00560     // is to get our one and only child and compare it against the
00561     // other node.  As such, that is exactly what we'll do.
00562     // *Sigh*  These silly hacks are quite disgusting, really....
00563 
00564     nsCOMPtr<nsIDOMNode> ourOnlyChild;
00565     GetFirstChild(getter_AddRefs(ourOnlyChild));
00566 
00567     nsCOMPtr<nsIDOM3Node> longLostRelative(do_QueryInterface(aOther));
00568     NS_ASSERTION(longLostRelative, "All our data nodes support DOM3Node");
00569 
00570     longLostRelative->IsSameNode(ourOnlyChild, &sameNode);
00571     if (sameNode) {
00572       // Woohoo!  We found our long lost relative and it's our child!
00573       // Throw a party!  Celebrate by returning that it is contained
00574       // and following this node.
00575 
00576       mask |= (nsIDOM3Node::DOCUMENT_POSITION_CONTAINED_BY |
00577                nsIDOM3Node::DOCUMENT_POSITION_FOLLOWING);
00578 
00579       *aReturn = mask;
00580       return NS_OK;
00581     }
00582 
00583     // Sigh.  The other node isn't our child, but it still may be
00584     // related to us.  Fall through so we can keep looking.
00585   }
00586 
00587 
00588   // The other node isn't an attribute, or a child.
00589   // Compare position relative to this attribute's owner element.
00590 
00591   nsCOMPtr<nsIDOM3Node> parent(do_QueryInterface(el));
00592   parent->IsSameNode(aOther, &sameNode);
00593   if (sameNode) {
00594     // If the other node contains us, then it precedes us.
00595     mask |= (nsIDOM3Node::DOCUMENT_POSITION_CONTAINS |
00596              nsIDOM3Node::DOCUMENT_POSITION_PRECEDING);
00597 
00598     *aReturn = mask;
00599     return NS_OK;
00600   }
00601 
00602   PRUint16 parentMask = 0;
00603   parent->CompareDocumentPosition(aOther, &parentMask);
00604 
00605   // We already established earlier that the node is not contained
00606   // by this attribute.  So if it is contained by our owner element,
00607   // unset the flag.
00608   mask |= parentMask & ~nsIDOM3Node::DOCUMENT_POSITION_CONTAINED_BY;
00609 
00610   *aReturn = mask;
00611   return NS_OK;
00612 }
00613 
00614 NS_IMETHODIMP
00615 nsDOMAttribute::IsSameNode(nsIDOMNode* aOther,
00616                            PRBool* aReturn)
00617 {
00618   NS_ASSERTION(aReturn, "IsSameNode() called with aReturn == nsnull!");
00619   
00620   *aReturn = SameCOMIdentity(NS_STATIC_CAST(nsIDOMNode*, this), aOther);
00621 
00622   return NS_OK;
00623 }
00624 
00625 NS_IMETHODIMP
00626 nsDOMAttribute::IsEqualNode(nsIDOMNode* aOther,
00627                             PRBool* aReturn)
00628 {
00629   NS_NOTYETIMPLEMENTED("nsDocument::IsEqualNode()");
00630 
00631   return NS_ERROR_NOT_IMPLEMENTED;
00632 }
00633 
00634 NS_IMETHODIMP
00635 nsDOMAttribute::IsDefaultNamespace(const nsAString& aNamespaceURI,
00636                                    PRBool* aReturn)
00637 {
00638   *aReturn = PR_FALSE;
00639   nsCOMPtr<nsIDOM3Node> node(do_QueryInterface(GetContentInternal()));
00640   if (node) {
00641     return node->IsDefaultNamespace(aNamespaceURI, aReturn);
00642   }
00643   return NS_OK;
00644 }
00645 
00646 NS_IMETHODIMP
00647 nsDOMAttribute::GetTextContent(nsAString &aTextContent)
00648 {
00649   return GetNodeValue(aTextContent);
00650 }
00651 
00652 NS_IMETHODIMP
00653 nsDOMAttribute::SetTextContent(const nsAString& aTextContent)
00654 {
00655   return SetNodeValue(aTextContent);
00656 }
00657 
00658 
00659 NS_IMETHODIMP
00660 nsDOMAttribute::GetFeature(const nsAString& aFeature,
00661                            const nsAString& aVersion,
00662                            nsISupports** aReturn)
00663 {
00664   return nsGenericElement::InternalGetFeature(NS_STATIC_CAST(nsIDOMAttr*, this), 
00665                                               aFeature, aVersion, aReturn);
00666 }
00667 
00668 NS_IMETHODIMP
00669 nsDOMAttribute::SetUserData(const nsAString& aKey,
00670                             nsIVariant* aData,
00671                             nsIDOMUserDataHandler* aHandler,
00672                             nsIVariant** aReturn)
00673 {
00674   NS_NOTYETIMPLEMENTED("nsDocument::SetUserData()");
00675 
00676   return NS_ERROR_NOT_IMPLEMENTED;
00677 }
00678 
00679 NS_IMETHODIMP
00680 nsDOMAttribute::GetUserData(const nsAString& aKey,
00681                             nsIVariant** aReturn)
00682 {
00683   NS_NOTYETIMPLEMENTED("nsDocument::GetUserData()");
00684 
00685   return NS_ERROR_NOT_IMPLEMENTED;
00686 }
00687 
00688 NS_IMETHODIMP
00689 nsDOMAttribute::LookupPrefix(const nsAString& aNamespaceURI,
00690                              nsAString& aPrefix)
00691 {
00692   aPrefix.Truncate();
00693 
00694   nsCOMPtr<nsIDOM3Node> node(do_QueryInterface(GetContentInternal()));
00695   if (node) {
00696     return node->LookupPrefix(aNamespaceURI, aPrefix);
00697   }
00698 
00699   return NS_OK;
00700 }
00701 
00702 NS_IMETHODIMP
00703 nsDOMAttribute::LookupNamespaceURI(const nsAString& aNamespacePrefix,
00704                                    nsAString& aNamespaceURI)
00705 {
00706   aNamespaceURI.Truncate();
00707   nsresult rv = NS_OK;
00708   nsCOMPtr<nsIDOM3Node> node(do_QueryInterface(GetContentInternal()));
00709   if (node)
00710     rv = node->LookupNamespaceURI(aNamespacePrefix, aNamespaceURI);
00711   return rv;
00712 }
00713 
00714 void*
00715 nsDOMAttribute::GetProperty(nsIAtom* aPropertyName, nsresult* aStatus)
00716 {
00717   nsIDocument *doc = GetOwnerDoc();
00718   if (!doc)
00719     return nsnull;
00720 
00721   return doc->PropertyTable()->GetProperty(this, aPropertyName, aStatus);
00722 }
00723 
00724 nsresult
00725 nsDOMAttribute::SetProperty(nsIAtom            *aPropertyName,
00726                             void               *aValue,
00727                             NSPropertyDtorFunc  aDtor)
00728 {
00729   nsIDocument *doc = GetOwnerDoc();
00730   if (!doc)
00731     return NS_ERROR_FAILURE;
00732 
00733   return doc->PropertyTable()->SetProperty(this, aPropertyName, aValue, aDtor,
00734                                            nsnull);
00735 }
00736 
00737 nsresult
00738 nsDOMAttribute::DeleteProperty(nsIAtom* aPropertyName)
00739 {
00740   nsIDocument *doc = GetOwnerDoc();
00741   if (!doc)
00742     return nsnull;
00743 
00744   return doc->PropertyTable()->DeleteProperty(this, aPropertyName);
00745 }
00746 
00747 void*
00748 nsDOMAttribute::UnsetProperty(nsIAtom* aPropertyName, nsresult* aStatus)
00749 {
00750   nsIDocument *doc = GetOwnerDoc();
00751   if (!doc)
00752     return nsnull;
00753 
00754   return doc->PropertyTable()->UnsetProperty(this, aPropertyName, aStatus);
00755 }
00756 
00757 void
00758 nsDOMAttribute::Initialize()
00759 {
00760   sInitialized = PR_TRUE;
00761 }
00762 
00763 void
00764 nsDOMAttribute::Shutdown()
00765 {
00766   sInitialized = PR_FALSE;
00767 }
00768 
00769 //----------------------------------------------------------------------
00770 
00771 nsAttributeChildList::nsAttributeChildList(nsDOMAttribute* aAttribute)
00772 {
00773   // Don't increment the reference count. The attribute will tell
00774   // us when it's going away
00775   mAttribute = aAttribute;
00776 }
00777 
00778 nsAttributeChildList::~nsAttributeChildList()
00779 {
00780 }
00781 
00782 NS_IMETHODIMP
00783 nsAttributeChildList::GetLength(PRUint32* aLength)
00784 {
00785   *aLength = 0;
00786   if (mAttribute) {
00787     nsAutoString value;
00788     mAttribute->GetValue(value);
00789     if (!value.IsEmpty()) {
00790       *aLength = 1;
00791     }
00792   }
00793 
00794   return NS_OK;
00795 }
00796 
00797 NS_IMETHODIMP
00798 nsAttributeChildList::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
00799 {
00800   *aReturn = nsnull;
00801   if (mAttribute && 0 == aIndex) {
00802     mAttribute->GetFirstChild(aReturn);
00803   }
00804 
00805   return NS_OK;
00806 }
00807 
00808 void
00809 nsAttributeChildList::DropReference()
00810 {
00811   mAttribute = nsnull;
00812 }