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 <bookmarkcontainer.hxx>
21 
22 #include <osl/diagnose.h>
23 #include <comphelper/enumhelper.hxx>
24 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
25 #include <com/sun/star/lang/NoSupportException.hpp>
26 #include <cppuhelper/supportsservice.hxx>
27 
28 using namespace ::com::sun::star::uno;
29 using namespace ::com::sun::star::lang;
30 using namespace ::com::sun::star::container;
31 using namespace ::osl;
32 using namespace ::comphelper;
33 using namespace ::cppu;
34 
35 namespace dbaccess
36 {
37 
38 // OBookmarkContainer
39 
OBookmarkContainer(OWeakObject & _rParent,Mutex & _rMutex)40 OBookmarkContainer::OBookmarkContainer(OWeakObject& _rParent, Mutex& _rMutex)
41     :m_rParent(_rParent)
42     ,m_aContainerListeners(_rMutex)
43     ,m_rMutex(_rMutex)
44 {
45 }
46 
47 
acquire()48 void SAL_CALL OBookmarkContainer::acquire(  ) noexcept
49 {
50     m_rParent.acquire();
51 }
52 
release()53 void SAL_CALL OBookmarkContainer::release(  ) noexcept
54 {
55     m_rParent.release();
56 }
57 
~OBookmarkContainer()58 OBookmarkContainer::~OBookmarkContainer()
59 {
60 }
61 
62 // XServiceInfo
getImplementationName()63 OUString SAL_CALL OBookmarkContainer::getImplementationName(  )
64 {
65     return "com.sun.star.comp.dba.OBookmarkContainer";
66 }
67 
supportsService(const OUString & _rServiceName)68 sal_Bool SAL_CALL OBookmarkContainer::supportsService( const OUString& _rServiceName )
69 {
70     return cppu::supportsService(this, _rServiceName);
71 }
72 
getSupportedServiceNames()73 Sequence< OUString > SAL_CALL OBookmarkContainer::getSupportedServiceNames(  )
74 {
75     return { "com.sun.star.sdb.DefinitionContainer" };
76 }
77 
78 // XNameContainer
insertByName(const OUString & _rName,const Any & aElement)79 void SAL_CALL OBookmarkContainer::insertByName( const OUString& _rName, const Any& aElement )
80 {
81     MutexGuard aGuard(m_rMutex);
82 
83     if (checkExistence(_rName))
84         throw ElementExistException();
85 
86     if (_rName.isEmpty())
87         throw IllegalArgumentException();
88 
89     // approve the new object
90     OUString sNewLink;
91     if (!(aElement >>= sNewLink))
92         throw IllegalArgumentException();
93 
94     implAppend(_rName, sNewLink);
95 
96     // notify the listeners
97     if (m_aContainerListeners.getLength())
98     {
99         ContainerEvent aEvent(*this, makeAny(_rName), makeAny(sNewLink), Any());
100         OInterfaceIteratorHelper2 aListenerIterator(m_aContainerListeners);
101         while (aListenerIterator.hasMoreElements())
102             static_cast< XContainerListener* >(aListenerIterator.next())->elementInserted(aEvent);
103     }
104 }
105 
removeByName(const OUString & _rName)106 void SAL_CALL OBookmarkContainer::removeByName( const OUString& _rName )
107 {
108     OUString sOldBookmark;
109     {
110         MutexGuard aGuard(m_rMutex);
111 
112         // check the arguments
113         if (_rName.isEmpty())
114             throw IllegalArgumentException();
115 
116         if (!checkExistence(_rName))
117             throw NoSuchElementException();
118 
119         // the old element (for the notifications)
120         sOldBookmark = m_aBookmarks[_rName];
121 
122         // do the removal
123         implRemove(_rName);
124     }
125 
126     // notify the listeners
127     if (m_aContainerListeners.getLength())
128     {
129         ContainerEvent aEvent(*this, makeAny(_rName), makeAny(sOldBookmark), Any());
130         OInterfaceIteratorHelper2 aListenerIterator(m_aContainerListeners);
131         while (aListenerIterator.hasMoreElements())
132             static_cast< XContainerListener* >(aListenerIterator.next())->elementRemoved(aEvent);
133     }
134 }
135 
136 // XNameReplace
replaceByName(const OUString & _rName,const Any & aElement)137 void SAL_CALL OBookmarkContainer::replaceByName( const OUString& _rName, const Any& aElement )
138 {
139     ClearableMutexGuard aGuard(m_rMutex);
140 
141     // check the arguments
142     if (_rName.isEmpty())
143         throw IllegalArgumentException();
144 
145     // do we have such an element?
146     if (!checkExistence(_rName))
147         throw NoSuchElementException();
148 
149     // approve the new object
150     OUString sNewLink;
151     if (!(aElement >>= sNewLink))
152         throw IllegalArgumentException();
153 
154     // the old element (for the notifications)
155     OUString sOldLink = m_aBookmarks[_rName];
156 
157     // do the replace
158     implReplace(_rName, sNewLink);
159 
160     // notify the listeners
161     aGuard.clear();
162     if (m_aContainerListeners.getLength())
163     {
164         ContainerEvent aEvent(*this, makeAny(_rName), makeAny(sNewLink), makeAny(sOldLink));
165         OInterfaceIteratorHelper2 aListenerIterator(m_aContainerListeners);
166         while (aListenerIterator.hasMoreElements())
167             static_cast< XContainerListener* >(aListenerIterator.next())->elementReplaced(aEvent);
168     }
169 }
170 
addContainerListener(const Reference<XContainerListener> & _rxListener)171 void SAL_CALL OBookmarkContainer::addContainerListener( const Reference< XContainerListener >& _rxListener )
172 {
173     MutexGuard aGuard(m_rMutex);
174     if (_rxListener.is())
175         m_aContainerListeners.addInterface(_rxListener);
176 }
177 
removeContainerListener(const Reference<XContainerListener> & _rxListener)178 void SAL_CALL OBookmarkContainer::removeContainerListener( const Reference< XContainerListener >& _rxListener )
179 {
180     MutexGuard aGuard(m_rMutex);
181     if (_rxListener.is())
182         m_aContainerListeners.removeInterface(_rxListener);
183 }
184 
185 // XElementAccess
getElementType()186 Type SAL_CALL OBookmarkContainer::getElementType( )
187 {
188     MutexGuard aGuard(m_rMutex);
189     return ::cppu::UnoType<OUString>::get();
190 }
191 
hasElements()192 sal_Bool SAL_CALL OBookmarkContainer::hasElements( )
193 {
194     MutexGuard aGuard(m_rMutex);
195     return !m_aBookmarks.empty();
196 }
197 
198 // XEnumerationAccess
createEnumeration()199 Reference< XEnumeration > SAL_CALL OBookmarkContainer::createEnumeration(  )
200 {
201     MutexGuard aGuard(m_rMutex);
202     return new ::comphelper::OEnumerationByIndex(static_cast<XIndexAccess*>(this));
203 }
204 
205 // XIndexAccess
getCount()206 sal_Int32 SAL_CALL OBookmarkContainer::getCount(  )
207 {
208     MutexGuard aGuard(m_rMutex);
209     return m_aBookmarks.size();
210 }
211 
getByIndex(sal_Int32 _nIndex)212 Any SAL_CALL OBookmarkContainer::getByIndex( sal_Int32 _nIndex )
213 {
214     MutexGuard aGuard(m_rMutex);
215 
216     if ((_nIndex < 0) || (_nIndex >= static_cast<sal_Int32>(m_aBookmarksIndexed.size())))
217         throw IndexOutOfBoundsException();
218 
219     return makeAny(m_aBookmarksIndexed[_nIndex]->second);
220 }
221 
getByName(const OUString & _rName)222 Any SAL_CALL OBookmarkContainer::getByName( const OUString& _rName )
223 {
224     MutexGuard aGuard(m_rMutex);
225 
226     if (!checkExistence(_rName))
227         throw NoSuchElementException();
228 
229     return makeAny(m_aBookmarks[_rName]);
230 }
231 
getElementNames()232 Sequence< OUString > SAL_CALL OBookmarkContainer::getElementNames(  )
233 {
234     MutexGuard aGuard(m_rMutex);
235 
236     Sequence< OUString > aNames(m_aBookmarks.size());
237     OUString* pNames = aNames.getArray();
238 
239     for (auto const& bookmarkIndexed : m_aBookmarksIndexed)
240     {
241         *pNames = bookmarkIndexed->first;
242         ++pNames;
243     }
244 
245     return aNames;
246 }
247 
hasByName(const OUString & _rName)248 sal_Bool SAL_CALL OBookmarkContainer::hasByName( const OUString& _rName )
249 {
250     MutexGuard aGuard(m_rMutex);
251 
252     return checkExistence(_rName);
253 }
254 
implRemove(const OUString & _rName)255 void OBookmarkContainer::implRemove(const OUString& _rName)
256 {
257     MutexGuard aGuard(m_rMutex);
258 
259     // look for the name in the index access vector
260     MapString2String::const_iterator aMapPos = m_aBookmarks.end();
261     auto aSearch = std::find_if(m_aBookmarksIndexed.begin(), m_aBookmarksIndexed.end(),
262         [&_rName](const MapString2String::iterator& rIter) { return rIter->first == _rName; });
263     if (aSearch != m_aBookmarksIndexed.end())
264     {
265         aMapPos = *aSearch;
266         m_aBookmarksIndexed.erase(aSearch);
267     }
268 
269     if (m_aBookmarks.end() == aMapPos)
270     {
271         OSL_FAIL("OBookmarkContainer::implRemove: inconsistence!");
272         return;
273     }
274 
275     // remove the map entries
276     m_aBookmarks.erase(aMapPos);
277 }
278 
implAppend(const OUString & _rName,const OUString & _rDocumentLocation)279 void OBookmarkContainer::implAppend(const OUString& _rName, const OUString& _rDocumentLocation)
280 {
281     MutexGuard aGuard(m_rMutex);
282 
283     OSL_ENSURE(m_aBookmarks.find(_rName) == m_aBookmarks.end(),"Bookmark already known!");
284     m_aBookmarksIndexed.push_back(m_aBookmarks.emplace( _rName,_rDocumentLocation).first);
285 }
286 
implReplace(const OUString & _rName,const OUString & _rNewLink)287 void OBookmarkContainer::implReplace(const OUString& _rName, const OUString& _rNewLink)
288 {
289     MutexGuard aGuard(m_rMutex);
290     OSL_ENSURE(checkExistence(_rName), "OBookmarkContainer::implReplace : invalid name !");
291 
292     m_aBookmarks[_rName] = _rNewLink;
293 }
294 
getParent()295 Reference< XInterface > SAL_CALL OBookmarkContainer::getParent(  )
296 {
297     return m_rParent;
298 }
299 
setParent(const Reference<XInterface> &)300 void SAL_CALL OBookmarkContainer::setParent( const Reference< XInterface >& /*Parent*/ )
301 {
302     throw NoSupportException();
303 }
304 
305 }   // namespace dbaccess
306 
307 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
308