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