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