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