| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_dbaccess.hxx" |
| |
| #ifndef _DBAUI_INDEXCOLLECTION_HXX_ |
| #include "indexcollection.hxx" |
| #endif |
| #ifndef TOOLS_DIAGNOSE_EX_H |
| #include <tools/diagnose_ex.h> |
| #endif |
| #ifndef _COM_SUN_STAR_SDBCX_XAPPEND_HPP_ |
| #include <com/sun/star/sdbcx/XAppend.hpp> |
| #endif |
| #ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ |
| #include <com/sun/star/beans/XPropertySet.hpp> |
| #endif |
| #ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_ |
| #include <com/sun/star/sdbcx/XColumnsSupplier.hpp> |
| #endif |
| #ifndef _COM_SUN_STAR_SDBCX_XDATADESCRIPTORFACTORY_HPP_ |
| #include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp> |
| #endif |
| #ifndef _COMPHELPER_EXTRACT_HXX_ |
| #include <comphelper/extract.hxx> |
| #endif |
| #ifndef _COM_SUN_STAR_SDBCX_XDROP_HPP_ |
| #include <com/sun/star/sdbcx/XDrop.hpp> |
| #endif |
| #ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_ |
| #include <com/sun/star/container/XNameContainer.hpp> |
| #endif |
| |
| //...................................................................... |
| namespace dbaui |
| { |
| //...................................................................... |
| |
| using namespace ::com::sun::star::uno; |
| using namespace ::com::sun::star::container; |
| using namespace ::com::sun::star::beans; |
| using namespace ::com::sun::star::sdbcx; |
| using namespace ::com::sun::star::sdbc; |
| |
| //================================================================== |
| //= OIndexCollection |
| //================================================================== |
| //------------------------------------------------------------------ |
| OIndexCollection::OIndexCollection() |
| { |
| } |
| |
| //------------------------------------------------------------------ |
| OIndexCollection::OIndexCollection(const OIndexCollection& _rSource) |
| { |
| *this = _rSource; |
| } |
| |
| //------------------------------------------------------------------ |
| // OIndexCollection::OIndexCollection(const Reference< XNameAccess >& _rxIndexes) |
| // { |
| // implConstructFrom(_rxIndexes); |
| // } |
| |
| //------------------------------------------------------------------ |
| const OIndexCollection& OIndexCollection::operator=(const OIndexCollection& _rSource) |
| { |
| detach(); |
| m_xIndexes = _rSource.m_xIndexes; |
| m_aIndexes = _rSource.m_aIndexes; |
| return *this; |
| } |
| |
| //------------------------------------------------------------------ |
| void OIndexCollection::attach(const Reference< XNameAccess >& _rxIndexes) |
| { |
| implConstructFrom(_rxIndexes); |
| } |
| |
| //------------------------------------------------------------------ |
| void OIndexCollection::detach() |
| { |
| m_xIndexes.clear(); |
| m_aIndexes.clear(); |
| } |
| |
| //------------------------------------------------------------------ |
| Indexes::const_iterator OIndexCollection::find(const String& _rName) const |
| { |
| ::rtl::OUString sNameCompare(_rName); |
| |
| // loop'n'compare |
| Indexes::const_iterator aSearch = m_aIndexes.begin(); |
| Indexes::const_iterator aEnd = m_aIndexes.end(); |
| for (; aSearch != aEnd; ++aSearch) |
| if (aSearch->sName == sNameCompare) |
| break; |
| |
| return aSearch; |
| } |
| |
| //------------------------------------------------------------------ |
| Indexes::iterator OIndexCollection::find(const String& _rName) |
| { |
| ::rtl::OUString sNameCompare(_rName); |
| |
| // loop'n'compare |
| Indexes::iterator aSearch = m_aIndexes.begin(); |
| Indexes::iterator aEnd = m_aIndexes.end(); |
| for (; aSearch != aEnd; ++aSearch) |
| if (aSearch->sName == sNameCompare) |
| break; |
| |
| return aSearch; |
| } |
| |
| //------------------------------------------------------------------ |
| Indexes::const_iterator OIndexCollection::findOriginal(const String& _rName) const |
| { |
| ::rtl::OUString sNameCompare(_rName); |
| |
| // loop'n'compare |
| Indexes::const_iterator aSearch = m_aIndexes.begin(); |
| Indexes::const_iterator aEnd = m_aIndexes.end(); |
| for (; aSearch != aEnd; ++aSearch) |
| if (aSearch->getOriginalName() == sNameCompare) |
| break; |
| |
| return aSearch; |
| } |
| |
| //------------------------------------------------------------------ |
| Indexes::iterator OIndexCollection::findOriginal(const String& _rName) |
| { |
| ::rtl::OUString sNameCompare(_rName); |
| |
| // loop'n'compare |
| Indexes::iterator aSearch = m_aIndexes.begin(); |
| Indexes::iterator aEnd = m_aIndexes.end(); |
| for (; aSearch != aEnd; ++aSearch) |
| if (aSearch->getOriginalName() == sNameCompare) |
| break; |
| |
| return aSearch; |
| } |
| |
| //------------------------------------------------------------------ |
| void OIndexCollection::commitNewIndex(const Indexes::iterator& _rPos) SAL_THROW((SQLException)) |
| { |
| OSL_ENSURE(_rPos->isNew(), "OIndexCollection::commitNewIndex: index must be new!"); |
| |
| try |
| { |
| Reference< XDataDescriptorFactory > xIndexFactory(m_xIndexes, UNO_QUERY); |
| Reference< XAppend > xAppendIndex(xIndexFactory, UNO_QUERY); |
| if (!xAppendIndex.is()) |
| { |
| OSL_ENSURE(sal_False, "OIndexCollection::commitNewIndex: missing an interface of the index container!"); |
| return; |
| } |
| |
| Reference< XPropertySet > xIndexDescriptor = xIndexFactory->createDataDescriptor(); |
| Reference< XColumnsSupplier > xColsSupp(xIndexDescriptor, UNO_QUERY); |
| Reference< XNameAccess > xCols; |
| if (xColsSupp.is()) |
| xCols = xColsSupp->getColumns(); |
| |
| Reference< XDataDescriptorFactory > xColumnFactory(xCols, UNO_QUERY); |
| Reference< XAppend > xAppendCols(xColumnFactory, UNO_QUERY); |
| if (!xAppendCols.is()) |
| { |
| OSL_ENSURE(sal_False, "OIndexCollection::commitNewIndex: invalid index descriptor returned!"); |
| return; |
| } |
| |
| // set the properties |
| static const ::rtl::OUString s_sUniquePropertyName = ::rtl::OUString::createFromAscii("IsUnique"); |
| static const ::rtl::OUString s_sSortPropertyName = ::rtl::OUString::createFromAscii("IsAscending"); |
| static const ::rtl::OUString s_sNamePropertyName = ::rtl::OUString::createFromAscii("Name"); |
| // the index' own props |
| xIndexDescriptor->setPropertyValue(s_sUniquePropertyName, ::cppu::bool2any(_rPos->bUnique)); |
| xIndexDescriptor->setPropertyValue(s_sNamePropertyName, makeAny(_rPos->sName)); |
| |
| // the fields |
| for ( ConstIndexFieldsIterator aFieldLoop = _rPos->aFields.begin(); |
| aFieldLoop != _rPos->aFields.end(); |
| ++aFieldLoop |
| ) |
| { |
| OSL_ENSURE(!xCols->hasByName(aFieldLoop->sFieldName), "OIndexCollection::commitNewIndex: double column name (need to prevent this outside)!"); |
| |
| Reference< XPropertySet > xColDescriptor = xColumnFactory->createDataDescriptor(); |
| OSL_ENSURE(xColDescriptor.is(), "OIndexCollection::commitNewIndex: invalid column descriptor!"); |
| if (xColDescriptor.is()) |
| { |
| xColDescriptor->setPropertyValue(s_sSortPropertyName, ::cppu::bool2any(aFieldLoop->bSortAscending)); |
| xColDescriptor->setPropertyValue(s_sNamePropertyName, makeAny(::rtl::OUString(aFieldLoop->sFieldName))); |
| xAppendCols->appendByDescriptor(xColDescriptor); |
| } |
| } |
| |
| xAppendIndex->appendByDescriptor(xIndexDescriptor); |
| |
| _rPos->flagAsCommitted(GrantIndexAccess()); |
| _rPos->clearModified(); |
| } |
| catch(SQLException&) |
| { // allowed to pass |
| throw; |
| } |
| catch( const Exception& ) |
| { |
| DBG_UNHANDLED_EXCEPTION(); |
| } |
| } |
| |
| //------------------------------------------------------------------ |
| sal_Bool OIndexCollection::dropNoRemove(const Indexes::iterator& _rPos) SAL_THROW((SQLException)) |
| { |
| try |
| { |
| OSL_ENSURE(m_xIndexes->hasByName(_rPos->getOriginalName()), "OIndexCollection::drop: invalid name!"); |
| |
| Reference< XDrop > xDropIndex(m_xIndexes, UNO_QUERY); |
| if (!xDropIndex.is()) |
| { |
| OSL_ENSURE(sal_False, "OIndexCollection::drop: no XDrop interface!"); |
| return sal_False; |
| } |
| |
| xDropIndex->dropByName(_rPos->getOriginalName()); |
| } |
| catch(SQLException&) |
| { // allowed to pass |
| throw; |
| } |
| catch( const Exception& ) |
| { |
| DBG_UNHANDLED_EXCEPTION(); |
| return sal_False; |
| } |
| |
| // adjust the OIndex structure |
| Indexes::iterator aDropped = findOriginal(_rPos->getOriginalName()); |
| OSL_ENSURE(aDropped != m_aIndexes.end(), "OIndexCollection::drop: invalid original name, but successful commit?!"); |
| aDropped->flagAsNew(GrantIndexAccess()); |
| |
| return sal_True; |
| } |
| |
| //------------------------------------------------------------------ |
| sal_Bool OIndexCollection::drop(const Indexes::iterator& _rPos) SAL_THROW((SQLException)) |
| { |
| OSL_ENSURE((_rPos >= m_aIndexes.begin()) && (_rPos < m_aIndexes.end()), |
| "OIndexCollection::drop: invalid position (fasten your seatbelt .... this will crash)!"); |
| |
| if (!_rPos->isNew()) |
| if (!dropNoRemove(_rPos)) |
| return sal_False; |
| |
| // adjust the index array |
| m_aIndexes.erase(_rPos); |
| return sal_True; |
| } |
| |
| //------------------------------------------------------------------ |
| void OIndexCollection::implFillIndexInfo(OIndex& _rIndex) SAL_THROW((Exception)) |
| { |
| // get the UNO descriptor for the index |
| Reference< XPropertySet > xIndex; |
| m_xIndexes->getByName(_rIndex.getOriginalName()) >>= xIndex; |
| if (!xIndex.is()) |
| { |
| OSL_ENSURE(sal_False, "OIndexCollection::implFillIndexInfo: got an invalid index object!"); |
| } |
| else |
| implFillIndexInfo(_rIndex, xIndex); |
| } |
| |
| //------------------------------------------------------------------ |
| void OIndexCollection::implFillIndexInfo(OIndex& _rIndex, Reference< XPropertySet > _rxDescriptor) SAL_THROW((Exception)) |
| { |
| static const ::rtl::OUString s_sPrimaryIndexPropertyName = ::rtl::OUString::createFromAscii("IsPrimaryKeyIndex"); |
| static const ::rtl::OUString s_sUniquePropertyName = ::rtl::OUString::createFromAscii("IsUnique"); |
| static const ::rtl::OUString s_sSortPropertyName = ::rtl::OUString::createFromAscii("IsAscending"); |
| static const ::rtl::OUString s_sCatalogPropertyName = ::rtl::OUString::createFromAscii("Catalog"); |
| |
| _rIndex.bPrimaryKey = ::cppu::any2bool(_rxDescriptor->getPropertyValue(s_sPrimaryIndexPropertyName)); |
| _rIndex.bUnique = ::cppu::any2bool(_rxDescriptor->getPropertyValue(s_sUniquePropertyName)); |
| _rxDescriptor->getPropertyValue(s_sCatalogPropertyName) >>= _rIndex.sDescription; |
| |
| // the columns |
| Reference< XColumnsSupplier > xSuppCols(_rxDescriptor, UNO_QUERY); |
| Reference< XNameAccess > xCols; |
| if (xSuppCols.is()) |
| xCols = xSuppCols->getColumns(); |
| OSL_ENSURE(xCols.is(), "OIndexCollection::implFillIndexInfo: the index does not have columns!"); |
| if (xCols.is()) |
| { |
| Sequence< ::rtl::OUString > aFieldNames = xCols->getElementNames(); |
| _rIndex.aFields.resize(aFieldNames.getLength()); |
| |
| const ::rtl::OUString* pFieldNames = aFieldNames.getConstArray(); |
| const ::rtl::OUString* pFieldNamesEnd = pFieldNames + aFieldNames.getLength(); |
| IndexFields::iterator aCopyTo = _rIndex.aFields.begin(); |
| |
| Reference< XPropertySet > xIndexColumn; |
| for (;pFieldNames < pFieldNamesEnd; ++pFieldNames, ++aCopyTo) |
| { |
| // extract the column |
| xIndexColumn.clear(); |
| xCols->getByName(*pFieldNames) >>= xIndexColumn; |
| if (!xIndexColumn.is()) |
| { |
| OSL_ENSURE(sal_False, "OIndexCollection::implFillIndexInfo: invalid index column!"); |
| --aCopyTo; |
| continue; |
| } |
| |
| // get the relevant properties |
| aCopyTo->sFieldName = *pFieldNames; |
| aCopyTo->bSortAscending = ::cppu::any2bool(xIndexColumn->getPropertyValue(s_sSortPropertyName)); |
| } |
| |
| _rIndex.aFields.resize(aCopyTo - _rIndex.aFields.begin()); |
| // (just in case some fields were invalid ...) |
| } |
| } |
| |
| //------------------------------------------------------------------ |
| void OIndexCollection::resetIndex(const Indexes::iterator& _rPos) SAL_THROW((SQLException)) |
| { |
| OSL_ENSURE(_rPos >= m_aIndexes.begin() && _rPos < m_aIndexes.end(), |
| "OIndexCollection::resetIndex: invalid position!"); |
| |
| try |
| { |
| _rPos->sName = _rPos->getOriginalName(); |
| implFillIndexInfo(*_rPos); |
| |
| _rPos->clearModified(); |
| _rPos->flagAsCommitted(GrantIndexAccess()); |
| } |
| catch(SQLException&) |
| { // allowed to pass |
| throw; |
| } |
| catch( const Exception& ) |
| { |
| DBG_UNHANDLED_EXCEPTION(); |
| } |
| } |
| |
| //------------------------------------------------------------------ |
| Indexes::iterator OIndexCollection::insert(const String& _rName) |
| { |
| OSL_ENSURE(end() == find(_rName), "OIndexCollection::insert: invalid new name!"); |
| String tmpName; |
| OIndex aNewIndex(tmpName); // the empty string indicates the index is a new one |
| aNewIndex.sName = _rName; |
| m_aIndexes.push_back(aNewIndex); |
| return m_aIndexes.end() - 1; // the last element is the new one ... |
| } |
| |
| //------------------------------------------------------------------ |
| void OIndexCollection::implConstructFrom(const Reference< XNameAccess >& _rxIndexes) |
| { |
| detach(); |
| |
| m_xIndexes = _rxIndexes; |
| if (m_xIndexes.is()) |
| { |
| // loop through all the indexes |
| Sequence< ::rtl::OUString > aNames = m_xIndexes->getElementNames(); |
| const ::rtl::OUString* pNames = aNames.getConstArray(); |
| const ::rtl::OUString* pEnd = pNames + aNames.getLength(); |
| for (; pNames < pEnd; ++pNames) |
| { |
| // extract the index object |
| Reference< XPropertySet > xIndex; |
| m_xIndexes->getByName(*pNames) >>= xIndex; |
| if (!xIndex.is()) |
| { |
| OSL_ENSURE(sal_False, "OIndexCollection::implConstructFrom: got an invalid index object ... ignoring!"); |
| continue; |
| } |
| |
| // fill the OIndex structure |
| OIndex aCurrentIndex(*pNames); |
| implFillIndexInfo(aCurrentIndex); |
| m_aIndexes.push_back(aCurrentIndex); |
| } |
| } |
| } |
| |
| //...................................................................... |
| } // namespace dbaui |
| //...................................................................... |
| |