1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include "elementlist.hxx" 29 30 #include <string.h> 31 32 #include <element.hxx> 33 #include <document.hxx> 34 35 36 namespace DOM 37 { 38 39 static xmlChar* lcl_initXmlString(::rtl::OUString const& rString) 40 { 41 ::rtl::OString const os = 42 ::rtl::OUStringToOString(rString, RTL_TEXTENCODING_UTF8); 43 xmlChar *const pRet = new xmlChar[os.getLength() + 1]; 44 strcpy(reinterpret_cast<char*>(pRet), os.getStr()); 45 return pRet; 46 } 47 48 CElementList::CElementList(::rtl::Reference<CElement> const& pElement, 49 ::osl::Mutex & rMutex, 50 OUString const& rName, OUString const*const pURI) 51 : m_pElement(pElement) 52 , m_rMutex(rMutex) 53 , m_pName(lcl_initXmlString(rName)) 54 , m_pURI((pURI) ? lcl_initXmlString(*pURI) : 0) 55 , m_bRebuild(true) 56 { 57 if (m_pElement.is()) { 58 registerListener(*m_pElement); 59 } 60 } 61 62 void CElementList::registerListener(CElement & rElement) 63 { 64 try { 65 Reference< XEventTarget > const xTarget( 66 static_cast<XElement*>(& rElement), UNO_QUERY_THROW); 67 OUString aType = OUString::createFromAscii("DOMSubtreeModified"); 68 sal_Bool capture = sal_False; 69 xTarget->addEventListener(aType, 70 Reference< XEventListener >(this), capture); 71 } catch (Exception &e){ 72 OString aMsg("Exception caught while registering NodeList as listener:\n"); 73 aMsg += OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US); 74 OSL_ENSURE(sal_False, aMsg.getStr()); 75 } 76 } 77 78 void CElementList::buildlist(xmlNodePtr pNode, sal_Bool start) 79 { 80 // bail out if no rebuild is needed 81 if (start) { 82 if (!m_bRebuild) 83 { 84 return; 85 } else { 86 m_nodevector.erase(m_nodevector.begin(), m_nodevector.end()); 87 m_bRebuild = false; // don't rebuild until tree is mutated 88 } 89 } 90 91 while (pNode != NULL ) 92 { 93 if (pNode->type == XML_ELEMENT_NODE && 94 (strcmp((char*)pNode->name, (char*)m_pName.get()) == 0)) 95 { 96 if (!m_pURI) { 97 m_nodevector.push_back(pNode); 98 } else { 99 if (pNode->ns != NULL && (0 == 100 strcmp((char*)pNode->ns->href, (char*)m_pURI.get()))) 101 { 102 m_nodevector.push_back(pNode); 103 } 104 } 105 } 106 if (pNode->children != NULL) buildlist(pNode->children, sal_False); 107 108 if (!start) pNode = pNode->next; 109 else break; // fold back 110 } 111 } 112 113 /** 114 The number of nodes in the list. 115 */ 116 sal_Int32 SAL_CALL CElementList::getLength() throw (RuntimeException) 117 { 118 ::osl::MutexGuard const g(m_rMutex); 119 120 if (!m_pElement.is()) { return 0; } 121 122 // this has to be 'live' 123 buildlist(m_pElement->GetNodePtr()); 124 return m_nodevector.size(); 125 } 126 /** 127 Returns the indexth item in the collection. 128 */ 129 Reference< XNode > SAL_CALL CElementList::item(sal_Int32 index) 130 throw (RuntimeException) 131 { 132 if (index < 0) throw RuntimeException(); 133 134 ::osl::MutexGuard const g(m_rMutex); 135 136 if (!m_pElement.is()) { return 0; } 137 138 buildlist(m_pElement->GetNodePtr()); 139 if (m_nodevector.size() <= static_cast<size_t>(index)) { 140 throw RuntimeException(); 141 } 142 Reference< XNode > const xRet( 143 m_pElement->GetOwnerDocument().GetCNode(m_nodevector[index]).get()); 144 return xRet; 145 } 146 147 // tree mutations can change the list 148 void SAL_CALL CElementList::handleEvent(Reference< XEvent > const&) 149 throw (RuntimeException) 150 { 151 ::osl::MutexGuard const g(m_rMutex); 152 153 m_bRebuild = true; 154 } 155 } 156