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 "indexcollection.hxx"
21 : #include <tools/diagnose_ex.h>
22 : #include <com/sun/star/sdbcx/XAppend.hpp>
23 : #include <com/sun/star/beans/XPropertySet.hpp>
24 : #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
25 : #include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
26 : #include <comphelper/extract.hxx>
27 : #include <com/sun/star/sdbcx/XDrop.hpp>
28 : #include <com/sun/star/container/XNameContainer.hpp>
29 :
30 : namespace dbaui
31 : {
32 :
33 : using namespace ::com::sun::star::uno;
34 : using namespace ::com::sun::star::container;
35 : using namespace ::com::sun::star::beans;
36 : using namespace ::com::sun::star::sdbcx;
37 : using namespace ::com::sun::star::sdbc;
38 :
39 : // OIndexCollection
40 0 : OIndexCollection::OIndexCollection()
41 : {
42 0 : }
43 :
44 0 : OIndexCollection::OIndexCollection(const OIndexCollection& _rSource)
45 : {
46 0 : *this = _rSource;
47 0 : }
48 :
49 0 : const OIndexCollection& OIndexCollection::operator=(const OIndexCollection& _rSource)
50 : {
51 0 : detach();
52 0 : m_xIndexes = _rSource.m_xIndexes;
53 0 : m_aIndexes = _rSource.m_aIndexes;
54 0 : return *this;
55 : }
56 :
57 0 : void OIndexCollection::attach(const Reference< XNameAccess >& _rxIndexes)
58 : {
59 0 : implConstructFrom(_rxIndexes);
60 0 : }
61 :
62 0 : void OIndexCollection::detach()
63 : {
64 0 : m_xIndexes.clear();
65 0 : m_aIndexes.clear();
66 0 : }
67 :
68 0 : Indexes::const_iterator OIndexCollection::find(const OUString& _rName) const
69 : {
70 0 : OUString sNameCompare(_rName);
71 :
72 : // loop'n'compare
73 0 : Indexes::const_iterator aSearch = m_aIndexes.begin();
74 0 : Indexes::const_iterator aEnd = m_aIndexes.end();
75 0 : for (; aSearch != aEnd; ++aSearch)
76 0 : if (aSearch->sName == sNameCompare)
77 0 : break;
78 :
79 0 : return aSearch;
80 : }
81 :
82 0 : Indexes::iterator OIndexCollection::find(const OUString& _rName)
83 : {
84 0 : OUString sNameCompare(_rName);
85 :
86 : // loop'n'compare
87 0 : Indexes::iterator aSearch = m_aIndexes.begin();
88 0 : Indexes::iterator aEnd = m_aIndexes.end();
89 0 : for (; aSearch != aEnd; ++aSearch)
90 0 : if (aSearch->sName == sNameCompare)
91 0 : break;
92 :
93 0 : return aSearch;
94 : }
95 :
96 0 : Indexes::const_iterator OIndexCollection::findOriginal(const OUString& _rName) const
97 : {
98 0 : OUString sNameCompare(_rName);
99 :
100 : // loop'n'compare
101 0 : Indexes::const_iterator aSearch = m_aIndexes.begin();
102 0 : Indexes::const_iterator aEnd = m_aIndexes.end();
103 0 : for (; aSearch != aEnd; ++aSearch)
104 0 : if (aSearch->getOriginalName() == sNameCompare)
105 0 : break;
106 :
107 0 : return aSearch;
108 : }
109 :
110 0 : Indexes::iterator OIndexCollection::findOriginal(const OUString& _rName)
111 : {
112 0 : OUString sNameCompare(_rName);
113 :
114 : // loop'n'compare
115 0 : Indexes::iterator aSearch = m_aIndexes.begin();
116 0 : Indexes::iterator aEnd = m_aIndexes.end();
117 0 : for (; aSearch != aEnd; ++aSearch)
118 0 : if (aSearch->getOriginalName() == sNameCompare)
119 0 : break;
120 :
121 0 : return aSearch;
122 : }
123 :
124 0 : void OIndexCollection::commitNewIndex(const Indexes::iterator& _rPos) SAL_THROW((SQLException))
125 : {
126 : OSL_ENSURE(_rPos->isNew(), "OIndexCollection::commitNewIndex: index must be new!");
127 :
128 : try
129 : {
130 0 : Reference< XDataDescriptorFactory > xIndexFactory(m_xIndexes, UNO_QUERY);
131 0 : Reference< XAppend > xAppendIndex(xIndexFactory, UNO_QUERY);
132 0 : if (!xAppendIndex.is())
133 : {
134 : OSL_FAIL("OIndexCollection::commitNewIndex: missing an interface of the index container!");
135 0 : return;
136 : }
137 :
138 0 : Reference< XPropertySet > xIndexDescriptor = xIndexFactory->createDataDescriptor();
139 0 : Reference< XColumnsSupplier > xColsSupp(xIndexDescriptor, UNO_QUERY);
140 0 : Reference< XNameAccess > xCols;
141 0 : if (xColsSupp.is())
142 0 : xCols = xColsSupp->getColumns();
143 :
144 0 : Reference< XDataDescriptorFactory > xColumnFactory(xCols, UNO_QUERY);
145 0 : Reference< XAppend > xAppendCols(xColumnFactory, UNO_QUERY);
146 0 : if (!xAppendCols.is())
147 : {
148 : OSL_FAIL("OIndexCollection::commitNewIndex: invalid index descriptor returned!");
149 0 : return;
150 : }
151 :
152 : // set the properties
153 0 : static const OUString s_sUniquePropertyName = "IsUnique";
154 0 : static const OUString s_sSortPropertyName = "IsAscending";
155 0 : static const OUString s_sNamePropertyName = "Name";
156 : // the index' own props
157 0 : xIndexDescriptor->setPropertyValue(s_sUniquePropertyName, css::uno::makeAny(_rPos->bUnique));
158 0 : xIndexDescriptor->setPropertyValue(s_sNamePropertyName, makeAny(_rPos->sName));
159 :
160 : // the fields
161 0 : for ( IndexFields::const_iterator aFieldLoop = _rPos->aFields.begin();
162 0 : aFieldLoop != _rPos->aFields.end();
163 : ++aFieldLoop
164 : )
165 : {
166 : OSL_ENSURE(!xCols->hasByName(aFieldLoop->sFieldName), "OIndexCollection::commitNewIndex: double column name (need to prevent this outside)!");
167 :
168 0 : Reference< XPropertySet > xColDescriptor = xColumnFactory->createDataDescriptor();
169 : OSL_ENSURE(xColDescriptor.is(), "OIndexCollection::commitNewIndex: invalid column descriptor!");
170 0 : if (xColDescriptor.is())
171 : {
172 0 : xColDescriptor->setPropertyValue(s_sSortPropertyName, css::uno::makeAny(aFieldLoop->bSortAscending));
173 0 : xColDescriptor->setPropertyValue(s_sNamePropertyName, makeAny(OUString(aFieldLoop->sFieldName)));
174 0 : xAppendCols->appendByDescriptor(xColDescriptor);
175 : }
176 0 : }
177 :
178 0 : xAppendIndex->appendByDescriptor(xIndexDescriptor);
179 :
180 0 : _rPos->flagAsCommitted(GrantIndexAccess());
181 0 : _rPos->clearModified();
182 : }
183 0 : catch(SQLException&)
184 : { // allowed to pass
185 0 : throw;
186 : }
187 0 : catch( const Exception& )
188 : {
189 : DBG_UNHANDLED_EXCEPTION();
190 : }
191 : }
192 :
193 0 : sal_Bool OIndexCollection::dropNoRemove(const Indexes::iterator& _rPos) SAL_THROW((SQLException))
194 : {
195 : try
196 : {
197 : OSL_ENSURE(m_xIndexes->hasByName(_rPos->getOriginalName()), "OIndexCollection::drop: invalid name!");
198 :
199 0 : Reference< XDrop > xDropIndex(m_xIndexes, UNO_QUERY);
200 0 : if (!xDropIndex.is())
201 : {
202 : OSL_FAIL("OIndexCollection::drop: no XDrop interface!");
203 0 : return sal_False;
204 : }
205 :
206 0 : xDropIndex->dropByName(_rPos->getOriginalName());
207 : }
208 0 : catch(SQLException&)
209 : { // allowed to pass
210 0 : throw;
211 : }
212 0 : catch( const Exception& )
213 : {
214 : DBG_UNHANDLED_EXCEPTION();
215 0 : return sal_False;
216 : }
217 :
218 : // adjust the OIndex structure
219 0 : Indexes::iterator aDropped = findOriginal(_rPos->getOriginalName());
220 : OSL_ENSURE(aDropped != m_aIndexes.end(), "OIndexCollection::drop: invalid original name, but successful commit?!");
221 0 : aDropped->flagAsNew(GrantIndexAccess());
222 :
223 0 : return sal_True;
224 : }
225 :
226 0 : sal_Bool OIndexCollection::drop(const Indexes::iterator& _rPos) SAL_THROW((SQLException))
227 : {
228 : OSL_ENSURE((_rPos >= m_aIndexes.begin()) && (_rPos < m_aIndexes.end()),
229 : "OIndexCollection::drop: invalid position (fasten your seatbelt .... this will crash)!");
230 :
231 0 : if (!_rPos->isNew())
232 0 : if (!dropNoRemove(_rPos))
233 0 : return sal_False;
234 :
235 : // adjust the index array
236 0 : m_aIndexes.erase(_rPos);
237 0 : return sal_True;
238 : }
239 :
240 0 : void OIndexCollection::implFillIndexInfo(OIndex& _rIndex) SAL_THROW((Exception))
241 : {
242 : // get the UNO descriptor for the index
243 0 : Reference< XPropertySet > xIndex;
244 0 : m_xIndexes->getByName(_rIndex.getOriginalName()) >>= xIndex;
245 0 : if (!xIndex.is())
246 : {
247 : OSL_FAIL("OIndexCollection::implFillIndexInfo: got an invalid index object!");
248 : }
249 : else
250 0 : implFillIndexInfo(_rIndex, xIndex);
251 0 : }
252 :
253 0 : void OIndexCollection::implFillIndexInfo(OIndex& _rIndex, Reference< XPropertySet > _rxDescriptor) SAL_THROW((Exception))
254 : {
255 0 : static const OUString s_sPrimaryIndexPropertyName = "IsPrimaryKeyIndex";
256 0 : static const OUString s_sUniquePropertyName = "IsUnique";
257 0 : static const OUString s_sSortPropertyName = "IsAscending";
258 0 : static const OUString s_sCatalogPropertyName = "Catalog";
259 :
260 0 : _rIndex.bPrimaryKey = ::cppu::any2bool(_rxDescriptor->getPropertyValue(s_sPrimaryIndexPropertyName));
261 0 : _rIndex.bUnique = ::cppu::any2bool(_rxDescriptor->getPropertyValue(s_sUniquePropertyName));
262 0 : _rxDescriptor->getPropertyValue(s_sCatalogPropertyName) >>= _rIndex.sDescription;
263 :
264 : // the columns
265 0 : Reference< XColumnsSupplier > xSuppCols(_rxDescriptor, UNO_QUERY);
266 0 : Reference< XNameAccess > xCols;
267 0 : if (xSuppCols.is())
268 0 : xCols = xSuppCols->getColumns();
269 : OSL_ENSURE(xCols.is(), "OIndexCollection::implFillIndexInfo: the index does not have columns!");
270 0 : if (xCols.is())
271 : {
272 0 : Sequence< OUString > aFieldNames = xCols->getElementNames();
273 0 : _rIndex.aFields.resize(aFieldNames.getLength());
274 :
275 0 : const OUString* pFieldNames = aFieldNames.getConstArray();
276 0 : const OUString* pFieldNamesEnd = pFieldNames + aFieldNames.getLength();
277 0 : IndexFields::iterator aCopyTo = _rIndex.aFields.begin();
278 :
279 0 : Reference< XPropertySet > xIndexColumn;
280 0 : for (;pFieldNames < pFieldNamesEnd; ++pFieldNames, ++aCopyTo)
281 : {
282 : // extract the column
283 0 : xIndexColumn.clear();
284 0 : xCols->getByName(*pFieldNames) >>= xIndexColumn;
285 0 : if (!xIndexColumn.is())
286 : {
287 : OSL_FAIL("OIndexCollection::implFillIndexInfo: invalid index column!");
288 0 : --aCopyTo;
289 0 : continue;
290 : }
291 :
292 : // get the relevant properties
293 0 : aCopyTo->sFieldName = *pFieldNames;
294 0 : aCopyTo->bSortAscending = ::cppu::any2bool(xIndexColumn->getPropertyValue(s_sSortPropertyName));
295 : }
296 :
297 0 : _rIndex.aFields.resize(aCopyTo - _rIndex.aFields.begin());
298 : // (just in case some fields were invalid ...)
299 0 : }
300 0 : }
301 :
302 0 : void OIndexCollection::resetIndex(const Indexes::iterator& _rPos) SAL_THROW((SQLException))
303 : {
304 : OSL_ENSURE(_rPos >= m_aIndexes.begin() && _rPos < m_aIndexes.end(),
305 : "OIndexCollection::resetIndex: invalid position!");
306 :
307 : try
308 : {
309 0 : _rPos->sName = _rPos->getOriginalName();
310 0 : implFillIndexInfo(*_rPos);
311 :
312 0 : _rPos->clearModified();
313 0 : _rPos->flagAsCommitted(GrantIndexAccess());
314 : }
315 0 : catch(SQLException&)
316 : { // allowed to pass
317 0 : throw;
318 : }
319 0 : catch( const Exception& )
320 : {
321 : DBG_UNHANDLED_EXCEPTION();
322 : }
323 0 : }
324 :
325 0 : Indexes::iterator OIndexCollection::insert(const OUString& _rName)
326 : {
327 : OSL_ENSURE(end() == find(_rName), "OIndexCollection::insert: invalid new name!");
328 0 : OUString tmpName;
329 0 : OIndex aNewIndex(tmpName); // the empty string indicates the index is a new one
330 0 : aNewIndex.sName = _rName;
331 0 : m_aIndexes.push_back(aNewIndex);
332 0 : return m_aIndexes.end() - 1; // the last element is the new one ...
333 : }
334 :
335 0 : void OIndexCollection::implConstructFrom(const Reference< XNameAccess >& _rxIndexes)
336 : {
337 0 : detach();
338 :
339 0 : m_xIndexes = _rxIndexes;
340 0 : if (m_xIndexes.is())
341 : {
342 : // loop through all the indexes
343 0 : Sequence< OUString > aNames = m_xIndexes->getElementNames();
344 0 : const OUString* pNames = aNames.getConstArray();
345 0 : const OUString* pEnd = pNames + aNames.getLength();
346 0 : for (; pNames < pEnd; ++pNames)
347 : {
348 : // extract the index object
349 0 : Reference< XPropertySet > xIndex;
350 0 : m_xIndexes->getByName(*pNames) >>= xIndex;
351 0 : if (!xIndex.is())
352 : {
353 : OSL_FAIL("OIndexCollection::implConstructFrom: got an invalid index object ... ignoring!");
354 0 : continue;
355 : }
356 :
357 : // fill the OIndex structure
358 0 : OIndex aCurrentIndex(*pNames);
359 0 : implFillIndexInfo(aCurrentIndex);
360 0 : m_aIndexes.push_back(aCurrentIndex);
361 0 : }
362 : }
363 0 : }
364 :
365 : } // namespace dbaui
366 :
367 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|