Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <algorithm>
21 : #include <comphelper/numberedcollection.hxx>
22 : #include <com/sun/star/frame/UntitledNumbersConst.hpp>
23 :
24 : namespace comphelper{
25 :
26 : static const char ERRMSG_INVALID_COMPONENT_PARAM[] = "NULL as component reference not allowed.";
27 :
28 :
29 3467 : NumberedCollection::NumberedCollection()
30 : : ::cppu::BaseMutex ()
31 : , m_sUntitledPrefix ()
32 : , m_lComponents ()
33 3467 : , m_xOwner ()
34 : {
35 3467 : }
36 :
37 :
38 6768 : NumberedCollection::~NumberedCollection()
39 : {
40 6768 : }
41 :
42 :
43 3467 : void NumberedCollection::setOwner(const css::uno::Reference< css::uno::XInterface >& xOwner)
44 : {
45 : // SYNCHRONIZED ->
46 3467 : ::osl::ResettableMutexGuard aLock(m_aMutex);
47 :
48 3467 : m_xOwner = xOwner;
49 :
50 : // <- SYNCHRONIZED
51 3467 : }
52 :
53 :
54 3460 : void NumberedCollection::setUntitledPrefix(const OUString& sPrefix)
55 : {
56 : // SYNCHRONIZED ->
57 3460 : ::osl::ResettableMutexGuard aLock(m_aMutex);
58 :
59 3460 : m_sUntitledPrefix = sPrefix;
60 :
61 : // <- SYNCHRONIZED
62 3460 : }
63 :
64 :
65 4378 : ::sal_Int32 SAL_CALL NumberedCollection::leaseNumber(const css::uno::Reference< css::uno::XInterface >& xComponent)
66 : throw (css::lang::IllegalArgumentException,
67 : css::uno::RuntimeException, std::exception )
68 : {
69 : // SYNCHRONIZED ->
70 4378 : ::osl::ResettableMutexGuard aLock(m_aMutex);
71 :
72 4378 : if ( ! xComponent.is ())
73 0 : throw css::lang::IllegalArgumentException (OUString(ERRMSG_INVALID_COMPONENT_PARAM), m_xOwner.get(), 1);
74 :
75 4378 : sal_IntPtr pComponent = reinterpret_cast<sal_IntPtr>( xComponent.get() );
76 4378 : TNumberedItemHash::const_iterator pIt = m_lComponents.find (pComponent);
77 :
78 : // a) component already exists - return it's number directly
79 4378 : if (pIt != m_lComponents.end())
80 0 : return pIt->second.nNumber;
81 :
82 : // b) component must be added new to this container
83 :
84 : // b1) collection is full - no further components possible
85 : // -> return INVALID_NUMBER
86 4378 : ::sal_Int32 nFreeNumber = impl_searchFreeNumber();
87 4378 : if (nFreeNumber == css::frame::UntitledNumbersConst::INVALID_NUMBER)
88 0 : return css::frame::UntitledNumbersConst::INVALID_NUMBER;
89 :
90 : // b2) add component to collection and return its number
91 8756 : TNumberedItem aItem;
92 4378 : aItem.xItem = css::uno::WeakReference< css::uno::XInterface >(xComponent);
93 4378 : aItem.nNumber = nFreeNumber;
94 4378 : m_lComponents[pComponent] = aItem;
95 :
96 8756 : return nFreeNumber;
97 :
98 : // <- SYNCHRONIZED
99 : }
100 :
101 :
102 1103 : void SAL_CALL NumberedCollection::releaseNumber(::sal_Int32 nNumber)
103 : throw (css::lang::IllegalArgumentException,
104 : css::uno::RuntimeException, std::exception )
105 : {
106 : // SYNCHRONIZED ->
107 1103 : ::osl::ResettableMutexGuard aLock(m_aMutex);
108 :
109 1103 : if (nNumber == css::frame::UntitledNumbersConst::INVALID_NUMBER)
110 0 : throw css::lang::IllegalArgumentException ("Special valkud INVALID_NUMBER not allowed as input parameter.", m_xOwner.get(), 1);
111 :
112 2206 : TDeadItemList lDeadItems;
113 1103 : TNumberedItemHash::iterator pComponent;
114 :
115 4008 : for ( pComponent = m_lComponents.begin ();
116 2672 : pComponent != m_lComponents.end ();
117 : ++pComponent )
118 : {
119 1336 : const TNumberedItem& rItem = pComponent->second;
120 1336 : const css::uno::Reference< css::uno::XInterface > xItem = rItem.xItem.get();
121 :
122 1336 : if ( ! xItem.is ())
123 : {
124 0 : lDeadItems.push_back(pComponent->first);
125 0 : continue;
126 : }
127 :
128 1336 : if (rItem.nNumber == nNumber)
129 : {
130 1103 : m_lComponents.erase (pComponent);
131 1103 : break;
132 : }
133 233 : }
134 :
135 2206 : impl_cleanUpDeadItems(m_lComponents, lDeadItems);
136 :
137 : // <- SYNCHRONIZED
138 1103 : }
139 :
140 :
141 0 : void SAL_CALL NumberedCollection::releaseNumberForComponent(const css::uno::Reference< css::uno::XInterface >& xComponent)
142 : throw (css::lang::IllegalArgumentException,
143 : css::uno::RuntimeException, std::exception )
144 : {
145 : // SYNCHRONIZED ->
146 0 : ::osl::ResettableMutexGuard aLock(m_aMutex);
147 :
148 0 : if ( ! xComponent.is ())
149 0 : throw css::lang::IllegalArgumentException (OUString(ERRMSG_INVALID_COMPONENT_PARAM), m_xOwner.get(), 1);
150 :
151 0 : sal_IntPtr pComponent = reinterpret_cast<sal_IntPtr>( xComponent.get() );
152 0 : TNumberedItemHash::iterator pIt = m_lComponents.find (pComponent);
153 :
154 : // a) component exists and will be removed
155 0 : if (pIt != m_lComponents.end())
156 0 : m_lComponents.erase(pIt);
157 :
158 : // else
159 : // b) component does not exists - nothing todo here (ignore request!)
160 :
161 : // <- SYNCHRONIZED
162 0 : }
163 :
164 :
165 5753 : OUString SAL_CALL NumberedCollection::getUntitledPrefix()
166 : throw (css::uno::RuntimeException, std::exception)
167 : {
168 : // SYNCHRONIZED ->
169 5753 : ::osl::ResettableMutexGuard aLock(m_aMutex);
170 :
171 5753 : return m_sUntitledPrefix;
172 :
173 : // <- SYNCHRONIZED
174 : }
175 :
176 :
177 : /** create an ordered list of all possible numbers ...
178 : e.g. {1,2,3,...,N} Max size of these list will be
179 : current size of component list + 1 .
180 :
181 : "+1" ... because in case all numbers in range 1..n
182 : are in use we need a new number n+1 :-)
183 :
184 : Every item which is already used as unique number
185 : will be removed. At the end a list of e.g. {3,6,...,M}
186 : exists where the first item represent the lowest free
187 : number (in this example 3).
188 : */
189 4378 : ::sal_Int32 NumberedCollection::impl_searchFreeNumber ()
190 : {
191 : // create ordered list of all possible numbers.
192 4378 : ::std::vector< ::sal_Int32 > lPossibleNumbers;
193 4378 : ::sal_Int32 c = (::sal_Int32)m_lComponents.size ();
194 4378 : ::sal_Int32 i = 1;
195 :
196 : // c can't be less then 0 ... otherwise hash.size() has an error :-)
197 : // But we need at least n+1 numbers here.
198 4378 : c += 1;
199 :
200 9966 : for (i=1; i<=c; ++i)
201 5588 : lPossibleNumbers.push_back (i);
202 :
203 : // SYNCHRONIZED ->
204 8756 : ::osl::ResettableMutexGuard aLock(m_aMutex);
205 :
206 8756 : TDeadItemList lDeadItems;
207 4378 : TNumberedItemHash::const_iterator pComponent;
208 :
209 16764 : for ( pComponent = m_lComponents.begin ();
210 11176 : pComponent != m_lComponents.end ();
211 : ++pComponent )
212 : {
213 1210 : const TNumberedItem& rItem = pComponent->second;
214 1210 : const css::uno::Reference< css::uno::XInterface > xItem = rItem.xItem.get();
215 :
216 1210 : if ( ! xItem.is ())
217 : {
218 0 : lDeadItems.push_back(pComponent->first);
219 0 : continue;
220 : }
221 :
222 1210 : ::std::vector< ::sal_Int32 >::iterator pPossible = ::std::find(lPossibleNumbers.begin (), lPossibleNumbers.end (), rItem.nNumber);
223 1210 : if (pPossible != lPossibleNumbers.end ())
224 1210 : lPossibleNumbers.erase (pPossible);
225 1210 : }
226 :
227 4378 : impl_cleanUpDeadItems(m_lComponents, lDeadItems);
228 :
229 : // a) non free numbers ... return INVALID_NUMBER
230 4378 : if (lPossibleNumbers.size () < 1)
231 0 : return css::frame::UntitledNumbersConst::INVALID_NUMBER;
232 :
233 : // b) return first free number
234 8756 : return *(lPossibleNumbers.begin ());
235 :
236 : // <- SYNCHRONIZED
237 : }
238 :
239 5481 : void NumberedCollection::impl_cleanUpDeadItems ( TNumberedItemHash& lItems ,
240 : const TDeadItemList& lDeadItems)
241 : {
242 5481 : TDeadItemList::const_iterator pIt;
243 :
244 16443 : for ( pIt = lDeadItems.begin ();
245 10962 : pIt != lDeadItems.end ();
246 : ++pIt )
247 : {
248 0 : const long& rDeadItem = *pIt;
249 0 : lItems.erase(rDeadItem);
250 : }
251 5481 : }
252 :
253 : } // namespace comphelper
254 :
255 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|