| /************************************************************** | 
 |  *  | 
 |  * 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 successfull 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 | 
 | //...................................................................... | 
 |  |