| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_comphelper.hxx" |
| |
| #include <comphelper/numberedcollection.hxx> |
| #include <algorithm> |
| |
| //_______________________________________________ |
| // includes |
| |
| #include <com/sun/star/frame/UntitledNumbersConst.hpp> |
| |
| //_______________________________________________ |
| // namespace |
| |
| namespace comphelper{ |
| |
| namespace css = ::com::sun::star; |
| |
| //_______________________________________________ |
| // definitions |
| |
| static const ::rtl::OUString ERRMSG_INVALID_COMPONENT_PARAM = ::rtl::OUString::createFromAscii("NULL as component reference not allowed."); |
| static const ::rtl::OUString ERRMSG_INVALID_NUMBER_PARAM = ::rtl::OUString::createFromAscii("Special valkud INVALID_NUMBER not allowed as input parameter."); |
| |
| //----------------------------------------------- |
| NumberedCollection::NumberedCollection() |
| : ::cppu::BaseMutex () |
| , m_sUntitledPrefix () |
| , m_lComponents () |
| , m_xOwner () |
| { |
| } |
| |
| //----------------------------------------------- |
| NumberedCollection::~NumberedCollection() |
| { |
| } |
| |
| //----------------------------------------------- |
| void NumberedCollection::setOwner(const css::uno::Reference< css::uno::XInterface >& xOwner) |
| { |
| // SYNCHRONIZED -> |
| ::osl::ResettableMutexGuard aLock(m_aMutex); |
| |
| m_xOwner = xOwner; |
| |
| // <- SYNCHRONIZED |
| } |
| |
| //----------------------------------------------- |
| void NumberedCollection::setUntitledPrefix(const ::rtl::OUString& sPrefix) |
| { |
| // SYNCHRONIZED -> |
| ::osl::ResettableMutexGuard aLock(m_aMutex); |
| |
| m_sUntitledPrefix = sPrefix; |
| |
| // <- SYNCHRONIZED |
| } |
| |
| //----------------------------------------------- |
| ::sal_Int32 SAL_CALL NumberedCollection::leaseNumber(const css::uno::Reference< css::uno::XInterface >& xComponent) |
| throw (css::lang::IllegalArgumentException, |
| css::uno::RuntimeException ) |
| { |
| // SYNCHRONIZED -> |
| ::osl::ResettableMutexGuard aLock(m_aMutex); |
| |
| if ( ! xComponent.is ()) |
| throw css::lang::IllegalArgumentException (ERRMSG_INVALID_COMPONENT_PARAM, m_xOwner.get(), 1); |
| |
| long pComponent = (long) xComponent.get (); |
| TNumberedItemHash::const_iterator pIt = m_lComponents.find (pComponent); |
| |
| // a) component already exists - return it's number directly |
| if (pIt != m_lComponents.end()) |
| return pIt->second.nNumber; |
| |
| // b) component must be added new to this container |
| |
| // b1) collection is full - no further components possible |
| // -> return INVALID_NUMBER |
| ::sal_Int32 nFreeNumber = impl_searchFreeNumber(); |
| if (nFreeNumber == css::frame::UntitledNumbersConst::INVALID_NUMBER) |
| return css::frame::UntitledNumbersConst::INVALID_NUMBER; |
| |
| // b2) add component to collection and return its number |
| TNumberedItem aItem; |
| aItem.xItem = css::uno::WeakReference< css::uno::XInterface >(xComponent); |
| aItem.nNumber = nFreeNumber; |
| m_lComponents[pComponent] = aItem; |
| |
| return nFreeNumber; |
| |
| // <- SYNCHRONIZED |
| } |
| |
| //----------------------------------------------- |
| void SAL_CALL NumberedCollection::releaseNumber(::sal_Int32 nNumber) |
| throw (css::lang::IllegalArgumentException, |
| css::uno::RuntimeException ) |
| { |
| // SYNCHRONIZED -> |
| ::osl::ResettableMutexGuard aLock(m_aMutex); |
| |
| if (nNumber == css::frame::UntitledNumbersConst::INVALID_NUMBER) |
| throw css::lang::IllegalArgumentException (ERRMSG_INVALID_NUMBER_PARAM, m_xOwner.get(), 1); |
| |
| TDeadItemList lDeadItems; |
| TNumberedItemHash::iterator pComponent; |
| |
| for ( pComponent = m_lComponents.begin (); |
| pComponent != m_lComponents.end (); |
| ++pComponent ) |
| { |
| const TNumberedItem& rItem = pComponent->second; |
| const css::uno::Reference< css::uno::XInterface > xItem = rItem.xItem.get(); |
| |
| if ( ! xItem.is ()) |
| { |
| lDeadItems.push_back(pComponent->first); |
| continue; |
| } |
| |
| if (rItem.nNumber == nNumber) |
| { |
| m_lComponents.erase (pComponent); |
| break; |
| } |
| } |
| |
| impl_cleanUpDeadItems(m_lComponents, lDeadItems); |
| |
| // <- SYNCHRONIZED |
| } |
| |
| //----------------------------------------------- |
| void SAL_CALL NumberedCollection::releaseNumberForComponent(const css::uno::Reference< css::uno::XInterface >& xComponent) |
| throw (css::lang::IllegalArgumentException, |
| css::uno::RuntimeException ) |
| { |
| // SYNCHRONIZED -> |
| ::osl::ResettableMutexGuard aLock(m_aMutex); |
| |
| if ( ! xComponent.is ()) |
| throw css::lang::IllegalArgumentException (ERRMSG_INVALID_COMPONENT_PARAM, m_xOwner.get(), 1); |
| |
| long pComponent = (long) xComponent.get (); |
| TNumberedItemHash::iterator pIt = m_lComponents.find (pComponent); |
| |
| // a) component exists and will be removed |
| if (pIt != m_lComponents.end()) |
| m_lComponents.erase(pIt); |
| |
| // else |
| // b) component does not exists - nothing todo here (ignore request!) |
| |
| // <- SYNCHRONIZED |
| } |
| |
| //----------------------------------------------- |
| ::rtl::OUString SAL_CALL NumberedCollection::getUntitledPrefix() |
| throw (css::uno::RuntimeException) |
| { |
| // SYNCHRONIZED -> |
| ::osl::ResettableMutexGuard aLock(m_aMutex); |
| |
| return m_sUntitledPrefix; |
| |
| // <- SYNCHRONIZED |
| } |
| |
| //----------------------------------------------- |
| /** create an ordered list of all possible numbers ... |
| e.g. {1,2,3,...,N} Max size of these list will be |
| current size of component list + 1 . |
| |
| "+1" ... because in case all numbers in range 1..n |
| are in use we need a new number n+1 :-) |
| |
| Every item which is already used as unique number |
| will be removed. At the end a list of e.g. {3,6,...,M} |
| exists where the first item represent the lowest free |
| number (in this example 3). |
| */ |
| ::sal_Int32 NumberedCollection::impl_searchFreeNumber () |
| { |
| // create ordered list of all possible numbers. |
| ::std::vector< ::sal_Int32 > lPossibleNumbers; |
| ::sal_Int32 c = (::sal_Int32)m_lComponents.size (); |
| ::sal_Int32 i = 1; |
| |
| // c can't be less than 0 ... otherwise hash.size() has an error :-) |
| // But we need at least n+1 numbers here. |
| c += 1; |
| |
| for (i=1; i<=c; ++i) |
| lPossibleNumbers.push_back (i); |
| |
| // SYNCHRONIZED -> |
| ::osl::ResettableMutexGuard aLock(m_aMutex); |
| |
| TDeadItemList lDeadItems; |
| TNumberedItemHash::const_iterator pComponent; |
| |
| for ( pComponent = m_lComponents.begin (); |
| pComponent != m_lComponents.end (); |
| ++pComponent ) |
| { |
| const TNumberedItem& rItem = pComponent->second; |
| const css::uno::Reference< css::uno::XInterface > xItem = rItem.xItem.get(); |
| |
| if ( ! xItem.is ()) |
| { |
| lDeadItems.push_back(pComponent->first); |
| continue; |
| } |
| |
| ::std::vector< ::sal_Int32 >::iterator pPossible = ::std::find(lPossibleNumbers.begin (), lPossibleNumbers.end (), rItem.nNumber); |
| if (pPossible != lPossibleNumbers.end ()) |
| lPossibleNumbers.erase (pPossible); |
| } |
| |
| impl_cleanUpDeadItems(m_lComponents, lDeadItems); |
| |
| // a) non free numbers ... return INVALID_NUMBER |
| if (lPossibleNumbers.size () < 1) |
| return css::frame::UntitledNumbersConst::INVALID_NUMBER; |
| |
| // b) return first free number |
| return *(lPossibleNumbers.begin ()); |
| |
| // <- SYNCHRONIZED |
| } |
| |
| void NumberedCollection::impl_cleanUpDeadItems ( TNumberedItemHash& lItems , |
| const TDeadItemList& lDeadItems) |
| { |
| TDeadItemList::const_iterator pIt; |
| |
| for ( pIt = lDeadItems.begin (); |
| pIt != lDeadItems.end (); |
| ++pIt ) |
| { |
| const long& rDeadItem = *pIt; |
| lItems.erase(rDeadItem); |
| } |
| } |
| |
| } // namespace comphelper |