xref: /aoo41x/main/unoxml/source/dom/node.cxx (revision e9cbe144)
1*e9cbe144SAndrew Rist /**************************************************************
2*e9cbe144SAndrew Rist  *
3*e9cbe144SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*e9cbe144SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*e9cbe144SAndrew Rist  * distributed with this work for additional information
6*e9cbe144SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*e9cbe144SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*e9cbe144SAndrew Rist  * "License"); you may not use this file except in compliance
9*e9cbe144SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*e9cbe144SAndrew Rist  *
11*e9cbe144SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*e9cbe144SAndrew Rist  *
13*e9cbe144SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*e9cbe144SAndrew Rist  * software distributed under the License is distributed on an
15*e9cbe144SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*e9cbe144SAndrew Rist  * KIND, either express or implied.  See the License for the
17*e9cbe144SAndrew Rist  * specific language governing permissions and limitations
18*e9cbe144SAndrew Rist  * under the License.
19*e9cbe144SAndrew Rist  *
20*e9cbe144SAndrew Rist  *************************************************************/
21*e9cbe144SAndrew Rist 
22*e9cbe144SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #include <node.hxx>
25cdf0e10cSrcweir 
26cdf0e10cSrcweir #include <stdio.h>
27cdf0e10cSrcweir #include <string.h>
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #include <libxml/xmlstring.h>
30cdf0e10cSrcweir 
31cdf0e10cSrcweir #include <algorithm>
32cdf0e10cSrcweir 
33cdf0e10cSrcweir #include <boost/bind.hpp>
34cdf0e10cSrcweir 
35cdf0e10cSrcweir #include <rtl/uuid.h>
36cdf0e10cSrcweir #include <rtl/instance.hxx>
37cdf0e10cSrcweir #include <osl/mutex.hxx>
38cdf0e10cSrcweir 
39cdf0e10cSrcweir #include <com/sun/star/xml/sax/FastToken.hpp>
40cdf0e10cSrcweir 
41cdf0e10cSrcweir #include <document.hxx>
42cdf0e10cSrcweir #include <attr.hxx>
43cdf0e10cSrcweir #include <childlist.hxx>
44cdf0e10cSrcweir 
45cdf0e10cSrcweir #include "../events/eventdispatcher.hxx"
46cdf0e10cSrcweir #include "../events/mutationevent.hxx"
47cdf0e10cSrcweir 
48cdf0e10cSrcweir 
49cdf0e10cSrcweir 
50cdf0e10cSrcweir using namespace ::com::sun::star;
51cdf0e10cSrcweir 
52cdf0e10cSrcweir 
53cdf0e10cSrcweir namespace {
54cdf0e10cSrcweir     struct UnoTunnelId
55cdf0e10cSrcweir         : public ::rtl::StaticWithInit< Sequence<sal_Int8>, UnoTunnelId >
56cdf0e10cSrcweir     {
operator ()__anon1dd777fe0111::UnoTunnelId57cdf0e10cSrcweir         Sequence<sal_Int8> operator() ()
58cdf0e10cSrcweir         {
59cdf0e10cSrcweir             Sequence<sal_Int8> ret(16);
60cdf0e10cSrcweir             rtl_createUuid(
61cdf0e10cSrcweir                 reinterpret_cast<sal_uInt8*>(ret.getArray()), 0, sal_True);
62cdf0e10cSrcweir             return ret;
63cdf0e10cSrcweir         }
64cdf0e10cSrcweir     };
65cdf0e10cSrcweir }
66cdf0e10cSrcweir 
67cdf0e10cSrcweir namespace DOM
68cdf0e10cSrcweir {
pushContext(Context & io_rContext)69cdf0e10cSrcweir     void pushContext(Context& io_rContext)
70cdf0e10cSrcweir     {
71cdf0e10cSrcweir         io_rContext.maNamespaces.push_back(
72cdf0e10cSrcweir             io_rContext.maNamespaces.back());
73cdf0e10cSrcweir     }
74cdf0e10cSrcweir 
popContext(Context & io_rContext)75cdf0e10cSrcweir     void popContext(Context& io_rContext)
76cdf0e10cSrcweir     {
77cdf0e10cSrcweir         io_rContext.maNamespaces.pop_back();
78cdf0e10cSrcweir     }
79cdf0e10cSrcweir 
addNamespaces(Context & io_rContext,xmlNodePtr pNode)80cdf0e10cSrcweir     void addNamespaces(Context& io_rContext, xmlNodePtr pNode)
81cdf0e10cSrcweir     {
82cdf0e10cSrcweir         // add node's namespaces to current context
83cdf0e10cSrcweir         for (xmlNsPtr pNs = pNode->nsDef; pNs != 0; pNs = pNs->next) {
84cdf0e10cSrcweir             const xmlChar *pPrefix = pNs->prefix;
85cdf0e10cSrcweir             OString prefix(reinterpret_cast<const sal_Char*>(pPrefix),
86cdf0e10cSrcweir                            strlen(reinterpret_cast<const char*>(pPrefix)));
87cdf0e10cSrcweir             const xmlChar *pHref = pNs->href;
88cdf0e10cSrcweir             OUString val(reinterpret_cast<const sal_Char*>(pHref),
89cdf0e10cSrcweir                 strlen(reinterpret_cast<const char*>(pHref)),
90cdf0e10cSrcweir                 RTL_TEXTENCODING_UTF8);
91cdf0e10cSrcweir 
92cdf0e10cSrcweir             OSL_TRACE("Trying to add namespace %s (prefix %s)",
93cdf0e10cSrcweir                       (const char*)pHref, (const char*)pPrefix);
94cdf0e10cSrcweir 
95cdf0e10cSrcweir             Context::NamespaceMapType::iterator aIter=
96cdf0e10cSrcweir                 io_rContext.maNamespaceMap.find(val);
97cdf0e10cSrcweir             if( aIter != io_rContext.maNamespaceMap.end() )
98cdf0e10cSrcweir             {
99cdf0e10cSrcweir                 Context::Namespace aNS;
100cdf0e10cSrcweir                 aNS.maPrefix = prefix;
101cdf0e10cSrcweir                 aNS.mnToken = aIter->second;
102cdf0e10cSrcweir                 aNS.maNamespaceURL = val;
103cdf0e10cSrcweir 
104cdf0e10cSrcweir                 io_rContext.maNamespaces.back().push_back(aNS);
105cdf0e10cSrcweir 
106cdf0e10cSrcweir                 OSL_TRACE("Added with token 0x%x", aIter->second);
107cdf0e10cSrcweir             }
108cdf0e10cSrcweir         }
109cdf0e10cSrcweir     }
110cdf0e10cSrcweir 
getToken(const Context & rContext,const sal_Char * pToken)111cdf0e10cSrcweir     sal_Int32 getToken( const Context& rContext, const sal_Char* pToken )
112cdf0e10cSrcweir     {
113cdf0e10cSrcweir         const Sequence<sal_Int8> aSeq( (sal_Int8*)pToken, strlen( pToken ) );
114cdf0e10cSrcweir         return rContext.mxTokenHandler->getTokenFromUTF8( aSeq );
115cdf0e10cSrcweir     }
116cdf0e10cSrcweir 
getTokenWithPrefix(const Context & rContext,const sal_Char * pPrefix,const sal_Char * pName)117cdf0e10cSrcweir     sal_Int32 getTokenWithPrefix( const Context& rContext, const sal_Char* pPrefix, const sal_Char* pName )
118cdf0e10cSrcweir     {
119cdf0e10cSrcweir         sal_Int32 nNamespaceToken = FastToken::DONTKNOW;
120cdf0e10cSrcweir         OString prefix(pPrefix,
121cdf0e10cSrcweir                        strlen(reinterpret_cast<const char*>(pPrefix)));
122cdf0e10cSrcweir 
123cdf0e10cSrcweir         OSL_TRACE("getTokenWithPrefix(): prefix %s, name %s",
124cdf0e10cSrcweir                   (const char*)pPrefix, (const char*)pName);
125cdf0e10cSrcweir 
126cdf0e10cSrcweir         Context::NamespaceVectorType::value_type::const_iterator aIter;
127cdf0e10cSrcweir         if( (aIter=std::find_if(rContext.maNamespaces.back().begin(),
128cdf0e10cSrcweir                                 rContext.maNamespaces.back().end(),
129cdf0e10cSrcweir                                 boost::bind(std::equal_to<OString>(),
130cdf0e10cSrcweir                                             boost::bind(&Context::Namespace::getPrefix,
131cdf0e10cSrcweir                                                         _1),
132cdf0e10cSrcweir                                             boost::cref(prefix)))) != rContext.maNamespaces.back().end() )
133cdf0e10cSrcweir         {
134cdf0e10cSrcweir             nNamespaceToken = aIter->mnToken;
135cdf0e10cSrcweir             sal_Int32 nNameToken = getToken( rContext, pName );
136cdf0e10cSrcweir             if( nNameToken != FastToken::DONTKNOW )
137cdf0e10cSrcweir                 nNamespaceToken |= nNameToken;
138cdf0e10cSrcweir         }
139cdf0e10cSrcweir 
140cdf0e10cSrcweir         return nNamespaceToken;
141cdf0e10cSrcweir     }
142cdf0e10cSrcweir 
143cdf0e10cSrcweir 
CNode(CDocument const & rDocument,::osl::Mutex const & rMutex,NodeType const & reNodeType,xmlNodePtr const & rpNode)144cdf0e10cSrcweir     CNode::CNode(CDocument const& rDocument, ::osl::Mutex const& rMutex,
145cdf0e10cSrcweir                 NodeType const& reNodeType, xmlNodePtr const& rpNode)
146cdf0e10cSrcweir         :   m_bUnlinked(false)
147cdf0e10cSrcweir         ,   m_aNodeType(reNodeType)
148cdf0e10cSrcweir         ,   m_aNodePtr(rpNode)
149cdf0e10cSrcweir         // keep containing document alive
150cdf0e10cSrcweir         // (but not if this is a document; that would create a leak!)
151cdf0e10cSrcweir         ,   m_xDocument( (m_aNodePtr->type != XML_DOCUMENT_NODE)
152cdf0e10cSrcweir                 ? &const_cast<CDocument&>(rDocument) : 0 )
153cdf0e10cSrcweir         ,   m_rMutex(const_cast< ::osl::Mutex & >(rMutex))
154cdf0e10cSrcweir     {
155cdf0e10cSrcweir         OSL_ASSERT(m_aNodePtr);
156cdf0e10cSrcweir     }
157cdf0e10cSrcweir 
invalidate()158cdf0e10cSrcweir     void CNode::invalidate()
159cdf0e10cSrcweir     {
160cdf0e10cSrcweir         //remove from list if this wrapper goes away
161cdf0e10cSrcweir         if (m_aNodePtr != 0 && m_xDocument.is()) {
162cdf0e10cSrcweir             m_xDocument->RemoveCNode(m_aNodePtr, this);
163cdf0e10cSrcweir         }
164cdf0e10cSrcweir         // #i113663#: unlinked nodes will not be freed by xmlFreeDoc
165cdf0e10cSrcweir         if (m_bUnlinked) {
166cdf0e10cSrcweir             xmlFreeNode(m_aNodePtr);
167cdf0e10cSrcweir         }
168cdf0e10cSrcweir         m_aNodePtr = 0;
169cdf0e10cSrcweir     }
170cdf0e10cSrcweir 
~CNode()171cdf0e10cSrcweir     CNode::~CNode()
172cdf0e10cSrcweir     {
173cdf0e10cSrcweir         // if this is the document itself, the mutex is already freed!
174cdf0e10cSrcweir         if (NodeType_DOCUMENT_NODE == m_aNodeType) {
175cdf0e10cSrcweir             invalidate();
176cdf0e10cSrcweir         } else {
177cdf0e10cSrcweir             ::osl::MutexGuard const g(m_rMutex);
178cdf0e10cSrcweir             invalidate(); // other nodes are still alive so must lock mutex
179cdf0e10cSrcweir         }
180cdf0e10cSrcweir     }
181cdf0e10cSrcweir 
182cdf0e10cSrcweir     CNode *
GetImplementation(uno::Reference<uno::XInterface> const & xNode)183cdf0e10cSrcweir     CNode::GetImplementation(uno::Reference<uno::XInterface> const& xNode)
184cdf0e10cSrcweir     {
185cdf0e10cSrcweir         uno::Reference<lang::XUnoTunnel> const xUnoTunnel(xNode, UNO_QUERY);
186cdf0e10cSrcweir         if (!xUnoTunnel.is()) { return 0; }
187cdf0e10cSrcweir         CNode *const pCNode( reinterpret_cast< CNode* >(
188cdf0e10cSrcweir                         ::sal::static_int_cast< sal_IntPtr >(
189cdf0e10cSrcweir                             xUnoTunnel->getSomething(UnoTunnelId::get()))));
190cdf0e10cSrcweir         return pCNode;
191cdf0e10cSrcweir     }
192cdf0e10cSrcweir 
GetOwnerDocument()193cdf0e10cSrcweir     CDocument & CNode::GetOwnerDocument()
194cdf0e10cSrcweir     {
195cdf0e10cSrcweir         OSL_ASSERT(m_xDocument.is());
196cdf0e10cSrcweir         return *m_xDocument; // needs overriding in CDocument!
197cdf0e10cSrcweir     }
198cdf0e10cSrcweir 
199cdf0e10cSrcweir 
lcl_nsexchange(xmlNodePtr const aNode,xmlNsPtr const oldNs,xmlNsPtr const newNs)200cdf0e10cSrcweir     static void lcl_nsexchange(
201cdf0e10cSrcweir             xmlNodePtr const aNode, xmlNsPtr const oldNs, xmlNsPtr const newNs)
202cdf0e10cSrcweir     {
203cdf0e10cSrcweir         // recursively exchange any references to oldNs with references to newNs
204cdf0e10cSrcweir         xmlNodePtr cur = aNode;
205cdf0e10cSrcweir         while (cur != 0)
206cdf0e10cSrcweir         {
207cdf0e10cSrcweir             if (cur->ns == oldNs)
208cdf0e10cSrcweir                 cur->ns = newNs;
209cdf0e10cSrcweir             if (cur->type == XML_ELEMENT_NODE)
210cdf0e10cSrcweir             {
211cdf0e10cSrcweir                 xmlAttrPtr curAttr = cur->properties;
212cdf0e10cSrcweir                 while(curAttr != 0)
213cdf0e10cSrcweir                 {
214cdf0e10cSrcweir                     if (curAttr->ns == oldNs)
215cdf0e10cSrcweir                         curAttr->ns = newNs;
216cdf0e10cSrcweir                     curAttr = curAttr->next;
217cdf0e10cSrcweir                 }
218cdf0e10cSrcweir                 lcl_nsexchange(cur->children, oldNs, newNs);
219cdf0e10cSrcweir             }
220cdf0e10cSrcweir             cur = cur->next;
221cdf0e10cSrcweir         }
222cdf0e10cSrcweir     }
223cdf0e10cSrcweir 
nscleanup(const xmlNodePtr aNode,const xmlNodePtr aParent)224cdf0e10cSrcweir     /*static*/ void nscleanup(const xmlNodePtr aNode, const xmlNodePtr aParent)
225cdf0e10cSrcweir     {
226cdf0e10cSrcweir         xmlNodePtr cur = aNode;
227cdf0e10cSrcweir 
228cdf0e10cSrcweir         //handle attributes
229cdf0e10cSrcweir         if (cur != NULL && cur->type == XML_ELEMENT_NODE)
230cdf0e10cSrcweir         {
231cdf0e10cSrcweir             xmlAttrPtr curAttr = cur->properties;
232cdf0e10cSrcweir             while(curAttr != 0)
233cdf0e10cSrcweir             {
234cdf0e10cSrcweir                 if (curAttr->ns != NULL)
235cdf0e10cSrcweir                 {
236cdf0e10cSrcweir                     xmlNsPtr ns = xmlSearchNs(cur->doc, aParent, curAttr->ns->prefix);
237cdf0e10cSrcweir                     if (ns != NULL)
238cdf0e10cSrcweir                         curAttr->ns = ns;
239cdf0e10cSrcweir                 }
240cdf0e10cSrcweir                 curAttr = curAttr->next;
241cdf0e10cSrcweir             }
242cdf0e10cSrcweir         }
243cdf0e10cSrcweir 
244cdf0e10cSrcweir         while (cur != NULL)
245cdf0e10cSrcweir         {
246cdf0e10cSrcweir             nscleanup(cur->children, cur);
247cdf0e10cSrcweir             if (cur->ns != NULL)
248cdf0e10cSrcweir             {
249cdf0e10cSrcweir                 xmlNsPtr ns = xmlSearchNs(cur->doc, aParent, cur->ns->prefix);
250cdf0e10cSrcweir                 if (ns != NULL && ns != cur->ns && strcmp((char*)ns->href, (char*)cur->ns->href)==0)
251cdf0e10cSrcweir                 {
252cdf0e10cSrcweir                     xmlNsPtr curDef = cur->nsDef;
253cdf0e10cSrcweir                     xmlNsPtr *refp = &(cur->nsDef); // insert point
254cdf0e10cSrcweir                     while (curDef != NULL)
255cdf0e10cSrcweir                     {
256cdf0e10cSrcweir                         ns = xmlSearchNs(cur->doc, aParent, curDef->prefix);
257cdf0e10cSrcweir                         if (ns != NULL && ns != curDef && strcmp((char*)ns->href, (char*)curDef->href)==0)
258cdf0e10cSrcweir                         {
259cdf0e10cSrcweir                             // reconnect ns pointers in sub-tree to newly found ns before
260cdf0e10cSrcweir                             // removing redundant nsdecl to prevent dangling pointers.
261cdf0e10cSrcweir                             lcl_nsexchange(cur, curDef, ns);
262cdf0e10cSrcweir                             *refp = curDef->next;
263cdf0e10cSrcweir                             xmlFreeNs(curDef);
264cdf0e10cSrcweir                             curDef = *refp;
265cdf0e10cSrcweir                         } else {
266cdf0e10cSrcweir                             refp = &(curDef->next);
267cdf0e10cSrcweir                             curDef = curDef->next;
268cdf0e10cSrcweir                         }
269cdf0e10cSrcweir                     }
270cdf0e10cSrcweir                 }
271cdf0e10cSrcweir             }
272cdf0e10cSrcweir             cur = cur->next;
273cdf0e10cSrcweir         }
274cdf0e10cSrcweir     }
275cdf0e10cSrcweir 
saxify(const Reference<XDocumentHandler> & i_xHandler)276cdf0e10cSrcweir     void CNode::saxify(const Reference< XDocumentHandler >& i_xHandler)
277cdf0e10cSrcweir     {
278cdf0e10cSrcweir         if (!i_xHandler.is()) throw RuntimeException();
279cdf0e10cSrcweir         // default: do nothing
280cdf0e10cSrcweir     }
281cdf0e10cSrcweir 
fastSaxify(Context & io_rContext)282cdf0e10cSrcweir     void CNode::fastSaxify(Context& io_rContext)
283cdf0e10cSrcweir     {
284cdf0e10cSrcweir         if (!io_rContext.mxDocHandler.is()) throw RuntimeException();
285cdf0e10cSrcweir         // default: do nothing
286cdf0e10cSrcweir     }
287cdf0e10cSrcweir 
IsChildTypeAllowed(NodeType const)288cdf0e10cSrcweir     bool CNode::IsChildTypeAllowed(NodeType const /*nodeType*/)
289cdf0e10cSrcweir     {
290cdf0e10cSrcweir         // default: no children allowed
291cdf0e10cSrcweir         return false;
292cdf0e10cSrcweir     }
293cdf0e10cSrcweir 
294cdf0e10cSrcweir     /**
295cdf0e10cSrcweir     Adds the node newChild to the end of the list of children of this node.
296cdf0e10cSrcweir     */
appendChild(Reference<XNode> const & xNewChild)297cdf0e10cSrcweir     Reference< XNode > SAL_CALL CNode::appendChild(
298cdf0e10cSrcweir             Reference< XNode > const& xNewChild)
299cdf0e10cSrcweir         throw (RuntimeException, DOMException)
300cdf0e10cSrcweir     {
301cdf0e10cSrcweir         ::osl::ClearableMutexGuard guard(m_rMutex);
302cdf0e10cSrcweir 
303cdf0e10cSrcweir         if (0 == m_aNodePtr) { return 0; }
304cdf0e10cSrcweir 
305cdf0e10cSrcweir         CNode *const pNewChild(CNode::GetImplementation(xNewChild));
306cdf0e10cSrcweir         if (!pNewChild) { throw RuntimeException(); }
307cdf0e10cSrcweir         xmlNodePtr const cur = pNewChild->GetNodePtr();
308cdf0e10cSrcweir         if (!cur) { throw RuntimeException(); }
309cdf0e10cSrcweir 
310cdf0e10cSrcweir         // error checks:
311cdf0e10cSrcweir         // from other document
312cdf0e10cSrcweir         if (cur->doc != m_aNodePtr->doc) {
313cdf0e10cSrcweir             DOMException e;
314cdf0e10cSrcweir             e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
315cdf0e10cSrcweir             throw e;
316cdf0e10cSrcweir         }
317cdf0e10cSrcweir         // same node
318cdf0e10cSrcweir         if (cur == m_aNodePtr) {
319cdf0e10cSrcweir             DOMException e;
320cdf0e10cSrcweir             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
321cdf0e10cSrcweir             throw e;
322cdf0e10cSrcweir         }
323cdf0e10cSrcweir         if (cur->parent != NULL) {
324cdf0e10cSrcweir             DOMException e;
325cdf0e10cSrcweir             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
326cdf0e10cSrcweir             throw e;
327cdf0e10cSrcweir         }
328cdf0e10cSrcweir         if (!IsChildTypeAllowed(pNewChild->m_aNodeType)) {
329cdf0e10cSrcweir             DOMException e;
330cdf0e10cSrcweir             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
331cdf0e10cSrcweir             throw e;
332cdf0e10cSrcweir         }
333cdf0e10cSrcweir 
334cdf0e10cSrcweir         // check whether this is an attribute node; it needs special handling
335cdf0e10cSrcweir         xmlNodePtr res = NULL;
336cdf0e10cSrcweir         if (cur->type == XML_ATTRIBUTE_NODE)
337cdf0e10cSrcweir         {
338cdf0e10cSrcweir             xmlChar const*const pChildren((cur->children)
339cdf0e10cSrcweir                     ? cur->children->content
340cdf0e10cSrcweir                     : reinterpret_cast<xmlChar const*>(""));
341cdf0e10cSrcweir             CAttr *const pCAttr(dynamic_cast<CAttr *>(pNewChild));
342cdf0e10cSrcweir             if (!pCAttr) { throw RuntimeException(); }
343cdf0e10cSrcweir             xmlNsPtr const pNs( pCAttr->GetNamespace(m_aNodePtr) );
344cdf0e10cSrcweir             if (pNs) {
345cdf0e10cSrcweir                 res = reinterpret_cast<xmlNodePtr>(
346cdf0e10cSrcweir                         xmlNewNsProp(m_aNodePtr, pNs, cur->name, pChildren));
347cdf0e10cSrcweir             } else {
348cdf0e10cSrcweir                 res = reinterpret_cast<xmlNodePtr>(
349cdf0e10cSrcweir                         xmlNewProp(m_aNodePtr, cur->name, pChildren));
350cdf0e10cSrcweir             }
351cdf0e10cSrcweir         }
352cdf0e10cSrcweir         else
353cdf0e10cSrcweir         {
354cdf0e10cSrcweir             res = xmlAddChild(m_aNodePtr, cur);
355cdf0e10cSrcweir 
356cdf0e10cSrcweir             // libxml can do optimization when appending nodes.
357cdf0e10cSrcweir             // if res != cur, something was optimized and the newchild-wrapper
358cdf0e10cSrcweir             // should be updated
359cdf0e10cSrcweir             if (res && (cur != res)) {
360cdf0e10cSrcweir                 pNewChild->invalidate(); // cur has been freed
361cdf0e10cSrcweir             }
362cdf0e10cSrcweir         }
363cdf0e10cSrcweir 
364cdf0e10cSrcweir         if (!res) { return 0; }
365cdf0e10cSrcweir 
366cdf0e10cSrcweir         // use custom ns cleanup instead of
367cdf0e10cSrcweir         // xmlReconciliateNs(m_aNodePtr->doc, m_aNodePtr);
368cdf0e10cSrcweir         // because that will not remove unneeded ns decls
369cdf0e10cSrcweir         nscleanup(res, m_aNodePtr);
370cdf0e10cSrcweir 
371cdf0e10cSrcweir         ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(res);
372cdf0e10cSrcweir 
373cdf0e10cSrcweir         if (!pNode.is()) { return 0; }
374cdf0e10cSrcweir 
375cdf0e10cSrcweir         // dispatch DOMNodeInserted event, target is the new node
376cdf0e10cSrcweir         // this node is the related node
377cdf0e10cSrcweir         // does bubble
378cdf0e10cSrcweir         pNode->m_bUnlinked = false; // will be deleted by xmlFreeDoc
379cdf0e10cSrcweir         Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
380cdf0e10cSrcweir         Reference< XMutationEvent > event(docevent->createEvent(
381cdf0e10cSrcweir             OUString::createFromAscii("DOMNodeInserted")), UNO_QUERY);
382cdf0e10cSrcweir         event->initMutationEvent(OUString::createFromAscii("DOMNodeInserted")
383cdf0e10cSrcweir             , sal_True, sal_False,
384cdf0e10cSrcweir             this,
385cdf0e10cSrcweir             OUString(), OUString(), OUString(), (AttrChangeType)0 );
386cdf0e10cSrcweir 
387cdf0e10cSrcweir         // the following dispatch functions use only UNO interfaces
388cdf0e10cSrcweir         // and call event listeners, so release mutex to prevent deadlocks.
389cdf0e10cSrcweir         guard.clear();
390cdf0e10cSrcweir 
391cdf0e10cSrcweir         dispatchEvent(Reference< XEvent >(event, UNO_QUERY));
392cdf0e10cSrcweir         // dispatch subtree modified for this node
393cdf0e10cSrcweir         dispatchSubtreeModified();
394cdf0e10cSrcweir 
395cdf0e10cSrcweir         return pNode.get();
396cdf0e10cSrcweir     }
397cdf0e10cSrcweir 
398cdf0e10cSrcweir     /**
399cdf0e10cSrcweir     Returns a duplicate of this node, i.e., serves as a generic copy
400cdf0e10cSrcweir     constructor for nodes.
401cdf0e10cSrcweir     */
cloneNode(sal_Bool bDeep)402cdf0e10cSrcweir     Reference< XNode > SAL_CALL CNode::cloneNode(sal_Bool bDeep)
403cdf0e10cSrcweir         throw (RuntimeException)
404cdf0e10cSrcweir     {
405cdf0e10cSrcweir         ::osl::MutexGuard const g(m_rMutex);
406cdf0e10cSrcweir 
407cdf0e10cSrcweir         if (0 == m_aNodePtr) {
408cdf0e10cSrcweir             return 0;
409cdf0e10cSrcweir         }
410cdf0e10cSrcweir         ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(
411cdf0e10cSrcweir             xmlCopyNode(m_aNodePtr, (bDeep) ? 1 : 0));
412cdf0e10cSrcweir         if (!pNode.is()) { return 0; }
413cdf0e10cSrcweir         pNode->m_bUnlinked = true; // not linked yet
414cdf0e10cSrcweir         return pNode.get();
415cdf0e10cSrcweir     }
416cdf0e10cSrcweir 
417cdf0e10cSrcweir     /**
418cdf0e10cSrcweir     A NamedNodeMap containing the attributes of this node (if it is an Element)
419cdf0e10cSrcweir     or null otherwise.
420cdf0e10cSrcweir     */
getAttributes()421cdf0e10cSrcweir     Reference< XNamedNodeMap > SAL_CALL CNode::getAttributes()
422cdf0e10cSrcweir         throw (RuntimeException)
423cdf0e10cSrcweir     {
424cdf0e10cSrcweir         // return empty reference; only element node may override this impl
425cdf0e10cSrcweir         return Reference< XNamedNodeMap>();
426cdf0e10cSrcweir     }
427cdf0e10cSrcweir 
428cdf0e10cSrcweir     /**
429cdf0e10cSrcweir     A NodeList that contains all children of this node.
430cdf0e10cSrcweir     */
getChildNodes()431cdf0e10cSrcweir     Reference< XNodeList > SAL_CALL CNode::getChildNodes()
432cdf0e10cSrcweir         throw (RuntimeException)
433cdf0e10cSrcweir     {
434cdf0e10cSrcweir         ::osl::MutexGuard const g(m_rMutex);
435cdf0e10cSrcweir 
436cdf0e10cSrcweir         if (0 == m_aNodePtr) {
437cdf0e10cSrcweir             return 0;
438cdf0e10cSrcweir         }
439cdf0e10cSrcweir         Reference< XNodeList > const xNodeList(new CChildList(this, m_rMutex));
440cdf0e10cSrcweir         return xNodeList;
441cdf0e10cSrcweir     }
442cdf0e10cSrcweir 
443cdf0e10cSrcweir     /**
444cdf0e10cSrcweir     The first child of this node.
445cdf0e10cSrcweir     */
getFirstChild()446cdf0e10cSrcweir     Reference< XNode > SAL_CALL CNode::getFirstChild()
447cdf0e10cSrcweir         throw (RuntimeException)
448cdf0e10cSrcweir     {
449cdf0e10cSrcweir         ::osl::MutexGuard const g(m_rMutex);
450cdf0e10cSrcweir 
451cdf0e10cSrcweir         if (0 == m_aNodePtr) {
452cdf0e10cSrcweir             return 0;
453cdf0e10cSrcweir         }
454cdf0e10cSrcweir         Reference< XNode > const xNode(
455cdf0e10cSrcweir                 GetOwnerDocument().GetCNode(m_aNodePtr->children).get());
456cdf0e10cSrcweir         return xNode;
457cdf0e10cSrcweir     }
458cdf0e10cSrcweir 
459cdf0e10cSrcweir     /**
460cdf0e10cSrcweir     The last child of this node.
461cdf0e10cSrcweir     */
getLastChild()462cdf0e10cSrcweir     Reference< XNode > SAL_CALL CNode::getLastChild()
463cdf0e10cSrcweir         throw (RuntimeException)
464cdf0e10cSrcweir     {
465cdf0e10cSrcweir         ::osl::MutexGuard const g(m_rMutex);
466cdf0e10cSrcweir 
467cdf0e10cSrcweir         if (0 == m_aNodePtr) {
468cdf0e10cSrcweir             return 0;
469cdf0e10cSrcweir         }
470cdf0e10cSrcweir         Reference< XNode > const xNode(
471cdf0e10cSrcweir             GetOwnerDocument().GetCNode(xmlGetLastChild(m_aNodePtr)).get());
472cdf0e10cSrcweir         return xNode;
473cdf0e10cSrcweir     }
474cdf0e10cSrcweir 
475cdf0e10cSrcweir     /**
476cdf0e10cSrcweir     Returns the local part of the qualified name of this node.
477cdf0e10cSrcweir     */
getLocalName()478cdf0e10cSrcweir     OUString SAL_CALL CNode::getLocalName()
479cdf0e10cSrcweir         throw (RuntimeException)
480cdf0e10cSrcweir     {
481cdf0e10cSrcweir         // see CElement/CAttr
482cdf0e10cSrcweir         return ::rtl::OUString();
483cdf0e10cSrcweir     }
484cdf0e10cSrcweir 
485cdf0e10cSrcweir 
486cdf0e10cSrcweir     /**
487cdf0e10cSrcweir     The namespace URI of this node, or null if it is unspecified.
488cdf0e10cSrcweir     */
getNamespaceURI()489cdf0e10cSrcweir     OUString SAL_CALL CNode::getNamespaceURI()
490cdf0e10cSrcweir         throw (RuntimeException)
491cdf0e10cSrcweir     {
492cdf0e10cSrcweir         ::osl::MutexGuard const g(m_rMutex);
493cdf0e10cSrcweir 
494cdf0e10cSrcweir         OUString aURI;
495cdf0e10cSrcweir         if (m_aNodePtr != NULL &&
496cdf0e10cSrcweir             (m_aNodePtr->type == XML_ELEMENT_NODE || m_aNodePtr->type == XML_ATTRIBUTE_NODE) &&
497cdf0e10cSrcweir             m_aNodePtr->ns != NULL)
498cdf0e10cSrcweir         {
499cdf0e10cSrcweir             const xmlChar* xHref = m_aNodePtr->ns->href;
500cdf0e10cSrcweir             aURI = OUString((sal_Char*)xHref, strlen((char*)xHref), RTL_TEXTENCODING_UTF8);
501cdf0e10cSrcweir         }
502cdf0e10cSrcweir         return aURI;
503cdf0e10cSrcweir     }
504cdf0e10cSrcweir 
505cdf0e10cSrcweir     /**
506cdf0e10cSrcweir     The node immediately following this node.
507cdf0e10cSrcweir     */
getNextSibling()508cdf0e10cSrcweir     Reference< XNode > SAL_CALL CNode::getNextSibling()
509cdf0e10cSrcweir         throw (RuntimeException)
510cdf0e10cSrcweir     {
511cdf0e10cSrcweir         ::osl::MutexGuard const g(m_rMutex);
512cdf0e10cSrcweir 
513cdf0e10cSrcweir         if (0 == m_aNodePtr) {
514cdf0e10cSrcweir             return 0;
515cdf0e10cSrcweir         }
516cdf0e10cSrcweir         Reference< XNode > const xNode(
517cdf0e10cSrcweir                 GetOwnerDocument().GetCNode(m_aNodePtr->next).get());
518cdf0e10cSrcweir         return xNode;
519cdf0e10cSrcweir     }
520cdf0e10cSrcweir 
521cdf0e10cSrcweir     /**
522cdf0e10cSrcweir     The name of this node, depending on its type; see the table above.
523cdf0e10cSrcweir     */
getNodeName()524cdf0e10cSrcweir     OUString SAL_CALL CNode::getNodeName()
525cdf0e10cSrcweir         throw (RuntimeException)
526cdf0e10cSrcweir     {
527cdf0e10cSrcweir         /*
528cdf0e10cSrcweir         Interface  	     nodeName  	            nodeValue  	                    attributes
529cdf0e10cSrcweir         --------------------------------------------------------------------------------------
530cdf0e10cSrcweir         Attr 	         name of attribute 	    value of attribute 	            null
531cdf0e10cSrcweir         CDATASection 	 "#cdata-section" 	    content of the CDATA Section 	null
532cdf0e10cSrcweir         Comment 	     "#comment" 	        content of the comment 	        null
533cdf0e10cSrcweir         Document 	     "#document" 	        null 	                        null
534cdf0e10cSrcweir         DocumentFragment "#document-fragment" 	null 	                        null
535cdf0e10cSrcweir         DocumentType 	 document type name 	null 	                        null
536cdf0e10cSrcweir         Element 	     tag name 	            null 	                        NamedNodeMap
537cdf0e10cSrcweir         Entity 	         entity name 	        null 	                        null
538cdf0e10cSrcweir         EntityReference  name of entity         null 	                        null
539cdf0e10cSrcweir                          referenced
540cdf0e10cSrcweir         Notation 	     notation name 	        null 	                        null
541cdf0e10cSrcweir         Processing\   	 target                 entire content excluding        null
542cdf0e10cSrcweir         Instruction 	                        the target
543cdf0e10cSrcweir         Text 	         "#text" 	            content of the text node     	null
544cdf0e10cSrcweir         */
545cdf0e10cSrcweir         OUString aName;
546cdf0e10cSrcweir         return aName;
547cdf0e10cSrcweir     }
548cdf0e10cSrcweir 
549cdf0e10cSrcweir     /**
550cdf0e10cSrcweir     A code representing the type of the underlying object, as defined above.
551cdf0e10cSrcweir     */
getNodeType()552cdf0e10cSrcweir     NodeType SAL_CALL CNode::getNodeType()
553cdf0e10cSrcweir         throw (RuntimeException)
554cdf0e10cSrcweir     {
555cdf0e10cSrcweir         ::osl::MutexGuard const g(m_rMutex);
556cdf0e10cSrcweir 
557cdf0e10cSrcweir         return m_aNodeType;
558cdf0e10cSrcweir     }
559cdf0e10cSrcweir 
560cdf0e10cSrcweir     /**
561cdf0e10cSrcweir     The value of this node, depending on its type; see the table above.
562cdf0e10cSrcweir     */
getNodeValue()563cdf0e10cSrcweir     OUString SAL_CALL CNode::getNodeValue()
564cdf0e10cSrcweir         throw (RuntimeException)
565cdf0e10cSrcweir     {
566cdf0e10cSrcweir         OUString aValue;
567cdf0e10cSrcweir         return aValue;
568cdf0e10cSrcweir     }
569cdf0e10cSrcweir 
570cdf0e10cSrcweir     /**
571cdf0e10cSrcweir     The Document object associated with this node.
572cdf0e10cSrcweir     */
getOwnerDocument()573cdf0e10cSrcweir     Reference< XDocument > SAL_CALL CNode::getOwnerDocument()
574cdf0e10cSrcweir         throw (RuntimeException)
575cdf0e10cSrcweir     {
576cdf0e10cSrcweir         ::osl::MutexGuard const g(m_rMutex);
577cdf0e10cSrcweir 
578cdf0e10cSrcweir         if (0 == m_aNodePtr) {
579cdf0e10cSrcweir             return 0;
580cdf0e10cSrcweir         }
581cdf0e10cSrcweir         Reference< XDocument > const xDoc(& GetOwnerDocument());
582cdf0e10cSrcweir         return xDoc;
583cdf0e10cSrcweir     }
584cdf0e10cSrcweir 
585cdf0e10cSrcweir     /**
586cdf0e10cSrcweir     The parent of this node.
587cdf0e10cSrcweir     */
getParentNode()588cdf0e10cSrcweir     Reference< XNode > SAL_CALL CNode::getParentNode()
589cdf0e10cSrcweir         throw (RuntimeException)
590cdf0e10cSrcweir     {
591cdf0e10cSrcweir         ::osl::MutexGuard const g(m_rMutex);
592cdf0e10cSrcweir 
593cdf0e10cSrcweir         if (0 == m_aNodePtr) {
594cdf0e10cSrcweir             return 0;
595cdf0e10cSrcweir         }
596cdf0e10cSrcweir         Reference< XNode > const xNode(
597cdf0e10cSrcweir                 GetOwnerDocument().GetCNode(m_aNodePtr->parent).get());
598cdf0e10cSrcweir         return xNode;
599cdf0e10cSrcweir     }
600cdf0e10cSrcweir 
601cdf0e10cSrcweir     /**
602cdf0e10cSrcweir     The namespace prefix of this node, or null if it is unspecified.
603cdf0e10cSrcweir     */
getPrefix()604cdf0e10cSrcweir     OUString SAL_CALL CNode::getPrefix()
605cdf0e10cSrcweir         throw (RuntimeException)
606cdf0e10cSrcweir     {
607cdf0e10cSrcweir         ::osl::MutexGuard const g(m_rMutex);
608cdf0e10cSrcweir 
609cdf0e10cSrcweir         OUString aPrefix;
610cdf0e10cSrcweir         if (m_aNodePtr != NULL &&
611cdf0e10cSrcweir             (m_aNodePtr->type == XML_ELEMENT_NODE || m_aNodePtr->type == XML_ATTRIBUTE_NODE) &&
612cdf0e10cSrcweir             m_aNodePtr->ns != NULL)
613cdf0e10cSrcweir         {
614cdf0e10cSrcweir             const xmlChar* xPrefix = m_aNodePtr->ns->prefix;
615cdf0e10cSrcweir             if( xPrefix != NULL )
616cdf0e10cSrcweir                 aPrefix = OUString((sal_Char*)xPrefix, strlen((char*)xPrefix), RTL_TEXTENCODING_UTF8);
617cdf0e10cSrcweir         }
618cdf0e10cSrcweir         return aPrefix;
619cdf0e10cSrcweir 
620cdf0e10cSrcweir     }
621cdf0e10cSrcweir 
622cdf0e10cSrcweir     /**
623cdf0e10cSrcweir     The node immediately preceding this node.
624cdf0e10cSrcweir     */
getPreviousSibling()625cdf0e10cSrcweir     Reference< XNode > SAL_CALL CNode::getPreviousSibling()
626cdf0e10cSrcweir         throw (RuntimeException)
627cdf0e10cSrcweir     {
628cdf0e10cSrcweir         ::osl::MutexGuard const g(m_rMutex);
629cdf0e10cSrcweir 
630cdf0e10cSrcweir         if (0 == m_aNodePtr) {
631cdf0e10cSrcweir             return 0;
632cdf0e10cSrcweir         }
633cdf0e10cSrcweir         Reference< XNode > const xNode(
634cdf0e10cSrcweir                 GetOwnerDocument().GetCNode(m_aNodePtr->prev).get());
635cdf0e10cSrcweir         return xNode;
636cdf0e10cSrcweir     }
637cdf0e10cSrcweir 
638cdf0e10cSrcweir     /**
639cdf0e10cSrcweir     Returns whether this node (if it is an element) has any attributes.
640cdf0e10cSrcweir     */
hasAttributes()641cdf0e10cSrcweir     sal_Bool SAL_CALL CNode::hasAttributes()
642cdf0e10cSrcweir         throw (RuntimeException)
643cdf0e10cSrcweir     {
644cdf0e10cSrcweir         ::osl::MutexGuard const g(m_rMutex);
645cdf0e10cSrcweir 
646cdf0e10cSrcweir         return (m_aNodePtr != NULL && m_aNodePtr->properties != NULL);
647cdf0e10cSrcweir     }
648cdf0e10cSrcweir 
649cdf0e10cSrcweir     /**
650cdf0e10cSrcweir     Returns whether this node has any children.
651cdf0e10cSrcweir     */
hasChildNodes()652cdf0e10cSrcweir     sal_Bool SAL_CALL CNode::hasChildNodes()
653cdf0e10cSrcweir         throw (RuntimeException)
654cdf0e10cSrcweir     {
655cdf0e10cSrcweir         ::osl::MutexGuard const g(m_rMutex);
656cdf0e10cSrcweir 
657cdf0e10cSrcweir         return (m_aNodePtr != NULL && m_aNodePtr->children != NULL);
658cdf0e10cSrcweir     }
659cdf0e10cSrcweir 
660cdf0e10cSrcweir     /**
661cdf0e10cSrcweir     Inserts the node newChild before the existing child node refChild.
662cdf0e10cSrcweir     */
insertBefore(const Reference<XNode> & newChild,const Reference<XNode> & refChild)663cdf0e10cSrcweir     Reference< XNode > SAL_CALL CNode::insertBefore(
664cdf0e10cSrcweir             const Reference< XNode >& newChild, const Reference< XNode >& refChild)
665cdf0e10cSrcweir         throw (RuntimeException, DOMException)
666cdf0e10cSrcweir     {
667cdf0e10cSrcweir         if (!newChild.is() || !refChild.is()) { throw RuntimeException(); }
668cdf0e10cSrcweir 
669cdf0e10cSrcweir         if (newChild->getOwnerDocument() != getOwnerDocument()) {
670cdf0e10cSrcweir             DOMException e;
671cdf0e10cSrcweir             e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
672cdf0e10cSrcweir             throw e;
673cdf0e10cSrcweir         }
674cdf0e10cSrcweir         if (refChild->getParentNode() != Reference< XNode >(this)) {
675cdf0e10cSrcweir             DOMException e;
676cdf0e10cSrcweir             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
677cdf0e10cSrcweir             throw e;
678cdf0e10cSrcweir         }
679cdf0e10cSrcweir 
680cdf0e10cSrcweir         ::osl::ClearableMutexGuard guard(m_rMutex);
681cdf0e10cSrcweir 
682cdf0e10cSrcweir         CNode *const pNewNode(CNode::GetImplementation(newChild));
683cdf0e10cSrcweir         CNode *const pRefNode(CNode::GetImplementation(refChild));
684cdf0e10cSrcweir         if (!pNewNode || !pRefNode) { throw RuntimeException(); }
685cdf0e10cSrcweir         xmlNodePtr const pNewChild(pNewNode->GetNodePtr());
686cdf0e10cSrcweir         xmlNodePtr const pRefChild(pRefNode->GetNodePtr());
687cdf0e10cSrcweir         if (!pNewChild || !pRefChild) { throw RuntimeException(); }
688cdf0e10cSrcweir 
689cdf0e10cSrcweir         if (pNewChild == m_aNodePtr) {
690cdf0e10cSrcweir             DOMException e;
691cdf0e10cSrcweir             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
692cdf0e10cSrcweir             throw e;
693cdf0e10cSrcweir         }
694cdf0e10cSrcweir         // already has parent
695cdf0e10cSrcweir         if (pNewChild->parent != NULL)
696cdf0e10cSrcweir         {
697cdf0e10cSrcweir             DOMException e;
698cdf0e10cSrcweir             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
699cdf0e10cSrcweir             throw e;
700cdf0e10cSrcweir         }
701cdf0e10cSrcweir         if (!IsChildTypeAllowed(pNewNode->m_aNodeType)) {
702cdf0e10cSrcweir             DOMException e;
703cdf0e10cSrcweir             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
704cdf0e10cSrcweir             throw e;
705cdf0e10cSrcweir         }
706cdf0e10cSrcweir 
707cdf0e10cSrcweir         // attributes are unordered anyway, so just do appendChild
708cdf0e10cSrcweir         if (XML_ATTRIBUTE_NODE == pNewChild->type) {
709cdf0e10cSrcweir             guard.clear();
710cdf0e10cSrcweir             return appendChild(newChild);
711cdf0e10cSrcweir         }
712cdf0e10cSrcweir 
713cdf0e10cSrcweir         xmlNodePtr cur = m_aNodePtr->children;
714cdf0e10cSrcweir 
715cdf0e10cSrcweir         //search child before which to insert
716cdf0e10cSrcweir         while (cur != NULL)
717cdf0e10cSrcweir         {
718cdf0e10cSrcweir             if (cur == pRefChild) {
719cdf0e10cSrcweir                 // insert before
720cdf0e10cSrcweir                 pNewChild->next = cur;
721cdf0e10cSrcweir                 pNewChild->prev = cur->prev;
722cdf0e10cSrcweir                 cur->prev = pNewChild;
723cdf0e10cSrcweir                 if (pNewChild->prev != NULL) {
724cdf0e10cSrcweir                     pNewChild->prev->next = pNewChild;
725cdf0e10cSrcweir                 }
726cdf0e10cSrcweir                 pNewChild->parent = cur->parent;
727cdf0e10cSrcweir                 if (pNewChild->parent->children == cur) {
728cdf0e10cSrcweir                     pNewChild->parent->children = pNewChild;
729cdf0e10cSrcweir                 }
730cdf0e10cSrcweir                 // do not update parent->last here!
731cdf0e10cSrcweir                 pNewNode->m_bUnlinked = false; // will be deleted by xmlFreeDoc
732cdf0e10cSrcweir                 break;
733cdf0e10cSrcweir             }
734cdf0e10cSrcweir             cur = cur->next;
735cdf0e10cSrcweir         }
736cdf0e10cSrcweir         return refChild;
737cdf0e10cSrcweir     }
738cdf0e10cSrcweir 
739cdf0e10cSrcweir     /**
740cdf0e10cSrcweir     Tests whether the DOM implementation implements a specific feature and
741cdf0e10cSrcweir     that feature is supported by this node.
742cdf0e10cSrcweir     */
isSupported(const OUString &,const OUString &)743cdf0e10cSrcweir   sal_Bool SAL_CALL CNode::isSupported(const OUString& /*feature*/, const OUString& /*ver*/)
744cdf0e10cSrcweir         throw (RuntimeException)
745cdf0e10cSrcweir     {
746cdf0e10cSrcweir         OSL_ENSURE(false, "CNode::isSupported: not implemented (#i113683#)");
747cdf0e10cSrcweir         return sal_False;
748cdf0e10cSrcweir     }
749cdf0e10cSrcweir 
750cdf0e10cSrcweir     /**
751cdf0e10cSrcweir     Puts all Text nodes in the full depth of the sub-tree underneath this
752cdf0e10cSrcweir     Node, including attribute nodes, into a "normal" form where only structure
753cdf0e10cSrcweir     (e.g., elements, comments, processing instructions, CDATA sections, and
754cdf0e10cSrcweir     entity references) separates Text nodes, i.e., there are neither adjacent
755cdf0e10cSrcweir     Text nodes nor empty Text nodes.
756cdf0e10cSrcweir     */
normalize()757cdf0e10cSrcweir     void SAL_CALL CNode::normalize()
758cdf0e10cSrcweir         throw (RuntimeException)
759cdf0e10cSrcweir     {
760cdf0e10cSrcweir         //XXX combine adjacent text nodes and remove empty ones
761cdf0e10cSrcweir         OSL_ENSURE(false, "CNode::normalize: not implemented (#i113683#)");
762cdf0e10cSrcweir     }
763cdf0e10cSrcweir 
764cdf0e10cSrcweir     /**
765cdf0e10cSrcweir     Removes the child node indicated by oldChild from the list of children,
766cdf0e10cSrcweir     and returns it.
767cdf0e10cSrcweir     */
768cdf0e10cSrcweir     Reference< XNode > SAL_CALL
removeChild(const Reference<XNode> & xOldChild)769cdf0e10cSrcweir     CNode::removeChild(const Reference< XNode >& xOldChild)
770cdf0e10cSrcweir         throw (RuntimeException, DOMException)
771cdf0e10cSrcweir     {
772cdf0e10cSrcweir         if (!xOldChild.is()) {
773cdf0e10cSrcweir             throw RuntimeException();
774cdf0e10cSrcweir         }
775cdf0e10cSrcweir 
776cdf0e10cSrcweir         if (xOldChild->getOwnerDocument() != getOwnerDocument()) {
777cdf0e10cSrcweir             DOMException e;
778cdf0e10cSrcweir             e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
779cdf0e10cSrcweir             throw e;
780cdf0e10cSrcweir         }
781cdf0e10cSrcweir         if (xOldChild->getParentNode() != Reference< XNode >(this)) {
782cdf0e10cSrcweir             DOMException e;
783cdf0e10cSrcweir             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
784cdf0e10cSrcweir             throw e;
785cdf0e10cSrcweir         }
786cdf0e10cSrcweir 
787cdf0e10cSrcweir         ::osl::ClearableMutexGuard guard(m_rMutex);
788cdf0e10cSrcweir 
789cdf0e10cSrcweir         if (!m_aNodePtr) { throw RuntimeException(); }
790cdf0e10cSrcweir 
791cdf0e10cSrcweir         Reference<XNode> xReturn( xOldChild );
792cdf0e10cSrcweir 
793cdf0e10cSrcweir         ::rtl::Reference<CNode> const pOld(CNode::GetImplementation(xOldChild));
794cdf0e10cSrcweir         if (!pOld.is()) { throw RuntimeException(); }
795cdf0e10cSrcweir         xmlNodePtr const old = pOld->GetNodePtr();
796cdf0e10cSrcweir         if (!old) { throw RuntimeException(); }
797cdf0e10cSrcweir 
798cdf0e10cSrcweir         if( old->type == XML_ATTRIBUTE_NODE )
799cdf0e10cSrcweir         {
800cdf0e10cSrcweir             xmlAttrPtr pAttr = reinterpret_cast<xmlAttrPtr>(old);
801cdf0e10cSrcweir             xmlRemoveProp( pAttr );
802cdf0e10cSrcweir             pOld->invalidate(); // freed by xmlRemoveProp
803cdf0e10cSrcweir             xReturn.clear();
804cdf0e10cSrcweir         }
805cdf0e10cSrcweir         else
806cdf0e10cSrcweir         {
807cdf0e10cSrcweir             xmlUnlinkNode(old);
808cdf0e10cSrcweir             pOld->m_bUnlinked = true;
809cdf0e10cSrcweir         }
810cdf0e10cSrcweir 
811cdf0e10cSrcweir         /*DOMNodeRemoved
812cdf0e10cSrcweir          * Fired when a node is being removed from its parent node.
813cdf0e10cSrcweir          * This event is dispatched before the node is removed from the tree.
814cdf0e10cSrcweir          * The target of this event is the node being removed.
815cdf0e10cSrcweir          *   Bubbles: Yes
816cdf0e10cSrcweir          *   Cancelable: No
817cdf0e10cSrcweir          *   Context Info: relatedNode holds the parent node
818cdf0e10cSrcweir          */
819cdf0e10cSrcweir         Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
820cdf0e10cSrcweir         Reference< XMutationEvent > event(docevent->createEvent(
821cdf0e10cSrcweir             OUString::createFromAscii("DOMNodeRemoved")), UNO_QUERY);
822cdf0e10cSrcweir         event->initMutationEvent(OUString::createFromAscii("DOMNodeRemoved"),
823cdf0e10cSrcweir             sal_True,
824cdf0e10cSrcweir             sal_False,
825cdf0e10cSrcweir             this,
826cdf0e10cSrcweir             OUString(), OUString(), OUString(), (AttrChangeType)0 );
827cdf0e10cSrcweir 
828cdf0e10cSrcweir         // the following dispatch functions use only UNO interfaces
829cdf0e10cSrcweir         // and call event listeners, so release mutex to prevent deadlocks.
830cdf0e10cSrcweir         guard.clear();
831cdf0e10cSrcweir 
832cdf0e10cSrcweir         dispatchEvent(Reference< XEvent >(event, UNO_QUERY));
833cdf0e10cSrcweir         // subtree modified for this node
834cdf0e10cSrcweir         dispatchSubtreeModified();
835cdf0e10cSrcweir 
836cdf0e10cSrcweir         return xReturn;
837cdf0e10cSrcweir     }
838cdf0e10cSrcweir 
839cdf0e10cSrcweir     /**
840cdf0e10cSrcweir     Replaces the child node oldChild with newChild in the list of children,
841cdf0e10cSrcweir     and returns the oldChild node.
842cdf0e10cSrcweir     */
replaceChild(Reference<XNode> const & xNewChild,Reference<XNode> const & xOldChild)843cdf0e10cSrcweir     Reference< XNode > SAL_CALL CNode::replaceChild(
844cdf0e10cSrcweir             Reference< XNode > const& xNewChild,
845cdf0e10cSrcweir             Reference< XNode > const& xOldChild)
846cdf0e10cSrcweir         throw (RuntimeException, DOMException)
847cdf0e10cSrcweir     {
848cdf0e10cSrcweir         if (!xOldChild.is() || !xNewChild.is()) {
849cdf0e10cSrcweir             throw RuntimeException();
850cdf0e10cSrcweir         }
851cdf0e10cSrcweir 
852cdf0e10cSrcweir         if (xNewChild->getOwnerDocument() != getOwnerDocument()) {
853cdf0e10cSrcweir             DOMException e;
854cdf0e10cSrcweir             e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
855cdf0e10cSrcweir             throw e;
856cdf0e10cSrcweir         }
857cdf0e10cSrcweir         if (xOldChild->getParentNode() != Reference< XNode >(this)) {
858cdf0e10cSrcweir             DOMException e;
859cdf0e10cSrcweir             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
860cdf0e10cSrcweir             throw e;
861cdf0e10cSrcweir         }
862cdf0e10cSrcweir 
863cdf0e10cSrcweir         ::osl::ClearableMutexGuard guard(m_rMutex);
864cdf0e10cSrcweir 
865cdf0e10cSrcweir /*
866cdf0e10cSrcweir         Reference< XNode > aNode = removeChild(oldChild);
867cdf0e10cSrcweir         appendChild(newChild);
868cdf0e10cSrcweir */
869cdf0e10cSrcweir         ::rtl::Reference<CNode> const pOldNode(
870cdf0e10cSrcweir                 CNode::GetImplementation(xOldChild));
871cdf0e10cSrcweir         ::rtl::Reference<CNode> const pNewNode(
872cdf0e10cSrcweir                 CNode::GetImplementation(xNewChild));
873cdf0e10cSrcweir         if (!pOldNode.is() || !pNewNode.is()) { throw RuntimeException(); }
874cdf0e10cSrcweir         xmlNodePtr const pOld = pOldNode->GetNodePtr();
875cdf0e10cSrcweir         xmlNodePtr const pNew = pNewNode->GetNodePtr();
876cdf0e10cSrcweir         if (!pOld || !pNew) { throw RuntimeException(); }
877cdf0e10cSrcweir 
878cdf0e10cSrcweir         if (pNew == m_aNodePtr) {
879cdf0e10cSrcweir             DOMException e;
880cdf0e10cSrcweir             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
881cdf0e10cSrcweir             throw e;
882cdf0e10cSrcweir         }
883cdf0e10cSrcweir         // already has parent
884cdf0e10cSrcweir         if (pNew->parent != NULL) {
885cdf0e10cSrcweir             DOMException e;
886cdf0e10cSrcweir             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
887cdf0e10cSrcweir             throw e;
888cdf0e10cSrcweir         }
889cdf0e10cSrcweir         if (!IsChildTypeAllowed(pNewNode->m_aNodeType)) {
890cdf0e10cSrcweir             DOMException e;
891cdf0e10cSrcweir             e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
892cdf0e10cSrcweir             throw e;
893cdf0e10cSrcweir         }
894cdf0e10cSrcweir 
895cdf0e10cSrcweir         if( pOld->type == XML_ATTRIBUTE_NODE )
896cdf0e10cSrcweir         {
897cdf0e10cSrcweir             // can only replace attribute with attribute
898cdf0e10cSrcweir             if ( pOld->type != pNew->type )
899cdf0e10cSrcweir             {
900cdf0e10cSrcweir                 DOMException e;
901cdf0e10cSrcweir                 e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
902cdf0e10cSrcweir                 throw e;
903cdf0e10cSrcweir             }
904cdf0e10cSrcweir 
905cdf0e10cSrcweir             xmlAttrPtr pAttr = (xmlAttrPtr)pOld;
906cdf0e10cSrcweir             xmlRemoveProp( pAttr );
907cdf0e10cSrcweir             pOldNode->invalidate(); // freed by xmlRemoveProp
908cdf0e10cSrcweir             appendChild(xNewChild);
909cdf0e10cSrcweir         }
910cdf0e10cSrcweir         else
911cdf0e10cSrcweir         {
912cdf0e10cSrcweir 
913cdf0e10cSrcweir         xmlNodePtr cur = m_aNodePtr->children;
914cdf0e10cSrcweir         //find old node in child list
915cdf0e10cSrcweir         while (cur != NULL)
916cdf0e10cSrcweir         {
917cdf0e10cSrcweir             if(cur == pOld)
918cdf0e10cSrcweir             {
919cdf0e10cSrcweir                 // exchange nodes
920cdf0e10cSrcweir                 pNew->prev = pOld->prev;
921cdf0e10cSrcweir                 if (pNew->prev != NULL)
922cdf0e10cSrcweir                     pNew->prev->next = pNew;
923cdf0e10cSrcweir                 pNew->next = pOld->next;
924cdf0e10cSrcweir                 if (pNew->next != NULL)
925cdf0e10cSrcweir                     pNew->next->prev = pNew;
926cdf0e10cSrcweir                 pNew->parent = pOld->parent;
927cdf0e10cSrcweir                 if(pNew->parent->children == pOld)
928cdf0e10cSrcweir                     pNew->parent->children = pNew;
929cdf0e10cSrcweir                 if(pNew->parent->last == pOld)
930cdf0e10cSrcweir                     pNew->parent->last = pNew;
931cdf0e10cSrcweir                 pOld->next = NULL;
932cdf0e10cSrcweir                 pOld->prev = NULL;
933cdf0e10cSrcweir                 pOld->parent = NULL;
934cdf0e10cSrcweir                 pOldNode->m_bUnlinked = true;
935cdf0e10cSrcweir                 pNewNode->m_bUnlinked = false; // will be deleted by xmlFreeDoc
936cdf0e10cSrcweir             }
937cdf0e10cSrcweir             cur = cur->next;
938cdf0e10cSrcweir         }
939cdf0e10cSrcweir         }
940cdf0e10cSrcweir 
941cdf0e10cSrcweir         guard.clear(); // release for calling event handlers
942cdf0e10cSrcweir         dispatchSubtreeModified();
943cdf0e10cSrcweir 
944cdf0e10cSrcweir         return xOldChild;
945cdf0e10cSrcweir     }
946cdf0e10cSrcweir 
dispatchSubtreeModified()947cdf0e10cSrcweir     void CNode::dispatchSubtreeModified()
948cdf0e10cSrcweir     {
949cdf0e10cSrcweir         // only uses UNO interfaces => needs no mutex
950cdf0e10cSrcweir 
951cdf0e10cSrcweir         // dispatch DOMSubtreeModified
952cdf0e10cSrcweir         // target is _this_ node
953cdf0e10cSrcweir         Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
954cdf0e10cSrcweir         Reference< XMutationEvent > event(docevent->createEvent(
955cdf0e10cSrcweir             OUString::createFromAscii("DOMSubtreeModified")), UNO_QUERY);
956cdf0e10cSrcweir         event->initMutationEvent(
957cdf0e10cSrcweir             OUString::createFromAscii("DOMSubtreeModified"), sal_True,
958cdf0e10cSrcweir             sal_False, Reference< XNode >(),
959cdf0e10cSrcweir             OUString(), OUString(), OUString(), (AttrChangeType)0 );
960cdf0e10cSrcweir         dispatchEvent(Reference< XEvent >(event, UNO_QUERY));
961cdf0e10cSrcweir     }
962cdf0e10cSrcweir 
963cdf0e10cSrcweir     /**
964cdf0e10cSrcweir     The value of this node, depending on its type; see the table above.
965cdf0e10cSrcweir     */
setNodeValue(const OUString &)966cdf0e10cSrcweir     void SAL_CALL CNode::setNodeValue(const OUString& /*nodeValue*/)
967cdf0e10cSrcweir         throw (RuntimeException, DOMException)
968cdf0e10cSrcweir     {
969cdf0e10cSrcweir         // use specific node implememntation
970cdf0e10cSrcweir         // if we end up down here, something went wrong
971cdf0e10cSrcweir         DOMException e;
972cdf0e10cSrcweir         e.Code = DOMExceptionType_NO_MODIFICATION_ALLOWED_ERR;
973cdf0e10cSrcweir         throw e;
974cdf0e10cSrcweir     }
975cdf0e10cSrcweir 
976cdf0e10cSrcweir     /**
977cdf0e10cSrcweir     The namespace prefix of this node, or null if it is unspecified.
978cdf0e10cSrcweir     */
setPrefix(const OUString & prefix)979cdf0e10cSrcweir     void SAL_CALL CNode::setPrefix(const OUString& prefix)
980cdf0e10cSrcweir         throw (RuntimeException, DOMException)
981cdf0e10cSrcweir     {
982cdf0e10cSrcweir         ::osl::MutexGuard const g(m_rMutex);
983cdf0e10cSrcweir 
984cdf0e10cSrcweir         if ((0 == m_aNodePtr) ||
985cdf0e10cSrcweir             ((m_aNodePtr->type != XML_ELEMENT_NODE) &&
986cdf0e10cSrcweir              (m_aNodePtr->type != XML_ATTRIBUTE_NODE)))
987cdf0e10cSrcweir         {
988cdf0e10cSrcweir             DOMException e;
989cdf0e10cSrcweir             e.Code = DOMExceptionType_NO_MODIFICATION_ALLOWED_ERR;
990cdf0e10cSrcweir             throw e;
991cdf0e10cSrcweir         }
992cdf0e10cSrcweir         OString o1 = OUStringToOString(prefix, RTL_TEXTENCODING_UTF8);
993cdf0e10cSrcweir         xmlChar *pBuf = (xmlChar*)o1.getStr();
994cdf0e10cSrcweir         if (m_aNodePtr != NULL && m_aNodePtr->ns != NULL)
995cdf0e10cSrcweir         {
996cdf0e10cSrcweir             xmlFree(const_cast<xmlChar *>(m_aNodePtr->ns->prefix));
997cdf0e10cSrcweir             m_aNodePtr->ns->prefix = xmlStrdup(pBuf);
998cdf0e10cSrcweir         }
999cdf0e10cSrcweir 
1000cdf0e10cSrcweir     }
1001cdf0e10cSrcweir 
1002cdf0e10cSrcweir         // --- XEventTarget
addEventListener(const OUString & eventType,const Reference<com::sun::star::xml::dom::events::XEventListener> & listener,sal_Bool useCapture)1003cdf0e10cSrcweir     void SAL_CALL CNode::addEventListener(const OUString& eventType,
1004cdf0e10cSrcweir         const Reference< com::sun::star::xml::dom::events::XEventListener >& listener,
1005cdf0e10cSrcweir         sal_Bool useCapture)
1006cdf0e10cSrcweir         throw (RuntimeException)
1007cdf0e10cSrcweir     {
1008cdf0e10cSrcweir         ::osl::MutexGuard const g(m_rMutex);
1009cdf0e10cSrcweir 
1010cdf0e10cSrcweir         CDocument & rDocument(GetOwnerDocument());
1011cdf0e10cSrcweir         events::CEventDispatcher & rDispatcher(rDocument.GetEventDispatcher());
1012cdf0e10cSrcweir         rDispatcher.addListener(m_aNodePtr, eventType, listener, useCapture);
1013cdf0e10cSrcweir     }
1014cdf0e10cSrcweir 
removeEventListener(const OUString & eventType,const Reference<com::sun::star::xml::dom::events::XEventListener> & listener,sal_Bool useCapture)1015cdf0e10cSrcweir     void SAL_CALL CNode::removeEventListener(const OUString& eventType,
1016cdf0e10cSrcweir         const Reference< com::sun::star::xml::dom::events::XEventListener >& listener,
1017cdf0e10cSrcweir         sal_Bool useCapture)
1018cdf0e10cSrcweir         throw (RuntimeException)
1019cdf0e10cSrcweir     {
1020cdf0e10cSrcweir         ::osl::MutexGuard const g(m_rMutex);
1021cdf0e10cSrcweir 
1022cdf0e10cSrcweir         CDocument & rDocument(GetOwnerDocument());
1023cdf0e10cSrcweir         events::CEventDispatcher & rDispatcher(rDocument.GetEventDispatcher());
1024cdf0e10cSrcweir         rDispatcher.removeListener(m_aNodePtr, eventType, listener, useCapture);
1025cdf0e10cSrcweir     }
1026cdf0e10cSrcweir 
dispatchEvent(const Reference<XEvent> & evt)1027cdf0e10cSrcweir     sal_Bool SAL_CALL CNode::dispatchEvent(const Reference< XEvent >& evt)
1028cdf0e10cSrcweir         throw(RuntimeException, EventException)
1029cdf0e10cSrcweir     {
1030cdf0e10cSrcweir         CDocument * pDocument;
1031cdf0e10cSrcweir         events::CEventDispatcher * pDispatcher;
1032cdf0e10cSrcweir         xmlNodePtr pNode;
1033cdf0e10cSrcweir         {
1034cdf0e10cSrcweir             ::osl::MutexGuard const g(m_rMutex);
1035cdf0e10cSrcweir 
1036cdf0e10cSrcweir             pDocument = & GetOwnerDocument();
1037cdf0e10cSrcweir             pDispatcher = & pDocument->GetEventDispatcher();
1038cdf0e10cSrcweir             pNode = m_aNodePtr;
1039cdf0e10cSrcweir         }
1040cdf0e10cSrcweir         // this calls event listeners, do not call with locked mutex
1041cdf0e10cSrcweir         pDispatcher->dispatchEvent(*pDocument, m_rMutex, pNode, this, evt);
1042cdf0e10cSrcweir         return sal_True;
1043cdf0e10cSrcweir     }
1044cdf0e10cSrcweir 
1045cdf0e10cSrcweir     ::sal_Int64 SAL_CALL
getSomething(Sequence<::sal_Int8> const & rId)1046cdf0e10cSrcweir     CNode::getSomething(Sequence< ::sal_Int8 > const& rId)
1047cdf0e10cSrcweir         throw (RuntimeException)
1048cdf0e10cSrcweir     {
1049cdf0e10cSrcweir         if ((rId.getLength() == 16) &&
1050cdf0e10cSrcweir             (0 == rtl_compareMemory(UnoTunnelId::get().getConstArray(),
1051cdf0e10cSrcweir                                     rId.getConstArray(), 16)))
1052cdf0e10cSrcweir         {
1053cdf0e10cSrcweir             return ::sal::static_int_cast< sal_Int64 >(
1054cdf0e10cSrcweir                     reinterpret_cast< sal_IntPtr >(this) );
1055cdf0e10cSrcweir         }
1056cdf0e10cSrcweir         return 0;
1057cdf0e10cSrcweir     }
1058cdf0e10cSrcweir }
1059cdf0e10cSrcweir 
1060