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 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_comphelper.hxx" 30 31 #include <comphelper/numberedcollection.hxx> 32 33 //_______________________________________________ 34 // includes 35 36 #include <com/sun/star/frame/UntitledNumbersConst.hpp> 37 38 //_______________________________________________ 39 // namespace 40 41 namespace comphelper{ 42 43 namespace css = ::com::sun::star; 44 45 //_______________________________________________ 46 // definitions 47 48 static const ::rtl::OUString ERRMSG_INVALID_COMPONENT_PARAM = ::rtl::OUString::createFromAscii("NULL as component reference not allowed."); 49 static const ::rtl::OUString ERRMSG_INVALID_NUMBER_PARAM = ::rtl::OUString::createFromAscii("Special valkud INVALID_NUMBER not allowed as input parameter."); 50 51 //----------------------------------------------- 52 NumberedCollection::NumberedCollection() 53 : ::cppu::BaseMutex () 54 , m_sUntitledPrefix () 55 , m_lComponents () 56 , m_xOwner () 57 { 58 } 59 60 //----------------------------------------------- 61 NumberedCollection::~NumberedCollection() 62 { 63 } 64 65 //----------------------------------------------- 66 void NumberedCollection::setOwner(const css::uno::Reference< css::uno::XInterface >& xOwner) 67 { 68 // SYNCHRONIZED -> 69 ::osl::ResettableMutexGuard aLock(m_aMutex); 70 71 m_xOwner = xOwner; 72 73 // <- SYNCHRONIZED 74 } 75 76 //----------------------------------------------- 77 void NumberedCollection::setUntitledPrefix(const ::rtl::OUString& sPrefix) 78 { 79 // SYNCHRONIZED -> 80 ::osl::ResettableMutexGuard aLock(m_aMutex); 81 82 m_sUntitledPrefix = sPrefix; 83 84 // <- SYNCHRONIZED 85 } 86 87 //----------------------------------------------- 88 ::sal_Int32 SAL_CALL NumberedCollection::leaseNumber(const css::uno::Reference< css::uno::XInterface >& xComponent) 89 throw (css::lang::IllegalArgumentException, 90 css::uno::RuntimeException ) 91 { 92 // SYNCHRONIZED -> 93 ::osl::ResettableMutexGuard aLock(m_aMutex); 94 95 if ( ! xComponent.is ()) 96 throw css::lang::IllegalArgumentException (ERRMSG_INVALID_COMPONENT_PARAM, m_xOwner.get(), 1); 97 98 long pComponent = (long) xComponent.get (); 99 TNumberedItemHash::const_iterator pIt = m_lComponents.find (pComponent); 100 101 // a) component already exists - return it's number directly 102 if (pIt != m_lComponents.end()) 103 return pIt->second.nNumber; 104 105 // b) component must be added new to this container 106 107 // b1) collection is full - no further components possible 108 // -> return INVALID_NUMBER 109 ::sal_Int32 nFreeNumber = impl_searchFreeNumber(); 110 if (nFreeNumber == css::frame::UntitledNumbersConst::INVALID_NUMBER) 111 return css::frame::UntitledNumbersConst::INVALID_NUMBER; 112 113 // b2) add component to collection and return its number 114 TNumberedItem aItem; 115 aItem.xItem = css::uno::WeakReference< css::uno::XInterface >(xComponent); 116 aItem.nNumber = nFreeNumber; 117 m_lComponents[pComponent] = aItem; 118 119 return nFreeNumber; 120 121 // <- SYNCHRONIZED 122 } 123 124 //----------------------------------------------- 125 void SAL_CALL NumberedCollection::releaseNumber(::sal_Int32 nNumber) 126 throw (css::lang::IllegalArgumentException, 127 css::uno::RuntimeException ) 128 { 129 // SYNCHRONIZED -> 130 ::osl::ResettableMutexGuard aLock(m_aMutex); 131 132 if (nNumber == css::frame::UntitledNumbersConst::INVALID_NUMBER) 133 throw css::lang::IllegalArgumentException (ERRMSG_INVALID_NUMBER_PARAM, m_xOwner.get(), 1); 134 135 TDeadItemList lDeadItems; 136 TNumberedItemHash::iterator pComponent; 137 138 for ( pComponent = m_lComponents.begin (); 139 pComponent != m_lComponents.end (); 140 ++pComponent ) 141 { 142 const TNumberedItem& rItem = pComponent->second; 143 const css::uno::Reference< css::uno::XInterface > xItem = rItem.xItem.get(); 144 145 if ( ! xItem.is ()) 146 { 147 lDeadItems.push_back(pComponent->first); 148 continue; 149 } 150 151 if (rItem.nNumber == nNumber) 152 { 153 m_lComponents.erase (pComponent); 154 break; 155 } 156 } 157 158 impl_cleanUpDeadItems(m_lComponents, lDeadItems); 159 160 // <- SYNCHRONIZED 161 } 162 163 //----------------------------------------------- 164 void SAL_CALL NumberedCollection::releaseNumberForComponent(const css::uno::Reference< css::uno::XInterface >& xComponent) 165 throw (css::lang::IllegalArgumentException, 166 css::uno::RuntimeException ) 167 { 168 // SYNCHRONIZED -> 169 ::osl::ResettableMutexGuard aLock(m_aMutex); 170 171 if ( ! xComponent.is ()) 172 throw css::lang::IllegalArgumentException (ERRMSG_INVALID_COMPONENT_PARAM, m_xOwner.get(), 1); 173 174 long pComponent = (long) xComponent.get (); 175 TNumberedItemHash::iterator pIt = m_lComponents.find (pComponent); 176 177 // a) component exists and will be removed 178 if (pIt != m_lComponents.end()) 179 m_lComponents.erase(pIt); 180 181 // else 182 // b) component does not exists - nothing todo here (ignore request!) 183 184 // <- SYNCHRONIZED 185 } 186 187 //----------------------------------------------- 188 ::rtl::OUString SAL_CALL NumberedCollection::getUntitledPrefix() 189 throw (css::uno::RuntimeException) 190 { 191 // SYNCHRONIZED -> 192 ::osl::ResettableMutexGuard aLock(m_aMutex); 193 194 return m_sUntitledPrefix; 195 196 // <- SYNCHRONIZED 197 } 198 199 //----------------------------------------------- 200 /** create an ordered list of all possible numbers ... 201 e.g. {1,2,3,...,N} Max size of these list will be 202 current size of component list + 1 . 203 204 "+1" ... because in case all numbers in range 1..n 205 are in use we need a new number n+1 :-) 206 207 Every item which is already used as unique number 208 will be removed. At the end a list of e.g. {3,6,...,M} 209 exists where the first item represent the lowest free 210 number (in this example 3). 211 */ 212 ::sal_Int32 NumberedCollection::impl_searchFreeNumber () 213 { 214 // create ordered list of all possible numbers. 215 ::std::vector< ::sal_Int32 > lPossibleNumbers; 216 ::sal_Int32 c = (::sal_Int32)m_lComponents.size (); 217 ::sal_Int32 i = 1; 218 219 // c cant be less then 0 ... otherwhise hash.size() has an error :-) 220 // But we need at least n+1 numbers here. 221 c += 1; 222 223 for (i=1; i<=c; ++i) 224 lPossibleNumbers.push_back (i); 225 226 // SYNCHRONIZED -> 227 ::osl::ResettableMutexGuard aLock(m_aMutex); 228 229 TDeadItemList lDeadItems; 230 TNumberedItemHash::const_iterator pComponent; 231 232 for ( pComponent = m_lComponents.begin (); 233 pComponent != m_lComponents.end (); 234 ++pComponent ) 235 { 236 const TNumberedItem& rItem = pComponent->second; 237 const css::uno::Reference< css::uno::XInterface > xItem = rItem.xItem.get(); 238 239 if ( ! xItem.is ()) 240 { 241 lDeadItems.push_back(pComponent->first); 242 continue; 243 } 244 245 ::std::vector< ::sal_Int32 >::iterator pPossible = ::std::find(lPossibleNumbers.begin (), lPossibleNumbers.end (), rItem.nNumber); 246 if (pPossible != lPossibleNumbers.end ()) 247 lPossibleNumbers.erase (pPossible); 248 } 249 250 impl_cleanUpDeadItems(m_lComponents, lDeadItems); 251 252 // a) non free numbers ... return INVALID_NUMBER 253 if (lPossibleNumbers.size () < 1) 254 return css::frame::UntitledNumbersConst::INVALID_NUMBER; 255 256 // b) return first free number 257 return *(lPossibleNumbers.begin ()); 258 259 // <- SYNCHRONIZED 260 } 261 262 void NumberedCollection::impl_cleanUpDeadItems ( TNumberedItemHash& lItems , 263 const TDeadItemList& lDeadItems) 264 { 265 TDeadItemList::const_iterator pIt; 266 267 for ( pIt = lDeadItems.begin (); 268 pIt != lDeadItems.end (); 269 ++pIt ) 270 { 271 const long& rDeadItem = *pIt; 272 lItems.erase(rDeadItem); 273 } 274 } 275 276 } // namespace comphelper 277