1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include <attributesmap.hxx>
29 
30 #include <string.h>
31 
32 #include <element.hxx>
33 #include <document.hxx>
34 
35 
36 namespace DOM
37 {
38     CAttributesMap::CAttributesMap(::rtl::Reference<CElement> const& pElement,
39                 ::osl::Mutex & rMutex)
40         : m_pElement(pElement)
41         , m_rMutex(rMutex)
42     {
43     }
44 
45     /**
46     The number of nodes in this map.
47     */
48     sal_Int32 SAL_CALL CAttributesMap::getLength() throw (RuntimeException)
49     {
50         ::osl::MutexGuard const g(m_rMutex);
51 
52         sal_Int32 count = 0;
53         xmlNodePtr pNode = m_pElement->GetNodePtr();
54         if (pNode != NULL)
55         {
56             xmlAttrPtr cur = pNode->properties;
57             while (cur != NULL)
58             {
59                 count++;
60                 cur = cur->next;
61             }
62         }
63         return count;
64     }
65 
66     /**
67     Retrieves a node specified by local name
68     */
69     Reference< XNode > SAL_CALL
70     CAttributesMap::getNamedItem(OUString const& name) throw (RuntimeException)
71     {
72         ::osl::MutexGuard const g(m_rMutex);
73 
74         Reference< XNode > aNode;
75         xmlNodePtr pNode = m_pElement->GetNodePtr();
76         if (pNode != NULL)
77         {
78             OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
79             xmlChar* xName = (xmlChar*)o1.getStr();
80             xmlAttrPtr cur = pNode->properties;
81             while (cur != NULL)
82             {
83                 if( strcmp((char*)xName, (char*)cur->name) == 0)
84                 {
85                     aNode = Reference< XNode >(
86                             m_pElement->GetOwnerDocument().GetCNode(
87                                 reinterpret_cast<xmlNodePtr>(cur)).get() );
88                     break;
89                 }
90                 cur = cur->next;
91             }
92         }
93         return aNode;
94     }
95 
96     /**
97     Retrieves a node specified by local name and namespace URI.
98     */
99     Reference< XNode > SAL_CALL
100     CAttributesMap::getNamedItemNS(
101             OUString const& namespaceURI, OUString const& localName)
102     throw (RuntimeException)
103     {
104         ::osl::MutexGuard const g(m_rMutex);
105 
106         Reference< XNode > aNode;
107         xmlNodePtr pNode = m_pElement->GetNodePtr();
108         if (pNode != NULL)
109         {
110             OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
111             xmlChar* xName = (xmlChar*)o1.getStr();
112             OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
113             xmlChar const*const xNs =
114                 reinterpret_cast<xmlChar const*>(o2.getStr());
115             xmlNsPtr const pNs = xmlSearchNsByHref(pNode->doc, pNode, xNs);
116             xmlAttrPtr cur = pNode->properties;
117             while (cur != NULL && pNs != NULL)
118             {
119                 if( strcmp((char*)xName, (char*)cur->name) == 0 &&
120                     cur->ns == pNs)
121                 {
122                     aNode = Reference< XNode >(
123                             m_pElement->GetOwnerDocument().GetCNode(
124                                 reinterpret_cast<xmlNodePtr>(cur)).get() );
125                     break;
126                 }
127                 cur = cur->next;
128             }
129         }
130         return aNode;
131     }
132 
133     /**
134     Returns the indexth item in the map.
135     */
136     Reference< XNode > SAL_CALL
137     CAttributesMap::item(sal_Int32 index) throw (RuntimeException)
138     {
139         ::osl::MutexGuard const g(m_rMutex);
140 
141         Reference< XNode > aNode;
142         xmlNodePtr pNode = m_pElement->GetNodePtr();
143         if (pNode != NULL)
144         {
145             xmlAttrPtr cur = pNode->properties;
146             sal_Int32 count = 0;
147             while (cur != NULL)
148             {
149                 if (count == index)
150                 {
151                     aNode = Reference< XNode >(
152                             m_pElement->GetOwnerDocument().GetCNode(
153                                 reinterpret_cast<xmlNodePtr>(cur)).get() );
154                     break;
155                 }
156                 count++;
157                 cur = cur->next;
158             }
159         }
160         return aNode;
161     }
162 
163     /**
164     Removes a node specified by name.
165     */
166     Reference< XNode > SAL_CALL
167     CAttributesMap::removeNamedItem(OUString const& name)
168     throw (RuntimeException)
169     {
170         // no MutexGuard needed: m_pElement is const
171         Reference< XAttr > const xAttr(m_pElement->getAttributeNode(name));
172         if (!xAttr.is()) {
173             throw DOMException(OUString(RTL_CONSTASCII_USTRINGPARAM(
174                     "CAttributesMap::removeNamedItem: no such attribute")),
175                 static_cast<OWeakObject*>(this),
176                 DOMExceptionType_NOT_FOUND_ERR);
177         }
178         Reference< XNode > const xRet(
179             m_pElement->removeAttributeNode(xAttr), UNO_QUERY);
180         return xRet;
181     }
182 
183     /**
184     // Removes a node specified by local name and namespace URI.
185     */
186     Reference< XNode > SAL_CALL
187     CAttributesMap::removeNamedItemNS(
188             OUString const& namespaceURI, OUString const& localName)
189     throw (RuntimeException)
190     {
191         // no MutexGuard needed: m_pElement is const
192         Reference< XAttr > const xAttr(
193             m_pElement->getAttributeNodeNS(namespaceURI, localName));
194         if (!xAttr.is()) {
195             throw DOMException(OUString(RTL_CONSTASCII_USTRINGPARAM(
196                     "CAttributesMap::removeNamedItemNS: no such attribute")),
197                 static_cast<OWeakObject*>(this),
198                 DOMExceptionType_NOT_FOUND_ERR);
199         }
200         Reference< XNode > const xRet(
201             m_pElement->removeAttributeNode(xAttr), UNO_QUERY);
202         return xRet;
203     }
204 
205     /**
206     // Adds a node using its nodeName attribute.
207     */
208     Reference< XNode > SAL_CALL
209     CAttributesMap::setNamedItem(Reference< XNode > const& xNode)
210     throw (RuntimeException)
211     {
212         Reference< XAttr > const xAttr(xNode, UNO_QUERY);
213         if (!xNode.is()) {
214             throw DOMException(OUString(RTL_CONSTASCII_USTRINGPARAM(
215                     "CAttributesMap::setNamedItem: XAttr argument expected")),
216                 static_cast<OWeakObject*>(this),
217                 DOMExceptionType_HIERARCHY_REQUEST_ERR);
218         }
219         // no MutexGuard needed: m_pElement is const
220         Reference< XNode > const xRet(
221             m_pElement->setAttributeNode(xAttr), UNO_QUERY);
222         return xRet;
223     }
224 
225     /**
226     Adds a node using its namespaceURI and localName.
227     */
228     Reference< XNode > SAL_CALL
229     CAttributesMap::setNamedItemNS(Reference< XNode > const& xNode)
230     throw (RuntimeException)
231     {
232         Reference< XAttr > const xAttr(xNode, UNO_QUERY);
233         if (!xNode.is()) {
234             throw DOMException(OUString(RTL_CONSTASCII_USTRINGPARAM(
235                     "CAttributesMap::setNamedItemNS: XAttr argument expected")),
236                 static_cast<OWeakObject*>(this),
237                 DOMExceptionType_HIERARCHY_REQUEST_ERR);
238         }
239         // no MutexGuard needed: m_pElement is const
240         Reference< XNode > const xRet(
241             m_pElement->setAttributeNodeNS(xAttr), UNO_QUERY);
242         return xRet;
243     }
244 }
245