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