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