xref: /aoo4110/main/unoxml/source/dom/attr.cxx (revision b1cdbd2c)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include <attr.hxx>
25 
26 #include <string.h>
27 
28 #include <boost/shared_ptr.hpp>
29 
30 #include <com/sun/star/xml/dom/DOMException.hdl>
31 #include <com/sun/star/xml/dom/events/XMutationEvent.hpp>
32 
33 #include <document.hxx>
34 
35 
36 namespace DOM
37 {
CAttr(CDocument const & rDocument,::osl::Mutex const & rMutex,xmlAttrPtr const pAttr)38     CAttr::CAttr(CDocument const& rDocument, ::osl::Mutex const& rMutex,
39             xmlAttrPtr const pAttr)
40         : CAttr_Base(rDocument, rMutex,
41                 NodeType_ATTRIBUTE_NODE, reinterpret_cast<xmlNodePtr>(pAttr))
42         , m_aAttrPtr(pAttr)
43     {
44     }
45 
GetNamespace(xmlNodePtr const pNode)46     xmlNsPtr CAttr::GetNamespace(xmlNodePtr const pNode)
47     {
48         if (!m_pNamespace.get()) {
49             return 0;
50         }
51         xmlChar const*const pUri(reinterpret_cast<xmlChar const*>(
52                 m_pNamespace->first.getStr()));
53         xmlChar const*const pPrefix(reinterpret_cast<xmlChar const*>(
54                 m_pNamespace->second.getStr()));
55         xmlNsPtr pNs = xmlSearchNs(pNode->doc, pNode, pPrefix);
56         if (pNs && (0 != xmlStrcmp(pNs->href, pUri))) {
57             return pNs;
58         }
59         pNs = xmlNewNs(pNode, pUri, pPrefix);
60         if (pNs) {
61             return pNs;
62         }
63         pNs = xmlSearchNsByHref(pNode->doc, pNode, pUri);
64         // if (!pNs) hmm... now what? throw?
65         if (!pNs) { OSL_TRACE("CAtttr: cannot create namespace"); }
66         return pNs;
67     }
68 
IsChildTypeAllowed(NodeType const nodeType)69     bool CAttr::IsChildTypeAllowed(NodeType const nodeType)
70     {
71         switch (nodeType) {
72             case NodeType_TEXT_NODE:
73             case NodeType_ENTITY_REFERENCE_NODE:
74                 return true;
75             default:
76                 return false;
77         }
78     }
79 
getNodeName()80     OUString SAL_CALL CAttr::getNodeName()
81         throw (RuntimeException)
82     {
83         return getName();
84     }
getNodeValue()85     OUString SAL_CALL CAttr::getNodeValue()
86         throw (RuntimeException)
87     {
88         return getValue();
89     }
getLocalName()90     OUString SAL_CALL CAttr::getLocalName()
91         throw (RuntimeException)
92     {
93         return getName();
94     }
95 
96 
97     /**
98     Returns the name of this attribute.
99     */
getName()100     OUString SAL_CALL CAttr::getName() throw (RuntimeException)
101     {
102         ::osl::MutexGuard const g(m_rMutex);
103 
104         if ((0 == m_aNodePtr) || (0 == m_aAttrPtr)) {
105             return ::rtl::OUString();
106         }
107         OUString const aName((char*)m_aAttrPtr->name,
108                 strlen((char*)m_aAttrPtr->name), RTL_TEXTENCODING_UTF8);
109         return aName;
110     }
111 
112     /**
113     The Element node this attribute is attached to or null if this
114     attribute is not in use.
115     */
getOwnerElement()116     Reference< XElement > SAL_CALL CAttr::getOwnerElement()
117         throw (RuntimeException)
118     {
119         ::osl::MutexGuard const g(m_rMutex);
120 
121         if ((0 == m_aNodePtr) || (0 == m_aAttrPtr)) {
122             return 0;
123         }
124         if (0 == m_aAttrPtr->parent) {
125             return 0;
126         }
127         Reference< XElement > const xRet(
128             static_cast< XNode* >(GetOwnerDocument().GetCNode(
129                     m_aAttrPtr->parent).get()),
130             UNO_QUERY_THROW);
131         return xRet;
132     }
133 
134     /**
135     If this attribute was explicitly given a value in the original
136     document, this is true; otherwise, it is false.
137     */
getSpecified()138     sal_Bool SAL_CALL CAttr::getSpecified()
139         throw (RuntimeException)
140     {
141         // FIXME if this DOM implemenatation supported DTDs it would need
142         // to check that this attribute is not default or something
143         return sal_True;
144     }
145 
146     /**
147     On retrieval, the value of the attribute is returned as a string.
148     */
getValue()149     OUString SAL_CALL CAttr::getValue()
150         throw (RuntimeException)
151     {
152         ::osl::MutexGuard const g(m_rMutex);
153 
154         if ((0 == m_aNodePtr) || (0 == m_aAttrPtr)) {
155             return ::rtl::OUString();
156         }
157         if (0 == m_aAttrPtr->children) {
158             return ::rtl::OUString();
159         }
160         char const*const pContent((m_aAttrPtr->children)
161             ? reinterpret_cast<char const*>(m_aAttrPtr->children->content)
162             : "");
163         OUString const ret(pContent, strlen(pContent), RTL_TEXTENCODING_UTF8);
164         return ret;
165     }
166 
167     /**
168     Sets the value of the attribute from a string.
169     */
setValue(const OUString & value)170     void SAL_CALL CAttr::setValue(const OUString& value)
171         throw (RuntimeException, DOMException)
172     {
173         ::osl::ClearableMutexGuard guard(m_rMutex);
174 
175         if ((0 == m_aNodePtr) || (0 == m_aAttrPtr)) {
176             return;
177         }
178 
179         // remember old value (for mutation event)
180         OUString sOldValue = getValue();
181 
182         OString o1 = OUStringToOString(value, RTL_TEXTENCODING_UTF8);
183         xmlChar* xValue = (xmlChar*)o1.getStr();
184         // xmlChar* xName = OUStringToOString(m_aAttrPtr->name, RTL_TEXTENCODING_UTF8).getStr();
185         // this does not work if the attribute was created anew
186         // xmlNodePtr pNode = m_aAttrPtr->parent;
187         // xmlSetProp(pNode, m_aAttrPtr->name, xValue);
188         ::boost::shared_ptr<xmlChar const> const buffer(
189                 xmlEncodeEntitiesReentrant(m_aAttrPtr->doc, xValue), xmlFree);
190         xmlFreeNodeList(m_aAttrPtr->children);
191         m_aAttrPtr->children =
192             xmlStringGetNodeList(m_aAttrPtr->doc, buffer.get());
193         xmlNodePtr tmp = m_aAttrPtr->children;
194         while (tmp != NULL) {
195             tmp->parent = (xmlNodePtr) m_aNodePtr;
196             tmp->doc = m_aAttrPtr->doc;
197             if (tmp->next == NULL)
198                 m_aNodePtr->last = tmp;
199             tmp = tmp->next;
200         }
201 
202         // dispatch DOM events to signal change in attribute value
203         // dispatch DomAttrModified + DOMSubtreeModified
204         OUString sEventName( RTL_CONSTASCII_USTRINGPARAM("DOMAttrModified") );
205         Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
206         Reference< XMutationEvent > event(docevent->createEvent(sEventName),UNO_QUERY);
207         event->initMutationEvent(
208                 sEventName, sal_True, sal_False,
209                 Reference<XNode>( static_cast<XAttr*>( this ) ),
210                 sOldValue, value, getName(), AttrChangeType_MODIFICATION );
211 
212         guard.clear(); // release mutex before calling event handlers
213 
214         dispatchEvent(Reference< XEvent >(event, UNO_QUERY));
215         dispatchSubtreeModified();
216     }
217 
setPrefix(const OUString & prefix)218     void SAL_CALL CAttr::setPrefix(const OUString& prefix)
219         throw (RuntimeException, DOMException)
220     {
221         ::osl::MutexGuard const g(m_rMutex);
222 
223         if (!m_aNodePtr) { return; }
224 
225         if (m_pNamespace.get()) {
226             OSL_ASSERT(!m_aNodePtr->parent);
227             m_pNamespace->second =
228                 OUStringToOString(prefix, RTL_TEXTENCODING_UTF8);
229         } else {
230             CNode::setPrefix(prefix);
231         }
232     }
233 
getPrefix()234     OUString SAL_CALL CAttr::getPrefix()
235         throw (RuntimeException)
236     {
237         ::osl::MutexGuard const g(m_rMutex);
238 
239         if (!m_aNodePtr) { return ::rtl::OUString(); }
240 
241         if (m_pNamespace.get()) {
242             OSL_ASSERT(!m_aNodePtr->parent);
243             OUString const ret(::rtl::OStringToOUString(
244                         m_pNamespace->second, RTL_TEXTENCODING_UTF8));
245             return ret;
246         } else {
247             return CNode::getPrefix();
248         }
249     }
250 
getNamespaceURI()251     OUString SAL_CALL CAttr::getNamespaceURI()
252         throw (RuntimeException)
253     {
254         ::osl::MutexGuard const g(m_rMutex);
255 
256         if (!m_aNodePtr) { return ::rtl::OUString(); }
257 
258         if (m_pNamespace.get()) {
259             OSL_ASSERT(!m_aNodePtr->parent);
260             OUString const ret(::rtl::OStringToOUString(
261                         m_pNamespace->first, RTL_TEXTENCODING_UTF8));
262             return ret;
263         } else {
264             return CNode::getNamespaceURI();
265         }
266     }
267 }
268