1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: indexcollection.cxx,v $
10 * $Revision: 1.8.254.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_dbaccess.hxx"
34 #ifndef _DBAUI_INDEXCOLLECTION_HXX_
35 #include "indexcollection.hxx"
37 #ifndef TOOLS_DIAGNOSE_EX_H
38 #include <tools/diagnose_ex.h>
40 #ifndef _COM_SUN_STAR_SDBCX_XAPPEND_HPP_
41 #include <com/sun/star/sdbcx/XAppend.hpp>
43 #ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
44 #include <com/sun/star/beans/XPropertySet.hpp>
46 #ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_
47 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
49 #ifndef _COM_SUN_STAR_SDBCX_XDATADESCRIPTORFACTORY_HPP_
50 #include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
52 #ifndef _COMPHELPER_EXTRACT_HXX_
53 #include <comphelper/extract.hxx>
55 #ifndef _COM_SUN_STAR_SDBCX_XDROP_HPP_
56 #include <com/sun/star/sdbcx/XDrop.hpp>
58 #ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_
59 #include <com/sun/star/container/XNameContainer.hpp>
62 //......................................................................
65 //......................................................................
67 using namespace ::com::sun::star::uno
;
68 using namespace ::com::sun::star::container
;
69 using namespace ::com::sun::star::beans
;
70 using namespace ::com::sun::star::sdbcx
;
71 using namespace ::com::sun::star::sdbc
;
73 //==================================================================
75 //==================================================================
76 //------------------------------------------------------------------
77 OIndexCollection::OIndexCollection()
81 //------------------------------------------------------------------
82 OIndexCollection::OIndexCollection(const OIndexCollection
& _rSource
)
87 //------------------------------------------------------------------
88 // OIndexCollection::OIndexCollection(const Reference< XNameAccess >& _rxIndexes)
90 // implConstructFrom(_rxIndexes);
93 //------------------------------------------------------------------
94 const OIndexCollection
& OIndexCollection::operator=(const OIndexCollection
& _rSource
)
97 m_xIndexes
= _rSource
.m_xIndexes
;
98 m_aIndexes
= _rSource
.m_aIndexes
;
102 //------------------------------------------------------------------
103 void OIndexCollection::attach(const Reference
< XNameAccess
>& _rxIndexes
)
105 implConstructFrom(_rxIndexes
);
108 //------------------------------------------------------------------
109 void OIndexCollection::detach()
115 //------------------------------------------------------------------
116 Indexes::const_iterator
OIndexCollection::find(const String
& _rName
) const
118 ::rtl::OUString
sNameCompare(_rName
);
121 Indexes::const_iterator aSearch
= m_aIndexes
.begin();
122 Indexes::const_iterator aEnd
= m_aIndexes
.end();
123 for (; aSearch
!= aEnd
; ++aSearch
)
124 if (aSearch
->sName
== sNameCompare
)
130 //------------------------------------------------------------------
131 Indexes::iterator
OIndexCollection::find(const String
& _rName
)
133 ::rtl::OUString
sNameCompare(_rName
);
136 Indexes::iterator aSearch
= m_aIndexes
.begin();
137 Indexes::iterator aEnd
= m_aIndexes
.end();
138 for (; aSearch
!= aEnd
; ++aSearch
)
139 if (aSearch
->sName
== sNameCompare
)
145 //------------------------------------------------------------------
146 Indexes::const_iterator
OIndexCollection::findOriginal(const String
& _rName
) const
148 ::rtl::OUString
sNameCompare(_rName
);
151 Indexes::const_iterator aSearch
= m_aIndexes
.begin();
152 Indexes::const_iterator aEnd
= m_aIndexes
.end();
153 for (; aSearch
!= aEnd
; ++aSearch
)
154 if (aSearch
->getOriginalName() == sNameCompare
)
160 //------------------------------------------------------------------
161 Indexes::iterator
OIndexCollection::findOriginal(const String
& _rName
)
163 ::rtl::OUString
sNameCompare(_rName
);
166 Indexes::iterator aSearch
= m_aIndexes
.begin();
167 Indexes::iterator aEnd
= m_aIndexes
.end();
168 for (; aSearch
!= aEnd
; ++aSearch
)
169 if (aSearch
->getOriginalName() == sNameCompare
)
175 //------------------------------------------------------------------
176 void OIndexCollection::commitNewIndex(const Indexes::iterator
& _rPos
) SAL_THROW((SQLException
))
178 OSL_ENSURE(_rPos
->isNew(), "OIndexCollection::commitNewIndex: index must be new!");
182 Reference
< XDataDescriptorFactory
> xIndexFactory(m_xIndexes
, UNO_QUERY
);
183 Reference
< XAppend
> xAppendIndex(xIndexFactory
, UNO_QUERY
);
184 if (!xAppendIndex
.is())
186 OSL_ENSURE(sal_False
, "OIndexCollection::commitNewIndex: missing an interface of the index container!");
190 Reference
< XPropertySet
> xIndexDescriptor
= xIndexFactory
->createDataDescriptor();
191 Reference
< XColumnsSupplier
> xColsSupp(xIndexDescriptor
, UNO_QUERY
);
192 Reference
< XNameAccess
> xCols
;
194 xCols
= xColsSupp
->getColumns();
196 Reference
< XDataDescriptorFactory
> xColumnFactory(xCols
, UNO_QUERY
);
197 Reference
< XAppend
> xAppendCols(xColumnFactory
, UNO_QUERY
);
198 if (!xAppendCols
.is())
200 OSL_ENSURE(sal_False
, "OIndexCollection::commitNewIndex: invalid index descriptor returned!");
204 // set the properties
205 static const ::rtl::OUString s_sUniquePropertyName
= ::rtl::OUString::createFromAscii("IsUnique");
206 static const ::rtl::OUString s_sSortPropertyName
= ::rtl::OUString::createFromAscii("IsAscending");
207 static const ::rtl::OUString s_sNamePropertyName
= ::rtl::OUString::createFromAscii("Name");
208 // the index' own props
209 xIndexDescriptor
->setPropertyValue(s_sUniquePropertyName
, ::cppu::bool2any(_rPos
->bUnique
));
210 xIndexDescriptor
->setPropertyValue(s_sNamePropertyName
, makeAny(_rPos
->sName
));
213 for ( ConstIndexFieldsIterator aFieldLoop
= _rPos
->aFields
.begin();
214 aFieldLoop
!= _rPos
->aFields
.end();
218 OSL_ENSURE(!xCols
->hasByName(aFieldLoop
->sFieldName
), "OIndexCollection::commitNewIndex: double column name (need to prevent this outside)!");
220 Reference
< XPropertySet
> xColDescriptor
= xColumnFactory
->createDataDescriptor();
221 OSL_ENSURE(xColDescriptor
.is(), "OIndexCollection::commitNewIndex: invalid column descriptor!");
222 if (xColDescriptor
.is())
224 xColDescriptor
->setPropertyValue(s_sSortPropertyName
, ::cppu::bool2any(aFieldLoop
->bSortAscending
));
225 xColDescriptor
->setPropertyValue(s_sNamePropertyName
, makeAny(::rtl::OUString(aFieldLoop
->sFieldName
)));
226 xAppendCols
->appendByDescriptor(xColDescriptor
);
230 xAppendIndex
->appendByDescriptor(xIndexDescriptor
);
232 _rPos
->flagAsCommitted(GrantIndexAccess());
233 _rPos
->clearModified();
239 catch( const Exception
& )
241 DBG_UNHANDLED_EXCEPTION();
245 //------------------------------------------------------------------
246 sal_Bool
OIndexCollection::dropNoRemove(const Indexes::iterator
& _rPos
) SAL_THROW((SQLException
))
250 OSL_ENSURE(m_xIndexes
->hasByName(_rPos
->getOriginalName()), "OIndexCollection::drop: invalid name!");
252 Reference
< XDrop
> xDropIndex(m_xIndexes
, UNO_QUERY
);
253 if (!xDropIndex
.is())
255 OSL_ENSURE(sal_False
, "OIndexCollection::drop: no XDrop interface!");
259 xDropIndex
->dropByName(_rPos
->getOriginalName());
265 catch( const Exception
& )
267 DBG_UNHANDLED_EXCEPTION();
271 // adjust the OIndex structure
272 Indexes::iterator aDropped
= findOriginal(_rPos
->getOriginalName());
273 OSL_ENSURE(aDropped
!= m_aIndexes
.end(), "OIndexCollection::drop: invalid original name, but successfull commit?!");
274 aDropped
->flagAsNew(GrantIndexAccess());
279 //------------------------------------------------------------------
280 sal_Bool
OIndexCollection::drop(const Indexes::iterator
& _rPos
) SAL_THROW((SQLException
))
282 OSL_ENSURE((_rPos
>= m_aIndexes
.begin()) && (_rPos
< m_aIndexes
.end()),
283 "OIndexCollection::drop: invalid position (fasten your seatbelt .... this will crash)!");
286 if (!dropNoRemove(_rPos
))
289 // adjust the index array
290 m_aIndexes
.erase(_rPos
);
294 //------------------------------------------------------------------
295 void OIndexCollection::implFillIndexInfo(OIndex
& _rIndex
) SAL_THROW((Exception
))
297 // get the UNO descriptor for the index
298 Reference
< XPropertySet
> xIndex
;
299 m_xIndexes
->getByName(_rIndex
.getOriginalName()) >>= xIndex
;
302 OSL_ENSURE(sal_False
, "OIndexCollection::implFillIndexInfo: got an invalid index object!");
305 implFillIndexInfo(_rIndex
, xIndex
);
308 //------------------------------------------------------------------
309 void OIndexCollection::implFillIndexInfo(OIndex
& _rIndex
, Reference
< XPropertySet
> _rxDescriptor
) SAL_THROW((Exception
))
311 static const ::rtl::OUString s_sPrimaryIndexPropertyName
= ::rtl::OUString::createFromAscii("IsPrimaryKeyIndex");
312 static const ::rtl::OUString s_sUniquePropertyName
= ::rtl::OUString::createFromAscii("IsUnique");
313 static const ::rtl::OUString s_sSortPropertyName
= ::rtl::OUString::createFromAscii("IsAscending");
314 static const ::rtl::OUString s_sCatalogPropertyName
= ::rtl::OUString::createFromAscii("Catalog");
316 _rIndex
.bPrimaryKey
= ::cppu::any2bool(_rxDescriptor
->getPropertyValue(s_sPrimaryIndexPropertyName
));
317 _rIndex
.bUnique
= ::cppu::any2bool(_rxDescriptor
->getPropertyValue(s_sUniquePropertyName
));
318 _rxDescriptor
->getPropertyValue(s_sCatalogPropertyName
) >>= _rIndex
.sDescription
;
321 Reference
< XColumnsSupplier
> xSuppCols(_rxDescriptor
, UNO_QUERY
);
322 Reference
< XNameAccess
> xCols
;
324 xCols
= xSuppCols
->getColumns();
325 OSL_ENSURE(xCols
.is(), "OIndexCollection::implFillIndexInfo: the index does not have columns!");
328 Sequence
< ::rtl::OUString
> aFieldNames
= xCols
->getElementNames();
329 _rIndex
.aFields
.resize(aFieldNames
.getLength());
331 const ::rtl::OUString
* pFieldNames
= aFieldNames
.getConstArray();
332 const ::rtl::OUString
* pFieldNamesEnd
= pFieldNames
+ aFieldNames
.getLength();
333 IndexFields::iterator aCopyTo
= _rIndex
.aFields
.begin();
335 Reference
< XPropertySet
> xIndexColumn
;
336 for (;pFieldNames
< pFieldNamesEnd
; ++pFieldNames
, ++aCopyTo
)
338 // extract the column
339 xIndexColumn
.clear();
340 xCols
->getByName(*pFieldNames
) >>= xIndexColumn
;
341 if (!xIndexColumn
.is())
343 OSL_ENSURE(sal_False
, "OIndexCollection::implFillIndexInfo: invalid index column!");
348 // get the relevant properties
349 aCopyTo
->sFieldName
= *pFieldNames
;
350 aCopyTo
->bSortAscending
= ::cppu::any2bool(xIndexColumn
->getPropertyValue(s_sSortPropertyName
));
353 _rIndex
.aFields
.resize(aCopyTo
- _rIndex
.aFields
.begin());
354 // (just in case some fields were invalid ...)
358 //------------------------------------------------------------------
359 void OIndexCollection::resetIndex(const Indexes::iterator
& _rPos
) SAL_THROW((SQLException
))
361 OSL_ENSURE(_rPos
>= m_aIndexes
.begin() && _rPos
< m_aIndexes
.end(),
362 "OIndexCollection::resetIndex: invalid position!");
366 _rPos
->sName
= _rPos
->getOriginalName();
367 implFillIndexInfo(*_rPos
);
369 _rPos
->clearModified();
370 _rPos
->flagAsCommitted(GrantIndexAccess());
376 catch( const Exception
& )
378 DBG_UNHANDLED_EXCEPTION();
382 //------------------------------------------------------------------
383 Indexes::iterator
OIndexCollection::insert(const String
& _rName
)
385 OSL_ENSURE(end() == find(_rName
), "OIndexCollection::insert: invalid new name!");
387 OIndex
aNewIndex(tmpName
); // the empty string indicates the index is a new one
388 aNewIndex
.sName
= _rName
;
389 m_aIndexes
.push_back(aNewIndex
);
390 return m_aIndexes
.end() - 1; // the last element is the new one ...
393 //------------------------------------------------------------------
394 void OIndexCollection::implConstructFrom(const Reference
< XNameAccess
>& _rxIndexes
)
398 m_xIndexes
= _rxIndexes
;
401 // loop through all the indexes
402 Sequence
< ::rtl::OUString
> aNames
= m_xIndexes
->getElementNames();
403 const ::rtl::OUString
* pNames
= aNames
.getConstArray();
404 const ::rtl::OUString
* pEnd
= pNames
+ aNames
.getLength();
405 for (; pNames
< pEnd
; ++pNames
)
407 // extract the index object
408 Reference
< XPropertySet
> xIndex
;
409 m_xIndexes
->getByName(*pNames
) >>= xIndex
;
412 OSL_ENSURE(sal_False
, "OIndexCollection::implConstructFrom: got an invalid index object ... ignoring!");
416 // fill the OIndex structure
417 OIndex
aCurrentIndex(*pNames
);
418 implFillIndexInfo(aCurrentIndex
);
419 m_aIndexes
.push_back(aCurrentIndex
);
424 //......................................................................
426 //......................................................................