1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_dbaccess.hxx" 30 31 #ifndef DBAUI_WIZ_COLUMNSELECT_HXX 32 #include "WColumnSelect.hxx" 33 #endif 34 #ifndef _DBU_MISC_HRC_ 35 #include "dbu_misc.hrc" 36 #endif 37 #ifndef _TOOLS_DEBUG_HXX 38 #include <tools/debug.hxx> 39 #endif 40 #ifndef DBAUI_WIZARD_PAGES_HRC 41 #include "WizardPages.hrc" 42 #endif 43 #ifndef DBAUI_WIZ_COPYTABLEDIALOG_HXX 44 #include "WCopyTable.hxx" 45 #endif 46 #ifndef _COM_SUN_STAR_SDBCX_XDATADESCRIPTORFACTORY_HPP_ 47 #include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp> 48 #endif 49 #ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_ 50 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp> 51 #endif 52 #ifndef _COM_SUN_STAR_SDBCX_XAPPEND_HPP_ 53 #include <com/sun/star/sdbcx/XAppend.hpp> 54 #endif 55 #ifndef _DBAUI_MODULE_DBU_HXX_ 56 #include "moduledbu.hxx" 57 #endif 58 #ifndef _COM_SUN_STAR_SDBC_DATATYPE_HPP_ 59 #include <com/sun/star/sdbc/DataType.hpp> 60 #endif 61 #ifndef _COM_SUN_STAR_SDBC_COLUMNVALUE_HPP_ 62 #include <com/sun/star/sdbc/ColumnValue.hpp> 63 #endif 64 #ifndef _COM_SUN_STAR_SDB_APPLICATION_COPYTABLEOPERATION_HPP_ 65 #include <com/sun/star/sdb/application/CopyTableOperation.hpp> 66 #endif 67 #ifndef DBACCESS_SHARED_DBUSTRINGS_HRC 68 #include "dbustrings.hrc" 69 #endif 70 #include <functional> 71 72 using namespace ::com::sun::star::uno; 73 using namespace ::com::sun::star::beans; 74 using namespace ::com::sun::star::container; 75 using namespace ::com::sun::star::sdbc; 76 using namespace ::com::sun::star::sdbcx; 77 using namespace dbaui; 78 79 namespace CopyTableOperation = ::com::sun::star::sdb::application::CopyTableOperation; 80 81 // ----------------------------------------------------------------------- 82 String OWizColumnSelect::GetTitle() const { return String(ModuleRes(STR_WIZ_COLUMN_SELECT_TITEL)); } 83 // ----------------------------------------------------------------------------- 84 OWizardPage::OWizardPage( Window* pParent, const ResId& rResId ) 85 : TabPage(pParent,rResId) 86 ,m_pParent(static_cast<OCopyTableWizard*>(pParent)) 87 ,m_bFirstTime(sal_True) 88 { 89 } 90 //======================================================================== 91 // OWizColumnSelect 92 DBG_NAME(OWizColumnSelect); 93 //======================================================================== 94 OWizColumnSelect::OWizColumnSelect( Window* pParent) 95 :OWizardPage( pParent, ModuleRes( TAB_WIZ_COLUMN_SELECT )) 96 ,m_flColumns( this, ModuleRes( FL_COLUMN_SELECT ) ) 97 ,m_lbOrgColumnNames( this, ModuleRes( LB_ORG_COLUMN_NAMES ) ) 98 ,m_ibColumn_RH( this, ModuleRes( IB_COLUMN_RH ) ) 99 ,m_ibColumns_RH( this, ModuleRes( IB_COLUMNS_RH ) ) 100 ,m_ibColumn_LH( this, ModuleRes( IB_COLUMN_LH ) ) 101 ,m_ibColumns_LH( this, ModuleRes( IB_COLUMNS_LH ) ) 102 ,m_lbNewColumnNames( this, ModuleRes( LB_NEW_COLUMN_NAMES ) ) 103 { 104 DBG_CTOR(OWizColumnSelect,NULL); 105 m_ibColumn_RH.SetClickHdl(LINK(this,OWizColumnSelect,ButtonClickHdl)); 106 m_ibColumn_LH.SetClickHdl(LINK(this,OWizColumnSelect,ButtonClickHdl)); 107 m_ibColumns_RH.SetClickHdl(LINK(this,OWizColumnSelect,ButtonClickHdl)); 108 m_ibColumns_LH.SetClickHdl(LINK(this,OWizColumnSelect,ButtonClickHdl)); 109 110 m_lbOrgColumnNames.EnableMultiSelection(sal_True); 111 m_lbNewColumnNames.EnableMultiSelection(sal_True); 112 113 m_lbOrgColumnNames.SetDoubleClickHdl(LINK(this,OWizColumnSelect,ListDoubleClickHdl)); 114 m_lbNewColumnNames.SetDoubleClickHdl(LINK(this,OWizColumnSelect,ListDoubleClickHdl)); 115 FreeResource(); 116 } 117 // ----------------------------------------------------------------------- 118 OWizColumnSelect::~OWizColumnSelect() 119 { 120 DBG_DTOR(OWizColumnSelect,NULL); 121 while ( m_lbNewColumnNames.GetEntryCount() ) 122 { 123 void* pData = m_lbNewColumnNames.GetEntryData(0); 124 if ( pData ) 125 delete static_cast<OFieldDescription*>(pData); 126 127 m_lbNewColumnNames.RemoveEntry(0); 128 } 129 m_lbNewColumnNames.Clear(); 130 } 131 132 // ----------------------------------------------------------------------- 133 void OWizColumnSelect::Reset() 134 { 135 // urspr"unglichen zustand wiederherstellen 136 DBG_CHKTHIS(OWizColumnSelect,NULL); 137 138 clearListBox(m_lbOrgColumnNames); 139 clearListBox(m_lbNewColumnNames); 140 m_pParent->m_mNameMapping.clear(); 141 142 // insert the source columns in the left listbox 143 const ODatabaseExport::TColumnVector* pSrcColumns = m_pParent->getSrcVector(); 144 ODatabaseExport::TColumnVector::const_iterator aIter = pSrcColumns->begin(); 145 ODatabaseExport::TColumnVector::const_iterator aEnd = pSrcColumns->end(); 146 147 for(;aIter != aEnd;++aIter) 148 { 149 sal_uInt16 nPos = m_lbOrgColumnNames.InsertEntry((*aIter)->first); 150 m_lbOrgColumnNames.SetEntryData(nPos,(*aIter)->second); 151 } 152 153 // m_pParent->clearDestColumns(); 154 155 if(m_lbOrgColumnNames.GetEntryCount()) 156 m_lbOrgColumnNames.SelectEntryPos(0); 157 158 m_bFirstTime = sal_False; 159 } 160 // ----------------------------------------------------------------------- 161 void OWizColumnSelect::ActivatePage( ) 162 { 163 DBG_CHKTHIS(OWizColumnSelect,NULL); 164 // if there are no dest columns reset the left side with the origibnal columns 165 if(m_pParent->getDestColumns()->size() == 0) 166 Reset(); 167 168 clearListBox(m_lbNewColumnNames); 169 170 const ODatabaseExport::TColumnVector* pDestColumns = m_pParent->getDestVector(); 171 172 ODatabaseExport::TColumnVector::const_iterator aIter = pDestColumns->begin(); 173 ODatabaseExport::TColumnVector::const_iterator aEnd = pDestColumns->end(); 174 for(;aIter != aEnd;++aIter) 175 { 176 sal_uInt16 nPos = m_lbNewColumnNames.InsertEntry((*aIter)->first); 177 m_lbNewColumnNames.SetEntryData(nPos,new OFieldDescription(*((*aIter)->second))); 178 m_lbOrgColumnNames.RemoveEntry((*aIter)->first); 179 } 180 m_pParent->GetOKButton().Enable(m_lbNewColumnNames.GetEntryCount() != 0); 181 m_pParent->EnableButton(OCopyTableWizard::WIZARD_NEXT,m_lbNewColumnNames.GetEntryCount() && m_pParent->getOperation() != CopyTableOperation::AppendData); 182 m_ibColumns_RH.GrabFocus(); 183 } 184 // ----------------------------------------------------------------------- 185 sal_Bool OWizColumnSelect::LeavePage() 186 { 187 DBG_CHKTHIS(OWizColumnSelect,NULL); 188 189 // m_pParent->getColumns()->clear(); 190 m_pParent->clearDestColumns(); 191 192 for(sal_uInt16 i=0 ; i< m_lbNewColumnNames.GetEntryCount();++i) 193 { 194 OFieldDescription* pField = static_cast<OFieldDescription*>(m_lbNewColumnNames.GetEntryData(i)); 195 OSL_ENSURE(pField,"The field information can not be null!"); 196 m_pParent->insertColumn(i,pField); 197 } 198 199 clearListBox(m_lbNewColumnNames); 200 201 202 if ( m_pParent->GetPressedButton() == OCopyTableWizard::WIZARD_NEXT 203 || m_pParent->GetPressedButton() == OCopyTableWizard::WIZARD_FINISH 204 ) 205 return m_pParent->getDestColumns()->size() != 0; 206 else 207 return sal_True; 208 } 209 // ----------------------------------------------------------------------- 210 IMPL_LINK( OWizColumnSelect, ButtonClickHdl, Button *, pButton ) 211 { 212 MultiListBox *pLeft = NULL; 213 MultiListBox *pRight = NULL; 214 sal_Bool bAll = sal_False; 215 216 if(pButton == &m_ibColumn_RH) 217 { 218 pLeft = &m_lbOrgColumnNames; 219 pRight = &m_lbNewColumnNames; 220 } 221 else if(pButton == &m_ibColumn_LH) 222 { 223 pLeft = &m_lbNewColumnNames; 224 pRight = &m_lbOrgColumnNames; 225 } 226 else if(pButton == &m_ibColumns_RH) 227 { 228 pLeft = &m_lbOrgColumnNames; 229 pRight = &m_lbNewColumnNames; 230 bAll = sal_True; 231 } 232 else if(pButton == &m_ibColumns_LH) 233 { 234 pLeft = &m_lbNewColumnNames; 235 pRight = &m_lbOrgColumnNames; 236 bAll = sal_True; 237 } 238 // else ???? 239 240 Reference< XDatabaseMetaData > xMetaData( m_pParent->m_xDestConnection->getMetaData() ); 241 ::rtl::OUString sExtraChars = xMetaData->getExtraNameCharacters(); 242 sal_Int32 nMaxNameLen = m_pParent->getMaxColumnNameLength(); 243 244 ::comphelper::TStringMixEqualFunctor aCase(xMetaData->supportsMixedCaseQuotedIdentifiers()); 245 ::std::vector< ::rtl::OUString> aRightColumns; 246 fillColumns(pRight,aRightColumns); 247 248 String aColumnName; 249 if(!bAll) 250 { 251 for(sal_uInt16 i=0; i < pLeft->GetSelectEntryCount(); ++i) 252 moveColumn(pRight,pLeft,aRightColumns,pLeft->GetSelectEntry(i),sExtraChars,nMaxNameLen,aCase); 253 254 for(sal_uInt16 j=pLeft->GetSelectEntryCount(); j ; --j) 255 pLeft->RemoveEntry(pLeft->GetSelectEntry(j-1)); 256 } 257 else 258 { 259 sal_uInt16 nEntries = pLeft->GetEntryCount(); 260 for(sal_uInt16 i=0; i < nEntries; ++i) 261 moveColumn(pRight,pLeft,aRightColumns,pLeft->GetEntry(i),sExtraChars,nMaxNameLen,aCase); 262 for(sal_uInt16 j=pLeft->GetEntryCount(); j ; --j) 263 pLeft->RemoveEntry(j-1); 264 } 265 266 enableButtons(); 267 268 if(m_lbOrgColumnNames.GetEntryCount()) 269 m_lbOrgColumnNames.SelectEntryPos(0); 270 271 return 0; 272 } 273 // ----------------------------------------------------------------------- 274 IMPL_LINK( OWizColumnSelect, ListDoubleClickHdl, MultiListBox *, pListBox ) 275 { 276 MultiListBox *pLeft,*pRight; 277 if(pListBox == &m_lbOrgColumnNames) 278 { 279 pLeft = &m_lbOrgColumnNames; 280 pRight = &m_lbNewColumnNames; 281 } 282 else 283 { 284 pRight = &m_lbOrgColumnNames; 285 pLeft = &m_lbNewColumnNames; 286 } 287 288 ////////////////////////////////////////////////////////////////////// 289 // Wenn Datenbank PrimaryKeys verarbeiten kann, PrimaryKey anlegen 290 Reference< XDatabaseMetaData > xMetaData( m_pParent->m_xDestConnection->getMetaData() ); 291 ::rtl::OUString sExtraChars = xMetaData->getExtraNameCharacters(); 292 sal_Int32 nMaxNameLen = m_pParent->getMaxColumnNameLength(); 293 294 ::comphelper::TStringMixEqualFunctor aCase(xMetaData->supportsMixedCaseQuotedIdentifiers()); 295 ::std::vector< ::rtl::OUString> aRightColumns; 296 fillColumns(pRight,aRightColumns); 297 298 String aColumnName; 299 for(sal_uInt16 i=0; i < pLeft->GetSelectEntryCount(); ++i) 300 moveColumn(pRight,pLeft,aRightColumns,pLeft->GetSelectEntry(i),sExtraChars,nMaxNameLen,aCase); 301 for(sal_uInt16 j=pLeft->GetSelectEntryCount(); j ; --j) 302 pLeft->RemoveEntry(pLeft->GetSelectEntry(j-1)); 303 304 enableButtons(); 305 return 0; 306 } 307 // ----------------------------------------------------------------------------- 308 void OWizColumnSelect::clearListBox(MultiListBox& _rListBox) 309 { 310 while(_rListBox.GetEntryCount()) 311 _rListBox.RemoveEntry(0); 312 _rListBox.Clear(); 313 } 314 // ----------------------------------------------------------------------------- 315 void OWizColumnSelect::fillColumns(ListBox* pRight,::std::vector< ::rtl::OUString> &_rRightColumns) 316 { 317 sal_uInt16 nCount = pRight->GetEntryCount(); 318 _rRightColumns.reserve(nCount); 319 for(sal_uInt16 i=0; i < nCount;++i) 320 _rRightColumns.push_back(pRight->GetEntry(i)); 321 } 322 // ----------------------------------------------------------------------------- 323 void OWizColumnSelect::createNewColumn( ListBox* _pListbox, 324 OFieldDescription* _pSrcField, 325 ::std::vector< ::rtl::OUString>& _rRightColumns, 326 const ::rtl::OUString& _sColumnName, 327 const ::rtl::OUString& _sExtraChars, 328 sal_Int32 _nMaxNameLen, 329 const ::comphelper::TStringMixEqualFunctor& _aCase) 330 { 331 ::rtl::OUString sConvertedName = m_pParent->convertColumnName(TMultiListBoxEntryFindFunctor(&_rRightColumns,_aCase), 332 _sColumnName, 333 _sExtraChars, 334 _nMaxNameLen); 335 OFieldDescription* pNewField = new OFieldDescription(*_pSrcField); 336 pNewField->SetName(sConvertedName); 337 sal_Bool bNotConvert = sal_True; 338 pNewField->SetType(m_pParent->convertType(_pSrcField->getSpecialTypeInfo(),bNotConvert)); 339 if ( !m_pParent->supportsPrimaryKey() ) 340 pNewField->SetPrimaryKey(sal_False); 341 342 _pListbox->SetEntryData(_pListbox->InsertEntry(sConvertedName),pNewField); 343 _rRightColumns.push_back(sConvertedName); 344 345 if ( !bNotConvert ) 346 m_pParent->showColumnTypeNotSupported(sConvertedName); 347 } 348 // ----------------------------------------------------------------------------- 349 void OWizColumnSelect::moveColumn( ListBox* _pRight, 350 ListBox* _pLeft, 351 ::std::vector< ::rtl::OUString>& _rRightColumns, 352 const ::rtl::OUString& _sColumnName, 353 const ::rtl::OUString& _sExtraChars, 354 sal_Int32 _nMaxNameLen, 355 const ::comphelper::TStringMixEqualFunctor& _aCase) 356 { 357 if(_pRight == &m_lbNewColumnNames) 358 { 359 // we copy the column into the new format for the dest 360 OFieldDescription* pSrcField = static_cast<OFieldDescription*>(_pLeft->GetEntryData(_pLeft->GetEntryPos(String(_sColumnName)))); 361 createNewColumn(_pRight,pSrcField,_rRightColumns,_sColumnName,_sExtraChars,_nMaxNameLen,_aCase); 362 } 363 else 364 { 365 // find the new column in the dest name mapping to obtain the old column 366 OCopyTableWizard::TNameMapping::iterator aIter = ::std::find_if(m_pParent->m_mNameMapping.begin(),m_pParent->m_mNameMapping.end(), 367 ::std::compose1( 368 ::std::bind2nd(_aCase, _sColumnName), 369 ::std::select2nd<OCopyTableWizard::TNameMapping::value_type>()) 370 ); 371 372 DBG_ASSERT(aIter != m_pParent->m_mNameMapping.end(),"Column must be defined"); 373 if ( aIter == m_pParent->m_mNameMapping.end() ) 374 return; // do nothing 375 const ODatabaseExport::TColumns* pSrcColumns = m_pParent->getSourceColumns(); 376 ODatabaseExport::TColumns::const_iterator aSrcIter = pSrcColumns->find((*aIter).first); 377 if ( aSrcIter != pSrcColumns->end() ) 378 { 379 // we need also the old position of this column to insert it back on that position again 380 const ODatabaseExport::TColumnVector* pSrcVector = m_pParent->getSrcVector(); 381 ODatabaseExport::TColumnVector::const_iterator aPos = ::std::find(pSrcVector->begin(),pSrcVector->end(),aSrcIter); 382 OSL_ENSURE( aPos != pSrcVector->end(),"Invalid position for the iterator here!"); 383 ODatabaseExport::TColumnVector::size_type nPos = (aPos - pSrcVector->begin()) - adjustColumnPosition(_pLeft, _sColumnName, (aPos - pSrcVector->begin()), _aCase); 384 385 _pRight->SetEntryData( _pRight->InsertEntry( (*aIter).first, sal::static_int_cast< sal_uInt16 >(nPos)),aSrcIter->second ); 386 _rRightColumns.push_back((*aIter).first); 387 m_pParent->removeColumnNameFromNameMap(_sColumnName); 388 } 389 } 390 } 391 // ----------------------------------------------------------------------------- 392 // Simply returning fields back to their original position is 393 // not enough. We need to take into acccount what fields have 394 // been removed earlier and adjust accordingly. Based on the 395 // algorithm employed in moveColumn(). 396 sal_uInt16 OWizColumnSelect::adjustColumnPosition( ListBox* _pLeft, 397 const ::rtl::OUString& _sColumnName, 398 ODatabaseExport::TColumnVector::size_type nCurrentPos, 399 const ::comphelper::TStringMixEqualFunctor& _aCase) 400 { 401 sal_uInt16 nAdjustedPos = 0; 402 403 // if returning all entries to their original position, 404 // then there is no need to adjust the positions. 405 if (m_ibColumns_LH.HasFocus()) 406 return nAdjustedPos; 407 408 sal_uInt16 nCount = _pLeft->GetEntryCount(); 409 ::rtl::OUString sColumnString; 410 for(sal_uInt16 i=0; i < nCount; ++i) 411 { 412 sColumnString = _pLeft->GetEntry(i); 413 if(_sColumnName != sColumnString) 414 { 415 // find the new column in the dest name mapping to obtain the old column 416 OCopyTableWizard::TNameMapping::iterator aIter = ::std::find_if(m_pParent->m_mNameMapping.begin(),m_pParent->m_mNameMapping.end(), 417 ::std::compose1( 418 ::std::bind2nd(_aCase, sColumnString), 419 ::std::select2nd<OCopyTableWizard::TNameMapping::value_type>()) 420 ); 421 422 DBG_ASSERT(aIter != m_pParent->m_mNameMapping.end(),"Column must be defined"); 423 const ODatabaseExport::TColumns* pSrcColumns = m_pParent->getSourceColumns(); 424 ODatabaseExport::TColumns::const_iterator aSrcIter = pSrcColumns->find((*aIter).first); 425 if ( aSrcIter != pSrcColumns->end() ) 426 { 427 // we need also the old position of this column to insert it back on that position again 428 const ODatabaseExport::TColumnVector* pSrcVector = m_pParent->getSrcVector(); 429 ODatabaseExport::TColumnVector::const_iterator aPos = ::std::find(pSrcVector->begin(),pSrcVector->end(),aSrcIter); 430 ODatabaseExport::TColumnVector::size_type nPos = aPos - pSrcVector->begin(); 431 if( nPos < nCurrentPos) 432 { 433 nAdjustedPos++; 434 } 435 } 436 } 437 } 438 439 return nAdjustedPos; 440 } 441 // ----------------------------------------------------------------------------- 442 void OWizColumnSelect::enableButtons() 443 { 444 sal_Bool bEntries = m_lbNewColumnNames.GetEntryCount() != 0; 445 if(!bEntries) 446 m_pParent->m_mNameMapping.clear(); 447 448 m_pParent->GetOKButton().Enable(bEntries); 449 m_pParent->EnableButton(OCopyTableWizard::WIZARD_NEXT,bEntries && m_pParent->getOperation() != CopyTableOperation::AppendData); 450 } 451 // ----------------------------------------------------------------------------- 452 453