1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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>
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
;
40 OIndexCollection::OIndexCollection()
44 OIndexCollection::OIndexCollection(const OIndexCollection
& _rSource
)
49 const OIndexCollection
& OIndexCollection::operator=(const OIndexCollection
& _rSource
)
52 m_xIndexes
= _rSource
.m_xIndexes
;
53 m_aIndexes
= _rSource
.m_aIndexes
;
57 void OIndexCollection::attach(const Reference
< XNameAccess
>& _rxIndexes
)
59 implConstructFrom(_rxIndexes
);
62 void OIndexCollection::detach()
68 Indexes::const_iterator
OIndexCollection::find(const OUString
& _rName
) const
70 OUString
sNameCompare(_rName
);
73 Indexes::const_iterator aSearch
= m_aIndexes
.begin();
74 Indexes::const_iterator aEnd
= m_aIndexes
.end();
75 for (; aSearch
!= aEnd
; ++aSearch
)
76 if (aSearch
->sName
== sNameCompare
)
82 Indexes::iterator
OIndexCollection::find(const OUString
& _rName
)
84 OUString
sNameCompare(_rName
);
87 Indexes::iterator aSearch
= m_aIndexes
.begin();
88 Indexes::iterator aEnd
= m_aIndexes
.end();
89 for (; aSearch
!= aEnd
; ++aSearch
)
90 if (aSearch
->sName
== sNameCompare
)
96 Indexes::const_iterator
OIndexCollection::findOriginal(const OUString
& _rName
) const
98 OUString
sNameCompare(_rName
);
101 Indexes::const_iterator aSearch
= m_aIndexes
.begin();
102 Indexes::const_iterator aEnd
= m_aIndexes
.end();
103 for (; aSearch
!= aEnd
; ++aSearch
)
104 if (aSearch
->getOriginalName() == sNameCompare
)
110 Indexes::iterator
OIndexCollection::findOriginal(const OUString
& _rName
)
112 OUString
sNameCompare(_rName
);
115 Indexes::iterator aSearch
= m_aIndexes
.begin();
116 Indexes::iterator aEnd
= m_aIndexes
.end();
117 for (; aSearch
!= aEnd
; ++aSearch
)
118 if (aSearch
->getOriginalName() == sNameCompare
)
124 void OIndexCollection::commitNewIndex(const Indexes::iterator
& _rPos
)
126 OSL_ENSURE(_rPos
->isNew(), "OIndexCollection::commitNewIndex: index must be new!");
130 Reference
< XDataDescriptorFactory
> xIndexFactory(m_xIndexes
, UNO_QUERY
);
131 Reference
< XAppend
> xAppendIndex(xIndexFactory
, UNO_QUERY
);
132 if (!xAppendIndex
.is())
134 OSL_FAIL("OIndexCollection::commitNewIndex: missing an interface of the index container!");
138 Reference
< XPropertySet
> xIndexDescriptor
= xIndexFactory
->createDataDescriptor();
139 Reference
< XColumnsSupplier
> xColsSupp(xIndexDescriptor
, UNO_QUERY
);
140 Reference
< XNameAccess
> xCols
;
142 xCols
= xColsSupp
->getColumns();
144 Reference
< XDataDescriptorFactory
> xColumnFactory(xCols
, UNO_QUERY
);
145 Reference
< XAppend
> xAppendCols(xColumnFactory
, UNO_QUERY
);
146 if (!xAppendCols
.is())
148 OSL_FAIL("OIndexCollection::commitNewIndex: invalid index descriptor returned!");
152 // set the properties
153 static const char s_sUniquePropertyName
[] = "IsUnique";
154 static const char s_sSortPropertyName
[] = "IsAscending";
155 static const char s_sNamePropertyName
[] = "Name";
156 // the index' own props
157 xIndexDescriptor
->setPropertyValue(s_sUniquePropertyName
, css::uno::makeAny(_rPos
->bUnique
));
158 xIndexDescriptor
->setPropertyValue(s_sNamePropertyName
, makeAny(_rPos
->sName
));
161 for ( IndexFields::const_iterator aFieldLoop
= _rPos
->aFields
.begin();
162 aFieldLoop
!= _rPos
->aFields
.end();
166 OSL_ENSURE(!xCols
->hasByName(aFieldLoop
->sFieldName
), "OIndexCollection::commitNewIndex: double column name (need to prevent this outside)!");
168 Reference
< XPropertySet
> xColDescriptor
= xColumnFactory
->createDataDescriptor();
169 OSL_ENSURE(xColDescriptor
.is(), "OIndexCollection::commitNewIndex: invalid column descriptor!");
170 if (xColDescriptor
.is())
172 xColDescriptor
->setPropertyValue(s_sSortPropertyName
, css::uno::makeAny(aFieldLoop
->bSortAscending
));
173 xColDescriptor
->setPropertyValue(s_sNamePropertyName
, makeAny(OUString(aFieldLoop
->sFieldName
)));
174 xAppendCols
->appendByDescriptor(xColDescriptor
);
178 xAppendIndex
->appendByDescriptor(xIndexDescriptor
);
180 _rPos
->flagAsCommitted(GrantIndexAccess());
181 _rPos
->clearModified();
187 catch( const Exception
& )
189 DBG_UNHANDLED_EXCEPTION();
193 bool OIndexCollection::dropNoRemove(const Indexes::iterator
& _rPos
)
197 OSL_ENSURE(m_xIndexes
->hasByName(_rPos
->getOriginalName()), "OIndexCollection::drop: invalid name!");
199 Reference
< XDrop
> xDropIndex(m_xIndexes
, UNO_QUERY
);
200 if (!xDropIndex
.is())
202 OSL_FAIL("OIndexCollection::drop: no XDrop interface!");
206 xDropIndex
->dropByName(_rPos
->getOriginalName());
212 catch( const Exception
& )
214 DBG_UNHANDLED_EXCEPTION();
218 // adjust the OIndex structure
219 Indexes::iterator aDropped
= findOriginal(_rPos
->getOriginalName());
220 OSL_ENSURE(aDropped
!= m_aIndexes
.end(), "OIndexCollection::drop: invalid original name, but successful commit?!");
221 aDropped
->flagAsNew(GrantIndexAccess());
226 bool OIndexCollection::drop(const Indexes::iterator
& _rPos
)
228 OSL_ENSURE((_rPos
>= m_aIndexes
.begin()) && (_rPos
< m_aIndexes
.end()),
229 "OIndexCollection::drop: invalid position (fasten your seatbelt .... this will crash)!");
232 if (!dropNoRemove(_rPos
))
235 // adjust the index array
236 m_aIndexes
.erase(_rPos
);
240 void OIndexCollection::implFillIndexInfo(OIndex
& _rIndex
)
242 // get the UNO descriptor for the index
243 Reference
< XPropertySet
> xIndex
;
244 m_xIndexes
->getByName(_rIndex
.getOriginalName()) >>= xIndex
;
247 OSL_FAIL("OIndexCollection::implFillIndexInfo: got an invalid index object!");
250 implFillIndexInfo(_rIndex
, xIndex
);
253 void OIndexCollection::implFillIndexInfo(OIndex
& _rIndex
, Reference
< XPropertySet
> _rxDescriptor
)
255 static const char s_sPrimaryIndexPropertyName
[] = "IsPrimaryKeyIndex";
256 static const char s_sUniquePropertyName
[] = "IsUnique";
257 static const char s_sSortPropertyName
[] = "IsAscending";
258 static const char s_sCatalogPropertyName
[] = "Catalog";
260 _rIndex
.bPrimaryKey
= ::cppu::any2bool(_rxDescriptor
->getPropertyValue(s_sPrimaryIndexPropertyName
));
261 _rIndex
.bUnique
= ::cppu::any2bool(_rxDescriptor
->getPropertyValue(s_sUniquePropertyName
));
262 _rxDescriptor
->getPropertyValue(s_sCatalogPropertyName
) >>= _rIndex
.sDescription
;
265 Reference
< XColumnsSupplier
> xSuppCols(_rxDescriptor
, UNO_QUERY
);
266 Reference
< XNameAccess
> xCols
;
268 xCols
= xSuppCols
->getColumns();
269 OSL_ENSURE(xCols
.is(), "OIndexCollection::implFillIndexInfo: the index does not have columns!");
272 Sequence
< OUString
> aFieldNames
= xCols
->getElementNames();
273 _rIndex
.aFields
.resize(aFieldNames
.getLength());
275 const OUString
* pFieldNames
= aFieldNames
.getConstArray();
276 const OUString
* pFieldNamesEnd
= pFieldNames
+ aFieldNames
.getLength();
277 IndexFields::iterator aCopyTo
= _rIndex
.aFields
.begin();
279 Reference
< XPropertySet
> xIndexColumn
;
280 for (;pFieldNames
< pFieldNamesEnd
; ++pFieldNames
, ++aCopyTo
)
282 // extract the column
283 xIndexColumn
.clear();
284 xCols
->getByName(*pFieldNames
) >>= xIndexColumn
;
285 if (!xIndexColumn
.is())
287 OSL_FAIL("OIndexCollection::implFillIndexInfo: invalid index column!");
292 // get the relevant properties
293 aCopyTo
->sFieldName
= *pFieldNames
;
294 aCopyTo
->bSortAscending
= ::cppu::any2bool(xIndexColumn
->getPropertyValue(s_sSortPropertyName
));
297 _rIndex
.aFields
.resize(aCopyTo
- _rIndex
.aFields
.begin());
298 // (just in case some fields were invalid ...)
302 void OIndexCollection::resetIndex(const Indexes::iterator
& _rPos
)
304 OSL_ENSURE(_rPos
>= m_aIndexes
.begin() && _rPos
< m_aIndexes
.end(),
305 "OIndexCollection::resetIndex: invalid position!");
309 _rPos
->sName
= _rPos
->getOriginalName();
310 implFillIndexInfo(*_rPos
);
312 _rPos
->clearModified();
313 _rPos
->flagAsCommitted(GrantIndexAccess());
319 catch( const Exception
& )
321 DBG_UNHANDLED_EXCEPTION();
325 Indexes::iterator
OIndexCollection::insert(const OUString
& _rName
)
327 OSL_ENSURE(end() == find(_rName
), "OIndexCollection::insert: invalid new name!");
329 OIndex
aNewIndex(tmpName
); // the empty string indicates the index is a new one
330 aNewIndex
.sName
= _rName
;
331 m_aIndexes
.push_back(aNewIndex
);
332 return m_aIndexes
.end() - 1; // the last element is the new one ...
335 void OIndexCollection::implConstructFrom(const Reference
< XNameAccess
>& _rxIndexes
)
339 m_xIndexes
= _rxIndexes
;
342 // loop through all the indexes
343 Sequence
< OUString
> aNames
= m_xIndexes
->getElementNames();
344 const OUString
* pNames
= aNames
.getConstArray();
345 const OUString
* pEnd
= pNames
+ aNames
.getLength();
346 for (; pNames
< pEnd
; ++pNames
)
348 // extract the index object
349 Reference
< XPropertySet
> xIndex
;
350 m_xIndexes
->getByName(*pNames
) >>= xIndex
;
353 OSL_FAIL("OIndexCollection::implConstructFrom: got an invalid index object ... ignoring!");
357 // fill the OIndex structure
358 OIndex
aCurrentIndex(*pNames
);
359 implFillIndexInfo(aCurrentIndex
);
360 m_aIndexes
.push_back(aCurrentIndex
);
367 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */