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