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 <com/sun/star/uno/Sequence.h>
21 : :
22 : : #include "document.hxx"
23 : : #include "attr.hxx"
24 : : #include "element.hxx"
25 : : #include "cdatasection.hxx"
26 : : #include "documentfragment.hxx"
27 : : #include "text.hxx"
28 : : #include "cdatasection.hxx"
29 : : #include "comment.hxx"
30 : : #include "processinginstruction.hxx"
31 : : #include "entityreference.hxx"
32 : : #include "documenttype.hxx"
33 : : #include "elementlist.hxx"
34 : : #include "domimplementation.hxx"
35 : : #include <entity.hxx>
36 : : #include <notation.hxx>
37 : :
38 : : #include "../events/event.hxx"
39 : : #include "../events/mutationevent.hxx"
40 : : #include "../events/uievent.hxx"
41 : : #include "../events/mouseevent.hxx"
42 : : #include "../events/eventdispatcher.hxx"
43 : :
44 : : #include <string.h>
45 : :
46 : : #include <com/sun/star/xml/sax/FastToken.hpp>
47 : : #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
48 : :
49 : : namespace DOM
50 : : {
51 : 2 : static xmlNodePtr lcl_getDocumentType(xmlDocPtr const i_pDocument)
52 : : {
53 : : // find the doc type
54 : 2 : xmlNodePtr cur = i_pDocument->children;
55 [ - + ]: 2 : while (cur != NULL)
56 : : {
57 [ # # ][ # # ]: 0 : if ((cur->type == XML_DOCUMENT_TYPE_NODE) ||
58 : : (cur->type == XML_DTD_NODE)) {
59 : 0 : return cur;
60 : : }
61 : : }
62 : 2 : return 0;
63 : : }
64 : :
65 : : /// get the pointer to the root element node of the document
66 : 12060 : static xmlNodePtr lcl_getDocumentRootPtr(xmlDocPtr const i_pDocument)
67 : : {
68 : : // find the document element
69 : 12060 : xmlNodePtr cur = i_pDocument->children;
70 [ + + ]: 14168 : while (cur != NULL)
71 : : {
72 [ + + ]: 10526 : if (cur->type == XML_ELEMENT_NODE)
73 : 8418 : break;
74 : 2108 : cur = cur->next;
75 : : }
76 : 12060 : return cur;
77 : : }
78 : :
79 : 12369 : CDocument::CDocument(xmlDocPtr const pDoc)
80 : : : CDocument_Base(*this, m_Mutex,
81 : : NodeType_DOCUMENT_NODE, reinterpret_cast<xmlNodePtr>(pDoc))
82 : : , m_aDocPtr(pDoc)
83 : : , m_streamListeners()
84 [ + - ][ + - ]: 12369 : , m_pEventDispatcher(new events::CEventDispatcher())
[ + - ][ + - ]
[ + - ][ + - ]
85 : : {
86 : 12369 : }
87 : :
88 : 12369 : ::rtl::Reference<CDocument> CDocument::CreateCDocument(xmlDocPtr const pDoc)
89 : : {
90 [ + - ]: 12369 : ::rtl::Reference<CDocument> const xDoc(new CDocument(pDoc));
91 : : // add the doc itself to its nodemap!
92 : 12369 : xDoc->m_NodeMap.insert(
93 : : nodemap_t::value_type(reinterpret_cast<xmlNodePtr>(pDoc),
94 : : ::std::make_pair(
95 [ + - ]: 12369 : WeakReference<XNode>(static_cast<XDocument*>(xDoc.get())),
96 [ + - ][ + - ]: 37107 : xDoc.get())));
[ + - ]
[ + - + - ]
[ + - ][ + - ]
[ + - ]
97 : 12369 : return xDoc;
98 : : }
99 : :
100 [ + - ][ + - ]: 12201 : CDocument::~CDocument()
101 : : {
102 [ + - ]: 12201 : ::osl::MutexGuard const g(m_Mutex);
103 : : #ifdef DBG_UTIL
104 : : // node map must be empty now, otherwise CDocument must not die!
105 : : for (nodemap_t::iterator i = m_NodeMap.begin();
106 : : i != m_NodeMap.end(); ++i)
107 : : {
108 : : Reference<XNode> const xNode(i->second.first);
109 : : OSL_ENSURE(!xNode.is(),
110 : : "CDocument::~CDocument(): ERROR: live node in document node map!");
111 : : }
112 : : #endif
113 [ + - ][ + - ]: 12201 : xmlFreeDoc(m_aDocPtr);
114 [ - + ]: 24402 : }
115 : :
116 : :
117 : 126501 : events::CEventDispatcher & CDocument::GetEventDispatcher()
118 : : {
119 : 126501 : return *m_pEventDispatcher;
120 : : }
121 : :
122 : 8 : ::rtl::Reference< CElement > CDocument::GetDocumentElement()
123 : : {
124 : 8 : xmlNodePtr const pNode = lcl_getDocumentRootPtr(m_aDocPtr);
125 : : ::rtl::Reference< CElement > const xRet(
126 [ + + ]: 8 : dynamic_cast<CElement*>(GetCNode(pNode).get()));
127 : 8 : return xRet;
128 : : }
129 : :
130 : : void
131 : 156653 : CDocument::RemoveCNode(xmlNodePtr const pNode, CNode const*const pCNode)
132 : : {
133 [ + - ]: 156653 : nodemap_t::iterator const i = m_NodeMap.find(pNode);
134 [ + - ]: 156653 : if (i != m_NodeMap.end()) {
135 : : // #i113681# consider this scenario:
136 : : // T1 calls ~CNode
137 : : // T2 calls getCNode: lookup will find i->second->first invalid
138 : : // so a new CNode is created and inserted
139 : : // T1 calls removeCNode: i->second->second now points to a
140 : : // different CNode instance!
141 : : //
142 : : // check that the CNode is the right one
143 : 156653 : CNode *const pCurrent = i->second.second;
144 [ + - ]: 156653 : if (pCurrent == pCNode) {
145 [ + - ]: 156653 : m_NodeMap.erase(i);
146 : : }
147 : : }
148 : 156653 : }
149 : :
150 : : /** NB: this is the CNode factory.
151 : : it is the only place where CNodes may be instantiated.
152 : : all CNodes must be registered at the m_NodeMap.
153 : : */
154 : : ::rtl::Reference<CNode>
155 : 583248 : CDocument::GetCNode(xmlNodePtr const pNode, bool const bCreate)
156 : : {
157 [ + + ]: 583248 : if (0 == pNode) {
158 : 66965 : return 0;
159 : : }
160 : : //check whether there is already an instance for this node
161 [ + - ]: 516283 : nodemap_t::const_iterator const i = m_NodeMap.find(pNode);
162 [ + + ]: 516283 : if (i != m_NodeMap.end()) {
163 : : // #i113681# check that the CNode is still alive
164 [ + - ]: 359170 : uno::Reference<XNode> const xNode(i->second.first);
165 [ + - ]: 359170 : if (xNode.is())
166 : : {
167 : 359170 : ::rtl::Reference<CNode> ret(i->second.second);
168 : : OSL_ASSERT(ret.is());
169 : 359170 : return ret;
170 [ - + ]: 359170 : }
171 : : }
172 : :
173 [ + + ]: 157113 : if (!bCreate) { return 0; }
174 : :
175 : : // there is not yet an instance wrapping this node,
176 : : // create it and store it in the map
177 : :
178 : 157109 : ::rtl::Reference<CNode> pCNode;
179 [ + + + + : 157109 : switch (pNode->type)
- + + - -
+ - + - ]
180 : : {
181 : : case XML_ELEMENT_NODE:
182 : : // m_aNodeType = NodeType::ELEMENT_NODE;
183 : : pCNode = static_cast< CNode* >(
184 [ + - ][ + - ]: 108199 : new CElement(*this, m_Mutex, pNode));
185 : 108199 : break;
186 : : case XML_TEXT_NODE:
187 : : // m_aNodeType = NodeType::TEXT_NODE;
188 : : pCNode = static_cast< CNode* >(
189 [ + - ][ + - ]: 21795 : new CText(*this, m_Mutex, pNode));
190 : 21795 : break;
191 : : case XML_CDATA_SECTION_NODE:
192 : : // m_aNodeType = NodeType::CDATA_SECTION_NODE;
193 : : pCNode = static_cast< CNode* >(
194 [ + - ][ + - ]: 12 : new CCDATASection(*this, m_Mutex, pNode));
195 : 12 : break;
196 : : case XML_ENTITY_REF_NODE:
197 : : // m_aNodeType = NodeType::ENTITY_REFERENCE_NODE;
198 : : pCNode = static_cast< CNode* >(
199 [ + - ][ + - ]: 10 : new CEntityReference(*this, m_Mutex, pNode));
200 : 10 : break;
201 : : case XML_ENTITY_NODE:
202 : : // m_aNodeType = NodeType::ENTITY_NODE;
203 : : pCNode = static_cast< CNode* >(new CEntity(*this, m_Mutex,
204 [ # # ][ # # ]: 0 : reinterpret_cast<xmlEntityPtr>(pNode)));
205 : 0 : break;
206 : : case XML_PI_NODE:
207 : : // m_aNodeType = NodeType::PROCESSING_INSTRUCTION_NODE;
208 : : pCNode = static_cast< CNode* >(
209 [ + - ][ + - ]: 8 : new CProcessingInstruction(*this, m_Mutex, pNode));
210 : 8 : break;
211 : : case XML_COMMENT_NODE:
212 : : // m_aNodeType = NodeType::COMMENT_NODE;
213 : : pCNode = static_cast< CNode* >(
214 [ + - ][ + - ]: 18 : new CComment(*this, m_Mutex, pNode));
215 : 18 : break;
216 : : case XML_DOCUMENT_NODE:
217 : : // m_aNodeType = NodeType::DOCUMENT_NODE;
218 : : OSL_ENSURE(false, "CDocument::GetCNode is not supposed to"
219 : : " create a CDocument!!!");
220 : : pCNode = static_cast< CNode* >(new CDocument(
221 [ # # ][ # # ]: 0 : reinterpret_cast<xmlDocPtr>(pNode)));
222 : 0 : break;
223 : : case XML_DOCUMENT_TYPE_NODE:
224 : : case XML_DTD_NODE:
225 : : // m_aNodeType = NodeType::DOCUMENT_TYPE_NODE;
226 : : pCNode = static_cast< CNode* >(new CDocumentType(*this, m_Mutex,
227 [ # # ][ # # ]: 0 : reinterpret_cast<xmlDtdPtr>(pNode)));
228 : 0 : break;
229 : : case XML_DOCUMENT_FRAG_NODE:
230 : : // m_aNodeType = NodeType::DOCUMENT_FRAGMENT_NODE;
231 : : pCNode = static_cast< CNode* >(
232 [ + - ][ + - ]: 8 : new CDocumentFragment(*this, m_Mutex, pNode));
233 : 8 : break;
234 : : case XML_NOTATION_NODE:
235 : : // m_aNodeType = NodeType::NOTATION_NODE;
236 : : pCNode = static_cast< CNode* >(new CNotation(*this, m_Mutex,
237 [ # # ][ # # ]: 0 : reinterpret_cast<xmlNotationPtr>(pNode)));
238 : 0 : break;
239 : : case XML_ATTRIBUTE_NODE:
240 : : // m_aNodeType = NodeType::ATTRIBUTE_NODE;
241 : : pCNode = static_cast< CNode* >(new CAttr(*this, m_Mutex,
242 [ + - ][ + - ]: 27059 : reinterpret_cast<xmlAttrPtr>(pNode)));
243 : 27059 : break;
244 : : // unsupported node types
245 : : case XML_HTML_DOCUMENT_NODE:
246 : : case XML_ELEMENT_DECL:
247 : : case XML_ATTRIBUTE_DECL:
248 : : case XML_ENTITY_DECL:
249 : : case XML_NAMESPACE_DECL:
250 : : default:
251 : 0 : break;
252 : : }
253 : :
254 [ + - ]: 157109 : if (pCNode != 0) {
255 : : bool const bInserted = m_NodeMap.insert(
256 : : nodemap_t::value_type(pNode,
257 [ + - ]: 157109 : ::std::make_pair(WeakReference<XNode>(pCNode.get()),
258 : 157109 : pCNode.get()))
259 [ + - ][ + - ]: 157109 : ).second;
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
260 : : OSL_ASSERT(bInserted);
261 [ - + ]: 157109 : if (!bInserted) {
262 : : // if insertion failed, delete new instance and return null
263 : 0 : return 0;
264 : : }
265 : : }
266 : :
267 : : OSL_ENSURE(pCNode.is(), "no node produced during CDocument::GetCNode!");
268 : 583248 : return pCNode;
269 : : }
270 : :
271 : :
272 : 45263 : CDocument & CDocument::GetOwnerDocument()
273 : : {
274 : 45263 : return *this;
275 : : }
276 : :
277 : 50 : void CDocument::saxify(const Reference< XDocumentHandler >& i_xHandler)
278 : : {
279 : 50 : i_xHandler->startDocument();
280 [ + + ]: 100 : for (xmlNodePtr pChild = m_aNodePtr->children;
281 : : pChild != 0; pChild = pChild->next) {
282 [ + - ]: 50 : ::rtl::Reference<CNode> const pNode = GetCNode(pChild);
283 : : OSL_ENSURE(pNode != 0, "CNode::get returned 0");
284 [ + - ]: 50 : pNode->saxify(i_xHandler);
285 : 50 : }
286 : 50 : i_xHandler->endDocument();
287 : 50 : }
288 : :
289 : 15 : void CDocument::fastSaxify( Context& rContext )
290 : : {
291 : 15 : rContext.mxDocHandler->startDocument();
292 [ + + ]: 30 : for (xmlNodePtr pChild = m_aNodePtr->children;
293 : : pChild != 0; pChild = pChild->next) {
294 [ + - ]: 15 : ::rtl::Reference<CNode> const pNode = GetCNode(pChild);
295 : : OSL_ENSURE(pNode != 0, "CNode::get returned 0");
296 [ + - ]: 15 : pNode->fastSaxify(rContext);
297 : 15 : }
298 : 15 : rContext.mxDocHandler->endDocument();
299 : 15 : }
300 : :
301 : 3636 : bool CDocument::IsChildTypeAllowed(NodeType const nodeType)
302 : : {
303 [ + + - - ]: 3636 : switch (nodeType) {
304 : : case NodeType_PROCESSING_INSTRUCTION_NODE:
305 : : case NodeType_COMMENT_NODE:
306 : 4 : return true;
307 : : case NodeType_ELEMENT_NODE:
308 : : // there may be only one!
309 : 3632 : return 0 == lcl_getDocumentRootPtr(m_aDocPtr);
310 : : case NodeType_DOCUMENT_TYPE_NODE:
311 : : // there may be only one!
312 : 0 : return 0 == lcl_getDocumentType(m_aDocPtr);
313 : : default:
314 : 3636 : return false;
315 : : }
316 : : }
317 : :
318 : :
319 : 0 : void SAL_CALL CDocument::addListener(const Reference< XStreamListener >& aListener )
320 : : throw (RuntimeException)
321 : : {
322 [ # # ]: 0 : ::osl::MutexGuard const g(m_Mutex);
323 : :
324 [ # # ][ # # ]: 0 : m_streamListeners.insert(aListener);
325 : 0 : }
326 : :
327 : 0 : void SAL_CALL CDocument::removeListener(const Reference< XStreamListener >& aListener )
328 : : throw (RuntimeException)
329 : : {
330 [ # # ]: 0 : ::osl::MutexGuard const g(m_Mutex);
331 : :
332 [ # # ][ # # ]: 0 : m_streamListeners.erase(aListener);
333 : 0 : }
334 : :
335 : : // IO context functions for libxml2 interaction
336 : : typedef struct {
337 : : Reference< XOutputStream > stream;
338 : : bool allowClose;
339 : 3308 : } IOContext;
340 : :
341 : : extern "C" {
342 : : // write callback
343 : : // int xmlOutputWriteCallback (void * context, const char * buffer, int len)
344 : 5416 : static int writeCallback(void *context, const char* buffer, int len){
345 : : // create a sequence and write it to the stream
346 : 5416 : IOContext *pContext = static_cast<IOContext*>(context);
347 [ + - ]: 5416 : Sequence<sal_Int8> bs(reinterpret_cast<const sal_Int8*>(buffer), len);
348 [ + - ][ + - ]: 5416 : pContext->stream->writeBytes(bs);
349 [ + - ]: 5416 : return len;
350 : : }
351 : :
352 : : // clsoe callback
353 : : //int xmlOutputCloseCallback (void * context)
354 : 3308 : static int closeCallback(void *context)
355 : : {
356 : 3308 : IOContext *pContext = static_cast<IOContext*>(context);
357 [ - + ]: 3308 : if (pContext->allowClose) {
358 : 0 : pContext->stream->closeOutput();
359 : : }
360 : 3308 : return 0;
361 : : }
362 : : } // extern "C"
363 : :
364 : 3308 : void SAL_CALL CDocument::start()
365 : : throw (RuntimeException)
366 : : {
367 [ + - ]: 3308 : listenerlist_t streamListeners;
368 : : {
369 [ + - ]: 3308 : ::osl::MutexGuard const g(m_Mutex);
370 : :
371 [ - + ][ # # ]: 3308 : if (! m_rOutputStream.is()) { throw RuntimeException(); }
372 [ + - ][ + - ]: 3308 : streamListeners = m_streamListeners;
373 : : }
374 : :
375 : : // notify listeners about start
376 : 3308 : listenerlist_t::const_iterator iter1 = streamListeners.begin();
377 [ - + ]: 3308 : while (iter1 != streamListeners.end()) {
378 : 0 : Reference< XStreamListener > aListener = *iter1;
379 [ # # ][ # # ]: 0 : aListener->started();
380 : 0 : ++iter1;
381 : 0 : }
382 : :
383 : : {
384 [ + - ]: 3308 : ::osl::MutexGuard const g(m_Mutex);
385 : :
386 : : // check again! could have been reset...
387 [ - + ][ # # ]: 3308 : if (! m_rOutputStream.is()) { throw RuntimeException(); }
388 : :
389 : : // setup libxml IO and write data to output stream
390 : 3308 : IOContext ioctx = {m_rOutputStream, false};
391 : : xmlOutputBufferPtr pOut = xmlOutputBufferCreateIO(
392 [ + - ]: 3308 : writeCallback, closeCallback, &ioctx, NULL);
393 [ + - ][ + - ]: 3308 : xmlSaveFileTo(pOut, m_aNodePtr->doc, NULL);
[ + - ]
394 : : }
395 : :
396 : : // call listeners
397 : 3308 : listenerlist_t::const_iterator iter2 = streamListeners.begin();
398 [ - + ]: 3308 : while (iter2 != streamListeners.end()) {
399 : 0 : Reference< XStreamListener > aListener = *iter2;
400 [ # # ][ # # ]: 0 : aListener->closed();
401 : 0 : ++iter2;
402 : 3308 : }
403 : 3308 : }
404 : :
405 : 0 : void SAL_CALL CDocument::terminate()
406 : : throw (RuntimeException)
407 : : {
408 : : // not supported
409 : 0 : }
410 : :
411 : 3308 : void SAL_CALL CDocument::setOutputStream( const Reference< XOutputStream >& aStream )
412 : : throw (RuntimeException)
413 : : {
414 [ + - ]: 3308 : ::osl::MutexGuard const g(m_Mutex);
415 : :
416 [ + - ][ + - ]: 3308 : m_rOutputStream = aStream;
417 : 3308 : }
418 : :
419 : 0 : Reference< XOutputStream > SAL_CALL CDocument::getOutputStream() throw (RuntimeException)
420 : : {
421 [ # # ]: 0 : ::osl::MutexGuard const g(m_Mutex);
422 : :
423 [ # # ]: 0 : return m_rOutputStream;
424 : : }
425 : :
426 : : // Creates an Attr of the given name.
427 : 10 : Reference< XAttr > SAL_CALL CDocument::createAttribute(const OUString& name)
428 : : throw (RuntimeException, DOMException)
429 : : {
430 [ + - ]: 10 : ::osl::MutexGuard const g(m_Mutex);
431 : :
432 [ + - ]: 10 : OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
433 : 10 : xmlChar *xName = (xmlChar*)o1.getStr();
434 [ + - ]: 10 : xmlAttrPtr const pAttr = xmlNewDocProp(m_aDocPtr, xName, NULL);
435 : : ::rtl::Reference< CAttr > const pCAttr(
436 : : dynamic_cast< CAttr* >(GetCNode(
437 [ + - ][ - + ]: 10 : reinterpret_cast<xmlNodePtr>(pAttr)).get()));
438 : 10 : pCAttr->m_bUnlinked = true;
439 [ + - ][ + - ]: 10 : return pCAttr.get();
[ + - ]
440 : : };
441 : :
442 : : // Creates an attribute of the given qualified name and namespace URI.
443 : 10 : Reference< XAttr > SAL_CALL CDocument::createAttributeNS(
444 : : const OUString& ns, const OUString& qname)
445 : : throw (RuntimeException, DOMException)
446 : : {
447 [ + - ]: 10 : ::osl::MutexGuard const g(m_Mutex);
448 : :
449 : : // libxml does not allow a NS definition to be attached to an
450 : : // attribute node - which is a good thing, since namespaces are
451 : : // only defined as parts of element nodes
452 : : // thus the namespace data is stored in CAttr::m_pNamespace
453 : 10 : sal_Int32 i = qname.indexOf(':');
454 : 10 : OString oPrefix, oName, oUri;
455 [ + + ]: 10 : if (i != -1)
456 : : {
457 [ + - ]: 6 : oPrefix = OUStringToOString(qname.copy(0, i), RTL_TEXTENCODING_UTF8);
458 [ + - ]: 6 : oName = OUStringToOString(qname.copy(i+1, qname.getLength()-i-1), RTL_TEXTENCODING_UTF8);
459 : : }
460 : : else
461 : : {
462 [ + - ]: 4 : oName = OUStringToOString(qname, RTL_TEXTENCODING_UTF8);
463 : : }
464 [ + - ]: 10 : oUri = OUStringToOString(ns, RTL_TEXTENCODING_UTF8);
465 : : xmlAttrPtr const pAttr = xmlNewDocProp(m_aDocPtr,
466 [ + - ]: 10 : reinterpret_cast<xmlChar const*>(oName.getStr()), 0);
467 : : ::rtl::Reference< CAttr > const pCAttr(
468 : : dynamic_cast< CAttr* >(GetCNode(
469 [ + - ][ - + ]: 10 : reinterpret_cast<xmlNodePtr>(pAttr)).get()));
470 [ # # ][ - + ]: 10 : if (!pCAttr.is()) { throw RuntimeException(); }
471 : : // store the namespace data!
472 [ + - ]: 10 : pCAttr->m_pNamespace.reset( new stringpair_t(oUri, oPrefix) );
473 : 10 : pCAttr->m_bUnlinked = true;
474 : :
475 [ + - ][ + - ]: 10 : return pCAttr.get();
[ + - ]
476 : : };
477 : :
478 : : // Creates a CDATASection node whose value is the specified string.
479 : 8 : Reference< XCDATASection > SAL_CALL CDocument::createCDATASection(const OUString& data)
480 : : throw (RuntimeException)
481 : : {
482 [ + - ]: 8 : ::osl::MutexGuard const g(m_Mutex);
483 : :
484 : : OString const oData(
485 [ + - ]: 8 : ::rtl::OUStringToOString(data, RTL_TEXTENCODING_UTF8));
486 : : xmlChar const*const pData =
487 : 8 : reinterpret_cast<xmlChar const*>(oData.getStr());
488 : : xmlNodePtr const pText =
489 [ + - ]: 8 : xmlNewCDataBlock(m_aDocPtr, pData, strlen(oData.getStr()));
490 : : Reference< XCDATASection > const xRet(
491 [ + - ][ + - ]: 16 : static_cast< XNode* >(GetCNode(pText).get()),
492 [ + - ]: 8 : UNO_QUERY_THROW);
493 [ + - ]: 8 : return xRet;
494 : : }
495 : :
496 : : // Creates a Comment node given the specified string.
497 : 14 : Reference< XComment > SAL_CALL CDocument::createComment(const OUString& data)
498 : : throw (RuntimeException)
499 : : {
500 [ + - ]: 14 : ::osl::MutexGuard const g(m_Mutex);
501 : :
502 [ + - ]: 14 : OString o1 = OUStringToOString(data, RTL_TEXTENCODING_UTF8);
503 : 14 : xmlChar *xData = (xmlChar*)o1.getStr();
504 [ + - ]: 14 : xmlNodePtr pComment = xmlNewDocComment(m_aDocPtr, xData);
505 : : Reference< XComment > const xRet(
506 [ + - ][ + - ]: 28 : static_cast< XNode* >(GetCNode(pComment).get()),
507 [ + - ]: 14 : UNO_QUERY_THROW);
508 [ + - ]: 14 : return xRet;
509 : : }
510 : :
511 : : //Creates an empty DocumentFragment object.
512 : 4 : Reference< XDocumentFragment > SAL_CALL CDocument::createDocumentFragment()
513 : : throw (RuntimeException)
514 : : {
515 [ + - ]: 4 : ::osl::MutexGuard const g(m_Mutex);
516 : :
517 [ + - ]: 4 : xmlNodePtr pFrag = xmlNewDocFragment(m_aDocPtr);
518 : : Reference< XDocumentFragment > const xRet(
519 [ + - ][ + - ]: 8 : static_cast< XNode* >(GetCNode(pFrag).get()),
520 [ + - ]: 4 : UNO_QUERY_THROW);
521 [ + - ]: 4 : return xRet;
522 : : }
523 : :
524 : : // Creates an element of the type specified.
525 : 62 : Reference< XElement > SAL_CALL CDocument::createElement(const OUString& tagName)
526 : : throw (RuntimeException, DOMException)
527 : : {
528 [ + - ]: 62 : ::osl::MutexGuard const g(m_Mutex);
529 : :
530 [ + - ]: 62 : OString o1 = OUStringToOString(tagName, RTL_TEXTENCODING_UTF8);
531 : 62 : xmlChar *xName = (xmlChar*)o1.getStr();
532 [ + - ]: 62 : xmlNodePtr const pNode = xmlNewDocNode(m_aDocPtr, NULL, xName, NULL);
533 : : Reference< XElement > const xRet(
534 [ + - ][ + - ]: 124 : static_cast< XNode* >(GetCNode(pNode).get()),
535 [ + - ]: 62 : UNO_QUERY_THROW);
536 [ + - ]: 62 : return xRet;
537 : : }
538 : :
539 : : // Creates an element of the given qualified name and namespace URI.
540 : 27671 : Reference< XElement > SAL_CALL CDocument::createElementNS(
541 : : const OUString& ns, const OUString& qname)
542 : : throw (RuntimeException, DOMException)
543 : : {
544 [ + - ]: 27671 : ::osl::MutexGuard const g(m_Mutex);
545 : :
546 : 27671 : sal_Int32 i = qname.indexOf(':');
547 [ # # ][ - + ]: 27671 : if (ns.isEmpty()) throw RuntimeException();
548 : : xmlChar *xPrefix;
549 : : xmlChar *xName;
550 : 27671 : OString o1, o2, o3;
551 [ + + ]: 27671 : if ( i != -1) {
552 [ + - ]: 27669 : o1 = OUStringToOString(qname.copy(0, i), RTL_TEXTENCODING_UTF8);
553 : 27669 : xPrefix = (xmlChar*)o1.getStr();
554 [ + - ]: 27669 : o2 = OUStringToOString(qname.copy(i+1, qname.getLength()-i-1), RTL_TEXTENCODING_UTF8);
555 : 27669 : xName = (xmlChar*)o2.getStr();
556 : : } else {
557 : : // default prefix
558 : 2 : xPrefix = (xmlChar*)"";
559 [ + - ]: 2 : o2 = OUStringToOString(qname, RTL_TEXTENCODING_UTF8);
560 : 2 : xName = (xmlChar*)o2.getStr();
561 : : }
562 [ + - ]: 27671 : o3 = OUStringToOString(ns, RTL_TEXTENCODING_UTF8);
563 : 27671 : xmlChar *xUri = (xmlChar*)o3.getStr();
564 : :
565 : : // xmlNsPtr aNsPtr = xmlNewReconciledNs?
566 : : // xmlNsPtr aNsPtr = xmlNewGlobalNs?
567 [ + - ]: 27671 : xmlNodePtr const pNode = xmlNewDocNode(m_aDocPtr, NULL, xName, NULL);
568 [ + - ]: 27671 : xmlNsPtr const pNs = xmlNewNs(pNode, xUri, xPrefix);
569 [ + - ]: 27671 : xmlSetNs(pNode, pNs);
570 : : Reference< XElement > const xRet(
571 [ + - ][ + - ]: 55342 : static_cast< XNode* >(GetCNode(pNode).get()),
572 [ + - ]: 27671 : UNO_QUERY_THROW);
573 [ + - ]: 27671 : return xRet;
574 : : }
575 : :
576 : : //Creates an EntityReference object.
577 : 6 : Reference< XEntityReference > SAL_CALL CDocument::createEntityReference(const OUString& name)
578 : : throw (RuntimeException, DOMException)
579 : : {
580 [ + - ]: 6 : ::osl::MutexGuard const g(m_Mutex);
581 : :
582 [ + - ]: 6 : OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
583 : 6 : xmlChar *xName = (xmlChar*)o1.getStr();
584 [ + - ]: 6 : xmlNodePtr const pNode = xmlNewReference(m_aDocPtr, xName);
585 : : Reference< XEntityReference > const xRet(
586 [ + - ][ + - ]: 12 : static_cast< XNode* >(GetCNode(pNode).get()),
587 [ + - ]: 6 : UNO_QUERY_THROW);
588 [ + - ]: 6 : return xRet;
589 : : }
590 : :
591 : : // Creates a ProcessingInstruction node given the specified name and
592 : : // data strings.
593 : 4 : Reference< XProcessingInstruction > SAL_CALL CDocument::createProcessingInstruction(
594 : : const OUString& target, const OUString& data)
595 : : throw (RuntimeException, DOMException)
596 : : {
597 [ + - ]: 4 : ::osl::MutexGuard const g(m_Mutex);
598 : :
599 [ + - ]: 4 : OString o1 = OUStringToOString(target, RTL_TEXTENCODING_UTF8);
600 : 4 : xmlChar *xTarget = (xmlChar*)o1.getStr();
601 [ + - ]: 4 : OString o2 = OUStringToOString(data, RTL_TEXTENCODING_UTF8);
602 : 4 : xmlChar *xData = (xmlChar*)o2.getStr();
603 [ + - ]: 4 : xmlNodePtr const pNode = xmlNewDocPI(m_aDocPtr, xTarget, xData);
604 : 4 : pNode->doc = m_aDocPtr;
605 : : Reference< XProcessingInstruction > const xRet(
606 [ + - ][ + - ]: 8 : static_cast< XNode* >(GetCNode(pNode).get()),
607 [ + - ]: 4 : UNO_QUERY_THROW);
608 [ + - ]: 4 : return xRet;
609 : : }
610 : :
611 : : // Creates a Text node given the specified string.
612 : 13200 : Reference< XText > SAL_CALL CDocument::createTextNode(const OUString& data)
613 : : throw (RuntimeException)
614 : : {
615 [ + - ]: 13200 : ::osl::MutexGuard const g(m_Mutex);
616 : :
617 [ + - ]: 13200 : OString o1 = OUStringToOString(data, RTL_TEXTENCODING_UTF8);
618 : 13200 : xmlChar *xData = (xmlChar*)o1.getStr();
619 [ + - ]: 13200 : xmlNodePtr const pNode = xmlNewDocText(m_aDocPtr, xData);
620 : : Reference< XText > const xRet(
621 [ + - ][ + - ]: 26400 : static_cast< XNode* >(GetCNode(pNode).get()),
622 [ + - ]: 13200 : UNO_QUERY_THROW);
623 [ + - ]: 13200 : return xRet;
624 : : }
625 : :
626 : : // The Document Type Declaration (see DocumentType) associated with this
627 : : // document.
628 : 2 : Reference< XDocumentType > SAL_CALL CDocument::getDoctype()
629 : : throw (RuntimeException)
630 : : {
631 [ + - ]: 2 : ::osl::MutexGuard const g(m_Mutex);
632 : :
633 : 2 : xmlNodePtr const pDocType(lcl_getDocumentType(m_aDocPtr));
634 : : Reference< XDocumentType > const xRet(
635 [ - + ][ + - ]: 4 : static_cast< XNode* >(GetCNode(pDocType).get()),
636 [ + - ]: 2 : UNO_QUERY);
637 [ + - ]: 2 : return xRet;
638 : : }
639 : :
640 : : // This is a convenience attribute that allows direct access to the child
641 : : // node that is the root element of the document.
642 : 8351 : Reference< XElement > SAL_CALL CDocument::getDocumentElement()
643 : : throw (RuntimeException)
644 : : {
645 [ + - ]: 8351 : ::osl::MutexGuard const g(m_Mutex);
646 : :
647 : 8351 : xmlNodePtr const pNode = lcl_getDocumentRootPtr(m_aDocPtr);
648 [ + - ][ + + ]: 8351 : if (!pNode) { return 0; }
649 : : Reference< XElement > const xRet(
650 [ + - ][ + - ]: 16694 : static_cast< XNode* >(GetCNode(pNode).get()),
651 [ + - ]: 8347 : UNO_QUERY);
652 [ + - ]: 8351 : return xRet;
653 : : }
654 : :
655 : : static xmlNodePtr
656 : 4 : lcl_search_element_by_id(const xmlNodePtr cur, const xmlChar* id)
657 : : {
658 [ - + ]: 4 : if (cur == NULL)
659 : 0 : return NULL;
660 : : // look in current node
661 [ + - ]: 4 : if (cur->type == XML_ELEMENT_NODE)
662 : : {
663 : 4 : xmlAttrPtr a = cur->properties;
664 [ + + ]: 4 : while (a != NULL)
665 : : {
666 [ + - ]: 2 : if (a->atype == XML_ATTRIBUTE_ID) {
667 [ + - ]: 2 : if (strcmp((char*)a->children->content, (char*)id) == 0)
668 : 2 : return cur;
669 : : }
670 : 0 : a = a->next;
671 : : }
672 : : }
673 : : // look in children
674 : 2 : xmlNodePtr result = lcl_search_element_by_id(cur->children, id);
675 [ + - ]: 2 : if (result != NULL)
676 : 2 : return result;
677 : 0 : result = lcl_search_element_by_id(cur->next, id);
678 : 4 : return result;
679 : : }
680 : :
681 : : // Returns the Element whose ID is given by elementId.
682 : : Reference< XElement > SAL_CALL
683 : 4 : CDocument::getElementById(const OUString& elementId)
684 : : throw (RuntimeException)
685 : : {
686 [ + - ]: 4 : ::osl::MutexGuard const g(m_Mutex);
687 : :
688 : : // search the tree for an element with the given ID
689 [ + - ]: 4 : OString o1 = OUStringToOString(elementId, RTL_TEXTENCODING_UTF8);
690 : 4 : xmlChar *xId = (xmlChar*)o1.getStr();
691 : 4 : xmlNodePtr const pStart = lcl_getDocumentRootPtr(m_aDocPtr);
692 [ + - ][ + + ]: 4 : if (!pStart) { return 0; }
693 [ + - ]: 2 : xmlNodePtr const pNode = lcl_search_element_by_id(pStart, xId);
694 : : Reference< XElement > const xRet(
695 [ + - ][ + - ]: 4 : static_cast< XNode* >(GetCNode(pNode).get()),
696 [ + - ]: 2 : UNO_QUERY);
697 [ + - ]: 4 : return xRet;
698 : : }
699 : :
700 : :
701 : : Reference< XNodeList > SAL_CALL
702 : 4 : CDocument::getElementsByTagName(OUString const& rTagname)
703 : : throw (RuntimeException)
704 : : {
705 [ + - ]: 4 : ::osl::MutexGuard const g(m_Mutex);
706 : :
707 : : Reference< XNodeList > const xRet(
708 [ + - ][ + - ]: 4 : new CElementList(this->GetDocumentElement(), m_Mutex, rTagname));
[ + - ][ + - ]
709 [ + - ]: 4 : return xRet;
710 : : }
711 : :
712 : 4 : Reference< XNodeList > SAL_CALL CDocument::getElementsByTagNameNS(
713 : : OUString const& rNamespaceURI, OUString const& rLocalName)
714 : : throw (RuntimeException)
715 : : {
716 [ + - ]: 4 : ::osl::MutexGuard const g(m_Mutex);
717 : :
718 : : Reference< XNodeList > const xRet(
719 : : new CElementList(this->GetDocumentElement(), m_Mutex,
720 [ + - ][ + - ]: 4 : rLocalName, &rNamespaceURI));
[ + - ][ + - ]
721 [ + - ]: 4 : return xRet;
722 : : }
723 : :
724 : 2 : Reference< XDOMImplementation > SAL_CALL CDocument::getImplementation()
725 : : throw (RuntimeException)
726 : : {
727 : : // does not need mutex currently
728 [ + - ]: 2 : return Reference< XDOMImplementation >(CDOMImplementation::get());
729 : : }
730 : :
731 : : // helper function to recursively import siblings
732 : 752 : static void lcl_ImportSiblings(
733 : : Reference< XDocument > const& xTargetDocument,
734 : : Reference< XNode > const& xTargetParent,
735 : : Reference< XNode > const& xChild)
736 : : {
737 : 752 : Reference< XNode > xSibling = xChild;
738 [ + + ]: 1986 : while (xSibling.is())
739 : : {
740 : : Reference< XNode > const xTmp(
741 [ + - ][ + - ]: 1234 : xTargetDocument->importNode(xSibling, sal_True));
742 [ + - ][ + - ]: 1234 : xTargetParent->appendChild(xTmp);
743 [ + - ][ + - ]: 1234 : xSibling = xSibling->getNextSibling();
[ + - ]
744 : 1986 : }
745 : 752 : }
746 : :
747 : : static Reference< XNode >
748 : 1397 : lcl_ImportNode( Reference< XDocument > const& xDocument,
749 : : Reference< XNode > const& xImportedNode, sal_Bool deep)
750 : : {
751 : 1397 : Reference< XNode > xNode;
752 [ + - ][ + - ]: 1397 : NodeType aNodeType = xImportedNode->getNodeType();
753 [ - - - - : 1397 : switch (aNodeType)
+ - - +
- ]
754 : : {
755 : : case NodeType_ATTRIBUTE_NODE:
756 : : {
757 [ # # ]: 0 : Reference< XAttr > const xAttr(xImportedNode, UNO_QUERY_THROW);
758 : : Reference< XAttr > const xNew =
759 [ # # ][ # # ]: 0 : xDocument->createAttribute(xAttr->getName());
[ # # ][ # # ]
760 [ # # ][ # # ]: 0 : xNew->setValue(xAttr->getValue());
[ # # ][ # # ]
761 [ # # ]: 0 : xNode.set(xNew, UNO_QUERY);
762 : 0 : break;
763 : : }
764 : : case NodeType_CDATA_SECTION_NODE:
765 : : {
766 : : Reference< XCDATASection > const xCData(xImportedNode,
767 [ # # ]: 0 : UNO_QUERY_THROW);
768 : : Reference< XCDATASection > const xNewCData =
769 [ # # ][ # # ]: 0 : xDocument->createCDATASection(xCData->getData());
[ # # ][ # # ]
770 [ # # ]: 0 : xNode.set(xNewCData, UNO_QUERY);
771 : 0 : break;
772 : : }
773 : : case NodeType_COMMENT_NODE:
774 : : {
775 : : Reference< XComment > const xComment(xImportedNode,
776 [ # # ]: 0 : UNO_QUERY_THROW);
777 : : Reference< XComment > const xNewComment =
778 [ # # ][ # # ]: 0 : xDocument->createComment(xComment->getData());
[ # # ][ # # ]
779 [ # # ]: 0 : xNode.set(xNewComment, UNO_QUERY);
780 : 0 : break;
781 : : }
782 : : case NodeType_DOCUMENT_FRAGMENT_NODE:
783 : : {
784 : : Reference< XDocumentFragment > const xFrag(xImportedNode,
785 [ # # ]: 0 : UNO_QUERY_THROW);
786 : : Reference< XDocumentFragment > const xNewFrag =
787 [ # # ][ # # ]: 0 : xDocument->createDocumentFragment();
788 [ # # ]: 0 : xNode.set(xNewFrag, UNO_QUERY);
789 : 0 : break;
790 : : }
791 : : case NodeType_ELEMENT_NODE:
792 : : {
793 : : Reference< XElement > const xElement(xImportedNode,
794 [ + - ]: 881 : UNO_QUERY_THROW);
795 [ + - ][ + - ]: 881 : OUString const aNsUri = xImportedNode->getNamespaceURI();
796 [ + - ][ + - ]: 881 : OUString const aNsPrefix = xImportedNode->getPrefix();
797 [ + - ][ + - ]: 881 : OUString aQName = xElement->getTagName();
798 : 881 : Reference< XElement > xNewElement;
799 [ + + ]: 881 : if (!aNsUri.isEmpty())
800 : : {
801 [ + - ]: 873 : if (!aNsPrefix.isEmpty()) {
802 : 873 : aQName = aNsPrefix + ":" + aQName;
803 : : }
804 [ + - ][ + - ]: 873 : xNewElement = xDocument->createElementNS(aNsUri, aQName);
[ + - ]
805 : : } else {
806 [ + - ][ + - ]: 8 : xNewElement = xDocument->createElement(aQName);
[ + - ]
807 : : }
808 : :
809 : : // get attributes
810 [ + - ][ + - ]: 881 : if (xElement->hasAttributes())
[ + + ]
811 : : {
812 [ + - ][ + - ]: 328 : Reference< XNamedNodeMap > attribs = xElement->getAttributes();
813 [ + - ][ + - ]: 1013 : for (sal_Int32 i = 0; i < attribs->getLength(); i++)
[ + + ]
814 : : {
815 [ + - ]: 685 : Reference< XAttr > const curAttr(attribs->item(i),
816 [ + - ][ + - ]: 685 : UNO_QUERY_THROW);
817 [ + - ][ + - ]: 685 : OUString const aAttrUri = curAttr->getNamespaceURI();
818 [ + - ][ + - ]: 685 : OUString const aAttrPrefix = curAttr->getPrefix();
819 [ + - ][ + - ]: 685 : OUString aAttrName = curAttr->getName();
820 [ + - ][ + - ]: 685 : OUString const sValue = curAttr->getValue();
821 [ + + ]: 685 : if (!aAttrUri.isEmpty())
822 : : {
823 [ + - ]: 681 : if (!aAttrPrefix.isEmpty()) {
824 : 681 : aAttrName = aAttrPrefix + ":" + aAttrName;
825 : : }
826 [ + - ]: 681 : xNewElement->setAttributeNS(
827 [ + - ]: 681 : aAttrUri, aAttrName, sValue);
828 : : } else {
829 [ + - ][ + - ]: 4 : xNewElement->setAttribute(aAttrName, sValue);
830 : : }
831 : 1013 : }
832 : : }
833 [ + - ]: 881 : xNode.set(xNewElement, UNO_QUERY);
834 : 881 : break;
835 : : }
836 : : case NodeType_ENTITY_REFERENCE_NODE:
837 : : {
838 : : Reference< XEntityReference > const xRef(xImportedNode,
839 [ # # ]: 0 : UNO_QUERY_THROW);
840 : : Reference< XEntityReference > const xNewRef(
841 [ # # ][ # # ]: 0 : xDocument->createEntityReference(xRef->getNodeName()));
[ # # ][ # # ]
842 [ # # ]: 0 : xNode.set(xNewRef, UNO_QUERY);
843 : 0 : break;
844 : : }
845 : : case NodeType_PROCESSING_INSTRUCTION_NODE:
846 : : {
847 : : Reference< XProcessingInstruction > const xPi(xImportedNode,
848 [ # # ]: 0 : UNO_QUERY_THROW);
849 : : Reference< XProcessingInstruction > const xNewPi(
850 [ # # ]: 0 : xDocument->createProcessingInstruction(
851 [ # # ][ # # ]: 0 : xPi->getTarget(), xPi->getData()));
[ # # ][ # # ]
[ # # ]
852 [ # # ]: 0 : xNode.set(xNewPi, UNO_QUERY);
853 : 0 : break;
854 : : }
855 : : case NodeType_TEXT_NODE:
856 : : {
857 [ + - ]: 516 : Reference< XText > const xText(xImportedNode, UNO_QUERY_THROW);
858 : : Reference< XText > const xNewText(
859 [ + - ][ + - ]: 516 : xDocument->createTextNode(xText->getData()));
[ + - ][ + - ]
860 [ + - ]: 516 : xNode.set(xNewText, UNO_QUERY);
861 : 516 : break;
862 : : }
863 : : case NodeType_ENTITY_NODE:
864 : : case NodeType_DOCUMENT_NODE:
865 : : case NodeType_DOCUMENT_TYPE_NODE:
866 : : case NodeType_NOTATION_NODE:
867 : : default:
868 : : // can't be imported
869 [ # # ]: 0 : throw RuntimeException();
870 : :
871 : : }
872 [ + + ]: 1397 : if (deep)
873 : : {
874 : : // get children and import them
875 [ + - ][ + - ]: 1395 : Reference< XNode > const xChild = xImportedNode->getFirstChild();
876 [ + + ]: 1395 : if (xChild.is())
877 : : {
878 [ + - ]: 752 : lcl_ImportSiblings(xDocument, xNode, xChild);
879 : 1395 : }
880 : : }
881 : :
882 : : /* DOMNodeInsertedIntoDocument
883 : : * Fired when a node is being inserted into a document,
884 : : * either through direct insertion of the Node or insertion of a
885 : : * subtree in which it is contained. This event is dispatched after
886 : : * the insertion has taken place. The target of this event is the node
887 : : * being inserted. If the Node is being directly inserted the DOMNodeInserted
888 : : * event will fire before the DOMNodeInsertedIntoDocument event.
889 : : * Bubbles: No
890 : : * Cancelable: No
891 : : * Context Info: None
892 : : */
893 [ + - ]: 1397 : if (xNode.is())
894 : : {
895 [ + - ]: 1397 : Reference< XDocumentEvent > const xDocevent(xDocument, UNO_QUERY);
896 [ + - ]: 1397 : Reference< XMutationEvent > const event(xDocevent->createEvent(
897 [ + - ][ + - ]: 1397 : "DOMNodeInsertedIntoDocument"), UNO_QUERY_THROW);
898 [ + - ]: 1397 : event->initMutationEvent(
899 : : "DOMNodeInsertedIntoDocument", sal_True, sal_False, Reference< XNode >(),
900 [ + - ]: 1397 : OUString(), OUString(), OUString(), (AttrChangeType)0 );
901 [ + - ]: 1397 : Reference< XEventTarget > const xDocET(xDocument, UNO_QUERY);
902 [ + - ][ + - ]: 1397 : xDocET->dispatchEvent(Reference< XEvent >(event, UNO_QUERY));
[ + - ]
903 : : }
904 : :
905 : 1397 : return xNode;
906 : : }
907 : :
908 : 1401 : Reference< XNode > SAL_CALL CDocument::importNode(
909 : : Reference< XNode > const& xImportedNode, sal_Bool deep)
910 : : throw (RuntimeException, DOMException)
911 : : {
912 [ + + ][ + - ]: 1401 : if (!xImportedNode.is()) { throw RuntimeException(); }
913 : :
914 : : // NB: this whole operation inherently accesses 2 distinct documents.
915 : : // The imported node could even be from a different DOM implementation,
916 : : // so this implementation cannot make any assumptions about the
917 : : // locking strategy of the imported node.
918 : : // So the import takes no lock on this document;
919 : : // it only calls UNO methods on this document that temporarily
920 : : // lock the document, and UNO methods on the imported node that
921 : : // may temporarily lock the other document.
922 : : // As a consequence, the import is not atomic with regard to
923 : : // concurrent modifications of either document, but it should not
924 : : // deadlock.
925 : : // To ensure that no members are accessed, the implementation is in
926 : : // static non-member functions.
927 : :
928 [ + - ]: 1399 : Reference< XDocument > const xDocument(this);
929 : : // already in doc?
930 [ + - ][ + - ]: 1399 : if (xImportedNode->getOwnerDocument() == xDocument) {
[ + - ][ + + ]
931 : 2 : return xImportedNode;
932 : : }
933 : :
934 : : Reference< XNode > const xNode(
935 [ + - ]: 1397 : lcl_ImportNode(xDocument, xImportedNode, deep) );
936 : 1401 : return xNode;
937 : : }
938 : :
939 : 2 : OUString SAL_CALL CDocument::getNodeName()throw (RuntimeException)
940 : : {
941 : : // does not need mutex currently
942 : 2 : return OUString("#document");
943 : : }
944 : :
945 : 2 : OUString SAL_CALL CDocument::getNodeValue() throw (RuntimeException)
946 : : {
947 : : // does not need mutex currently
948 : 2 : return OUString();
949 : : }
950 : :
951 : 4 : Reference< XNode > SAL_CALL CDocument::cloneNode(sal_Bool bDeep)
952 : : throw (RuntimeException)
953 : : {
954 [ + - ]: 4 : ::osl::MutexGuard const g(m_rMutex);
955 : :
956 : : OSL_ASSERT(0 != m_aNodePtr);
957 [ - + ]: 4 : if (0 == m_aNodePtr) {
958 [ # # ]: 0 : return 0;
959 : : }
960 [ + + ][ + - ]: 4 : xmlDocPtr const pClone(xmlCopyDoc(m_aDocPtr, (bDeep) ? 1 : 0));
961 [ - + ][ # # ]: 4 : if (0 == pClone) { return 0; }
962 : : Reference< XNode > const xRet(
963 [ + - ][ + - ]: 4 : static_cast<CNode*>(CDocument::CreateCDocument(pClone).get()));
[ + - ]
964 [ + - ]: 4 : return xRet;
965 : : }
966 : :
967 : 126487 : Reference< XEvent > SAL_CALL CDocument::createEvent(const OUString& aType) throw (RuntimeException)
968 : : {
969 : : // does not need mutex currently
970 : 126487 : events::CEvent *pEvent = 0;
971 [ + + ][ + + ]: 191103 : if ( aType == "DOMSubtreeModified" || aType == "DOMNodeInserted" || aType == "DOMNodeRemoved"
[ + + + -
+ + + + +
- ][ + - ]
972 : 64417 : || aType == "DOMNodeRemovedFromDocument" || aType == "DOMNodeInsertedIntoDocument" || aType == "DOMAttrModified"
973 : 199 : || aType == "DOMCharacterDataModified")
974 : : {
975 [ + - ]: 126487 : pEvent = new events::CMutationEvent;
976 : :
977 [ # # ][ # # ]: 0 : } else if ( aType == "DOMFocusIn" || aType == "DOMFocusOut" || aType == "DOMActivate")
[ # # ][ # # ]
978 : : {
979 [ # # ]: 0 : pEvent = new events::CUIEvent;
980 [ # # ][ # # ]: 0 : } else if ( aType == "click" || aType == "mousedown" || aType == "mouseup"
[ # # # #
# # # # ]
[ # # ]
981 : 0 : || aType == "mouseover" || aType == "mousemove" || aType == "mouseout" )
982 : : {
983 [ # # ]: 0 : pEvent = new events::CMouseEvent;
984 : : }
985 : : else // generic event
986 : : {
987 [ # # ]: 0 : pEvent = new events::CEvent;
988 : : }
989 [ + - ]: 126487 : return Reference< XEvent >(pEvent);
990 : : }
991 : :
992 : : // ::com::sun::star::xml::sax::XSAXSerializable
993 : 50 : void SAL_CALL CDocument::serialize(
994 : : const Reference< XDocumentHandler >& i_xHandler,
995 : : const Sequence< beans::StringPair >& i_rNamespaces)
996 : : throw (RuntimeException, SAXException)
997 : : {
998 [ + - ]: 50 : ::osl::MutexGuard const g(m_Mutex);
999 : :
1000 : : // add new namespaces to root node
1001 : 50 : xmlNodePtr const pRoot = lcl_getDocumentRootPtr(m_aDocPtr);
1002 [ + - ]: 50 : if (0 != pRoot) {
1003 : 50 : const beans::StringPair * pSeq = i_rNamespaces.getConstArray();
1004 [ + + ]: 1038 : for (const beans::StringPair *pNsDef = pSeq;
1005 : 519 : pNsDef < pSeq + i_rNamespaces.getLength(); ++pNsDef) {
1006 : : OString prefix = OUStringToOString(pNsDef->First,
1007 [ + - ]: 469 : RTL_TEXTENCODING_UTF8);
1008 : : OString href = OUStringToOString(pNsDef->Second,
1009 [ + - ]: 469 : RTL_TEXTENCODING_UTF8);
1010 : : // this will only add the ns if it does not exist already
1011 : 469 : xmlNewNs(pRoot, reinterpret_cast<const xmlChar*>(href.getStr()),
1012 [ + - ]: 938 : reinterpret_cast<const xmlChar*>(prefix.getStr()));
1013 : 469 : }
1014 : : // eliminate duplicate namespace declarations
1015 [ + - ]: 50 : nscleanup(pRoot->children, pRoot);
1016 : : }
1017 [ + - ][ + - ]: 50 : saxify(i_xHandler);
1018 : 50 : }
1019 : :
1020 : : // ::com::sun::star::xml::sax::XFastSAXSerializable
1021 : 15 : void SAL_CALL CDocument::fastSerialize( const Reference< XFastDocumentHandler >& i_xHandler,
1022 : : const Reference< XFastTokenHandler >& i_xTokenHandler,
1023 : : const Sequence< beans::StringPair >& i_rNamespaces,
1024 : : const Sequence< beans::Pair< rtl::OUString, sal_Int32 > >& i_rRegisterNamespaces )
1025 : : throw (SAXException, RuntimeException)
1026 : : {
1027 [ + - ]: 15 : ::osl::MutexGuard const g(m_Mutex);
1028 : :
1029 : : // add new namespaces to root node
1030 : 15 : xmlNodePtr const pRoot = lcl_getDocumentRootPtr(m_aDocPtr);
1031 [ + - ]: 15 : if (0 != pRoot) {
1032 : 15 : const beans::StringPair * pSeq = i_rNamespaces.getConstArray();
1033 [ - + ]: 30 : for (const beans::StringPair *pNsDef = pSeq;
1034 : 15 : pNsDef < pSeq + i_rNamespaces.getLength(); ++pNsDef) {
1035 : : OString prefix = OUStringToOString(pNsDef->First,
1036 [ # # ]: 0 : RTL_TEXTENCODING_UTF8);
1037 : : OString href = OUStringToOString(pNsDef->Second,
1038 [ # # ]: 0 : RTL_TEXTENCODING_UTF8);
1039 : : // this will only add the ns if it does not exist already
1040 : 0 : xmlNewNs(pRoot, reinterpret_cast<const xmlChar*>(href.getStr()),
1041 [ # # ]: 0 : reinterpret_cast<const xmlChar*>(prefix.getStr()));
1042 : 0 : }
1043 : : // eliminate duplicate namespace declarations
1044 [ + - ]: 15 : nscleanup(pRoot->children, pRoot);
1045 : : }
1046 : :
1047 : : Context aContext(i_xHandler,
1048 [ + - ]: 15 : i_xTokenHandler);
1049 : :
1050 : : // register namespace ids
1051 : 15 : const beans::Pair<OUString,sal_Int32>* pSeq = i_rRegisterNamespaces.getConstArray();
1052 [ + + ]: 660 : for (const beans::Pair<OUString,sal_Int32>* pNs = pSeq;
1053 : 330 : pNs < pSeq + i_rRegisterNamespaces.getLength(); ++pNs)
1054 : : {
1055 : : OSL_ENSURE(pNs->Second >= FastToken::NAMESPACE,
1056 : : "CDocument::fastSerialize(): invalid NS token id");
1057 [ + - ]: 315 : aContext.maNamespaceMap[ pNs->First ] = pNs->Second;
1058 : : }
1059 : :
1060 [ + - ][ + - ]: 15 : fastSaxify(aContext);
[ + - ]
1061 : 15 : }
1062 : : }
1063 : :
1064 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|