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 <osl/diagnose.h>
27 :
28 : #include <com/sun/star/xml/dom/DOMException.hpp>
29 : #include <com/sun/star/xml/dom/events/XMutationEvent.hpp>
30 :
31 : #include <document.hxx>
32 :
33 : using namespace css::uno;
34 : using namespace css::xml::dom;
35 : using namespace css::xml::dom::events;
36 :
37 : namespace DOM
38 : {
39 652381 : CAttr::CAttr(CDocument const& rDocument, ::osl::Mutex const& rMutex,
40 : xmlAttrPtr const pAttr)
41 : : CAttr_Base(rDocument, rMutex,
42 : NodeType_ATTRIBUTE_NODE, reinterpret_cast<xmlNodePtr>(pAttr))
43 652381 : , m_aAttrPtr(pAttr)
44 : {
45 652381 : }
46 :
47 3 : xmlNsPtr CAttr::GetNamespace(xmlNodePtr const pNode)
48 : {
49 3 : if (!m_pNamespace.get()) {
50 1 : return 0;
51 : }
52 : xmlChar const*const pUri(reinterpret_cast<xmlChar const*>(
53 2 : m_pNamespace->first.getStr()));
54 : xmlChar const*const pPrefix(reinterpret_cast<xmlChar const*>(
55 2 : m_pNamespace->second.getStr()));
56 2 : xmlNsPtr pNs = xmlSearchNs(pNode->doc, pNode, pPrefix);
57 2 : if (pNs && (0 != xmlStrcmp(pNs->href, pUri))) {
58 0 : return pNs;
59 : }
60 2 : pNs = xmlNewNs(pNode, pUri, pPrefix);
61 2 : if (pNs) {
62 1 : return pNs;
63 : }
64 1 : pNs = xmlSearchNsByHref(pNode->doc, pNode, pUri);
65 : // if (!pNs) hmm... now what? throw?
66 : if (!pNs) { OSL_TRACE("CAtttr: cannot create namespace"); }
67 1 : return pNs;
68 : }
69 :
70 2 : bool CAttr::IsChildTypeAllowed(NodeType const nodeType)
71 : {
72 2 : switch (nodeType) {
73 : case NodeType_TEXT_NODE:
74 : case NodeType_ENTITY_REFERENCE_NODE:
75 2 : return true;
76 : default:
77 0 : return false;
78 : }
79 : }
80 :
81 4 : OUString SAL_CALL CAttr::getNodeName()
82 : throw (RuntimeException, std::exception)
83 : {
84 4 : return getName();
85 : }
86 591395 : OUString SAL_CALL CAttr::getNodeValue()
87 : throw (RuntimeException, std::exception)
88 : {
89 591395 : return getValue();
90 : }
91 145050 : OUString SAL_CALL CAttr::getLocalName()
92 : throw (RuntimeException, std::exception)
93 : {
94 145050 : return getName();
95 : }
96 :
97 :
98 : /**
99 : Returns the name of this attribute.
100 : */
101 155276 : OUString SAL_CALL CAttr::getName() throw (RuntimeException, std::exception)
102 : {
103 155276 : ::osl::MutexGuard const g(m_rMutex);
104 :
105 155276 : if ((0 == m_aNodePtr) || (0 == m_aAttrPtr)) {
106 0 : return OUString();
107 : }
108 : OUString const aName(reinterpret_cast<char const *>(m_aAttrPtr->name),
109 310552 : strlen(reinterpret_cast<char const *>(m_aAttrPtr->name)), RTL_TEXTENCODING_UTF8);
110 310552 : return aName;
111 : }
112 :
113 : /**
114 : The Element node this attribute is attached to or null if this
115 : attribute is not in use.
116 : */
117 6 : Reference< XElement > SAL_CALL CAttr::getOwnerElement()
118 : throw (RuntimeException, std::exception)
119 : {
120 6 : ::osl::MutexGuard const g(m_rMutex);
121 :
122 6 : if ((0 == m_aNodePtr) || (0 == m_aAttrPtr)) {
123 0 : return 0;
124 : }
125 6 : if (0 == m_aAttrPtr->parent) {
126 3 : return 0;
127 : }
128 : Reference< XElement > const xRet(
129 3 : static_cast< XNode* >(GetOwnerDocument().GetCNode(
130 9 : m_aAttrPtr->parent).get()),
131 6 : UNO_QUERY_THROW);
132 9 : return xRet;
133 : }
134 :
135 : /**
136 : If this attribute was explicitly given a value in the original
137 : document, this is true; otherwise, it is false.
138 : */
139 1 : sal_Bool SAL_CALL CAttr::getSpecified()
140 : throw (RuntimeException, std::exception)
141 : {
142 : // FIXME if this DOM implemenatation supported DTDs it would need
143 : // to check that this attribute is not default or something
144 1 : return sal_True;
145 : }
146 :
147 : /**
148 : On retrieval, the value of the attribute is returned as a string.
149 : */
150 601616 : OUString SAL_CALL CAttr::getValue()
151 : throw (RuntimeException, std::exception)
152 : {
153 601616 : ::osl::MutexGuard const g(m_rMutex);
154 :
155 601616 : if ((0 == m_aNodePtr) || (0 == m_aAttrPtr)) {
156 0 : return OUString();
157 : }
158 601616 : if (0 == m_aAttrPtr->children) {
159 11 : return OUString();
160 : }
161 : char const*const pContent((m_aAttrPtr->children)
162 : ? reinterpret_cast<char const*>(m_aAttrPtr->children->content)
163 601605 : : "");
164 1203210 : OUString const ret(pContent, strlen(pContent), RTL_TEXTENCODING_UTF8);
165 1203221 : return ret;
166 : }
167 :
168 : /**
169 : Sets the value of the attribute from a string.
170 : */
171 12 : void SAL_CALL CAttr::setValue(const OUString& value)
172 : throw (RuntimeException, DOMException, std::exception)
173 : {
174 12 : ::osl::ClearableMutexGuard guard(m_rMutex);
175 :
176 12 : if ((0 == m_aNodePtr) || (0 == m_aAttrPtr)) {
177 12 : return;
178 : }
179 :
180 : // remember old value (for mutation event)
181 24 : OUString sOldValue = getValue();
182 :
183 24 : OString o1 = OUStringToOString(value, RTL_TEXTENCODING_UTF8);
184 12 : xmlChar const * xValue = reinterpret_cast<xmlChar const *>(o1.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 24 : xmlEncodeEntitiesReentrant(m_aAttrPtr->doc, xValue), xmlFree);
190 12 : xmlFreeNodeList(m_aAttrPtr->children);
191 : m_aAttrPtr->children =
192 12 : xmlStringGetNodeList(m_aAttrPtr->doc, buffer.get());
193 12 : xmlNodePtr tmp = m_aAttrPtr->children;
194 34 : while (tmp != NULL) {
195 10 : tmp->parent = m_aNodePtr;
196 10 : tmp->doc = m_aAttrPtr->doc;
197 10 : if (tmp->next == NULL)
198 10 : m_aNodePtr->last = tmp;
199 10 : tmp = tmp->next;
200 : }
201 :
202 : // dispatch DOM events to signal change in attribute value
203 : // dispatch DomAttrModified + DOMSubtreeModified
204 24 : OUString sEventName( "DOMAttrModified" );
205 24 : Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
206 24 : Reference< XMutationEvent > event(docevent->createEvent(sEventName),UNO_QUERY);
207 12 : event->initMutationEvent(
208 : sEventName, sal_True, sal_False,
209 : Reference<XNode>( static_cast<XAttr*>( this ) ),
210 12 : sOldValue, value, getName(), AttrChangeType_MODIFICATION );
211 :
212 12 : guard.clear(); // release mutex before calling event handlers
213 :
214 12 : dispatchEvent(event);
215 24 : dispatchSubtreeModified();
216 : }
217 :
218 1 : void SAL_CALL CAttr::setPrefix(const OUString& prefix)
219 : throw (RuntimeException, DOMException, std::exception)
220 : {
221 1 : ::osl::MutexGuard const g(m_rMutex);
222 :
223 2 : if (!m_aNodePtr) { return; }
224 :
225 1 : if (m_pNamespace.get()) {
226 : OSL_ASSERT(!m_aNodePtr->parent);
227 2 : m_pNamespace->second =
228 1 : OUStringToOString(prefix, RTL_TEXTENCODING_UTF8);
229 : } else {
230 0 : CNode::setPrefix(prefix);
231 1 : }
232 : }
233 :
234 155252 : OUString SAL_CALL CAttr::getPrefix()
235 : throw (RuntimeException, std::exception)
236 : {
237 155252 : ::osl::MutexGuard const g(m_rMutex);
238 :
239 155252 : if (!m_aNodePtr) { return OUString(); }
240 :
241 155252 : if (m_pNamespace.get()) {
242 : OSL_ASSERT(!m_aNodePtr->parent);
243 : OUString const ret(OStringToOUString(
244 2 : m_pNamespace->second, RTL_TEXTENCODING_UTF8));
245 2 : return ret;
246 : } else {
247 155250 : return CNode::getPrefix();
248 155252 : }
249 : }
250 :
251 10207 : OUString SAL_CALL CAttr::getNamespaceURI()
252 : throw (RuntimeException, std::exception)
253 : {
254 10207 : ::osl::MutexGuard const g(m_rMutex);
255 :
256 10207 : if (!m_aNodePtr) { return OUString(); }
257 :
258 10207 : if (m_pNamespace.get()) {
259 : OSL_ASSERT(!m_aNodePtr->parent);
260 : OUString const ret(OStringToOUString(
261 1 : m_pNamespace->first, RTL_TEXTENCODING_UTF8));
262 1 : return ret;
263 : } else {
264 10206 : return CNode::getNamespaceURI();
265 10207 : }
266 : }
267 : }
268 :
269 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|