xref: /aoo4110/main/unoxml/source/dom/elementlist.cxx (revision b1cdbd2c)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "elementlist.hxx"
25 
26 #include <string.h>
27 
28 #include <element.hxx>
29 #include <document.hxx>
30 
31 
32 namespace DOM
33 {
34 
lcl_initXmlString(::rtl::OUString const & rString)35     static xmlChar* lcl_initXmlString(::rtl::OUString const& rString)
36     {
37         ::rtl::OString const os =
38             ::rtl::OUStringToOString(rString, RTL_TEXTENCODING_UTF8);
39         xmlChar *const pRet = new xmlChar[os.getLength() + 1];
40         strcpy(reinterpret_cast<char*>(pRet), os.getStr());
41         return pRet;
42     }
43 
CElementList(::rtl::Reference<CElement> const & pElement,::osl::Mutex & rMutex,OUString const & rName,OUString const * const pURI)44     CElementList::CElementList(::rtl::Reference<CElement> const& pElement,
45             ::osl::Mutex & rMutex,
46             OUString const& rName, OUString const*const pURI)
47         : m_pElement(pElement)
48         , m_rMutex(rMutex)
49         , m_pName(lcl_initXmlString(rName))
50         , m_pURI((pURI) ? lcl_initXmlString(*pURI) : 0)
51         , m_bRebuild(true)
52     {
53         if (m_pElement.is()) {
54             registerListener(*m_pElement);
55         }
56     }
57 
registerListener(CElement & rElement)58     void CElementList::registerListener(CElement & rElement)
59     {
60         try {
61             Reference< XEventTarget > const xTarget(
62                     static_cast<XElement*>(& rElement), UNO_QUERY_THROW);
63             OUString aType = OUString::createFromAscii("DOMSubtreeModified");
64             sal_Bool capture = sal_False;
65             xTarget->addEventListener(aType,
66                     Reference< XEventListener >(this), capture);
67         } catch (Exception &e){
68             OString aMsg("Exception caught while registering NodeList as listener:\n");
69             aMsg += OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
70             OSL_ENSURE(sal_False, aMsg.getStr());
71         }
72     }
73 
buildlist(xmlNodePtr pNode,sal_Bool start)74     void CElementList::buildlist(xmlNodePtr pNode, sal_Bool start)
75     {
76         // bail out if no rebuild is needed
77         if (start) {
78             if (!m_bRebuild)
79             {
80                 return;
81             } else {
82                 m_nodevector.erase(m_nodevector.begin(), m_nodevector.end());
83                 m_bRebuild = false; // don't rebuild until tree is mutated
84             }
85         }
86 
87         while (pNode != NULL )
88         {
89             if (pNode->type == XML_ELEMENT_NODE &&
90                 (strcmp((char*)pNode->name, (char*)m_pName.get()) == 0))
91             {
92                 if (!m_pURI) {
93                     m_nodevector.push_back(pNode);
94                 } else {
95                     if (pNode->ns != NULL && (0 ==
96                          strcmp((char*)pNode->ns->href, (char*)m_pURI.get())))
97                     {
98                         m_nodevector.push_back(pNode);
99                     }
100                 }
101             }
102             if (pNode->children != NULL) buildlist(pNode->children, sal_False);
103 
104             if (!start) pNode = pNode->next;
105             else break; // fold back
106         }
107     }
108 
109     /**
110     The number of nodes in the list.
111     */
getLength()112     sal_Int32 SAL_CALL CElementList::getLength() throw (RuntimeException)
113     {
114         ::osl::MutexGuard const g(m_rMutex);
115 
116         if (!m_pElement.is()) { return 0; }
117 
118         // this has to be 'live'
119         buildlist(m_pElement->GetNodePtr());
120         return m_nodevector.size();
121     }
122     /**
123     Returns the indexth item in the collection.
124     */
item(sal_Int32 index)125     Reference< XNode > SAL_CALL CElementList::item(sal_Int32 index)
126         throw (RuntimeException)
127     {
128         if (index < 0) throw RuntimeException();
129 
130         ::osl::MutexGuard const g(m_rMutex);
131 
132         if (!m_pElement.is()) { return 0; }
133 
134         buildlist(m_pElement->GetNodePtr());
135         if (m_nodevector.size() <= static_cast<size_t>(index)) {
136             throw RuntimeException();
137         }
138         Reference< XNode > const xRet(
139             m_pElement->GetOwnerDocument().GetCNode(m_nodevector[index]).get());
140         return xRet;
141     }
142 
143     // tree mutations can change the list
handleEvent(Reference<XEvent> const &)144     void SAL_CALL CElementList::handleEvent(Reference< XEvent > const&)
145         throw (RuntimeException)
146     {
147         ::osl::MutexGuard const g(m_rMutex);
148 
149         m_bRebuild = true;
150     }
151 }
152